From 835e373b3eeaabcd0621ed6798ab500f37982fae Mon Sep 17 00:00:00 2001 From: Calvin Morrison Date: Wed, 5 Apr 2023 14:13:39 -0400 Subject: xpdf-no-select-disable --- xpdf/AcroForm.cc | 3889 +++++++++ xpdf/AcroForm.h | 169 + xpdf/Annot.cc | 1448 ++++ xpdf/Annot.h | 185 + xpdf/Array.cc | 74 + xpdf/Array.h | 70 + xpdf/BuiltinFont.cc | 67 + xpdf/BuiltinFont.h | 58 + xpdf/BuiltinFontTables.cc | 4285 ++++++++++ xpdf/BuiltinFontTables.h | 23 + xpdf/CMakeFiles/CMakeDirectoryInformation.cmake | 16 + xpdf/CMakeFiles/pdfdetach.dir/CXX.includecache | 244 + xpdf/CMakeFiles/pdfdetach.dir/DependInfo.cmake | 26 + xpdf/CMakeFiles/pdfdetach.dir/build.make | 206 + xpdf/CMakeFiles/pdfdetach.dir/cmake_clean.cmake | 10 + xpdf/CMakeFiles/pdfdetach.dir/depend.internal | 28 + xpdf/CMakeFiles/pdfdetach.dir/depend.make | 28 + xpdf/CMakeFiles/pdfdetach.dir/flags.make | 10 + xpdf/CMakeFiles/pdfdetach.dir/link.txt | 1 + xpdf/CMakeFiles/pdfdetach.dir/pdfdetach.cc.o | Bin 0 -> 12160 bytes xpdf/CMakeFiles/pdfdetach.dir/progress.make | 3 + xpdf/CMakeFiles/pdffonts.dir/CXX.includecache | 258 + xpdf/CMakeFiles/pdffonts.dir/DependInfo.cmake | 26 + xpdf/CMakeFiles/pdffonts.dir/build.make | 206 + xpdf/CMakeFiles/pdffonts.dir/cmake_clean.cmake | 10 + xpdf/CMakeFiles/pdffonts.dir/depend.internal | 29 + xpdf/CMakeFiles/pdffonts.dir/depend.make | 29 + xpdf/CMakeFiles/pdffonts.dir/flags.make | 10 + xpdf/CMakeFiles/pdffonts.dir/link.txt | 1 + xpdf/CMakeFiles/pdffonts.dir/pdffonts.cc.o | Bin 0 -> 24000 bytes xpdf/CMakeFiles/pdffonts.dir/progress.make | 3 + xpdf/CMakeFiles/pdfimages.dir/CXX.includecache | 306 + xpdf/CMakeFiles/pdfimages.dir/DependInfo.cmake | 27 + xpdf/CMakeFiles/pdfimages.dir/ImageOutputDev.cc.o | Bin 0 -> 27856 bytes xpdf/CMakeFiles/pdfimages.dir/build.make | 221 + xpdf/CMakeFiles/pdfimages.dir/cmake_clean.cmake | 11 + xpdf/CMakeFiles/pdfimages.dir/depend.internal | 49 + xpdf/CMakeFiles/pdfimages.dir/depend.make | 49 + xpdf/CMakeFiles/pdfimages.dir/flags.make | 10 + xpdf/CMakeFiles/pdfimages.dir/link.txt | 1 + xpdf/CMakeFiles/pdfimages.dir/pdfimages.cc.o | Bin 0 -> 9904 bytes xpdf/CMakeFiles/pdfimages.dir/progress.make | 4 + xpdf/CMakeFiles/pdfinfo.dir/CXX.includecache | 288 + xpdf/CMakeFiles/pdfinfo.dir/DependInfo.cmake | 26 + xpdf/CMakeFiles/pdfinfo.dir/build.make | 206 + xpdf/CMakeFiles/pdfinfo.dir/cmake_clean.cmake | 10 + xpdf/CMakeFiles/pdfinfo.dir/depend.internal | 30 + xpdf/CMakeFiles/pdfinfo.dir/depend.make | 30 + xpdf/CMakeFiles/pdfinfo.dir/flags.make | 10 + xpdf/CMakeFiles/pdfinfo.dir/link.txt | 1 + xpdf/CMakeFiles/pdfinfo.dir/pdfinfo.cc.o | Bin 0 -> 27168 bytes xpdf/CMakeFiles/pdfinfo.dir/progress.make | 3 + xpdf/CMakeFiles/pdftohtml.dir/CXX.includecache | 734 ++ xpdf/CMakeFiles/pdftohtml.dir/DependInfo.cmake | 32 + xpdf/CMakeFiles/pdftohtml.dir/HTMLGen.cc.o | Bin 0 -> 47208 bytes xpdf/CMakeFiles/pdftohtml.dir/ShadingImage.cc.o | Bin 0 -> 43568 bytes xpdf/CMakeFiles/pdftohtml.dir/SplashOutputDev.cc.o | Bin 0 -> 149112 bytes xpdf/CMakeFiles/pdftohtml.dir/TextOutputDev.cc.o | Bin 0 -> 208392 bytes xpdf/CMakeFiles/pdftohtml.dir/WebFont.cc.o | Bin 0 -> 11992 bytes xpdf/CMakeFiles/pdftohtml.dir/build.make | 285 + xpdf/CMakeFiles/pdftohtml.dir/cmake_clean.cmake | 15 + xpdf/CMakeFiles/pdftohtml.dir/depend.internal | 189 + xpdf/CMakeFiles/pdftohtml.dir/depend.make | 189 + xpdf/CMakeFiles/pdftohtml.dir/flags.make | 10 + xpdf/CMakeFiles/pdftohtml.dir/link.txt | 1 + xpdf/CMakeFiles/pdftohtml.dir/pdftohtml.cc.o | Bin 0 -> 16736 bytes xpdf/CMakeFiles/pdftohtml.dir/progress.make | 8 + xpdf/CMakeFiles/pdftopng.dir/CXX.includecache | 580 ++ xpdf/CMakeFiles/pdftopng.dir/DependInfo.cmake | 29 + xpdf/CMakeFiles/pdftopng.dir/ShadingImage.cc.o | Bin 0 -> 43568 bytes xpdf/CMakeFiles/pdftopng.dir/SplashOutputDev.cc.o | Bin 0 -> 149112 bytes xpdf/CMakeFiles/pdftopng.dir/build.make | 240 + xpdf/CMakeFiles/pdftopng.dir/cmake_clean.cmake | 12 + xpdf/CMakeFiles/pdftopng.dir/depend.internal | 112 + xpdf/CMakeFiles/pdftopng.dir/depend.make | 112 + xpdf/CMakeFiles/pdftopng.dir/flags.make | 10 + xpdf/CMakeFiles/pdftopng.dir/link.txt | 1 + xpdf/CMakeFiles/pdftopng.dir/pdftopng.cc.o | Bin 0 -> 19472 bytes xpdf/CMakeFiles/pdftopng.dir/progress.make | 5 + xpdf/CMakeFiles/pdftoppm.dir/CXX.includecache | 578 ++ xpdf/CMakeFiles/pdftoppm.dir/DependInfo.cmake | 29 + xpdf/CMakeFiles/pdftoppm.dir/ShadingImage.cc.o | Bin 0 -> 43568 bytes xpdf/CMakeFiles/pdftoppm.dir/SplashOutputDev.cc.o | Bin 0 -> 149112 bytes xpdf/CMakeFiles/pdftoppm.dir/build.make | 238 + xpdf/CMakeFiles/pdftoppm.dir/cmake_clean.cmake | 12 + xpdf/CMakeFiles/pdftoppm.dir/depend.internal | 112 + xpdf/CMakeFiles/pdftoppm.dir/depend.make | 112 + xpdf/CMakeFiles/pdftoppm.dir/flags.make | 10 + xpdf/CMakeFiles/pdftoppm.dir/link.txt | 1 + xpdf/CMakeFiles/pdftoppm.dir/pdftoppm.cc.o | Bin 0 -> 13760 bytes xpdf/CMakeFiles/pdftoppm.dir/progress.make | 5 + xpdf/CMakeFiles/pdftops.dir/CXX.includecache | 740 ++ xpdf/CMakeFiles/pdftops.dir/DependInfo.cmake | 31 + xpdf/CMakeFiles/pdftops.dir/PSOutputDev.cc.o | Bin 0 -> 322304 bytes xpdf/CMakeFiles/pdftops.dir/PreScanOutputDev.cc.o | Bin 0 -> 23112 bytes xpdf/CMakeFiles/pdftops.dir/ShadingImage.cc.o | Bin 0 -> 43568 bytes xpdf/CMakeFiles/pdftops.dir/SplashOutputDev.cc.o | Bin 0 -> 149112 bytes xpdf/CMakeFiles/pdftops.dir/build.make | 268 + xpdf/CMakeFiles/pdftops.dir/cmake_clean.cmake | 14 + xpdf/CMakeFiles/pdftops.dir/depend.internal | 174 + xpdf/CMakeFiles/pdftops.dir/depend.make | 174 + xpdf/CMakeFiles/pdftops.dir/flags.make | 10 + xpdf/CMakeFiles/pdftops.dir/link.txt | 1 + xpdf/CMakeFiles/pdftops.dir/pdftops.cc.o | Bin 0 -> 21168 bytes xpdf/CMakeFiles/pdftops.dir/progress.make | 7 + xpdf/CMakeFiles/pdftotext.dir/CXX.includecache | 388 + xpdf/CMakeFiles/pdftotext.dir/DependInfo.cmake | 27 + xpdf/CMakeFiles/pdftotext.dir/TextOutputDev.cc.o | Bin 0 -> 208392 bytes xpdf/CMakeFiles/pdftotext.dir/build.make | 221 + xpdf/CMakeFiles/pdftotext.dir/cmake_clean.cmake | 11 + xpdf/CMakeFiles/pdftotext.dir/depend.internal | 60 + xpdf/CMakeFiles/pdftotext.dir/depend.make | 60 + xpdf/CMakeFiles/pdftotext.dir/flags.make | 10 + xpdf/CMakeFiles/pdftotext.dir/link.txt | 1 + xpdf/CMakeFiles/pdftotext.dir/pdftotext.cc.o | Bin 0 -> 17584 bytes xpdf/CMakeFiles/pdftotext.dir/progress.make | 4 + xpdf/CMakeFiles/progress.marks | 1 + xpdf/CMakeFiles/xpdf_objs.dir/AcroForm.cc.o | Bin 0 -> 172512 bytes xpdf/CMakeFiles/xpdf_objs.dir/Annot.cc.o | Bin 0 -> 72032 bytes xpdf/CMakeFiles/xpdf_objs.dir/Array.cc.o | Bin 0 -> 5128 bytes xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFont.cc.o | Bin 0 -> 3248 bytes .../xpdf_objs.dir/BuiltinFontTables.cc.o | Bin 0 -> 214016 bytes xpdf/CMakeFiles/xpdf_objs.dir/CMap.cc.o | Bin 0 -> 17400 bytes xpdf/CMakeFiles/xpdf_objs.dir/CXX.includecache | 1596 ++++ xpdf/CMakeFiles/xpdf_objs.dir/Catalog.cc.o | Bin 0 -> 52016 bytes .../xpdf_objs.dir/CharCodeToUnicode.cc.o | Bin 0 -> 25312 bytes xpdf/CMakeFiles/xpdf_objs.dir/Decrypt.cc.o | Bin 0 -> 42344 bytes xpdf/CMakeFiles/xpdf_objs.dir/DependInfo.cmake | 66 + xpdf/CMakeFiles/xpdf_objs.dir/Dict.cc.o | Bin 0 -> 8368 bytes xpdf/CMakeFiles/xpdf_objs.dir/Error.cc.o | Bin 0 -> 5544 bytes .../xpdf_objs.dir/FontEncodingTables.cc.o | Bin 0 -> 52624 bytes xpdf/CMakeFiles/xpdf_objs.dir/Function.cc.o | Bin 0 -> 73088 bytes xpdf/CMakeFiles/xpdf_objs.dir/Gfx.cc.o | Bin 0 -> 207224 bytes xpdf/CMakeFiles/xpdf_objs.dir/GfxFont.cc.o | Bin 0 -> 98704 bytes xpdf/CMakeFiles/xpdf_objs.dir/GfxState.cc.o | Bin 0 -> 286648 bytes xpdf/CMakeFiles/xpdf_objs.dir/GlobalParams.cc.o | Bin 0 -> 386824 bytes .../xpdf_objs.dir/JArithmeticDecoder.cc.o | Bin 0 -> 12288 bytes xpdf/CMakeFiles/xpdf_objs.dir/JBIG2Stream.cc.o | Bin 0 -> 130112 bytes xpdf/CMakeFiles/xpdf_objs.dir/JPXStream.cc.o | Bin 0 -> 92752 bytes xpdf/CMakeFiles/xpdf_objs.dir/Lexer.cc.o | Bin 0 -> 21960 bytes xpdf/CMakeFiles/xpdf_objs.dir/Link.cc.o | Bin 0 -> 74104 bytes xpdf/CMakeFiles/xpdf_objs.dir/NameToCharCode.cc.o | Bin 0 -> 4016 bytes xpdf/CMakeFiles/xpdf_objs.dir/Object.cc.o | Bin 0 -> 35464 bytes xpdf/CMakeFiles/xpdf_objs.dir/OptionalContent.cc.o | Bin 0 -> 26656 bytes xpdf/CMakeFiles/xpdf_objs.dir/Outline.cc.o | Bin 0 -> 12584 bytes xpdf/CMakeFiles/xpdf_objs.dir/OutputDev.cc.o | Bin 0 -> 36896 bytes xpdf/CMakeFiles/xpdf_objs.dir/PDF417Barcode.cc.o | Bin 0 -> 41840 bytes xpdf/CMakeFiles/xpdf_objs.dir/PDFDoc.cc.o | Bin 0 -> 34704 bytes xpdf/CMakeFiles/xpdf_objs.dir/PDFDocEncoding.cc.o | Bin 0 -> 2000 bytes xpdf/CMakeFiles/xpdf_objs.dir/PSTokenizer.cc.o | Bin 0 -> 3224 bytes xpdf/CMakeFiles/xpdf_objs.dir/Page.cc.o | Bin 0 -> 43304 bytes xpdf/CMakeFiles/xpdf_objs.dir/Parser.cc.o | Bin 0 -> 14352 bytes xpdf/CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.o | Bin 0 -> 22944 bytes xpdf/CMakeFiles/xpdf_objs.dir/Stream.cc.o | Bin 0 -> 210688 bytes xpdf/CMakeFiles/xpdf_objs.dir/TextString.cc.o | Bin 0 -> 8768 bytes xpdf/CMakeFiles/xpdf_objs.dir/UTF8.cc.o | Bin 0 -> 5264 bytes xpdf/CMakeFiles/xpdf_objs.dir/UnicodeMap.cc.o | Bin 0 -> 9936 bytes .../CMakeFiles/xpdf_objs.dir/UnicodeRemapping.cc.o | Bin 0 -> 6816 bytes .../CMakeFiles/xpdf_objs.dir/UnicodeTypeTable.cc.o | Bin 0 -> 57728 bytes xpdf/CMakeFiles/xpdf_objs.dir/XFAScanner.cc.o | Bin 0 -> 30616 bytes xpdf/CMakeFiles/xpdf_objs.dir/XRef.cc.o | Bin 0 -> 46408 bytes xpdf/CMakeFiles/xpdf_objs.dir/Zoox.cc.o | Bin 0 -> 65240 bytes xpdf/CMakeFiles/xpdf_objs.dir/build.make | 697 ++ xpdf/CMakeFiles/xpdf_objs.dir/cmake_clean.cmake | 50 + xpdf/CMakeFiles/xpdf_objs.dir/depend.internal | 786 ++ xpdf/CMakeFiles/xpdf_objs.dir/depend.make | 786 ++ xpdf/CMakeFiles/xpdf_objs.dir/flags.make | 10 + xpdf/CMakeFiles/xpdf_objs.dir/progress.make | 44 + .../xpdf_widget_objs.dir/CXX.includecache | 952 +++ .../xpdf_widget_objs.dir/DependInfo.cmake | 33 + .../xpdf_widget_objs.dir/DisplayState.cc.o | Bin 0 -> 21096 bytes xpdf/CMakeFiles/xpdf_widget_objs.dir/PDFCore.cc.o | Bin 0 -> 79888 bytes .../xpdf_widget_objs.dir/PSOutputDev.cc.o | Bin 0 -> 324512 bytes .../xpdf_widget_objs.dir/PreScanOutputDev.cc.o | Bin 0 -> 23848 bytes .../xpdf_widget_objs.dir/ShadingImage.cc.o | Bin 0 -> 43576 bytes .../xpdf_widget_objs.dir/SplashOutputDev.cc.o | Bin 0 -> 149072 bytes .../xpdf_widget_objs.dir/TextOutputDev.cc.o | Bin 0 -> 210256 bytes .../CMakeFiles/xpdf_widget_objs.dir/TileCache.cc.o | Bin 0 -> 16888 bytes .../xpdf_widget_objs.dir/TileCompositor.cc.o | Bin 0 -> 13776 bytes xpdf/CMakeFiles/xpdf_widget_objs.dir/TileMap.cc.o | Bin 0 -> 54208 bytes xpdf/CMakeFiles/xpdf_widget_objs.dir/build.make | 235 + .../xpdf_widget_objs.dir/cmake_clean.cmake | 17 + .../xpdf_widget_objs.dir/depend.internal | 308 + xpdf/CMakeFiles/xpdf_widget_objs.dir/depend.make | 308 + xpdf/CMakeFiles/xpdf_widget_objs.dir/flags.make | 10 + xpdf/CMakeFiles/xpdf_widget_objs.dir/progress.make | 11 + xpdf/CMakeLists.txt | 292 + xpdf/CMap.cc | 440 + xpdf/CMap.h | 115 + xpdf/Catalog.cc | 1197 +++ xpdf/Catalog.h | 166 + xpdf/CharCodeToUnicode.cc | 755 ++ xpdf/CharCodeToUnicode.h | 131 + xpdf/CharTypes.h | 24 + xpdf/CompactFontTables.h | 464 ++ xpdf/Decrypt.cc | 1620 ++++ xpdf/Decrypt.h | 133 + xpdf/Dict.cc | 145 + xpdf/Dict.h | 89 + xpdf/DisplayState.cc | 223 + xpdf/DisplayState.h | 173 + xpdf/Error.cc | 92 + xpdf/Error.h | 48 + xpdf/ErrorCodes.h | 36 + xpdf/FontEncodingTables.cc | 1825 +++++ xpdf/FontEncodingTables.h | 20 + xpdf/Function.cc | 1602 ++++ xpdf/Function.h | 240 + xpdf/Gfx.cc | 5386 +++++++++++++ xpdf/Gfx.h | 363 + xpdf/GfxFont.cc | 2415 ++++++ xpdf/GfxFont.h | 417 + xpdf/GfxState.cc | 4918 ++++++++++++ xpdf/GfxState.h | 1369 ++++ xpdf/GlobalParams.cc | 3858 +++++++++ xpdf/GlobalParams.h | 623 ++ xpdf/HTMLGen.cc | 1120 +++ xpdf/HTMLGen.h | 113 + xpdf/ImageOutputDev.cc | 453 ++ xpdf/ImageOutputDev.h | 116 + xpdf/JArithmeticDecoder.cc | 370 + xpdf/JArithmeticDecoder.h | 114 + xpdf/JBIG2Stream.cc | 4234 ++++++++++ xpdf/JBIG2Stream.h | 156 + xpdf/JPXStream.cc | 3610 +++++++++ xpdf/JPXStream.h | 364 + xpdf/Lexer.cc | 555 ++ xpdf/Lexer.h | 85 + xpdf/Link.cc | 926 +++ xpdf/Link.h | 453 ++ xpdf/Makefile | 2365 ++++++ xpdf/NameToCharCode.cc | 117 + xpdf/NameToCharCode.h | 42 + xpdf/NameToUnicodeTable.h | 4257 ++++++++++ xpdf/Object.cc | 245 + xpdf/Object.h | 320 + xpdf/OptionalContent.cc | 537 ++ xpdf/OptionalContent.h | 139 + xpdf/Outline.cc | 186 + xpdf/Outline.h | 84 + xpdf/OutputDev.cc | 140 + xpdf/OutputDev.h | 251 + xpdf/PDF417Barcode.cc | 1916 +++++ xpdf/PDF417Barcode.h | 32 + xpdf/PDFCore.cc | 2024 +++++ xpdf/PDFCore.h | 357 + xpdf/PDFDoc.cc | 679 ++ xpdf/PDFDoc.h | 228 + xpdf/PDFDocEncoding.cc | 46 + xpdf/PDFDocEncoding.h | 16 + xpdf/PSOutputDev.cc | 8448 ++++++++++++++++++++ xpdf/PSOutputDev.h | 513 ++ xpdf/PSTokenizer.cc | 136 + xpdf/PSTokenizer.h | 41 + xpdf/Page.cc | 554 ++ xpdf/Page.h | 207 + xpdf/Parser.cc | 316 + xpdf/Parser.h | 65 + xpdf/PreScanOutputDev.cc | 309 + xpdf/PreScanOutputDev.h | 149 + xpdf/SecurityHandler.cc | 370 + xpdf/SecurityHandler.h | 127 + xpdf/ShadingImage.cc | 1327 +++ xpdf/ShadingImage.h | 106 + xpdf/SplashOutputDev.cc | 4550 +++++++++++ xpdf/SplashOutputDev.h | 320 + xpdf/Stream-CCITT.h | 464 ++ xpdf/Stream.cc | 6064 ++++++++++++++ xpdf/Stream.h | 1071 +++ xpdf/TextOutputDev.cc | 6835 ++++++++++++++++ xpdf/TextOutputDev.h | 800 ++ xpdf/TextString.cc | 213 + xpdf/TextString.h | 71 + xpdf/TileCache.cc | 562 ++ xpdf/TileCache.h | 78 + xpdf/TileCompositor.cc | 452 ++ xpdf/TileCompositor.h | 77 + xpdf/TileMap.cc | 1690 ++++ xpdf/TileMap.h | 247 + xpdf/UTF8.cc | 183 + xpdf/UTF8.h | 42 + xpdf/UnicodeMap.cc | 281 + xpdf/UnicodeMap.h | 124 + xpdf/UnicodeMapTables.h | 366 + xpdf/UnicodeRemapping.cc | 201 + xpdf/UnicodeRemapping.h | 53 + xpdf/UnicodeTypeTable.cc | 1876 +++++ xpdf/UnicodeTypeTable.h | 32 + xpdf/WebFont.cc | 408 + xpdf/WebFont.h | 80 + xpdf/XFAScanner.cc | 677 ++ xpdf/XFAScanner.h | 166 + xpdf/XRef.cc | 1431 ++++ xpdf/XRef.h | 192 + xpdf/Zoox.cc | 1072 +++ xpdf/Zoox.h | 271 + xpdf/cmake_install.cmake | 228 + xpdf/config.h | 108 + xpdf/pdfdetach | Bin 0 -> 2307432 bytes xpdf/pdfdetach.cc | 216 + xpdf/pdffonts | Bin 0 -> 2312072 bytes xpdf/pdffonts.cc | 455 ++ xpdf/pdfimages | Bin 0 -> 2317440 bytes xpdf/pdfimages.cc | 174 + xpdf/pdfinfo | Bin 0 -> 2311992 bytes xpdf/pdfinfo.cc | 555 ++ xpdf/pdftohtml | Bin 0 -> 2915168 bytes xpdf/pdftohtml.cc | 300 + xpdf/pdftopng | Bin 0 -> 2733568 bytes xpdf/pdftopng.cc | 386 + xpdf/pdftoppm | Bin 0 -> 2728328 bytes xpdf/pdftoppm.cc | 280 + xpdf/pdftops | Bin 0 -> 2954976 bytes xpdf/pdftops.cc | 399 + xpdf/pdftotext | Bin 0 -> 2460304 bytes xpdf/pdftotext.cc | 332 + xpdf/winLongPath.exe.manifest | 15 + 317 files changed, 127360 insertions(+) create mode 100644 xpdf/AcroForm.cc create mode 100644 xpdf/AcroForm.h create mode 100644 xpdf/Annot.cc create mode 100644 xpdf/Annot.h create mode 100644 xpdf/Array.cc create mode 100644 xpdf/Array.h create mode 100644 xpdf/BuiltinFont.cc create mode 100644 xpdf/BuiltinFont.h create mode 100644 xpdf/BuiltinFontTables.cc create mode 100644 xpdf/BuiltinFontTables.h create mode 100644 xpdf/CMakeFiles/CMakeDirectoryInformation.cmake create mode 100644 xpdf/CMakeFiles/pdfdetach.dir/CXX.includecache create mode 100644 xpdf/CMakeFiles/pdfdetach.dir/DependInfo.cmake create mode 100644 xpdf/CMakeFiles/pdfdetach.dir/build.make create mode 100644 xpdf/CMakeFiles/pdfdetach.dir/cmake_clean.cmake create mode 100644 xpdf/CMakeFiles/pdfdetach.dir/depend.internal create mode 100644 xpdf/CMakeFiles/pdfdetach.dir/depend.make create mode 100644 xpdf/CMakeFiles/pdfdetach.dir/flags.make create mode 100644 xpdf/CMakeFiles/pdfdetach.dir/link.txt create mode 100644 xpdf/CMakeFiles/pdfdetach.dir/pdfdetach.cc.o create mode 100644 xpdf/CMakeFiles/pdfdetach.dir/progress.make create mode 100644 xpdf/CMakeFiles/pdffonts.dir/CXX.includecache create mode 100644 xpdf/CMakeFiles/pdffonts.dir/DependInfo.cmake create mode 100644 xpdf/CMakeFiles/pdffonts.dir/build.make create mode 100644 xpdf/CMakeFiles/pdffonts.dir/cmake_clean.cmake create mode 100644 xpdf/CMakeFiles/pdffonts.dir/depend.internal create mode 100644 xpdf/CMakeFiles/pdffonts.dir/depend.make create mode 100644 xpdf/CMakeFiles/pdffonts.dir/flags.make create mode 100644 xpdf/CMakeFiles/pdffonts.dir/link.txt create mode 100644 xpdf/CMakeFiles/pdffonts.dir/pdffonts.cc.o create mode 100644 xpdf/CMakeFiles/pdffonts.dir/progress.make create mode 100644 xpdf/CMakeFiles/pdfimages.dir/CXX.includecache create mode 100644 xpdf/CMakeFiles/pdfimages.dir/DependInfo.cmake create mode 100644 xpdf/CMakeFiles/pdfimages.dir/ImageOutputDev.cc.o create mode 100644 xpdf/CMakeFiles/pdfimages.dir/build.make create mode 100644 xpdf/CMakeFiles/pdfimages.dir/cmake_clean.cmake create mode 100644 xpdf/CMakeFiles/pdfimages.dir/depend.internal create mode 100644 xpdf/CMakeFiles/pdfimages.dir/depend.make create mode 100644 xpdf/CMakeFiles/pdfimages.dir/flags.make create mode 100644 xpdf/CMakeFiles/pdfimages.dir/link.txt create mode 100644 xpdf/CMakeFiles/pdfimages.dir/pdfimages.cc.o create mode 100644 xpdf/CMakeFiles/pdfimages.dir/progress.make create mode 100644 xpdf/CMakeFiles/pdfinfo.dir/CXX.includecache create mode 100644 xpdf/CMakeFiles/pdfinfo.dir/DependInfo.cmake create mode 100644 xpdf/CMakeFiles/pdfinfo.dir/build.make create mode 100644 xpdf/CMakeFiles/pdfinfo.dir/cmake_clean.cmake create mode 100644 xpdf/CMakeFiles/pdfinfo.dir/depend.internal create mode 100644 xpdf/CMakeFiles/pdfinfo.dir/depend.make create mode 100644 xpdf/CMakeFiles/pdfinfo.dir/flags.make create mode 100644 xpdf/CMakeFiles/pdfinfo.dir/link.txt create mode 100644 xpdf/CMakeFiles/pdfinfo.dir/pdfinfo.cc.o create mode 100644 xpdf/CMakeFiles/pdfinfo.dir/progress.make create mode 100644 xpdf/CMakeFiles/pdftohtml.dir/CXX.includecache create mode 100644 xpdf/CMakeFiles/pdftohtml.dir/DependInfo.cmake create mode 100644 xpdf/CMakeFiles/pdftohtml.dir/HTMLGen.cc.o create mode 100644 xpdf/CMakeFiles/pdftohtml.dir/ShadingImage.cc.o create mode 100644 xpdf/CMakeFiles/pdftohtml.dir/SplashOutputDev.cc.o create mode 100644 xpdf/CMakeFiles/pdftohtml.dir/TextOutputDev.cc.o create mode 100644 xpdf/CMakeFiles/pdftohtml.dir/WebFont.cc.o create mode 100644 xpdf/CMakeFiles/pdftohtml.dir/build.make create mode 100644 xpdf/CMakeFiles/pdftohtml.dir/cmake_clean.cmake create mode 100644 xpdf/CMakeFiles/pdftohtml.dir/depend.internal create mode 100644 xpdf/CMakeFiles/pdftohtml.dir/depend.make create mode 100644 xpdf/CMakeFiles/pdftohtml.dir/flags.make create mode 100644 xpdf/CMakeFiles/pdftohtml.dir/link.txt create mode 100644 xpdf/CMakeFiles/pdftohtml.dir/pdftohtml.cc.o create mode 100644 xpdf/CMakeFiles/pdftohtml.dir/progress.make create mode 100644 xpdf/CMakeFiles/pdftopng.dir/CXX.includecache create mode 100644 xpdf/CMakeFiles/pdftopng.dir/DependInfo.cmake create mode 100644 xpdf/CMakeFiles/pdftopng.dir/ShadingImage.cc.o create mode 100644 xpdf/CMakeFiles/pdftopng.dir/SplashOutputDev.cc.o create mode 100644 xpdf/CMakeFiles/pdftopng.dir/build.make create mode 100644 xpdf/CMakeFiles/pdftopng.dir/cmake_clean.cmake create mode 100644 xpdf/CMakeFiles/pdftopng.dir/depend.internal create mode 100644 xpdf/CMakeFiles/pdftopng.dir/depend.make create mode 100644 xpdf/CMakeFiles/pdftopng.dir/flags.make create mode 100644 xpdf/CMakeFiles/pdftopng.dir/link.txt create mode 100644 xpdf/CMakeFiles/pdftopng.dir/pdftopng.cc.o create mode 100644 xpdf/CMakeFiles/pdftopng.dir/progress.make create mode 100644 xpdf/CMakeFiles/pdftoppm.dir/CXX.includecache create mode 100644 xpdf/CMakeFiles/pdftoppm.dir/DependInfo.cmake create mode 100644 xpdf/CMakeFiles/pdftoppm.dir/ShadingImage.cc.o create mode 100644 xpdf/CMakeFiles/pdftoppm.dir/SplashOutputDev.cc.o create mode 100644 xpdf/CMakeFiles/pdftoppm.dir/build.make create mode 100644 xpdf/CMakeFiles/pdftoppm.dir/cmake_clean.cmake create mode 100644 xpdf/CMakeFiles/pdftoppm.dir/depend.internal create mode 100644 xpdf/CMakeFiles/pdftoppm.dir/depend.make create mode 100644 xpdf/CMakeFiles/pdftoppm.dir/flags.make create mode 100644 xpdf/CMakeFiles/pdftoppm.dir/link.txt create mode 100644 xpdf/CMakeFiles/pdftoppm.dir/pdftoppm.cc.o create mode 100644 xpdf/CMakeFiles/pdftoppm.dir/progress.make create mode 100644 xpdf/CMakeFiles/pdftops.dir/CXX.includecache create mode 100644 xpdf/CMakeFiles/pdftops.dir/DependInfo.cmake create mode 100644 xpdf/CMakeFiles/pdftops.dir/PSOutputDev.cc.o create mode 100644 xpdf/CMakeFiles/pdftops.dir/PreScanOutputDev.cc.o create mode 100644 xpdf/CMakeFiles/pdftops.dir/ShadingImage.cc.o create mode 100644 xpdf/CMakeFiles/pdftops.dir/SplashOutputDev.cc.o create mode 100644 xpdf/CMakeFiles/pdftops.dir/build.make create mode 100644 xpdf/CMakeFiles/pdftops.dir/cmake_clean.cmake create mode 100644 xpdf/CMakeFiles/pdftops.dir/depend.internal create mode 100644 xpdf/CMakeFiles/pdftops.dir/depend.make create mode 100644 xpdf/CMakeFiles/pdftops.dir/flags.make create mode 100644 xpdf/CMakeFiles/pdftops.dir/link.txt create mode 100644 xpdf/CMakeFiles/pdftops.dir/pdftops.cc.o create mode 100644 xpdf/CMakeFiles/pdftops.dir/progress.make create mode 100644 xpdf/CMakeFiles/pdftotext.dir/CXX.includecache create mode 100644 xpdf/CMakeFiles/pdftotext.dir/DependInfo.cmake create mode 100644 xpdf/CMakeFiles/pdftotext.dir/TextOutputDev.cc.o create mode 100644 xpdf/CMakeFiles/pdftotext.dir/build.make create mode 100644 xpdf/CMakeFiles/pdftotext.dir/cmake_clean.cmake create mode 100644 xpdf/CMakeFiles/pdftotext.dir/depend.internal create mode 100644 xpdf/CMakeFiles/pdftotext.dir/depend.make create mode 100644 xpdf/CMakeFiles/pdftotext.dir/flags.make create mode 100644 xpdf/CMakeFiles/pdftotext.dir/link.txt create mode 100644 xpdf/CMakeFiles/pdftotext.dir/pdftotext.cc.o create mode 100644 xpdf/CMakeFiles/pdftotext.dir/progress.make create mode 100644 xpdf/CMakeFiles/progress.marks create mode 100644 xpdf/CMakeFiles/xpdf_objs.dir/AcroForm.cc.o create mode 100644 xpdf/CMakeFiles/xpdf_objs.dir/Annot.cc.o create mode 100644 xpdf/CMakeFiles/xpdf_objs.dir/Array.cc.o create mode 100644 xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFont.cc.o create mode 100644 xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFontTables.cc.o create mode 100644 xpdf/CMakeFiles/xpdf_objs.dir/CMap.cc.o create mode 100644 xpdf/CMakeFiles/xpdf_objs.dir/CXX.includecache create mode 100644 xpdf/CMakeFiles/xpdf_objs.dir/Catalog.cc.o create mode 100644 xpdf/CMakeFiles/xpdf_objs.dir/CharCodeToUnicode.cc.o create mode 100644 xpdf/CMakeFiles/xpdf_objs.dir/Decrypt.cc.o create mode 100644 xpdf/CMakeFiles/xpdf_objs.dir/DependInfo.cmake create mode 100644 xpdf/CMakeFiles/xpdf_objs.dir/Dict.cc.o create mode 100644 xpdf/CMakeFiles/xpdf_objs.dir/Error.cc.o create mode 100644 xpdf/CMakeFiles/xpdf_objs.dir/FontEncodingTables.cc.o create mode 100644 xpdf/CMakeFiles/xpdf_objs.dir/Function.cc.o create mode 100644 xpdf/CMakeFiles/xpdf_objs.dir/Gfx.cc.o create mode 100644 xpdf/CMakeFiles/xpdf_objs.dir/GfxFont.cc.o create mode 100644 xpdf/CMakeFiles/xpdf_objs.dir/GfxState.cc.o create mode 100644 xpdf/CMakeFiles/xpdf_objs.dir/GlobalParams.cc.o create mode 100644 xpdf/CMakeFiles/xpdf_objs.dir/JArithmeticDecoder.cc.o create mode 100644 xpdf/CMakeFiles/xpdf_objs.dir/JBIG2Stream.cc.o create mode 100644 xpdf/CMakeFiles/xpdf_objs.dir/JPXStream.cc.o create mode 100644 xpdf/CMakeFiles/xpdf_objs.dir/Lexer.cc.o create mode 100644 xpdf/CMakeFiles/xpdf_objs.dir/Link.cc.o create mode 100644 xpdf/CMakeFiles/xpdf_objs.dir/NameToCharCode.cc.o create mode 100644 xpdf/CMakeFiles/xpdf_objs.dir/Object.cc.o create mode 100644 xpdf/CMakeFiles/xpdf_objs.dir/OptionalContent.cc.o create mode 100644 xpdf/CMakeFiles/xpdf_objs.dir/Outline.cc.o create mode 100644 xpdf/CMakeFiles/xpdf_objs.dir/OutputDev.cc.o create mode 100644 xpdf/CMakeFiles/xpdf_objs.dir/PDF417Barcode.cc.o create mode 100644 xpdf/CMakeFiles/xpdf_objs.dir/PDFDoc.cc.o create mode 100644 xpdf/CMakeFiles/xpdf_objs.dir/PDFDocEncoding.cc.o create mode 100644 xpdf/CMakeFiles/xpdf_objs.dir/PSTokenizer.cc.o create mode 100644 xpdf/CMakeFiles/xpdf_objs.dir/Page.cc.o create mode 100644 xpdf/CMakeFiles/xpdf_objs.dir/Parser.cc.o create mode 100644 xpdf/CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.o create mode 100644 xpdf/CMakeFiles/xpdf_objs.dir/Stream.cc.o create mode 100644 xpdf/CMakeFiles/xpdf_objs.dir/TextString.cc.o create mode 100644 xpdf/CMakeFiles/xpdf_objs.dir/UTF8.cc.o create mode 100644 xpdf/CMakeFiles/xpdf_objs.dir/UnicodeMap.cc.o create mode 100644 xpdf/CMakeFiles/xpdf_objs.dir/UnicodeRemapping.cc.o create mode 100644 xpdf/CMakeFiles/xpdf_objs.dir/UnicodeTypeTable.cc.o create mode 100644 xpdf/CMakeFiles/xpdf_objs.dir/XFAScanner.cc.o create mode 100644 xpdf/CMakeFiles/xpdf_objs.dir/XRef.cc.o create mode 100644 xpdf/CMakeFiles/xpdf_objs.dir/Zoox.cc.o create mode 100644 xpdf/CMakeFiles/xpdf_objs.dir/build.make create mode 100644 xpdf/CMakeFiles/xpdf_objs.dir/cmake_clean.cmake create mode 100644 xpdf/CMakeFiles/xpdf_objs.dir/depend.internal create mode 100644 xpdf/CMakeFiles/xpdf_objs.dir/depend.make create mode 100644 xpdf/CMakeFiles/xpdf_objs.dir/flags.make create mode 100644 xpdf/CMakeFiles/xpdf_objs.dir/progress.make create mode 100644 xpdf/CMakeFiles/xpdf_widget_objs.dir/CXX.includecache create mode 100644 xpdf/CMakeFiles/xpdf_widget_objs.dir/DependInfo.cmake create mode 100644 xpdf/CMakeFiles/xpdf_widget_objs.dir/DisplayState.cc.o create mode 100644 xpdf/CMakeFiles/xpdf_widget_objs.dir/PDFCore.cc.o create mode 100644 xpdf/CMakeFiles/xpdf_widget_objs.dir/PSOutputDev.cc.o create mode 100644 xpdf/CMakeFiles/xpdf_widget_objs.dir/PreScanOutputDev.cc.o create mode 100644 xpdf/CMakeFiles/xpdf_widget_objs.dir/ShadingImage.cc.o create mode 100644 xpdf/CMakeFiles/xpdf_widget_objs.dir/SplashOutputDev.cc.o create mode 100644 xpdf/CMakeFiles/xpdf_widget_objs.dir/TextOutputDev.cc.o create mode 100644 xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCache.cc.o create mode 100644 xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCompositor.cc.o create mode 100644 xpdf/CMakeFiles/xpdf_widget_objs.dir/TileMap.cc.o create mode 100644 xpdf/CMakeFiles/xpdf_widget_objs.dir/build.make create mode 100644 xpdf/CMakeFiles/xpdf_widget_objs.dir/cmake_clean.cmake create mode 100644 xpdf/CMakeFiles/xpdf_widget_objs.dir/depend.internal create mode 100644 xpdf/CMakeFiles/xpdf_widget_objs.dir/depend.make create mode 100644 xpdf/CMakeFiles/xpdf_widget_objs.dir/flags.make create mode 100644 xpdf/CMakeFiles/xpdf_widget_objs.dir/progress.make create mode 100644 xpdf/CMakeLists.txt create mode 100644 xpdf/CMap.cc create mode 100644 xpdf/CMap.h create mode 100644 xpdf/Catalog.cc create mode 100644 xpdf/Catalog.h create mode 100644 xpdf/CharCodeToUnicode.cc create mode 100644 xpdf/CharCodeToUnicode.h create mode 100644 xpdf/CharTypes.h create mode 100644 xpdf/CompactFontTables.h create mode 100644 xpdf/Decrypt.cc create mode 100644 xpdf/Decrypt.h create mode 100644 xpdf/Dict.cc create mode 100644 xpdf/Dict.h create mode 100644 xpdf/DisplayState.cc create mode 100644 xpdf/DisplayState.h create mode 100644 xpdf/Error.cc create mode 100644 xpdf/Error.h create mode 100644 xpdf/ErrorCodes.h create mode 100644 xpdf/FontEncodingTables.cc create mode 100644 xpdf/FontEncodingTables.h create mode 100644 xpdf/Function.cc create mode 100644 xpdf/Function.h create mode 100644 xpdf/Gfx.cc create mode 100644 xpdf/Gfx.h create mode 100644 xpdf/GfxFont.cc create mode 100644 xpdf/GfxFont.h create mode 100644 xpdf/GfxState.cc create mode 100644 xpdf/GfxState.h create mode 100644 xpdf/GlobalParams.cc create mode 100644 xpdf/GlobalParams.h create mode 100644 xpdf/HTMLGen.cc create mode 100644 xpdf/HTMLGen.h create mode 100644 xpdf/ImageOutputDev.cc create mode 100644 xpdf/ImageOutputDev.h create mode 100644 xpdf/JArithmeticDecoder.cc create mode 100644 xpdf/JArithmeticDecoder.h create mode 100644 xpdf/JBIG2Stream.cc create mode 100644 xpdf/JBIG2Stream.h create mode 100644 xpdf/JPXStream.cc create mode 100644 xpdf/JPXStream.h create mode 100644 xpdf/Lexer.cc create mode 100644 xpdf/Lexer.h create mode 100644 xpdf/Link.cc create mode 100644 xpdf/Link.h create mode 100644 xpdf/Makefile create mode 100644 xpdf/NameToCharCode.cc create mode 100644 xpdf/NameToCharCode.h create mode 100644 xpdf/NameToUnicodeTable.h create mode 100644 xpdf/Object.cc create mode 100644 xpdf/Object.h create mode 100644 xpdf/OptionalContent.cc create mode 100644 xpdf/OptionalContent.h create mode 100644 xpdf/Outline.cc create mode 100644 xpdf/Outline.h create mode 100644 xpdf/OutputDev.cc create mode 100644 xpdf/OutputDev.h create mode 100644 xpdf/PDF417Barcode.cc create mode 100644 xpdf/PDF417Barcode.h create mode 100644 xpdf/PDFCore.cc create mode 100644 xpdf/PDFCore.h create mode 100644 xpdf/PDFDoc.cc create mode 100644 xpdf/PDFDoc.h create mode 100644 xpdf/PDFDocEncoding.cc create mode 100644 xpdf/PDFDocEncoding.h create mode 100644 xpdf/PSOutputDev.cc create mode 100644 xpdf/PSOutputDev.h create mode 100644 xpdf/PSTokenizer.cc create mode 100644 xpdf/PSTokenizer.h create mode 100644 xpdf/Page.cc create mode 100644 xpdf/Page.h create mode 100644 xpdf/Parser.cc create mode 100644 xpdf/Parser.h create mode 100644 xpdf/PreScanOutputDev.cc create mode 100644 xpdf/PreScanOutputDev.h create mode 100644 xpdf/SecurityHandler.cc create mode 100644 xpdf/SecurityHandler.h create mode 100644 xpdf/ShadingImage.cc create mode 100644 xpdf/ShadingImage.h create mode 100644 xpdf/SplashOutputDev.cc create mode 100644 xpdf/SplashOutputDev.h create mode 100644 xpdf/Stream-CCITT.h create mode 100644 xpdf/Stream.cc create mode 100644 xpdf/Stream.h create mode 100644 xpdf/TextOutputDev.cc create mode 100644 xpdf/TextOutputDev.h create mode 100644 xpdf/TextString.cc create mode 100644 xpdf/TextString.h create mode 100644 xpdf/TileCache.cc create mode 100644 xpdf/TileCache.h create mode 100644 xpdf/TileCompositor.cc create mode 100644 xpdf/TileCompositor.h create mode 100644 xpdf/TileMap.cc create mode 100644 xpdf/TileMap.h create mode 100644 xpdf/UTF8.cc create mode 100644 xpdf/UTF8.h create mode 100644 xpdf/UnicodeMap.cc create mode 100644 xpdf/UnicodeMap.h create mode 100644 xpdf/UnicodeMapTables.h create mode 100644 xpdf/UnicodeRemapping.cc create mode 100644 xpdf/UnicodeRemapping.h create mode 100644 xpdf/UnicodeTypeTable.cc create mode 100644 xpdf/UnicodeTypeTable.h create mode 100644 xpdf/WebFont.cc create mode 100644 xpdf/WebFont.h create mode 100644 xpdf/XFAScanner.cc create mode 100644 xpdf/XFAScanner.h create mode 100644 xpdf/XRef.cc create mode 100644 xpdf/XRef.h create mode 100644 xpdf/Zoox.cc create mode 100644 xpdf/Zoox.h create mode 100644 xpdf/cmake_install.cmake create mode 100644 xpdf/config.h create mode 100755 xpdf/pdfdetach create mode 100644 xpdf/pdfdetach.cc create mode 100755 xpdf/pdffonts create mode 100644 xpdf/pdffonts.cc create mode 100755 xpdf/pdfimages create mode 100644 xpdf/pdfimages.cc create mode 100755 xpdf/pdfinfo create mode 100644 xpdf/pdfinfo.cc create mode 100755 xpdf/pdftohtml create mode 100644 xpdf/pdftohtml.cc create mode 100755 xpdf/pdftopng create mode 100644 xpdf/pdftopng.cc create mode 100755 xpdf/pdftoppm create mode 100644 xpdf/pdftoppm.cc create mode 100755 xpdf/pdftops create mode 100644 xpdf/pdftops.cc create mode 100755 xpdf/pdftotext create mode 100644 xpdf/pdftotext.cc create mode 100644 xpdf/winLongPath.exe.manifest (limited to 'xpdf') diff --git a/xpdf/AcroForm.cc b/xpdf/AcroForm.cc new file mode 100644 index 0000000..7b2b985 --- /dev/null +++ b/xpdf/AcroForm.cc @@ -0,0 +1,3889 @@ +//======================================================================== +// +// AcroForm.cc +// +// Copyright 2012 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include +#include "gmem.h" +#include "gmempp.h" +#include "GString.h" +#include "GList.h" +#include "GlobalParams.h" +#include "Error.h" +#include "Object.h" +#include "PDFDoc.h" +#include "TextString.h" +#include "Gfx.h" +#include "GfxFont.h" +#include "OptionalContent.h" +#include "Annot.h" +#include "Lexer.h" +#include "XFAScanner.h" +#include "UTF8.h" +#include "PDF417Barcode.h" +#include "AcroForm.h" + +//------------------------------------------------------------------------ + +#define acroFormFlagReadOnly (1 << 0) // all +#define acroFormFlagRequired (1 << 1) // all +#define acroFormFlagNoExport (1 << 2) // all +#define acroFormFlagMultiline (1 << 12) // text +#define acroFormFlagPassword (1 << 13) // text +#define acroFormFlagNoToggleToOff (1 << 14) // button +#define acroFormFlagRadio (1 << 15) // button +#define acroFormFlagPushbutton (1 << 16) // button +#define acroFormFlagCombo (1 << 17) // choice +#define acroFormFlagEdit (1 << 18) // choice +#define acroFormFlagSort (1 << 19) // choice +#define acroFormFlagFileSelect (1 << 20) // text +#define acroFormFlagMultiSelect (1 << 21) // choice +#define acroFormFlagDoNotSpellCheck (1 << 22) // text, choice +#define acroFormFlagDoNotScroll (1 << 23) // text +#define acroFormFlagComb (1 << 24) // text +#define acroFormFlagRadiosInUnison (1 << 25) // button +#define acroFormFlagRichText (1 << 25) // text +#define acroFormFlagCommitOnSelChange (1 << 26) // choice + +#define acroFormQuadLeft 0 +#define acroFormQuadCenter 1 +#define acroFormQuadRight 2 + +#define acroFormVAlignTop 0 +#define acroFormVAlignMiddle 1 +#define acroFormVAlignMiddleNoDescender 2 +#define acroFormVAlignBottom 3 + +#define annotFlagHidden 0x0002 +#define annotFlagPrint 0x0004 +#define annotFlagNoView 0x0020 + +// distance of Bezier control point from center for circle approximation +// = (4 * (sqrt(2) - 1) / 3) * r +#define bezierCircle 0.55228475 + +// limit recursive field-parent lookups to avoid infinite loops +#define maxFieldObjectDepth 50 + +//------------------------------------------------------------------------ + +// 5 bars + 5 spaces -- each can be wide (1) or narrow (0) +// (there are always exactly 3 wide elements; +// the last space is always narrow) +static Guchar code3Of9Data[128][10] = { + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 0x00 + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 0x10 + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 1, 1, 0, 0, 0, 1, 0, 0, 0 }, // ' ' = 0x20 + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 1, 0, 1, 0, 1, 0, 0, 0, 0 }, // '$' = 0x24 + { 0, 0, 0, 1, 0, 1, 0, 1, 0, 0 }, // '%' = 0x25 + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 1, 0, 0, 1, 0, 1, 0, 0, 0 }, // '*' = 0x2a + { 0, 1, 0, 0, 0, 1, 0, 1, 0, 0 }, // '+' = 0x2b + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 1, 0, 0, 0, 0, 1, 0, 1, 0 }, // '-' = 0x2d + { 1, 1, 0, 0, 0, 0, 1, 0, 0, 0 }, // '.' = 0x2e + { 0, 1, 0, 1, 0, 0, 0, 1, 0, 0 }, // '/' = 0x2f + { 0, 0, 0, 1, 1, 0, 1, 0, 0, 0 }, // '0' = 0x30 + { 1, 0, 0, 1, 0, 0, 0, 0, 1, 0 }, // '1' + { 0, 0, 1, 1, 0, 0, 0, 0, 1, 0 }, // '2' + { 1, 0, 1, 1, 0, 0, 0, 0, 0, 0 }, // '3' + { 0, 0, 0, 1, 1, 0, 0, 0, 1, 0 }, // '4' + { 1, 0, 0, 1, 1, 0, 0, 0, 0, 0 }, // '5' + { 0, 0, 1, 1, 1, 0, 0, 0, 0, 0 }, // '6' + { 0, 0, 0, 1, 0, 0, 1, 0, 1, 0 }, // '7' + { 1, 0, 0, 1, 0, 0, 1, 0, 0, 0 }, // '8' + { 0, 0, 1, 1, 0, 0, 1, 0, 0, 0 }, // '9' + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 0x40 + { 1, 0, 0, 0, 0, 1, 0, 0, 1, 0 }, // 'A' = 0x41 + { 0, 0, 1, 0, 0, 1, 0, 0, 1, 0 }, // 'B' + { 1, 0, 1, 0, 0, 1, 0, 0, 0, 0 }, // 'C' + { 0, 0, 0, 0, 1, 1, 0, 0, 1, 0 }, // 'D' + { 1, 0, 0, 0, 1, 1, 0, 0, 0, 0 }, // 'E' + { 0, 0, 1, 0, 1, 1, 0, 0, 0, 0 }, // 'F' + { 0, 0, 0, 0, 0, 1, 1, 0, 1, 0 }, // 'G' + { 1, 0, 0, 0, 0, 1, 1, 0, 0, 0 }, // 'H' + { 0, 0, 1, 0, 0, 1, 1, 0, 0, 0 }, // 'I' + { 0, 0, 0, 0, 1, 1, 1, 0, 0, 0 }, // 'J' + { 1, 0, 0, 0, 0, 0, 0, 1, 1, 0 }, // 'K' + { 0, 0, 1, 0, 0, 0, 0, 1, 1, 0 }, // 'L' + { 1, 0, 1, 0, 0, 0, 0, 1, 0, 0 }, // 'M' + { 0, 0, 0, 0, 1, 0, 0, 1, 1, 0 }, // 'N' + { 1, 0, 0, 0, 1, 0, 0, 1, 0, 0 }, // 'O' + { 0, 0, 1, 0, 1, 0, 0, 1, 0, 0 }, // 'P' = 0x50 + { 0, 0, 0, 0, 0, 0, 1, 1, 1, 0 }, // 'Q' + { 1, 0, 0, 0, 0, 0, 1, 1, 0, 0 }, // 'R' + { 0, 0, 1, 0, 0, 0, 1, 1, 0, 0 }, // 'S' + { 0, 0, 0, 0, 1, 0, 1, 1, 0, 0 }, // 'T' + { 1, 1, 0, 0, 0, 0, 0, 0, 1, 0 }, // 'U' + { 0, 1, 1, 0, 0, 0, 0, 0, 1, 0 }, // 'V' + { 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 }, // 'W' + { 0, 1, 0, 0, 1, 0, 0, 0, 1, 0 }, // 'X' + { 1, 1, 0, 0, 1, 0, 0, 0, 0, 0 }, // 'Y' + { 0, 1, 1, 0, 1, 0, 0, 0, 0, 0 }, // 'Z' + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 0x60 + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 0x70 + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } +}; + +// 3 bars + 3 spaces -- each can be 1, 2, 3, or 4 units wide +static Guchar code128Data[107][6] = { + { 2, 1, 2, 2, 2, 2 }, + { 2, 2, 2, 1, 2, 2 }, + { 2, 2, 2, 2, 2, 1 }, + { 1, 2, 1, 2, 2, 3 }, + { 1, 2, 1, 3, 2, 2 }, + { 1, 3, 1, 2, 2, 2 }, + { 1, 2, 2, 2, 1, 3 }, + { 1, 2, 2, 3, 1, 2 }, + { 1, 3, 2, 2, 1, 2 }, + { 2, 2, 1, 2, 1, 3 }, + { 2, 2, 1, 3, 1, 2 }, + { 2, 3, 1, 2, 1, 2 }, + { 1, 1, 2, 2, 3, 2 }, + { 1, 2, 2, 1, 3, 2 }, + { 1, 2, 2, 2, 3, 1 }, + { 1, 1, 3, 2, 2, 2 }, + { 1, 2, 3, 1, 2, 2 }, + { 1, 2, 3, 2, 2, 1 }, + { 2, 2, 3, 2, 1, 1 }, + { 2, 2, 1, 1, 3, 2 }, + { 2, 2, 1, 2, 3, 1 }, + { 2, 1, 3, 2, 1, 2 }, + { 2, 2, 3, 1, 1, 2 }, + { 3, 1, 2, 1, 3, 1 }, + { 3, 1, 1, 2, 2, 2 }, + { 3, 2, 1, 1, 2, 2 }, + { 3, 2, 1, 2, 2, 1 }, + { 3, 1, 2, 2, 1, 2 }, + { 3, 2, 2, 1, 1, 2 }, + { 3, 2, 2, 2, 1, 1 }, + { 2, 1, 2, 1, 2, 3 }, + { 2, 1, 2, 3, 2, 1 }, + { 2, 3, 2, 1, 2, 1 }, + { 1, 1, 1, 3, 2, 3 }, + { 1, 3, 1, 1, 2, 3 }, + { 1, 3, 1, 3, 2, 1 }, + { 1, 1, 2, 3, 1, 3 }, + { 1, 3, 2, 1, 1, 3 }, + { 1, 3, 2, 3, 1, 1 }, + { 2, 1, 1, 3, 1, 3 }, + { 2, 3, 1, 1, 1, 3 }, + { 2, 3, 1, 3, 1, 1 }, + { 1, 1, 2, 1, 3, 3 }, + { 1, 1, 2, 3, 3, 1 }, + { 1, 3, 2, 1, 3, 1 }, + { 1, 1, 3, 1, 2, 3 }, + { 1, 1, 3, 3, 2, 1 }, + { 1, 3, 3, 1, 2, 1 }, + { 3, 1, 3, 1, 2, 1 }, + { 2, 1, 1, 3, 3, 1 }, + { 2, 3, 1, 1, 3, 1 }, + { 2, 1, 3, 1, 1, 3 }, + { 2, 1, 3, 3, 1, 1 }, + { 2, 1, 3, 1, 3, 1 }, + { 3, 1, 1, 1, 2, 3 }, + { 3, 1, 1, 3, 2, 1 }, + { 3, 3, 1, 1, 2, 1 }, + { 3, 1, 2, 1, 1, 3 }, + { 3, 1, 2, 3, 1, 1 }, + { 3, 3, 2, 1, 1, 1 }, + { 3, 1, 4, 1, 1, 1 }, + { 2, 2, 1, 4, 1, 1 }, + { 4, 3, 1, 1, 1, 1 }, + { 1, 1, 1, 2, 2, 4 }, + { 1, 1, 1, 4, 2, 2 }, + { 1, 2, 1, 1, 2, 4 }, + { 1, 2, 1, 4, 2, 1 }, + { 1, 4, 1, 1, 2, 2 }, + { 1, 4, 1, 2, 2, 1 }, + { 1, 1, 2, 2, 1, 4 }, + { 1, 1, 2, 4, 1, 2 }, + { 1, 2, 2, 1, 1, 4 }, + { 1, 2, 2, 4, 1, 1 }, + { 1, 4, 2, 1, 1, 2 }, + { 1, 4, 2, 2, 1, 1 }, + { 2, 4, 1, 2, 1, 1 }, + { 2, 2, 1, 1, 1, 4 }, + { 4, 1, 3, 1, 1, 1 }, + { 2, 4, 1, 1, 1, 2 }, + { 1, 3, 4, 1, 1, 1 }, + { 1, 1, 1, 2, 4, 2 }, + { 1, 2, 1, 1, 4, 2 }, + { 1, 2, 1, 2, 4, 1 }, + { 1, 1, 4, 2, 1, 2 }, + { 1, 2, 4, 1, 1, 2 }, + { 1, 2, 4, 2, 1, 1 }, + { 4, 1, 1, 2, 1, 2 }, + { 4, 2, 1, 1, 1, 2 }, + { 4, 2, 1, 2, 1, 1 }, + { 2, 1, 2, 1, 4, 1 }, + { 2, 1, 4, 1, 2, 1 }, + { 4, 1, 2, 1, 2, 1 }, + { 1, 1, 1, 1, 4, 3 }, + { 1, 1, 1, 3, 4, 1 }, + { 1, 3, 1, 1, 4, 1 }, + { 1, 1, 4, 1, 1, 3 }, + { 1, 1, 4, 3, 1, 1 }, + { 4, 1, 1, 1, 1, 3 }, + { 4, 1, 1, 3, 1, 1 }, + { 1, 1, 3, 1, 4, 1 }, + { 1, 1, 4, 1, 3, 1 }, + { 3, 1, 1, 1, 4, 1 }, + { 4, 1, 1, 1, 3, 1 }, + { 2, 1, 1, 4, 1, 2 }, // start code A + { 2, 1, 1, 2, 1, 4 }, // start code B + { 2, 1, 1, 2, 3, 2 }, // start code C + { 2, 3, 3, 1, 1, 1 } // stop code (without final bar) +}; + +//------------------------------------------------------------------------ + +// map an annotation ref to a page number +class AcroFormAnnotPage { +public: + AcroFormAnnotPage(int annotNumA, int annotGenA, int pageNumA) + { annotNum = annotNumA; annotGen = annotGenA; pageNum = pageNumA; } + int annotNum; + int annotGen; + int pageNum; +}; + +//------------------------------------------------------------------------ +// AcroForm +//------------------------------------------------------------------------ + +AcroForm *AcroForm::load(PDFDoc *docA, Catalog *catalog, Object *acroFormObjA) { + Object acroFormObj2; + AcroForm *acroForm; + AcroFormField *field; + Object xfaObj, fieldsObj, annotsObj, annotRef, annotObj, obj1, obj2; + int pageNum, i, j; + + // this is the normal case: acroFormObj is a dictionary, as expected + if (acroFormObjA->isDict()) { + acroForm = new AcroForm(docA, acroFormObjA); + + if (globalParams->getEnableXFA()) { + if (!acroFormObjA->dictLookup("XFA", &xfaObj)->isNull()) { + acroForm->xfaScanner = XFAScanner::load(&xfaObj); + if (!catalog->getNeedsRendering()) { + acroForm->isStaticXFA = gTrue; + } + } + xfaObj.free(); + } + + if (acroFormObjA->dictLookup("NeedAppearances", &obj1)->isBool()) { + acroForm->needAppearances = obj1.getBool(); + } + obj1.free(); + + acroForm->buildAnnotPageList(catalog); + + if (!acroFormObjA->dictLookup("Fields", &obj1)->isArray()) { + if (!obj1.isNull()) { + error(errSyntaxError, -1, "AcroForm Fields entry is wrong type"); + } + obj1.free(); + delete acroForm; + return NULL; + } + for (i = 0; i < obj1.arrayGetLength(); ++i) { + obj1.arrayGetNF(i, &obj2); + acroForm->scanField(&obj2); + obj2.free(); + } + obj1.free(); + + // scan the annotations, looking for Widget-type annots that are + // not attached to the AcroForm object + for (pageNum = 1; pageNum <= catalog->getNumPages(); ++pageNum) { + if (catalog->getPage(pageNum)->getAnnots(&annotsObj)->isArray()) { + for (i = 0; i < annotsObj.arrayGetLength(); ++i) { + if (annotsObj.arrayGetNF(i, &annotRef)->isRef()) { + for (j = 0; j < acroForm->fields->getLength(); ++j) { + field = (AcroFormField *)acroForm->fields->get(j); + if (field->fieldRef.isRef()) { + if (field->fieldRef.getRefNum() == annotRef.getRefNum() && + field->fieldRef.getRefGen() == annotRef.getRefGen()) { + break; + } + } + } + if (j == acroForm->fields->getLength()) { + annotRef.fetch(acroForm->doc->getXRef(), &annotObj); + if (annotObj.isDict()) { + if (annotObj.dictLookup("Subtype", &obj1)->isName("Widget")) { + acroForm->scanField(&annotRef); + } + obj1.free(); + } + annotObj.free(); + } + } + annotRef.free(); + } + } + annotsObj.free(); + } + + // if acroFormObjA is a null object, but there are Widget-type + // annots, we still create an AcroForm + } else { + // create an empty dict for acroFormObj + acroFormObj2.initDict(docA->getXRef()); + acroForm = new AcroForm(docA, &acroFormObj2); + acroFormObj2.free(); + + acroForm->buildAnnotPageList(catalog); + + // scan the annotations, looking for any Widget-type annots + for (pageNum = 1; pageNum <= catalog->getNumPages(); ++pageNum) { + if (catalog->getPage(pageNum)->getAnnots(&annotsObj)->isArray()) { + for (i = 0; i < annotsObj.arrayGetLength(); ++i) { + if (annotsObj.arrayGetNF(i, &annotRef)->isRef()) { + annotRef.fetch(acroForm->doc->getXRef(), &annotObj); + if (annotObj.isDict()) { + if (annotObj.dictLookup("Subtype", &obj1)->isName("Widget")) { + acroForm->scanField(&annotRef); + } + obj1.free(); + } + annotObj.free(); + } + annotRef.free(); + } + } + annotsObj.free(); + } + + if (acroForm->fields->getLength() == 0) { + delete acroForm; + acroForm = NULL; + } + } + + return acroForm; +} + +AcroForm::AcroForm(PDFDoc *docA, Object *acroFormObjA) { + doc = docA; + acroFormObjA->copy(&acroFormObj); + needAppearances = gFalse; + annotPages = new GList(); + fields = new GList(); + xfaScanner = NULL; + isStaticXFA = gFalse; +} + +AcroForm::~AcroForm() { + acroFormObj.free(); + deleteGList(annotPages, AcroFormAnnotPage); + deleteGList(fields, AcroFormField); + delete xfaScanner; +} + +const char *AcroForm::getType() { + return isStaticXFA ? "static XFA" : "AcroForm"; +} + +void AcroForm::buildAnnotPageList(Catalog *catalog) { + Object annotsObj, annotObj; + int pageNum, i; + + for (pageNum = 1; pageNum <= catalog->getNumPages(); ++pageNum) { + if (catalog->getPage(pageNum)->getAnnots(&annotsObj)->isArray()) { + for (i = 0; i < annotsObj.arrayGetLength(); ++i) { + if (annotsObj.arrayGetNF(i, &annotObj)->isRef()) { + annotPages->append(new AcroFormAnnotPage(annotObj.getRefNum(), + annotObj.getRefGen(), + pageNum)); + } + annotObj.free(); + } + } + annotsObj.free(); + } + //~ sort the list +} + +int AcroForm::lookupAnnotPage(Object *annotRef) { + AcroFormAnnotPage *annotPage; + int num, gen, i; + + if (!annotRef->isRef()) { + return 0; + } + num = annotRef->getRefNum(); + gen = annotRef->getRefGen(); + //~ use bin search + for (i = 0; i < annotPages->getLength(); ++i) { + annotPage = (AcroFormAnnotPage *)annotPages->get(i); + if (annotPage->annotNum == num && annotPage->annotGen == gen) { + return annotPage->pageNum; + } + } + return 0; +} + +void AcroForm::scanField(Object *fieldRef) { + AcroFormField *field; + Object fieldObj, kidsObj, kidRef, kidObj, subtypeObj; + GBool isTerminal; + int i; + + fieldRef->fetch(doc->getXRef(), &fieldObj); + if (!fieldObj.isDict()) { + error(errSyntaxError, -1, "AcroForm field object is wrong type"); + fieldObj.free(); + return; + } + + // if this field has a Kids array, and all of the kids have a Parent + // reference (i.e., they're all form fields, not widget + // annotations), then this is a non-terminal field, and we need to + // scan the kids + isTerminal = gTrue; + if (fieldObj.dictLookup("Kids", &kidsObj)->isArray()) { + isTerminal = gFalse; + for (i = 0; !isTerminal && i < kidsObj.arrayGetLength(); ++i) { + kidsObj.arrayGet(i, &kidObj); + if (kidObj.isDict()) { + if (kidObj.dictLookup("Parent", &subtypeObj)->isNull()) { + isTerminal = gTrue; + } + subtypeObj.free(); + } + kidObj.free(); + } + if (!isTerminal) { + for (i = 0; !isTerminal && i < kidsObj.arrayGetLength(); ++i) { + kidsObj.arrayGetNF(i, &kidRef); + scanField(&kidRef); + kidRef.free(); + } + } + } + kidsObj.free(); + + if (isTerminal) { + if ((field = AcroFormField::load(this, fieldRef))) { + fields->append(field); + } + } + + fieldObj.free(); +} + +void AcroForm::draw(int pageNum, Gfx *gfx, GBool printing) { + int i; + + for (i = 0; i < fields->getLength(); ++i) { + ((AcroFormField *)fields->get(i))->draw(pageNum, gfx, printing); + } +} + +int AcroForm::getNumFields() { + return fields->getLength(); +} + +AcroFormField *AcroForm::getField(int idx) { + return (AcroFormField *)fields->get(idx); +} + +AcroFormField *AcroForm::findField(int pg, double x, double y) { + AcroFormField *field; + double llx, lly, urx, ury; + int i; + + for (i = 0; i < fields->getLength(); ++i) { + field = (AcroFormField *)fields->get(i); + if (field->getPageNum() == pg) { + field->getBBox(&llx, &lly, &urx, &ury); + if (llx <= x && x <= urx && lly <= y && y <= ury) { + return field; + } + } + } + return NULL; +} + +int AcroForm::findFieldIdx(int pg, double x, double y) { + AcroFormField *field; + double llx, lly, urx, ury; + int i; + + for (i = 0; i < fields->getLength(); ++i) { + field = (AcroFormField *)fields->get(i); + if (field->getPageNum() == pg) { + field->getBBox(&llx, &lly, &urx, &ury); + if (llx <= x && x <= urx && lly <= y && y <= ury) { + return i; + } + } + } + return -1; +} + +//------------------------------------------------------------------------ +// AcroFormField +//------------------------------------------------------------------------ + +AcroFormField *AcroFormField::load(AcroForm *acroFormA, Object *fieldRefA) { + GString *typeStr; + TextString *nameA; + GString *xfaName; + Guint flagsA; + GBool haveFlags, typeFromParentA; + Object fieldObjA, parentObj, parentObj2, obj1, obj2; + AcroFormFieldType typeA; + XFAField *xfaFieldA; + AcroFormField *field; + int depth, i0, i1; + + fieldRefA->fetch(acroFormA->doc->getXRef(), &fieldObjA); + + //----- get field info + + if (fieldObjA.dictLookup("T", &obj1)->isString()) { + nameA = new TextString(obj1.getString()); + } else { + nameA = new TextString(); + } + obj1.free(); + + if (fieldObjA.dictLookup("FT", &obj1)->isName()) { + typeStr = new GString(obj1.getName()); + typeFromParentA = gFalse; + } else { + typeStr = NULL; + typeFromParentA = gTrue; + } + obj1.free(); + + if (fieldObjA.dictLookup("Ff", &obj1)->isInt()) { + flagsA = (Guint)obj1.getInt(); + haveFlags = gTrue; + } else { + flagsA = 0; + haveFlags = gFalse; + } + obj1.free(); + + //----- get info from parent non-terminal fields + + fieldObjA.dictLookup("Parent", &parentObj); + depth = 0; + while (parentObj.isDict() && depth < maxFieldObjectDepth) { + + if (parentObj.dictLookup("T", &obj1)->isString()) { + if (nameA->getLength()) { + nameA->insert(0, (Unicode)'.'); + } + nameA->insert(0, obj1.getString()); + } + obj1.free(); + + if (!typeStr) { + if (parentObj.dictLookup("FT", &obj1)->isName()) { + typeStr = new GString(obj1.getName()); + } + obj1.free(); + } + + if (!haveFlags) { + if (parentObj.dictLookup("Ff", &obj1)->isInt()) { + flagsA = (Guint)obj1.getInt(); + haveFlags = gTrue; + } + obj1.free(); + } + + parentObj.dictLookup("Parent", &parentObj2); + parentObj.free(); + parentObj = parentObj2; + + ++depth; + } + parentObj.free(); + + if (!typeStr) { + error(errSyntaxError, -1, "Missing type in AcroForm field"); + goto err1; + } + + //----- get static XFA info + + xfaFieldA = NULL; + if (acroFormA->xfaScanner) { + // convert field name to UTF-8, and remove segments that start + // with '#' -- to match the XFA field name + xfaName = nameA->toUTF8(); + i0 = 0; + while (i0 < xfaName->getLength()) { + i1 = i0; + while (i1 < xfaName->getLength()) { + if (xfaName->getChar(i1) == '.') { + ++i1; + break; + } + ++i1; + } + if (xfaName->getChar(i0) == '#') { + xfaName->del(i0, i1 - i0); + } else { + i0 = i1; + } + } + xfaFieldA = acroFormA->xfaScanner->findField(xfaName); + delete xfaName; + } + + //----- check for a radio button + + // this is a kludge: if we see a Btn-type field with kids, and the + // Ff entry is missing, assume the kids are radio buttons + if (typeFromParentA && !typeStr->cmp("Btn") && !haveFlags) { + flagsA = acroFormFlagRadio; + } + + //----- determine field type + + if (!typeStr->cmp("Btn")) { + if (flagsA & acroFormFlagPushbutton) { + typeA = acroFormFieldPushbutton; + } else if (flagsA & acroFormFlagRadio) { + typeA = acroFormFieldRadioButton; + } else { + typeA = acroFormFieldCheckbox; + } + } else if (!typeStr->cmp("Tx")) { + if (xfaFieldA && xfaFieldA->getBarcodeInfo()) { + typeA = acroFormFieldBarcode; + } else if (flagsA & acroFormFlagFileSelect) { + typeA = acroFormFieldFileSelect; + } else if (flagsA & acroFormFlagMultiline) { + typeA = acroFormFieldMultilineText; + } else { + typeA = acroFormFieldText; + } + } else if (!typeStr->cmp("Ch")) { + if (flagsA & acroFormFlagCombo) { + typeA = acroFormFieldComboBox; + } else { + typeA = acroFormFieldListBox; + } + } else if (!typeStr->cmp("Sig")) { + typeA = acroFormFieldSignature; + } else { + error(errSyntaxError, -1, "Invalid type in AcroForm field"); + goto err1; + } + delete typeStr; + + field = new AcroFormField(acroFormA, fieldRefA, &fieldObjA, + typeA, nameA, flagsA, typeFromParentA, xfaFieldA); + fieldObjA.free(); + return field; + + err1: + delete typeStr; + delete nameA; + fieldObjA.free(); + return NULL; +} + +AcroFormField::AcroFormField(AcroForm *acroFormA, + Object *fieldRefA, Object *fieldObjA, + AcroFormFieldType typeA, TextString *nameA, + Guint flagsA, GBool typeFromParentA, + XFAField *xfaFieldA) { + acroForm = acroFormA; + fieldRefA->copy(&fieldRef); + fieldObjA->copy(&fieldObj); + type = typeA; + name = nameA; + flags = flagsA; + typeFromParent = typeFromParentA; + xfaField = xfaFieldA; +} + +AcroFormField::~AcroFormField() { + fieldRef.free(); + fieldObj.free(); + delete name; +} + +int AcroFormField::getPageNum() { + Object kidsObj, annotRef; + int pageNum; + + pageNum = 0; + if (fieldObj.dictLookup("Kids", &kidsObj)->isArray()) { + if (kidsObj.arrayGetLength() > 0) { + kidsObj.arrayGetNF(0, &annotRef); + pageNum = acroForm->lookupAnnotPage(&annotRef); + annotRef.free(); + } + } else { + pageNum = acroForm->lookupAnnotPage(&fieldRef); + } + kidsObj.free(); + return pageNum; +} + +const char *AcroFormField::getType() { + switch (type) { + case acroFormFieldPushbutton: return "PushButton"; + case acroFormFieldRadioButton: return "RadioButton"; + case acroFormFieldCheckbox: return "Checkbox"; + case acroFormFieldFileSelect: return "FileSelect"; + case acroFormFieldMultilineText: return "MultilineText"; + case acroFormFieldText: return "Text"; + case acroFormFieldBarcode: return "Barcode"; + case acroFormFieldComboBox: return "ComboBox"; + case acroFormFieldListBox: return "ListBox"; + case acroFormFieldSignature: return "Signature"; + default: return NULL; + } +} + +Unicode *AcroFormField::getName(int *length) { + Unicode *u, *ret; + int n; + + u = name->getUnicode(); + n = name->getLength(); + ret = (Unicode *)gmallocn(n, sizeof(Unicode)); + memcpy(ret, u, n * sizeof(Unicode)); + *length = n; + return ret; +} + +Unicode *AcroFormField::getValue(int *length) { + Object obj1, obj2; + Unicode *u; + char *s; + TextString *ts; + GString *gs; + int n, i; + + u = NULL; + *length = 0; + + // if this field has a counterpart in the XFA form, take the value + // from the XFA field (NB: an XFA field with no value overrides the + // AcroForm value) + if (xfaField) { + if (xfaField->getValue()) { + u = utf8ToUnicode(xfaField->getValue(), length); + } + + // no XFA form - take the AcroForm value + } else { + fieldLookup("V", &obj1); + if (obj1.isName()) { + s = obj1.getName(); + n = (int)strlen(s); + u = (Unicode *)gmallocn(n, sizeof(Unicode)); + for (i = 0; i < n; ++i) { + u[i] = s[i] & 0xff; + } + *length = n; + } else if (obj1.isString()) { + ts = new TextString(obj1.getString()); + n = ts->getLength(); + u = (Unicode *)gmallocn(n, sizeof(Unicode)); + memcpy(u, ts->getUnicode(), n * sizeof(Unicode)); + *length = n; + delete ts; + } else if (obj1.isDict()) { + obj1.dictLookup("Contents", &obj2); + if (obj2.isString()) { + gs = obj2.getString(); + n = gs->getLength(); + u = (Unicode *)gmallocn(n, sizeof(Unicode)); + for (i = 0; i < n; ++i) { + u[i] = gs->getChar(i) & 0xff; + } + *length = n; + } + obj2.free(); + } + obj1.free(); + } + + return u; +} + +void AcroFormField::getBBox(double *llx, double *lly, + double *urx, double *ury) { + Object annotObj, rectObj, numObj; + double t; + + *llx = *lly = *urx = *ury = 0; + + if (getAnnotObj(&annotObj)->isDict()) { + annotObj.dictLookup("Rect", &rectObj); + if (rectObj.isArray() && rectObj.arrayGetLength() == 4) { + rectObj.arrayGet(0, &numObj); + if (numObj.isNum()) { + *llx = numObj.getNum(); + } + numObj.free(); + rectObj.arrayGet(1, &numObj); + if (numObj.isNum()) { + *lly = numObj.getNum(); + } + numObj.free(); + rectObj.arrayGet(2, &numObj); + if (numObj.isNum()) { + *urx = numObj.getNum(); + } + numObj.free(); + rectObj.arrayGet(3, &numObj); + if (numObj.isNum()) { + *ury = numObj.getNum(); + } + numObj.free(); + } + rectObj.free(); + } + annotObj.free(); + + if (*llx > *urx) { + t = *llx; *llx = *urx; *urx = t; + } + if (*lly > *ury) { + t = *lly; *lly = *ury; *ury = t; + } +} + +void AcroFormField::getFont(Ref *fontID, double *fontSize) { + Object daObj; + GList *daToks; + char *fontTag; + double tfSize, m2, m3; + int tfPos, tmPos, i; + + fontID->num = fontID->gen = -1; + *fontSize = 0; + + if (fieldLookup("DA", &daObj)->isString()) { + + // parse the default appearance string + daToks = tokenize(daObj.getString()); + tfPos = tmPos = -1; + for (i = 2; i < daToks->getLength(); ++i) { + if (!((GString *)daToks->get(i))->cmp("Tf")) { + tfPos = i - 2; + } else if (i >= 6 && !((GString *)daToks->get(i))->cmp("Tm")) { + tmPos = i - 6; + } + } + + // handle the Tf operator + if (tfPos >= 0) { + fontTag = ((GString *)daToks->get(tfPos))->getCString(); + if (*fontTag == '/') { + ++fontTag; + } + *fontID = findFontName(fontTag); + tfSize = atof(((GString *)daToks->get(tfPos + 1))->getCString()); + } else { + tfSize = 1; + } + + // handle the Tm operator + if (tmPos >= 0) { + // transformed font size = sqrt(m[2]^2 + m[3]^2) * size + m2 = atof(((GString *)daToks->get(tfPos + 2))->getCString()); + m3 = atof(((GString *)daToks->get(tfPos + 3))->getCString()); + tfSize *= sqrt(m2*m2 + m3*m3); + } + *fontSize = tfSize; + + deleteGList(daToks, GString); + } + + daObj.free(); +} + +Ref AcroFormField::findFontName(char *fontTag) { + Object drObj, fontDictObj, fontObj, baseFontObj; + Ref fontID; + GBool found; + + fontID.num = fontID.gen = -1; + found = gFalse; + + if (fieldObj.dictLookup("DR", &drObj)->isDict()) { + if (drObj.dictLookup("Font", &fontDictObj)->isDict()) { + if (fontDictObj.dictLookupNF(fontTag, &fontObj)->isRef()) { + fontID = fontObj.getRef(); + found = gTrue; + } + fontObj.free(); + } + fontDictObj.free(); + } + drObj.free(); + if (found) { + return fontID; + } + + if (acroForm->acroFormObj.dictLookup("DR", &drObj)->isDict()) { + if (drObj.dictLookup("Font", &fontDictObj)->isDict()) { + if (fontDictObj.dictLookupNF(fontTag, &fontObj)->isRef()) { + fontID = fontObj.getRef(); + } + fontObj.free(); + } + fontDictObj.free(); + } + drObj.free(); + return fontID; +} + +void AcroFormField::getColor(double *red, double *green, double *blue) { + Object daObj; + GList *daToks; + int i; + + *red = *green = *blue = 0; + + if (fieldLookup("DA", &daObj)->isString()) { + + // parse the default appearance string + daToks = tokenize(daObj.getString()); + for (i = 1; i < daToks->getLength(); ++i) { + + // handle the g operator + if (!((GString *)daToks->get(i))->cmp("g")) { + *red = *green = *blue = + atof(((GString *)daToks->get(i - 1))->getCString()); + break; + + // handle the rg operator + } else if (i >= 3 && !((GString *)daToks->get(i))->cmp("rg")) { + *red = atof(((GString *)daToks->get(i - 3))->getCString()); + *green = atof(((GString *)daToks->get(i - 2))->getCString()); + *blue = atof(((GString *)daToks->get(i - 1))->getCString()); + break; + } + } + + deleteGList(daToks, GString); + } + + daObj.free(); +} + +int AcroFormField::getMaxLen() { + Object obj; + int len; + + if (fieldLookup("MaxLen", &obj)->isInt()) { + len = obj.getInt(); + } else { + len = -1; + } + obj.free(); + return len; +} + +void AcroFormField::draw(int pageNum, Gfx *gfx, GBool printing) { + Object kidsObj, annotRef, annotObj; + int i; + + // find the annotation object(s) + if (fieldObj.dictLookup("Kids", &kidsObj)->isArray()) { + for (i = 0; i < kidsObj.arrayGetLength(); ++i) { + kidsObj.arrayGetNF(i, &annotRef); + annotRef.fetch(acroForm->doc->getXRef(), &annotObj); + drawAnnot(pageNum, gfx, printing, &annotRef, &annotObj); + annotObj.free(); + annotRef.free(); + } + } else { + drawAnnot(pageNum, gfx, printing, &fieldRef, &fieldObj); + } + kidsObj.free(); +} + +void AcroFormField::drawAnnot(int pageNum, Gfx *gfx, GBool printing, + Object *annotRef, Object *annotObj) { + Object obj1, obj2; + double xMin, yMin, xMax, yMax, t; + int annotFlags; + GBool oc, render; + + if (!annotObj->isDict()) { + return; + } + + //----- get the page number + + // the "P" (page) field in annotations is optional, so we can't + // depend on it here + if (acroForm->lookupAnnotPage(annotRef) != pageNum) { + return; + } + + //----- check annotation flags + + if (annotObj->dictLookup("F", &obj1)->isInt()) { + annotFlags = obj1.getInt(); + } else { + annotFlags = 0; + } + obj1.free(); + if ((annotFlags & annotFlagHidden) || + (printing && !(annotFlags & annotFlagPrint)) || + (!printing && (annotFlags & annotFlagNoView))) { + return; + } + + //----- check the optional content entry + + annotObj->dictLookupNF("OC", &obj1); + if (acroForm->doc->getOptionalContent()->evalOCObject(&obj1, &oc) && !oc) { + obj1.free(); + return; + } + obj1.free(); + + //----- get the bounding box + + if (annotObj->dictLookup("Rect", &obj1)->isArray() && + obj1.arrayGetLength() == 4) { + xMin = yMin = xMax = yMax = 0; + if (obj1.arrayGet(0, &obj2)->isNum()) { + xMin = obj2.getNum(); + } + obj2.free(); + if (obj1.arrayGet(1, &obj2)->isNum()) { + yMin = obj2.getNum(); + } + obj2.free(); + if (obj1.arrayGet(2, &obj2)->isNum()) { + xMax = obj2.getNum(); + } + obj2.free(); + if (obj1.arrayGet(3, &obj2)->isNum()) { + yMax = obj2.getNum(); + } + obj2.free(); + if (xMin > xMax) { + t = xMin; xMin = xMax; xMax = t; + } + if (yMin > yMax) { + t = yMin; yMin = yMax; yMax = t; + } + } else { + error(errSyntaxError, -1, "Bad bounding box for annotation"); + obj1.free(); + return; + } + obj1.free(); + + //----- draw it + + render = gFalse; + if (acroForm->needAppearances) { + render = gTrue; + } else if (xfaField && xfaField->getValue()) { + render = gTrue; + } else { + if (!annotObj->dictLookup("AP", &obj1)->isDict()) { + render = gTrue; + } + obj1.free(); + } + if (render) { + drawNewAppearance(gfx, annotObj->getDict(), + xMin, yMin, xMax, yMax); + } else { + drawExistingAppearance(gfx, annotObj->getDict(), + xMin, yMin, xMax, yMax); + } +} + +// Draw the existing appearance stream for a single annotation +// attached to this field. +void AcroFormField::drawExistingAppearance(Gfx *gfx, Dict *annot, + double xMin, double yMin, + double xMax, double yMax) { + Object apObj, asObj, appearance, obj1; + + //----- get the appearance stream + + if (annot->lookup("AP", &apObj)->isDict()) { + apObj.dictLookup("N", &obj1); + if (obj1.isDict()) { + if (annot->lookup("AS", &asObj)->isName()) { + obj1.dictLookupNF(asObj.getName(), &appearance); + } else if (obj1.dictGetLength() == 1) { + obj1.dictGetValNF(0, &appearance); + } else { + obj1.dictLookupNF("Off", &appearance); + } + asObj.free(); + } else { + apObj.dictLookupNF("N", &appearance); + } + obj1.free(); + } + apObj.free(); + + //----- draw it + + if (!appearance.isNone()) { + gfx->drawAnnot(&appearance, NULL, xMin, yMin, xMax, yMax); + appearance.free(); + } +} + +// Regenerate the appearance for this field, and draw it. +void AcroFormField::drawNewAppearance(Gfx *gfx, Dict *annot, + double xMin, double yMin, + double xMax, double yMax) { + GString *appearBuf; + Object appearance, mkObj, ftObj, appearDict, drObj, apObj, asObj; + Object resources, fontResources, defaultFont, gfxStateDict; + Object obj1, obj2, obj3, obj4; + Dict *mkDict; + MemStream *appearStream; + GfxFontDict *fontDict; + GBool hasCaption; + double dx, dy, r; + GString *val, *caption, *da; + GString **text; + GBool done; + GBool *selection; + AnnotBorderType borderType; + double borderWidth; + double *borderDash; + GString *appearanceState; + int borderDashLength, rot, quadding, vAlign, comb, nOptions, topIdx, i; + + appearBuf = new GString(); +#if 0 //~debug + appearBuf->appendf("1 1 0 rg 0 0 {0:.4f} {1:.4f} re f\n", + xMax - xMin, yMax - yMin); +#endif +#if 0 //~debug + appearBuf->appendf("1 1 0 RG 0 0 {0:.4f} {1:.4f} re s\n", + xMax - xMin, yMax - yMin); +#endif + + // get the appearance characteristics (MK) dictionary + if (annot->lookup("MK", &mkObj)->isDict()) { + mkDict = mkObj.getDict(); + } else { + mkDict = NULL; + } + + // draw the background + if (mkDict) { + if (mkDict->lookup("BG", &obj1)->isArray() && + obj1.arrayGetLength() > 0) { + setColor(obj1.getArray(), gTrue, 0, appearBuf); + appearBuf->appendf("0 0 {0:.4f} {1:.4f} re f\n", + xMax - xMin, yMax - yMin); + } + obj1.free(); + } + + // get the field type + fieldLookup("FT", &ftObj); + + // draw the border + borderType = annotBorderSolid; + borderWidth = 1; + borderDash = NULL; + borderDashLength = 0; + if (annot->lookup("BS", &obj1)->isDict()) { + if (obj1.dictLookup("S", &obj2)->isName()) { + if (obj2.isName("S")) { + borderType = annotBorderSolid; + } else if (obj2.isName("D")) { + borderType = annotBorderDashed; + } else if (obj2.isName("B")) { + borderType = annotBorderBeveled; + } else if (obj2.isName("I")) { + borderType = annotBorderInset; + } else if (obj2.isName("U")) { + borderType = annotBorderUnderlined; + } + } + obj2.free(); + if (obj1.dictLookup("W", &obj2)->isNum()) { + borderWidth = obj2.getNum(); + } + obj2.free(); + if (obj1.dictLookup("D", &obj2)->isArray()) { + borderDashLength = obj2.arrayGetLength(); + borderDash = (double *)gmallocn(borderDashLength, sizeof(double)); + for (i = 0; i < borderDashLength; ++i) { + if (obj2.arrayGet(i, &obj3)->isNum()) { + borderDash[i] = obj3.getNum(); + } else { + borderDash[i] = 1; + } + obj3.free(); + } + } + obj2.free(); + } else { + obj1.free(); + if (annot->lookup("Border", &obj1)->isArray()) { + if (obj1.arrayGetLength() >= 3) { + if (obj1.arrayGet(2, &obj2)->isNum()) { + borderWidth = obj2.getNum(); + } + obj2.free(); + if (obj1.arrayGetLength() >= 4) { + if (obj1.arrayGet(3, &obj2)->isArray()) { + borderType = annotBorderDashed; + borderDashLength = obj2.arrayGetLength(); + borderDash = (double *)gmallocn(borderDashLength, sizeof(double)); + for (i = 0; i < borderDashLength; ++i) { + if (obj2.arrayGet(i, &obj3)->isNum()) { + borderDash[i] = obj3.getNum(); + } else { + borderDash[i] = 1; + } + obj3.free(); + } + } else { + // Adobe draws no border at all if the last element is of + // the wrong type. + borderWidth = 0; + } + obj2.free(); + } + } + } + } + obj1.free(); + if (mkDict) { + if (borderWidth > 0) { + mkDict->lookup("BC", &obj1); + if (!(obj1.isArray() && obj1.arrayGetLength() > 0)) { + obj1.free(); + mkDict->lookup("BG", &obj1); + } + if (obj1.isArray() && obj1.arrayGetLength() > 0) { + dx = xMax - xMin; + dy = yMax - yMin; + + // radio buttons with no caption have a round border + hasCaption = mkDict->lookup("CA", &obj2)->isString(); + obj2.free(); + if (ftObj.isName("Btn") && (flags & acroFormFlagRadio) && !hasCaption) { + r = 0.5 * (dx < dy ? dx : dy); + switch (borderType) { + case annotBorderDashed: + appearBuf->append("["); + for (i = 0; i < borderDashLength; ++i) { + appearBuf->appendf(" {0:.4f}", borderDash[i]); + } + appearBuf->append("] 0 d\n"); + // fall through to the solid case + case annotBorderSolid: + case annotBorderUnderlined: + appearBuf->appendf("{0:.4f} w\n", borderWidth); + setColor(obj1.getArray(), gFalse, 0, appearBuf); + drawCircle(0.5 * dx, 0.5 * dy, r - 0.5 * borderWidth, "s", + appearBuf); + break; + case annotBorderBeveled: + case annotBorderInset: + appearBuf->appendf("{0:.4f} w\n", 0.5 * borderWidth); + setColor(obj1.getArray(), gFalse, 0, appearBuf); + drawCircle(0.5 * dx, 0.5 * dy, r - 0.25 * borderWidth, "s", + appearBuf); + setColor(obj1.getArray(), gFalse, + borderType == annotBorderBeveled ? 1 : -1, + appearBuf); + drawCircleTopLeft(0.5 * dx, 0.5 * dy, r - 0.75 * borderWidth, + appearBuf); + setColor(obj1.getArray(), gFalse, + borderType == annotBorderBeveled ? -1 : 1, + appearBuf); + drawCircleBottomRight(0.5 * dx, 0.5 * dy, r - 0.75 * borderWidth, + appearBuf); + break; + } + + } else { + switch (borderType) { + case annotBorderDashed: + appearBuf->append("["); + for (i = 0; i < borderDashLength; ++i) { + appearBuf->appendf(" {0:.4f}", borderDash[i]); + } + appearBuf->append("] 0 d\n"); + // fall through to the solid case + case annotBorderSolid: + appearBuf->appendf("{0:.4f} w\n", borderWidth); + setColor(obj1.getArray(), gFalse, 0, appearBuf); + appearBuf->appendf("{0:.4f} {0:.4f} {1:.4f} {2:.4f} re s\n", + 0.5 * borderWidth, + dx - borderWidth, dy - borderWidth); + break; + case annotBorderBeveled: + case annotBorderInset: + setColor(obj1.getArray(), gTrue, + borderType == annotBorderBeveled ? 1 : -1, + appearBuf); + appearBuf->append("0 0 m\n"); + appearBuf->appendf("0 {0:.4f} l\n", dy); + appearBuf->appendf("{0:.4f} {1:.4f} l\n", dx, dy); + appearBuf->appendf("{0:.4f} {1:.4f} l\n", + dx - borderWidth, dy - borderWidth); + appearBuf->appendf("{0:.4f} {1:.4f} l\n", + borderWidth, dy - borderWidth); + appearBuf->appendf("{0:.4f} {0:.4f} l\n", borderWidth); + appearBuf->append("f\n"); + setColor(obj1.getArray(), gTrue, + borderType == annotBorderBeveled ? -1 : 1, + appearBuf); + appearBuf->append("0 0 m\n"); + appearBuf->appendf("{0:.4f} 0 l\n", dx); + appearBuf->appendf("{0:.4f} {1:.4f} l\n", dx, dy); + appearBuf->appendf("{0:.4f} {1:.4f} l\n", + dx - borderWidth, dy - borderWidth); + appearBuf->appendf("{0:.4f} {1:.4f} l\n", + dx - borderWidth, borderWidth); + appearBuf->appendf("{0:.4f} {0:.4f} l\n", borderWidth); + appearBuf->append("f\n"); + break; + case annotBorderUnderlined: + appearBuf->appendf("{0:.4f} w\n", borderWidth); + setColor(obj1.getArray(), gFalse, 0, appearBuf); + appearBuf->appendf("0 0 m {0:.4f} 0 l s\n", dx); + break; + } + + // clip to the inside of the border + appearBuf->appendf("{0:.4f} {0:.4f} {1:.4f} {2:.4f} re W n\n", + borderWidth, + dx - 2 * borderWidth, dy - 2 * borderWidth); + } + } + obj1.free(); + } + } + gfree(borderDash); + + // get the resource dictionary + buildDefaultResourceDict(&drObj); + + // build the font dictionary + if (drObj.isDict() && drObj.dictLookup("Font", &obj1)->isDict()) { + fontDict = new GfxFontDict(acroForm->doc->getXRef(), NULL, obj1.getDict()); + } else { + fontDict = NULL; + } + obj1.free(); + + // get the default appearance string + if (fieldLookup("DA", &obj1)->isString()) { + da = obj1.getString()->copy(); + } else { + da = NULL; + } + obj1.free(); + + // get the rotation value + rot = 0; + if (mkDict) { + if (mkDict->lookup("R", &obj1)->isInt()) { + rot = obj1.getInt(); + } + obj1.free(); + } + + // get the appearance state + annot->lookup("AP", &apObj); + annot->lookup("AS", &asObj); + appearanceState = NULL; + if (asObj.isName()) { + appearanceState = new GString(asObj.getName()); + } else if (apObj.isDict()) { + apObj.dictLookup("N", &obj1); + if (obj1.isDict() && obj1.dictGetLength() == 1) { + appearanceState = new GString(obj1.dictGetKey(0)); + } + obj1.free(); + } + if (!appearanceState) { + appearanceState = new GString("Off"); + } + asObj.free(); + apObj.free(); + + int valueLength; + Unicode *value = getValue(&valueLength); + + // draw the field contents + if (ftObj.isName("Btn")) { + caption = NULL; + if (mkDict) { + if (mkDict->lookup("CA", &obj1)->isString()) { + caption = obj1.getString()->copy(); + } + obj1.free(); + } + // radio button + if (flags & acroFormFlagRadio) { + //~ Acrobat doesn't draw a caption if there is no AP dict (?) + if (value && unicodeStringEqual(value, valueLength, + appearanceState->getCString())) { + if (caption) { + drawText(caption, da, fontDict, gFalse, 0, + acroFormQuadCenter, acroFormVAlignMiddleNoDescender, + gFalse, gTrue, rot, 0, 0, xMax - xMin, yMax - yMin, + borderWidth, gFalse, appearBuf); + } else { + if (mkDict) { + if (mkDict->lookup("BC", &obj2)->isArray() && + obj2.arrayGetLength() > 0) { + dx = xMax - xMin; + dy = yMax - yMin; + setColor(obj2.getArray(), gTrue, 0, appearBuf); + drawCircle(0.5 * dx, 0.5 * dy, 0.2 * (dx < dy ? dx : dy), "f", + appearBuf); + } + obj2.free(); + } + } + } + // pushbutton + } else if (flags & acroFormFlagPushbutton) { + if (caption) { + drawText(caption, da, fontDict, gFalse, 0, + acroFormQuadCenter, acroFormVAlignMiddle, + gFalse, gFalse, rot, 0, 0, xMax - xMin, yMax - yMin, + borderWidth, gFalse, appearBuf); + } + // checkbox + } else { + if (value && !(unicodeStringEqual(value, valueLength, "Off") || + unicodeStringEqual(value, valueLength, "No") || + unicodeStringEqual(value, valueLength, "0") || + valueLength == 0)) { + if (!caption) { + caption = new GString("3"); // ZapfDingbats checkmark + } + drawText(caption, da, fontDict, gFalse, 0, + acroFormQuadCenter, acroFormVAlignMiddleNoDescender, + gFalse, gTrue, rot, 0, 0, xMax - xMin, yMax - yMin, + borderWidth, gFalse, appearBuf); + } + } + if (caption) { + delete caption; + } + } else if (ftObj.isName("Tx")) { + XFAFieldBarcodeInfo *barcodeInfo = xfaField ? xfaField->getBarcodeInfo() + : (XFAFieldBarcodeInfo *)NULL; + if (value) { + //~ value strings can be Unicode + GString *valueLatin1 = unicodeToLatin1(value, valueLength); + if (barcodeInfo) { + drawBarcode(valueLatin1, da, fontDict, rot, xMin, yMin, xMax, yMax, + barcodeInfo, appearBuf); + } else { + if (fieldLookup("Q", &obj2)->isInt()) { + quadding = obj2.getInt(); + } else { + quadding = acroFormQuadLeft; + } + obj2.free(); + vAlign = (flags & acroFormFlagMultiline) ? acroFormVAlignTop + : acroFormVAlignMiddle; + XFAFieldLayoutInfo *layoutInfo = xfaField ? xfaField->getLayoutInfo() + : (XFAFieldLayoutInfo *)NULL; + if (layoutInfo) { + switch (layoutInfo->hAlign) { + case xfaFieldLayoutHAlignLeft: + default: + quadding = acroFormQuadLeft; + break; + case xfaFieldLayoutHAlignCenter: + quadding = acroFormQuadCenter; + break; + case xfaFieldLayoutHAlignRight: + quadding = acroFormQuadRight; + break; + } + switch (layoutInfo->vAlign) { + case xfaFieldLayoutVAlignTop: + default: + vAlign = acroFormVAlignTop; + break; + case xfaFieldLayoutVAlignMiddle: + vAlign = acroFormVAlignMiddle; + break; + case xfaFieldLayoutVAlignBottom: + vAlign = acroFormVAlignBottom; + break; + } + } + comb = 0; + if (flags & acroFormFlagComb) { + if (fieldLookup("MaxLen", &obj2)->isInt()) { + comb = obj2.getInt(); + } + obj2.free(); + } + XFAFieldPictureInfo *pictureInfo = + xfaField ? xfaField->getPictureInfo() + : (XFAFieldPictureInfo *)NULL; + GString *value2 = valueLatin1; + if (pictureInfo) { + switch (pictureInfo->subtype) { + case xfaFieldPictureDateTime: + value2 = pictureFormatDateTime(valueLatin1, pictureInfo->format); + break; + case xfaFieldPictureNumeric: + value2 = pictureFormatNumber(valueLatin1, pictureInfo->format); + break; + case xfaFieldPictureText: + value2 = pictureFormatText(valueLatin1, pictureInfo->format); + break; + } + } + drawText(value2, da, fontDict, + flags & acroFormFlagMultiline, comb, quadding, vAlign, + gTrue, gFalse, rot, 0, 0, xMax - xMin, yMax - yMin, + borderWidth, gFalse, appearBuf); + if (value2 != valueLatin1) { + delete value2; + } + } + delete valueLatin1; + } + } else if (ftObj.isName("Ch")) { + //~ value/option strings can be Unicode + if (fieldLookup("Q", &obj1)->isInt()) { + quadding = obj1.getInt(); + } else { + quadding = acroFormQuadLeft; + } + obj1.free(); + vAlign = acroFormVAlignMiddle; + XFAFieldLayoutInfo *layoutInfo = xfaField ? xfaField->getLayoutInfo() + : (XFAFieldLayoutInfo *)NULL; + if (layoutInfo) { + switch (layoutInfo->hAlign) { + case xfaFieldLayoutHAlignLeft: + default: + quadding = acroFormQuadLeft; + break; + case xfaFieldLayoutHAlignCenter: + quadding = acroFormQuadCenter; + break; + case xfaFieldLayoutHAlignRight: + quadding = acroFormQuadRight; + break; + } + switch (layoutInfo->vAlign) { + case xfaFieldLayoutVAlignTop: + default: + vAlign = acroFormVAlignTop; + break; + case xfaFieldLayoutVAlignMiddle: + vAlign = acroFormVAlignMiddle; + break; + case xfaFieldLayoutVAlignBottom: + vAlign = acroFormVAlignBottom; + break; + } + } + // combo box + if (flags & acroFormFlagCombo) { + if (value) { + val = unicodeToLatin1(value, valueLength); + if (fieldObj.dictLookup("Opt", &obj2)->isArray()) { + for (i = 0, done = false; i < obj2.arrayGetLength() && !done; ++i) { + obj2.arrayGet(i, &obj3); + if (obj3.isArray() && obj3.arrayGetLength() == 2) { + if (obj3.arrayGet(0, &obj4)->isString() && + obj4.getString()->cmp(val) == 0) { + obj4.free(); + if (obj3.arrayGet(1, &obj4)->isString()) { + delete val; + val = obj4.getString()->copy(); + } + done = gTrue; + } + obj4.free(); + } + obj3.free(); + } + } + obj2.free(); + drawText(val, da, fontDict, + gFalse, 0, quadding, vAlign, gTrue, gFalse, rot, + 0, 0, xMax - xMin, yMax - yMin, borderWidth, + gFalse, appearBuf); + delete val; + //~ Acrobat draws a popup icon on the right side + } + // list box + } else { + if (fieldObj.dictLookup("Opt", &obj1)->isArray()) { + nOptions = obj1.arrayGetLength(); + // get the option text + text = (GString **)gmallocn(nOptions, sizeof(GString *)); + for (i = 0; i < nOptions; ++i) { + text[i] = NULL; + obj1.arrayGet(i, &obj2); + if (obj2.isString()) { + text[i] = obj2.getString()->copy(); + } else if (obj2.isArray() && obj2.arrayGetLength() == 2) { + if (obj2.arrayGet(1, &obj3)->isString()) { + text[i] = obj3.getString()->copy(); + } + obj3.free(); + } + obj2.free(); + if (!text[i]) { + text[i] = new GString(); + } + } + // get the selected option(s) + selection = (GBool *)gmallocn(nOptions, sizeof(GBool)); + //~ need to use the I field in addition to the V field + for (i = 0; i < nOptions; ++i) { + selection[i] = unicodeStringEqual(value, valueLength, text[i]); + } + // get the top index + if (fieldObj.dictLookup("TI", &obj2)->isInt()) { + topIdx = obj2.getInt(); + if (topIdx < 0 || topIdx >= nOptions) { + topIdx = 0; + } + } else { + topIdx = 0; + } + obj2.free(); + // draw the text + drawListBox(text, selection, nOptions, topIdx, da, fontDict, quadding, + xMin, yMin, xMax, yMax, borderWidth, appearBuf); + for (i = 0; i < nOptions; ++i) { + delete text[i]; + } + gfree(text); + gfree(selection); + } + obj1.free(); + } + } else if (ftObj.isName("Sig")) { + //~ check to see if background is already drawn + gfxStateDict.initDict(acroForm->doc->getXRef()); + obj1.initReal(0.5); + gfxStateDict.dictAdd(copyString("ca"), &obj1); + appearBuf->append("/GS1 gs\n"); + appearBuf->appendf("0.7 0.7 1 rg 0 0 {0:.2f} {1:.2f} re f\n", + xMax - xMin, yMax - yMin); + caption = new GString("SIGN HERE"); + if (da) { + delete da; + } + da = new GString("/Helv 10 Tf 1 0 0 rg"); + drawText(caption, da, fontDict, gFalse, 0, + acroFormQuadLeft, acroFormVAlignMiddle, gFalse, gFalse, rot, + 0, 0, xMax - xMin, yMax - yMin, borderWidth, gFalse, appearBuf); + delete caption; + } else { + error(errSyntaxError, -1, "Unknown field type"); + } + + gfree(value); + + delete appearanceState; + if (da) { + delete da; + } + + // build the appearance stream dictionary + appearDict.initDict(acroForm->doc->getXRef()); + appearDict.dictAdd(copyString("Length"), + obj1.initInt(appearBuf->getLength())); + appearDict.dictAdd(copyString("Subtype"), obj1.initName("Form")); + obj1.initArray(acroForm->doc->getXRef()); + obj1.arrayAdd(obj2.initReal(0)); + obj1.arrayAdd(obj2.initReal(0)); + obj1.arrayAdd(obj2.initReal(xMax - xMin)); + obj1.arrayAdd(obj2.initReal(yMax - yMin)); + appearDict.dictAdd(copyString("BBox"), &obj1); + + // set the resource dictionary; add a default font + if (drObj.isDict()) { + drObj.copy(&resources); + } else { + resources.initDict(acroForm->doc->getXRef()); + } + drObj.free(); + fontResources.initDict(acroForm->doc->getXRef()); + if (resources.dictLookup("Font", &obj1)->isDict()) { + for (i = 0; i < obj1.dictGetLength(); ++i) { + obj1.dictGetValNF(i, &obj2); + fontResources.dictAdd(copyString(obj1.dictGetKey(i)), &obj2); + } + } + obj1.free(); + defaultFont.initDict(acroForm->doc->getXRef()); + defaultFont.dictAdd(copyString("Type"), obj1.initName("Font")); + defaultFont.dictAdd(copyString("Subtype"), obj1.initName("Type1")); + defaultFont.dictAdd(copyString("BaseFont"), obj1.initName("Helvetica")); + defaultFont.dictAdd(copyString("Encoding"), obj1.initName("WinAnsiEncoding")); + fontResources.dictAdd(copyString("xpdf_default_font"), &defaultFont); + resources.dictAdd(copyString("Font"), &fontResources); + if (gfxStateDict.isDict()) { + obj1.initDict(acroForm->doc->getXRef()); + obj1.dictAdd(copyString("GS1"), &gfxStateDict); + resources.dictAdd(copyString("ExtGState"), &obj1); + } + appearDict.dictAdd(copyString("Resources"), &resources); + + // build the appearance stream + appearStream = new MemStream(appearBuf->getCString(), 0, + appearBuf->getLength(), &appearDict); + appearance.initStream(appearStream); + + // draw it + gfx->drawAnnot(&appearance, NULL, xMin, yMin, xMax, yMax); + + appearance.free(); + delete appearBuf; + appearBuf = NULL; + if (fontDict) { + delete fontDict; + } + ftObj.free(); + mkObj.free(); +} + +// Set the current fill or stroke color, based on (which should +// have 1, 3, or 4 elements). If is +1, color is brightened; +// if is -1, color is darkened; otherwise color is not +// modified. +void AcroFormField::setColor(Array *a, GBool fill, int adjust, + GString *appearBuf) { + Object obj1; + double color[4]; + int nComps, i; + + nComps = a->getLength(); + if (nComps > 4) { + nComps = 4; + } + for (i = 0; i < nComps && i < 4; ++i) { + if (a->get(i, &obj1)->isNum()) { + color[i] = obj1.getNum(); + } else { + color[i] = 0; + } + obj1.free(); + } + if (nComps == 4) { + adjust = -adjust; + } + if (adjust > 0) { + for (i = 0; i < nComps; ++i) { + color[i] = 0.5 * color[i] + 0.5; + } + } else if (adjust < 0) { + for (i = 0; i < nComps; ++i) { + color[i] = 0.5 * color[i]; + } + } + if (nComps == 4) { + appearBuf->appendf("{0:.2f} {1:.2f} {2:.2f} {3:.2f} {4:c}\n", + color[0], color[1], color[2], color[3], + fill ? 'k' : 'K'); + } else if (nComps == 3) { + appearBuf->appendf("{0:.2f} {1:.2f} {2:.2f} {3:s}\n", + color[0], color[1], color[2], + fill ? "rg" : "RG"); + } else { + appearBuf->appendf("{0:.2f} {1:c}\n", + color[0], + fill ? 'g' : 'G'); + } +} + +// Draw the variable text or caption for a field. +void AcroFormField::drawText(GString *text, GString *da, GfxFontDict *fontDict, + GBool multiline, int comb, + int quadding, int vAlign, + GBool txField, GBool forceZapfDingbats, int rot, + double x, double y, double width, double height, + double border, GBool whiteBackground, + GString *appearBuf) { + GString *text2; + GList *daToks; + GString *tok; + GfxFont *font; + double dx, dy; + double fontSize, fontSize2, topBorder, xx, xPrev, yy, w, wMax; + double offset, offset2, charWidth, ascent, descent; + int tfPos, tmPos, nLines, i, j, k, c; + + //~ if there is no MK entry, this should use the existing content stream, + //~ 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; + } + if (text2->getLength() == 0) { + if (text2 != text) { + delete text2; + } + return; + } + + // parse the default appearance string + tfPos = tmPos = -1; + if (da) { + daToks = tokenize(da); + for (i = 2; i < daToks->getLength(); ++i) { + if (!((GString *)daToks->get(i))->cmp("Tf")) { + tfPos = i - 2; + } else if (i >= 6 && !((GString *)daToks->get(i))->cmp("Tm")) { + tmPos = i - 6; + } + } + } else { + daToks = NULL; + } + + // force ZapfDingbats + //~ this should create the font if needed (?) + if (forceZapfDingbats) { + if (tfPos >= 0) { + tok = (GString *)daToks->get(tfPos); + if (tok->cmp("/ZaDb")) { + tok->clear(); + tok->append("/ZaDb"); + } + } + } + + // get the font and font size + font = NULL; + fontSize = 0; + if (tfPos >= 0) { + tok = (GString *)daToks->get(tfPos); + if (tok->getLength() >= 1 && tok->getChar(0) == '/') { + if (!fontDict || !(font = fontDict->lookup(tok->getCString() + 1))) { + error(errSyntaxError, -1, "Unknown font in field's DA string"); + tok->clear(); + tok->append("/xpdf_default_font"); + } + } else { + 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(errSyntaxError, -1, "Missing 'Tf' operator in field's DA string"); + fontSize = 0; + if (!daToks) { + daToks = new GList(); + } + tfPos = daToks->getLength(); + daToks->append(new GString("/xpdf_default_font")); + daToks->append(new GString("10")); + daToks->append(new GString("Tf")); + } + + // setup + if (txField) { + appearBuf->append("/Tx BMC\n"); + } + appearBuf->append("q\n"); + if (rot == 90) { + appearBuf->appendf("0 1 -1 0 {0:.4f} 0 cm\n", width); + dx = height; + dy = width; + } else if (rot == 180) { + appearBuf->appendf("-1 0 0 -1 {0:.4f} {1:.4f} cm\n", width, height); + dx = width; + dy = height; + } else if (rot == 270) { + appearBuf->appendf("0 -1 1 0 0 {0:.4f} cm\n", height); + dx = height; + dy = width; + } else { // assume rot == 0 + dx = width; + dy = height; + } + + // multi-line text + if (multiline) { + // note: the comb flag is ignored in multiline mode + + wMax = dx - 2 * border - 4; + +#if 1 //~tmp + // this is a kludge that appears to match Adobe's behavior + if (height > 15) { + topBorder = 5; + } else { + topBorder = 2; + } +#else + topBorder = 5; +#endif + + // compute font autosize + if (fontSize == 0) { + for (fontSize = 10; fontSize > 1; --fontSize) { + yy = dy - topBorder; + i = 0; + while (i < text2->getLength()) { + getNextLine(text2, i, font, fontSize, wMax, &j, &w, &k); + i = k; + yy -= fontSize; + } + // approximate the descender for the last line + if (yy >= 0.25 * fontSize && w <= wMax) { + break; + } + } + if (tfPos >= 0) { + tok = (GString *)daToks->get(tfPos + 1); + tok->clear(); + tok->appendf("{0:.2f}", fontSize); + } + } + + // starting y coordinate + nLines = 0; + i = 0; + while (i < text2->getLength()) { + getNextLine(text2, i, font, fontSize, wMax, &j, &w, &k); + i = k; + ++nLines; + } + if (font) { + ascent = font->getDeclaredAscent() * fontSize; + descent = font->getDescent() * fontSize; + } else { + ascent = 0.75 * fontSize; + descent = -0.25 * fontSize; + } + switch (vAlign) { + case acroFormVAlignTop: + default: + yy = dy - ascent - topBorder; + break; + case acroFormVAlignMiddle: + yy = 0.5 * (dy - nLines * fontSize) + (nLines - 1) * fontSize - descent; + break; + case acroFormVAlignMiddleNoDescender: + yy = 0.5 * (dy - nLines * fontSize) + (nLines - 1) * fontSize; + break; + case acroFormVAlignBottom: + yy = (nLines - 1) * fontSize - descent; + break; + } + // if the field is shorter than a line of text, Acrobat positions + // the text relative to the bottom edge + if (dy < fontSize + topBorder) { + yy = 2 - descent; + } + // each line of text starts with a Td operator that moves down a + // line -- so move up a line here + yy += fontSize; + + appearBuf->append("BT\n"); + + // set the font matrix + if (tmPos >= 0) { + tok = (GString *)daToks->get(tmPos + 4); + tok->clear(); + tok->appendf("{0:.4f}", x); + tok = (GString *)daToks->get(tmPos + 5); + tok->clear(); + tok->appendf("{0:.4f}", y + yy); + } + + // write the DA string + if (daToks) { + for (i = 0; i < daToks->getLength(); ++i) { + appearBuf->append((GString *)daToks->get(i))->append(' '); + } + } + + // write the font matrix (if not part of the DA string) + if (tmPos < 0) { + appearBuf->appendf("1 0 0 1 {0:.4f} {1:.4f} Tm\n", x, y + yy); + } + + // write a series of lines of text + i = 0; + xPrev = 0; + while (i < text2->getLength()) { + + getNextLine(text2, i, font, fontSize, wMax, &j, &w, &k); + + // compute text start position + switch (quadding) { + case acroFormQuadLeft: + default: + xx = border + 2; + break; + case acroFormQuadCenter: + xx = (dx - w) / 2; + break; + case acroFormQuadRight: + xx = dx - border - 2 - w; + break; + } + + // draw the line + appearBuf->appendf("{0:.4f} {1:.4f} Td\n", xx - xPrev, -fontSize); + appearBuf->append('('); + for (; i < j; ++i) { + c = text2->getChar(i) & 0xff; + if (c == '(' || c == ')' || c == '\\') { + appearBuf->append('\\'); + appearBuf->append((char)c); + } else if (c < 0x20 || c >= 0x80) { + appearBuf->appendf("\\{0:03o}", c); + } else { + appearBuf->append((char)c); + } + } + appearBuf->append(") Tj\n"); + + // next line + i = k; + xPrev = xx; + } + + appearBuf->append("ET\n"); + + // single-line text + } else { + //~ replace newlines with spaces? - what does Acrobat do? + + // comb formatting + if (comb > 0) { + + // compute comb spacing + w = dx / comb; + + // compute font autosize + if (fontSize == 0) { + fontSize = dy - 2 * border; + if (w < fontSize) { + fontSize = w; + } + fontSize = floor(fontSize); + if (fontSize > 10) { + fontSize = 10; + } + if (tfPos >= 0) { + tok = (GString *)daToks->get(tfPos + 1); + tok->clear(); + tok->appendf("{0:.4f}", fontSize); + } + } + + // compute text start position + switch (quadding) { + case acroFormQuadLeft: + default: + xx = 0; + break; + case acroFormQuadCenter: + xx = ((comb - text2->getLength()) / 2) * w; + break; + case acroFormQuadRight: + xx = (comb - text2->getLength()) * w; + break; + } + if (font) { + ascent = font->getDeclaredAscent() * fontSize; + descent = font->getDescent() * fontSize; + } else { + ascent = 0.75 * fontSize; + descent = -0.25 * fontSize; + } + switch (vAlign) { + case acroFormVAlignTop: + default: + yy = dy - ascent; + break; + case acroFormVAlignMiddle: + yy = 0.5 * (dy - ascent - descent); + break; + case acroFormVAlignMiddleNoDescender: + yy = 0.5 * (dy - ascent); + break; + case acroFormVAlignBottom: + yy = -descent; + break; + } + + appearBuf->append("BT\n"); + + // set the font matrix + if (tmPos >= 0) { + tok = (GString *)daToks->get(tmPos + 4); + tok->clear(); + tok->appendf("{0:.4f}", x + xx); + tok = (GString *)daToks->get(tmPos + 5); + tok->clear(); + tok->appendf("{0:.4f}", y + yy); + } + + // write the DA string + if (daToks) { + for (i = 0; i < daToks->getLength(); ++i) { + appearBuf->append((GString *)daToks->get(i))->append(' '); + } + } + + // write the font matrix (if not part of the DA string) + if (tmPos < 0) { + appearBuf->appendf("1 0 0 1 {0:.4f} {1:.4f} Tm\n", x + xx, y + yy); + } + + // write the text string + offset = 0; + for (i = 0; i < text2->getLength(); ++i) { + c = text2->getChar(i) & 0xff; + if (c >= 0x20 && c < 0x80) { + if (font && !font->isCIDFont()) { + charWidth = ((Gfx8BitFont *)font)->getWidth((Guchar)c) * fontSize; + } else { + // otherwise, make a crude estimate + charWidth = 0.5 * fontSize; + } + offset2 = 0.5 * (w - charWidth); + appearBuf->appendf("{0:.4f} 0 Td\n", offset + offset2); + if (c == '(' || c == ')' || c == '\\') { + appearBuf->appendf("(\\{0:c}) Tj\n", c); + } else { + appearBuf->appendf("({0:c}) Tj\n", c); + } + offset = w - offset2; + } else { + offset += w; + } + } + + appearBuf->append("ET\n"); + + // regular (non-comb) formatting + } else { + + // compute string width + if (font && !font->isCIDFont()) { + w = 0; + for (i = 0; i < text2->getLength(); ++i) { + w += ((Gfx8BitFont *)font)->getWidth(text2->getChar(i)); + } + } else { + // otherwise, make a crude estimate + w = text2->getLength() * 0.5; + } + + // compute font autosize + if (fontSize == 0) { + fontSize = dy - 2 * border; + fontSize2 = (dx - 4 - 2 * border) / w; + if (fontSize2 < fontSize) { + fontSize = fontSize2; + } + fontSize = floor(fontSize); + if (fontSize > 10) { + fontSize = 10; + } + if (tfPos >= 0) { + tok = (GString *)daToks->get(tfPos + 1); + tok->clear(); + tok->appendf("{0:.4f}", fontSize); + } + } + + // compute text start position + w *= fontSize; + switch (quadding) { + case acroFormQuadLeft: + default: + xx = border + 2; + break; + case acroFormQuadCenter: + xx = (dx - w) / 2; + break; + case acroFormQuadRight: + xx = dx - border - 2 - w; + break; + } + if (font) { + ascent = font->getDeclaredAscent() * fontSize; + descent = font->getDescent() * fontSize; + } else { + ascent = 0.75 * fontSize; + descent = -0.25 * fontSize; + } + switch (vAlign) { + case acroFormVAlignTop: + default: + yy = dy - ascent; + break; + case acroFormVAlignMiddle: + yy = 0.5 * (dy - ascent - descent); + break; + case acroFormVAlignMiddleNoDescender: + yy = 0.5 * (dy - ascent); + break; + case acroFormVAlignBottom: + yy = -descent; + break; + } + + if (whiteBackground) { + appearBuf->appendf("q 1 g {0:.4f} {1:.4f} {2:.4f} {3:.4f} re f Q\n", + xx - 0.25 * fontSize, yy - 0.35 * fontSize, + w + 0.5 * fontSize, 1.2 * fontSize); + } + + appearBuf->append("BT\n"); + + // set the font matrix + if (tmPos >= 0) { + tok = (GString *)daToks->get(tmPos + 4); + tok->clear(); + tok->appendf("{0:.4f}", x + xx); + tok = (GString *)daToks->get(tmPos + 5); + tok->clear(); + tok->appendf("{0:.4f}", y + yy); + } + + // write the DA string + if (daToks) { + for (i = 0; i < daToks->getLength(); ++i) { + appearBuf->append((GString *)daToks->get(i))->append(' '); + } + } + + // write the font matrix (if not part of the DA string) + if (tmPos < 0) { + appearBuf->appendf("1 0 0 1 {0:.4f} {1:.4f} Tm\n", x + xx, y + yy); + } + + // write the text string + appearBuf->append('('); + for (i = 0; i < text2->getLength(); ++i) { + c = text2->getChar(i) & 0xff; + if (c == '(' || c == ')' || c == '\\') { + appearBuf->append('\\'); + appearBuf->append((char)c); + } else if (c < 0x20 || c >= 0x80) { + appearBuf->appendf("\\{0:03o}", c); + } else { + appearBuf->append((char)c); + } + } + appearBuf->append(") Tj\n"); + } + + appearBuf->append("ET\n"); + } + + // cleanup + appearBuf->append("Q\n"); + if (txField) { + appearBuf->append("EMC\n"); + } + + if (daToks) { + deleteGList(daToks, GString); + } + if (text2 != text) { + delete text2; + } +} + +// Draw the variable text or caption for a field. +void AcroFormField::drawListBox(GString **text, GBool *selection, + int nOptions, int topIdx, + GString *da, GfxFontDict *fontDict, + GBool quadding, double xMin, double yMin, + double xMax, double yMax, double border, + GString *appearBuf) { + GList *daToks; + GString *tok; + GfxFont *font; + double fontSize, fontSize2, x, y, w, wMax; + int tfPos, tmPos, i, j, c; + + //~ if there is no MK entry, this should use the existing content stream, + //~ and only replace the marked content portion of it + //~ (this is only relevant for Tx fields) + + // parse the default appearance string + tfPos = tmPos = -1; + if (da) { + daToks = tokenize(da); + for (i = 2; i < daToks->getLength(); ++i) { + if (i >= 2 && !((GString *)daToks->get(i))->cmp("Tf")) { + tfPos = i - 2; + } else if (i >= 6 && !((GString *)daToks->get(i))->cmp("Tm")) { + tmPos = i - 6; + } + } + } else { + daToks = NULL; + } + + // get the font and font size + font = NULL; + fontSize = 0; + if (tfPos >= 0) { + tok = (GString *)daToks->get(tfPos); + if (tok->getLength() >= 1 && tok->getChar(0) == '/') { + if (!fontDict || !(font = fontDict->lookup(tok->getCString() + 1))) { + error(errSyntaxError, -1, "Unknown font in field's DA string"); + tok->clear(); + tok->append("/xpdf_default_font"); + } + } else { + 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(errSyntaxError, -1, "Missing 'Tf' operator in field's DA string"); + } + + // compute font autosize + if (fontSize == 0) { + wMax = 0; + for (i = 0; i < nOptions; ++i) { + if (font && !font->isCIDFont()) { + w = 0; + for (j = 0; j < text[i]->getLength(); ++j) { + w += ((Gfx8BitFont *)font)->getWidth(text[i]->getChar(j)); + } + } else { + // otherwise, make a crude estimate + w = text[i]->getLength() * 0.5; + } + if (w > wMax) { + wMax = w; + } + } + fontSize = yMax - yMin - 2 * border; + fontSize2 = (xMax - xMin - 4 - 2 * border) / wMax; + if (fontSize2 < fontSize) { + fontSize = fontSize2; + } + fontSize = floor(fontSize); + if (fontSize > 10) { + fontSize = 10; + } + if (tfPos >= 0) { + tok = (GString *)daToks->get(tfPos + 1); + tok->clear(); + tok->appendf("{0:.4f}", fontSize); + } + } + + // draw the text + y = yMax - yMin - 1.1 * fontSize; + for (i = topIdx; i < nOptions; ++i) { + + // setup + appearBuf->append("q\n"); + + // draw the background if selected + if (selection[i]) { + appearBuf->append("0 g f\n"); + appearBuf->appendf("{0:.4f} {1:.4f} {2:.4f} {3:.4f} re f\n", + border, + y - 0.2 * fontSize, + xMax - xMin - 2 * border, + 1.1 * fontSize); + } + + // setup + appearBuf->append("BT\n"); + + // compute string width + if (font && !font->isCIDFont()) { + w = 0; + for (j = 0; j < text[i]->getLength(); ++j) { + w += ((Gfx8BitFont *)font)->getWidth(text[i]->getChar(j)); + } + } else { + // otherwise, make a crude estimate + w = text[i]->getLength() * 0.5; + } + + // compute text start position + w *= fontSize; + switch (quadding) { + case acroFormQuadLeft: + default: + x = border + 2; + break; + case acroFormQuadCenter: + x = (xMax - xMin - w) / 2; + break; + case acroFormQuadRight: + x = xMax - xMin - border - 2 - w; + break; + } + + // set the font matrix + if (tmPos >= 0) { + tok = (GString *)daToks->get(tmPos + 4); + tok->clear(); + tok->appendf("{0:.4f}", x); + tok = (GString *)daToks->get(tmPos + 5); + tok->clear(); + tok->appendf("{0:.4f}", y); + } + + // write the DA string + if (daToks) { + for (j = 0; j < daToks->getLength(); ++j) { + appearBuf->append((GString *)daToks->get(j))->append(' '); + } + } + + // write the font matrix (if not part of the DA string) + if (tmPos < 0) { + appearBuf->appendf("1 0 0 1 {0:.4f} {1:.4f} Tm\n", x, y); + } + + // change the text color if selected + if (selection[i]) { + appearBuf->append("1 g\n"); + } + + // write the text string + appearBuf->append('('); + for (j = 0; j < text[i]->getLength(); ++j) { + c = text[i]->getChar(j) & 0xff; + if (c == '(' || c == ')' || c == '\\') { + appearBuf->append('\\'); + appearBuf->append((char)c); + } else if (c < 0x20 || c >= 0x80) { + appearBuf->appendf("\\{0:03o}", c); + } else { + appearBuf->append((char)c); + } + } + appearBuf->append(") Tj\n"); + + // cleanup + appearBuf->append("ET\n"); + appearBuf->append("Q\n"); + + // next line + y -= 1.1 * fontSize; + } + + if (daToks) { + deleteGList(daToks, GString); + } +} + +// Figure out how much text will fit on the next line. Returns: +// *end = one past the last character to be included +// *width = width of the characters start .. end-1 +// *next = index of first character on the following line +void AcroFormField::getNextLine(GString *text, int start, + GfxFont *font, double fontSize, double wMax, + int *end, double *width, int *next) { + double w, dw; + int j, k, c; + + // figure out how much text will fit on the line + //~ what does Adobe do with tabs? + w = 0; + for (j = start; j < text->getLength() && w <= wMax; ++j) { + c = text->getChar(j) & 0xff; + if (c == 0x0a || c == 0x0d) { + break; + } + if (font && !font->isCIDFont()) { + dw = ((Gfx8BitFont *)font)->getWidth((Guchar)c) * fontSize; + } else { + // otherwise, make a crude estimate + dw = 0.5 * fontSize; + } + w += dw; + } + if (w > wMax) { + for (k = j; k > start && text->getChar(k-1) != ' '; --k) ; + for (; k > start && text->getChar(k-1) == ' '; --k) ; + if (k > start) { + j = k; + } + if (j == start) { + // handle the pathological case where the first character is + // too wide to fit on the line all by itself + j = start + 1; + } + } + *end = j; + + // compute the width + w = 0; + for (k = start; k < j; ++k) { + if (font && !font->isCIDFont()) { + dw = ((Gfx8BitFont *)font)->getWidth(text->getChar(k)) * fontSize; + } else { + // otherwise, make a crude estimate + dw = 0.5 * fontSize; + } + w += dw; + } + *width = w; + + // next line + while (j < text->getLength() && text->getChar(j) == ' ') { + ++j; + } + if (j < text->getLength() && text->getChar(j) == 0x0d) { + ++j; + } + if (j < text->getLength() && text->getChar(j) == 0x0a) { + ++j; + } + *next = j; +} + +// Draw an (approximate) circle of radius centered at (, ). +// is used to draw the circle ("f", "s", or "b"). +void AcroFormField::drawCircle(double cx, double cy, double r, + const char *cmd, GString *appearBuf) { + appearBuf->appendf("{0:.4f} {1:.4f} m\n", + cx + r, cy); + appearBuf->appendf("{0:.4f} {1:.4f} {2:.4f} {3:.4f} {4:.4f} {5:.4f} c\n", + cx + r, cy + bezierCircle * r, + cx + bezierCircle * r, cy + r, + cx, cy + r); + appearBuf->appendf("{0:.4f} {1:.4f} {2:.4f} {3:.4f} {4:.4f} {5:.4f} c\n", + cx - bezierCircle * r, cy + r, + cx - r, cy + bezierCircle * r, + cx - r, cy); + appearBuf->appendf("{0:.4f} {1:.4f} {2:.4f} {3:.4f} {4:.4f} {5:.4f} c\n", + cx - r, cy - bezierCircle * r, + cx - bezierCircle * r, cy - r, + cx, cy - r); + appearBuf->appendf("{0:.4f} {1:.4f} {2:.4f} {3:.4f} {4:.4f} {5:.4f} c\n", + cx + bezierCircle * r, cy - r, + cx + r, cy - bezierCircle * r, + cx + r, cy); + appearBuf->appendf("{0:s}\n", cmd); +} + +// Draw the top-left half of an (approximate) circle of radius +// centered at (, ). +void AcroFormField::drawCircleTopLeft(double cx, double cy, double r, + GString *appearBuf) { + double r2; + + r2 = r / sqrt(2.0); + appearBuf->appendf("{0:.4f} {1:.4f} m\n", + cx + r2, cy + r2); + appearBuf->appendf("{0:.4f} {1:.4f} {2:.4f} {3:.4f} {4:.4f} {5:.4f} c\n", + cx + (1 - bezierCircle) * r2, + cy + (1 + bezierCircle) * r2, + cx - (1 - bezierCircle) * r2, + cy + (1 + bezierCircle) * r2, + cx - r2, + cy + r2); + appearBuf->appendf("{0:.4f} {1:.4f} {2:.4f} {3:.4f} {4:.4f} {5:.4f} c\n", + cx - (1 + bezierCircle) * r2, + cy + (1 - bezierCircle) * r2, + cx - (1 + bezierCircle) * r2, + cy - (1 - bezierCircle) * r2, + cx - r2, + cy - r2); + appearBuf->append("S\n"); +} + +// Draw the bottom-right half of an (approximate) circle of radius +// centered at (, ). +void AcroFormField::drawCircleBottomRight(double cx, double cy, double r, + GString *appearBuf) { + double r2; + + r2 = r / sqrt(2.0); + appearBuf->appendf("{0:.4f} {1:.4f} m\n", + cx - r2, cy - r2); + appearBuf->appendf("{0:.4f} {1:.4f} {2:.4f} {3:.4f} {4:.4f} {5:.4f} c\n", + cx - (1 - bezierCircle) * r2, + cy - (1 + bezierCircle) * r2, + cx + (1 - bezierCircle) * r2, + cy - (1 + bezierCircle) * r2, + cx + r2, + cy - r2); + appearBuf->appendf("{0:.4f} {1:.4f} {2:.4f} {3:.4f} {4:.4f} {5:.4f} c\n", + cx + (1 + bezierCircle) * r2, + cy - (1 - bezierCircle) * r2, + cx + (1 + bezierCircle) * r2, + cy + (1 - bezierCircle) * r2, + cx + r2, + cy + r2); + appearBuf->append("S\n"); +} + +void AcroFormField::drawBarcode(GString *value, GString *da, + GfxFontDict *fontDict, int rot, + double xMin, double yMin, + double xMax, double yMax, + XFAFieldBarcodeInfo *barcodeInfo, + GString *appearBuf) { + //--- handle rotation + double w, h; + appearBuf->append("q\n"); + switch (rot) { + case 0: + default: + w = xMax - xMin; + h = yMax - yMin; + break; + case 90: + appearBuf->appendf("0 1 -1 0 {0:.4f} 0 cm\n", xMax - xMin); + w = yMax - yMin; + h = xMax - xMin; + break; + case 180: + appearBuf->appendf("0 -1 1 0 0 {0:.4f} cm\n", yMax - yMin); + w = yMax - yMin; + h = xMax - xMin; + break; + case 270: + appearBuf->appendf("0 -1 1 0 0 {0:.4f} cm\n", yMax - yMin); + w = yMax - yMin; + h = xMax - xMin; + break; + } + + //--- get the font size + double fontSize = 0.2 * h; + if (da) { + GList *daToks = tokenize(da); + for (int i = 2; i < daToks->getLength(); ++i) { + if (!((GString *)daToks->get(i))->cmp("Tf")) { + fontSize = atof(((GString *)daToks->get(i - 1))->getCString()); + break; + } + } + deleteGList(daToks, GString); + } + + //--- compute the embedded text type position + GBool doText = gTrue; + double yText = 0; + int vAlign = acroFormVAlignTop; + double yBarcode = 0; + double hBarcode = 0; + GBool whiteBackground = gFalse; + //~ this uses an estimate of the font baseline position + if (barcodeInfo->textLocation && + !barcodeInfo->textLocation->cmp("above")) { + yText = h; + vAlign = acroFormVAlignTop; + yBarcode = 0; + hBarcode = h - fontSize; + } else if (barcodeInfo->textLocation && + !barcodeInfo->textLocation->cmp("belowEmbedded")) { + yText = 0; + vAlign = acroFormVAlignBottom; + yBarcode = 0; + hBarcode = h; + whiteBackground = gTrue; + } else if (barcodeInfo->textLocation && + !barcodeInfo->textLocation->cmp("aboveEmbedded")) { + yText = h; + vAlign = acroFormVAlignTop; + yBarcode = 0; + hBarcode = h; + whiteBackground = gTrue; + } else if (barcodeInfo->textLocation && + !barcodeInfo->textLocation->cmp("none")) { + doText = gFalse; + } else { // default is "below" + yText = 0; + vAlign = acroFormVAlignBottom; + yBarcode = fontSize; + hBarcode = h - fontSize; + } + double wText = w; + + //--- remove extraneous start/stop chars + GString *value2 = value->copy(); + if (!barcodeInfo->barcodeType->cmp("code3Of9")) { + if (value2->getLength() >= 1 && value2->getChar(0) == '*') { + value2->del(0); + } + if (value2->getLength() >= 1 && + value2->getChar(value2->getLength() - 1) == '*') { + value2->del(value2->getLength() - 1); + } + } + + //--- draw the bar code + if (!barcodeInfo->barcodeType->cmp("code3Of9")) { + if (!barcodeInfo->dataLength) { + error(errSyntaxError, -1, + "Missing 'dataLength' attribute in barcode field"); + goto err; + } + appearBuf->append("0 g\n"); + double wNarrow = w / ((7 + 3 * barcodeInfo->wideNarrowRatio) + * (barcodeInfo->dataLength + 2)); + double xx = 0; + for (int i = -1; i <= value2->getLength(); ++i) { + int c; + if (i < 0 || i >= value2->getLength()) { + c = '*'; + } else { + c = value2->getChar(i) & 0x7f; + } + for (int j = 0; j < 10; j += 2) { + appearBuf->appendf("{0:.4f} {1:.4f} {2:.4f} {3:.4f} re f\n", + xx, yBarcode, + (code3Of9Data[c][j] ? barcodeInfo->wideNarrowRatio + : 1) * wNarrow, + hBarcode); + xx += ((code3Of9Data[c][j] ? barcodeInfo->wideNarrowRatio : 1) + + (code3Of9Data[c][j+1] ? barcodeInfo->wideNarrowRatio : 1)) + * wNarrow; + } + } + // center the text on the drawn barcode (not the max length barcode) + wText = (value2->getLength() + 2) * (7 + 3 * barcodeInfo->wideNarrowRatio) + * wNarrow; + } else if (!barcodeInfo->barcodeType->cmp("code128B")) { + if (!barcodeInfo->dataLength) { + error(errSyntaxError, -1, + "Missing 'dataLength' attribute in barcode field"); + goto err; + } + appearBuf->append("0 g\n"); + double wNarrow = w / (11 * (barcodeInfo->dataLength + 3) + 2); + double xx = 0; + int checksum = 0; + for (int i = -1; i <= value2->getLength() + 1; ++i) { + int c; + if (i == -1) { + // start code B + c = 104; + checksum += c; + } else if (i == value2->getLength()) { + // checksum + c = checksum % 103; + } else if (i == value2->getLength() + 1) { + // stop code + c = 106; + } else { + c = value2->getChar(i) & 0xff; + if (c >= 32 && c <= 127) { + c -= 32; + } else { + c = 0; + } + checksum += (i + 1) * c; + } + for (int j = 0; j < 6; j += 2) { + appearBuf->appendf("{0:.4f} {1:.4f} {2:.4f} {3:.4f} re f\n", + xx, yBarcode, + code128Data[c][j] * wNarrow, hBarcode); + xx += (code128Data[c][j] + code128Data[c][j+1]) * wNarrow; + } + } + // final bar of the stop code + appearBuf->appendf("{0:.4f} {1:.4f} {2:.4f} {3:.4f} re f\n", + xx, yBarcode, 2 * wNarrow, hBarcode); + // center the text on the drawn barcode (not the max length barcode) + wText = (11 * (value2->getLength() + 3) + 2) * wNarrow; + } else if (!barcodeInfo->barcodeType->cmp("pdf417")) { + drawPDF417Barcode(w, h, barcodeInfo->moduleWidth, + barcodeInfo->moduleHeight, + barcodeInfo->errorCorrectionLevel, + value2, appearBuf); + doText = gFalse; + } else { + error(errSyntaxError, -1, + "Unimplemented barcode type '{0:t}' in barcode field", + barcodeInfo->barcodeType); + } + //~ add other barcode types here + + //--- draw the embedded text + if (doText) { + drawText(value2, da, fontDict, gFalse, 0, acroFormQuadCenter, + vAlign, gFalse, gFalse, 0, 0, yText, wText, yText + fontSize, + 0, whiteBackground, appearBuf); + } + + appearBuf->append("Q\n"); + + err: + delete value2; +} + +GList *AcroFormField::tokenize(GString *s) { + GList *toks; + int i, j; + + toks = new GList(); + i = 0; + while (i < s->getLength()) { + while (i < s->getLength() && Lexer::isSpace(s->getChar(i))) { + ++i; + } + if (i < s->getLength()) { + for (j = i + 1; + j < s->getLength() && !Lexer::isSpace(s->getChar(j)); + ++j) ; + toks->append(new GString(s, i, j - i)); + i = j; + } + } + return toks; +} + +Object *AcroFormField::getResources(Object *res) { + Object kidsObj, annotObj, obj1; + int i; + + if (acroForm->needAppearances) { + fieldLookup("DR", res); + } else { + res->initArray(acroForm->doc->getXRef()); + // find the annotation object(s) + if (fieldObj.dictLookup("Kids", &kidsObj)->isArray()) { + for (i = 0; i < kidsObj.arrayGetLength(); ++i) { + kidsObj.arrayGet(i, &annotObj); + if (annotObj.isDict()) { + if (getAnnotResources(annotObj.getDict(), &obj1)->isDict()) { + res->arrayAdd(&obj1); + } else { + obj1.free(); + } + } + annotObj.free(); + } + } else { + if (getAnnotResources(fieldObj.getDict(), &obj1)->isDict()) { + res->arrayAdd(&obj1); + } else { + obj1.free(); + } + } + kidsObj.free(); + } + + return res; +} + +Object *AcroFormField::getFieldRef(Object *ref) { + return fieldRef.copy(ref); +} + +Object *AcroFormField::getValueObj(Object *val) { + return fieldLookup("V", val); +} + +Object *AcroFormField::getParentRef(Object *parent) { + return fieldObj.dictLookupNF("Parent", parent); +} + +// Get the first annotation object associated with this field. +Object *AcroFormField::getAnnotObj(Object *annotObj) { + Object kidsObj; + + if (fieldObj.dictLookup("Kids", &kidsObj)->isArray()) { + if (kidsObj.arrayGetLength() > 0) { + kidsObj.arrayGet(0, annotObj); + } else { + annotObj->initNull(); + } + } else { + fieldObj.copy(annotObj); + } + kidsObj.free(); + return annotObj; +} + +Object *AcroFormField::getAnnotResources(Dict *annot, Object *res) { + Object apObj, asObj, appearance, obj1; + + // get the appearance stream + if (annot->lookup("AP", &apObj)->isDict()) { + apObj.dictLookup("N", &obj1); + if (obj1.isDict()) { + if (annot->lookup("AS", &asObj)->isName()) { + obj1.dictLookup(asObj.getName(), &appearance); + } else if (obj1.dictGetLength() == 1) { + obj1.dictGetVal(0, &appearance); + } else { + obj1.dictLookup("Off", &appearance); + } + asObj.free(); + } else { + obj1.copy(&appearance); + } + obj1.free(); + } + apObj.free(); + + if (appearance.isStream()) { + appearance.streamGetDict()->lookup("Resources", res); + } else { + res->initNull(); + } + appearance.free(); + + return res; +} + +// Merge the field and AcroForm DR objects. +void AcroFormField::buildDefaultResourceDict(Object *dr) { + Object formDR, fieldDR, resDict, newResDict, resObj; + char *resType, *resName; + int i, j; + + // NB: we need to deep-copy the dictionaries here, because multiple + // threads can be sharing these objects. + + dr->initDict(acroForm->doc->getXRef()); + + acroForm->acroFormObj.dictLookup("DR", &formDR); + if (formDR.isDict()) { + for (i = 0; i < formDR.dictGetLength(); ++i) { + resType = formDR.dictGetKey(i); + formDR.dictGetVal(i, &resDict); + if (resDict.isDict()) { + newResDict.initDict(acroForm->doc->getXRef()); + dr->dictAdd(copyString(resType), &newResDict); + for (j = 0; j < resDict.dictGetLength(); ++j) { + resName = resDict.dictGetKey(j); + resDict.dictGetValNF(j, &resObj); + newResDict.dictAdd(copyString(resName), &resObj); + } + } + resDict.free(); + } + } + formDR.free(); + + fieldObj.dictLookup("DR", &fieldDR); + if (fieldDR.isDict()) { + for (i = 0; i < fieldDR.dictGetLength(); ++i) { + resType = fieldDR.dictGetKey(i); + fieldDR.dictGetVal(i, &resDict); + if (resDict.isDict()) { + dr->dictLookup(resType, &newResDict); + if (!newResDict.isDict()) { + newResDict.free(); + newResDict.initDict(acroForm->doc->getXRef()); + } + dr->dictAdd(copyString(resType), &newResDict); + for (j = 0; j < resDict.dictGetLength(); ++j) { + resName = resDict.dictGetKey(j); + resDict.dictGetValNF(j, &resObj); + newResDict.dictAdd(copyString(resName), &resObj); + } + } + resDict.free(); + } + } + fieldDR.free(); +} + +// Look up an inheritable field dictionary entry. +Object *AcroFormField::fieldLookup(const char *key, Object *obj) { + return fieldLookup(fieldObj.getDict(), key, obj); +} + +Object *AcroFormField::fieldLookup(Dict *dict, const char *key, Object *obj) { + Object parent, parent2; + int depth; + + if (!dict->lookup(key, obj)->isNull()) { + return obj; + } + obj->free(); + + dict->lookup("Parent", &parent)->isDict(); + depth = 0; + while (parent.isDict() && depth < maxFieldObjectDepth) { + if (!parent.dictLookup(key, obj)->isNull()) { + parent.free(); + return obj; + } + obj->free(); + parent.dictLookup("Parent", &parent2); + parent.free(); + parent = parent2; + ++depth; + } + parent.free(); + + // some fields don't specify a parent, so we check the AcroForm + // dictionary just in case + acroForm->acroFormObj.dictLookup(key, obj); + return obj; +} + +Unicode *AcroFormField::utf8ToUnicode(GString *s, int *unicodeLength) { + int n = 0; + int i = 0; + Unicode u; + while (getUTF8(s, &i, &u)) { + ++n; + } + Unicode *uVec = (Unicode *)gmallocn(n, sizeof(Unicode)); + n = 0; + i = 0; + while (getUTF8(s, &i, &uVec[n])) { + ++n; + } + *unicodeLength = n; + return uVec; +} + +GString *AcroFormField::unicodeToLatin1(Unicode *u, int unicodeLength) { + GString *s = new GString(); + for (int i = 0; i < unicodeLength; ++i) { + if (u[i] <= 0xff) { + s->append((char)u[i]); + } + } + return s; +} + +GBool AcroFormField::unicodeStringEqual(Unicode *u, int unicodeLength, + GString *s) { + if (s->getLength() != unicodeLength) { + return gFalse; + } + for (int i = 0; i < unicodeLength; ++i) { + if ((s->getChar(i) & 0xff) != u[i]) { + return gFalse; + } + } + return gTrue; +} + +GBool AcroFormField::unicodeStringEqual(Unicode *u, int unicodeLength, + const char *s) { + for (int i = 0; i < unicodeLength; ++i) { + if (!s[i] || (s[i] & 0xff) != u[i]) { + return gFalse; + } + } + return gTrue; +} + +//------------------------------------------------------------------------ +// 'picture' formatting +//------------------------------------------------------------------------ + +class PictureNode { +public: + virtual ~PictureNode() {} + virtual GBool isLiteral() { return gFalse; } + virtual GBool isSign() { return gFalse; } + virtual GBool isDigit() { return gFalse; } + virtual GBool isDecPt() { return gFalse; } + virtual GBool isSeparator() { return gFalse; } + virtual GBool isYear() { return gFalse; } + virtual GBool isMonth() { return gFalse; } + virtual GBool isDay() { return gFalse; } + virtual GBool isHour() { return gFalse; } + virtual GBool isMinute() { return gFalse; } + virtual GBool isSecond() { return gFalse; } + virtual GBool isChar() { return gFalse; } +}; + +class PictureLiteral: public PictureNode { +public: + PictureLiteral(GString *sA) { s = sA; } + virtual ~PictureLiteral() { delete s; } + virtual GBool isLiteral() { return gTrue; } + GString *s; +}; + +class PictureSign: public PictureNode { +public: + PictureSign(char cA) { c = cA; } + virtual GBool isSign() { return gTrue; } + char c; +}; + +class PictureDigit: public PictureNode { +public: + PictureDigit(char cA) { c = cA; pos = 0; } + virtual GBool isDigit() { return gTrue; } + char c; + int pos; +}; + +class PictureDecPt: public PictureNode { +public: + PictureDecPt() { } + virtual GBool isDecPt() { return gTrue; } +}; + +class PictureSeparator: public PictureNode { +public: + PictureSeparator() { } + virtual GBool isSeparator() { return gTrue; } +}; + +class PictureYear: public PictureNode { +public: + PictureYear(int nDigitsA) { nDigits = nDigitsA; } + virtual GBool isYear() { return gTrue; } + int nDigits; +}; + +class PictureMonth: public PictureNode { +public: + PictureMonth(int nDigitsA) { nDigits = nDigitsA; } + virtual GBool isMonth() { return gTrue; } + int nDigits; +}; + +class PictureDay: public PictureNode { +public: + PictureDay(int nDigitsA) { nDigits = nDigitsA; } + virtual GBool isDay() { return gTrue; } + int nDigits; +}; + +class PictureHour: public PictureNode { +public: + PictureHour(GBool is24HourA, int nDigitsA) + { is24Hour = is24HourA; nDigits = nDigitsA; } + virtual GBool isHour() { return gTrue; } + GBool is24Hour; + int nDigits; +}; + +class PictureMinute: public PictureNode { +public: + PictureMinute(int nDigitsA) { nDigits = nDigitsA; } + virtual GBool isMinute() { return gTrue; } + int nDigits; +}; + +class PictureSecond: public PictureNode { +public: + PictureSecond(int nDigitsA) { nDigits = nDigitsA; } + virtual GBool isSecond() { return gTrue; } + int nDigits; +}; + +class PictureChar: public PictureNode { +public: + PictureChar() {} + virtual GBool isChar() { return gTrue; } +}; + +GString *AcroFormField::pictureFormatDateTime(GString *value, + GString *picture) { + GList *pic; + PictureNode *node; + GString *ret, *s; + char c; + int year, month, day, hour, min, sec; + int len, picStart, picEnd, u, n, i, j; + + len = value->getLength(); + if (len == 0) { + return value->copy(); + } + + //--- parse the value + + // expected format is yyyy(-mm(-dd)?)?Thh(:mm(:ss)?)? + // where: + // - the '-'s and ':'s are optional + // - the 'T' is literal + // - we're ignoring optional time zone info at the end + // (if the value is not in this canonical format, we just punt and + // return the value string) + //~ another option would be to parse the value following the + //~ element + year = month = day = hour = min = sec = 0; + i = 0; + if (!(i + 4 <= len && isValidInt(value, i, 4))) { + return value->copy(); + } + year = convertInt(value, i, 4); + i += 4; + if (i < len && value->getChar(i) == '-') { + ++i; + } + if (i + 2 <= len && isValidInt(value, i, 2)) { + month = convertInt(value, i, 2); + i += 2; + if (i < len && value->getChar(i) == '-') { + ++i; + } + if (i + 2 <= len && isValidInt(value, i, 2)) { + day = convertInt(value, i, 2); + i += 2; + } + } + if (i < len) { + if (value->getChar(i) != 'T') { + return value->copy(); + } + ++i; + if (!(i + 2 <= len && isValidInt(value, i, 2))) { + return value->copy(); + } + hour = convertInt(value, i, 2); + i += 2; + if (i < len && value->getChar(i) == ':') { + ++i; + } + if (i + 2 <= len && isValidInt(value, i, 2)) { + min = convertInt(value, i, 2); + i += 2; + if (i < len && value->getChar(i) == ':') { + ++i; + } + if (i + 2 <= len && isValidInt(value, i, 2)) { + sec = convertInt(value, i, 2); + i += 2; + } + } + } + if (i < len) { + return value->copy(); + } + + //--- skip the category and locale in the picture + + picStart = 0; + picEnd = picture->getLength(); + for (i = 0; i < picture->getLength(); ++i) { + c = picture->getChar(i); + if (c == '{') { + picStart = i + 1; + for (picEnd = picStart; + picEnd < picture->getLength() && picture->getChar(picEnd) != '}'; + ++picEnd) ; + break; + } else if (!((c >= 'a' && c <= 'z') || + (c >= 'A' && c <= 'Z') || + c == '(' || + c == ')')) { + break; + } + } + + //--- parse the picture + + pic = new GList(); + i = picStart; + while (i < picEnd) { + c = picture->getChar(i); + ++i; + if (c == '\'') { + s = new GString(); + while (i < picEnd) { + c = picture->getChar(i); + if (c == '\'') { + ++i; + if (i < picEnd && picture->getChar(i) == '\'') { + s->append('\''); + ++i; + } else { + break; + } + } else if (c == '\\') { + ++i; + if (i == picEnd) { + break; + } + c = picture->getChar(i); + ++i; + if (c == 'u' && i+4 <= picEnd) { + u = 0; + for (j = 0; j < 4; ++j, ++i) { + c = picture->getChar(i); + u <<= 4; + if (c >= '0' && c <= '9') { + u += c - '0'; + } else if (c >= 'a' && c <= 'f') { + u += c - 'a' + 10; + } else if (c >= 'A' && c <= 'F') { + u += c - 'A' + 10; + } + } + //~ this should convert to UTF-8 (?) + if (u <= 0xff) { + s->append((char)u); + } + } else { + s->append(c); + } + } else { + s->append(c); + } + } + pic->append(new PictureLiteral(s)); + } else if (c == ',' || c == '-' || c == ':' || + c == '/' || c == '.' || c == ' ') { + s = new GString(); + s->append(c); + pic->append(new PictureLiteral(s)); + } else if (c == 'Y') { + for (n = 1; n < 4 && i < picEnd && picture->getChar(i) == 'Y'; ++n, ++i) ; + pic->append(new PictureYear(n)); + } else if (c == 'M') { + for (n = 1; n < 2 && i < picEnd && picture->getChar(i) == 'M'; ++n, ++i) ; + pic->append(new PictureMonth(n)); + } else if (c == 'D') { + for (n = 1; n < 2 && i < picEnd && picture->getChar(i) == 'D'; ++n, ++i) ; + pic->append(new PictureDay(n)); + } else if (c == 'h') { + for (n = 1; n < 2 && i < picEnd && picture->getChar(i) == 'h'; ++n, ++i) ; + pic->append(new PictureHour(gFalse, n)); + } else if (c == 'H') { + for (n = 1; n < 2 && i < picEnd && picture->getChar(i) == 'H'; ++n, ++i) ; + pic->append(new PictureHour(gTrue, n)); + } else if (c == 'M') { + for (n = 1; n < 2 && i < picEnd && picture->getChar(i) == 'M'; ++n, ++i) ; + pic->append(new PictureMinute(n)); + } else if (c == 'S') { + for (n = 1; n < 2 && i < picEnd && picture->getChar(i) == 'S'; ++n, ++i) ; + pic->append(new PictureSecond(n)); + } + } + + //--- generate formatted text + + ret = new GString(); + for (i = 0; i < pic->getLength(); ++i) { + node = (PictureNode *)pic->get(i); + if (node->isLiteral()) { + ret->append(((PictureLiteral *)node)->s); + } else if (node->isYear()) { + if (((PictureYear *)node)->nDigits == 2) { + if (year >= 1930 && year < 2030) { + ret->appendf("{0:02d}", year % 100); + } else { + ret->append("??"); + } + } else { + ret->appendf("{0:04d}", year); + } + } else if (node->isMonth()) { + if (((PictureMonth *)node)->nDigits == 1) { + ret->appendf("{0:d}", month); + } else { + ret->appendf("{0:02d}", month); + } + } else if (node->isDay()) { + if (((PictureDay *)node)->nDigits == 1) { + ret->appendf("{0:d}", day); + } else { + ret->appendf("{0:02d}", day); + } + } else if (node->isHour()) { + if (((PictureHour *)node)->is24Hour) { + n = hour; + } else { + n = hour % 12; + if (n == 0) { + n = 12; + } + } + if (((PictureHour *)node)->nDigits == 1) { + ret->appendf("{0:d}", n); + } else { + ret->appendf("{0:02d}", n); + } + } else if (node->isMinute()) { + if (((PictureMinute *)node)->nDigits == 1) { + ret->appendf("{0:d}", min); + } else { + ret->appendf("{0:02d}", min); + } + } else if (node->isSecond()) { + if (((PictureSecond *)node)->nDigits == 1) { + ret->appendf("{0:d}", sec); + } else { + ret->appendf("{0:02d}", sec); + } + } + } + deleteGList(pic, PictureNode); + + return ret; +} + +GString *AcroFormField::pictureFormatNumber(GString *value, GString *picture) { + GList *pic; + PictureNode *node; + GString *ret, *s; + GBool neg, haveDigits; + char c; + int start, decPt, trailingZero, len; + int picStart, picEnd, u, pos, i, j; + + len = value->getLength(); + if (len == 0) { + return value->copy(); + } + + //--- parse the value + + // -nnnn.nnnn0000 + // ^ ^ ^ ^ + // | | | +-- len + // | | +------ trailingZero + // | +----------- decPt + // +--------------- start + start = 0; + neg = gFalse; + if (value->getChar(start) == '-') { + neg = gTrue; + ++start; + } else if (value->getChar(start) == '+') { + ++start; + } + for (decPt = start; decPt < len && value->getChar(decPt) != '.'; ++decPt) ; + for (trailingZero = len; + trailingZero > decPt && value->getChar(trailingZero - 1) == '0'; + --trailingZero) ; + + //--- skip the category and locale in the picture + + picStart = 0; + picEnd = picture->getLength(); + for (i = 0; i < picture->getLength(); ++i) { + c = picture->getChar(i); + if (c == '{') { + picStart = i + 1; + for (picEnd = picStart; + picEnd < picture->getLength() && picture->getChar(picEnd) != '}'; + ++picEnd) ; + break; + } else if (!((c >= 'a' && c <= 'z') || + (c >= 'A' && c <= 'Z') || + c == '(' || + c == ')')) { + break; + } + } + + //--- parse the picture + + pic = new GList(); + i = picStart; + while (i < picEnd) { + c = picture->getChar(i); + ++i; + if (c == '\'') { + s = new GString(); + while (i < picEnd) { + c = picture->getChar(i); + if (c == '\'') { + ++i; + if (i < picEnd && picture->getChar(i) == '\'') { + s->append('\''); + ++i; + } else { + break; + } + } else if (c == '\\') { + ++i; + if (i == picEnd) { + break; + } + c = picture->getChar(i); + ++i; + if (c == 'u' && i+4 <= picEnd) { + u = 0; + for (j = 0; j < 4; ++j, ++i) { + c = picture->getChar(i); + u <<= 4; + if (c >= '0' && c <= '9') { + u += c - '0'; + } else if (c >= 'a' && c <= 'F') { + u += c - 'a' + 10; + } else if (c >= 'A' && c <= 'F') { + u += c - 'A' + 10; + } + } + //~ this should convert to UTF-8 (?) + if (u <= 0xff) { + s->append((char)u); + } + } else { + s->append(c); + } + } else { + s->append(c); + ++i; + } + } + pic->append(new PictureLiteral(s)); + } else if (c == '-' || c == ':' || c == '/' || c == ' ') { + s = new GString(); + s->append(c); + pic->append(new PictureLiteral(s)); + } else if (c == 's' || c == 'S') { + pic->append(new PictureSign(c)); + } else if (c == 'Z' || c == 'z' || c == '8' || c == '9') { + pic->append(new PictureDigit(c)); + } else if (c == '.') { + pic->append(new PictureDecPt()); + } else if (c == ',') { + pic->append(new PictureSeparator()); + } + } + for (i = 0; i < pic->getLength(); ++i) { + node = (PictureNode *)pic->get(i); + if (node->isDecPt()) { + break; + } + } + pos = 0; + for (j = i - 1; j >= 0; --j) { + node = (PictureNode *)pic->get(j); + if (node->isDigit()) { + ((PictureDigit *)node)->pos = pos; + ++pos; + } + } + pos = -1; + for (j = i + 1; j < pic->getLength(); ++j) { + node = (PictureNode *)pic->get(j); + if (node->isDigit()) { + ((PictureDigit *)node)->pos = pos; + --pos; + } + } + + //--- generate formatted text + + ret = new GString(); + haveDigits = gFalse; + for (i = 0; i < pic->getLength(); ++i) { + node = (PictureNode *)pic->get(i); + if (node->isLiteral()) { + ret->append(((PictureLiteral *)node)->s); + } else if (node->isSign()) { + if (((PictureSign *)node)->c == 'S') { + ret->append(neg ? '-' : ' '); + } else { + if (neg) { + ret->append('-'); + } + } + } else if (node->isDigit()) { + pos = ((PictureDigit *)node)->pos; + c = ((PictureDigit *)node)->c; + if (pos >= 0 && pos < decPt - start) { + ret->append(value->getChar(decPt - 1 - pos)); + haveDigits = gTrue; + } else if (pos < 0 && -pos <= trailingZero - decPt - 1) { + ret->append(value->getChar(decPt - pos)); + haveDigits = gTrue; + } else if (c == '8' && + pos < 0 && + -pos <= len - decPt - 1) { + ret->append('0'); + haveDigits = gTrue; + } else if (c == '9') { + ret->append('0'); + haveDigits = gTrue; + } else if (c == 'Z' && pos >= 0) { + ret->append(' '); + } + } else if (node->isDecPt()) { + if (!(i+1 < pic->getLength() && + ((PictureNode *)pic->get(i+1))->isDigit() && + ((PictureDigit *)pic->get(i+1))->c == 'z') || + trailingZero > decPt + 1) { + ret->append('.'); + } + } else if (node->isSeparator()) { + if (haveDigits) { + ret->append(','); + } + } + } + deleteGList(pic, PictureNode); + + return ret; +} + +GString *AcroFormField::pictureFormatText(GString *value, GString *picture) { + GList *pic; + PictureNode *node; + GString *ret, *s; + char c; + int len, picStart, picEnd, u, i, j; + + len = value->getLength(); + if (len == 0) { + return value->copy(); + } + + //--- skip the category and locale in the picture + + picStart = 0; + picEnd = picture->getLength(); + for (i = 0; i < picture->getLength(); ++i) { + c = picture->getChar(i); + if (c == '{') { + picStart = i + 1; + for (picEnd = picStart; + picEnd < picture->getLength() && picture->getChar(picEnd) != '}'; + ++picEnd) ; + break; + } else if (!((c >= 'a' && c <= 'z') || + (c >= 'A' && c <= 'Z') || + c == '(' || + c == ')')) { + break; + } + } + + //--- parse the picture + + pic = new GList(); + i = picStart; + while (i < picEnd) { + c = picture->getChar(i); + ++i; + if (c == '\'') { + s = new GString(); + while (i < picEnd) { + c = picture->getChar(i); + if (c == '\'') { + ++i; + if (i < picEnd && picture->getChar(i) == '\'') { + s->append('\''); + ++i; + } else { + break; + } + } else if (c == '\\') { + ++i; + if (i == picEnd) { + break; + } + c = picture->getChar(i); + ++i; + if (c == 'u' && i+4 <= picEnd) { + u = 0; + for (j = 0; j < 4; ++j, ++i) { + c = picture->getChar(i); + u <<= 4; + if (c >= '0' && c <= '9') { + u += c - '0'; + } else if (c >= 'a' && c <= 'F') { + u += c - 'a' + 10; + } else if (c >= 'A' && c <= 'F') { + u += c - 'A' + 10; + } + } + //~ this should convert to UTF-8 (?) + if (u <= 0xff) { + s->append((char)u); + } + } else { + s->append(c); + } + } else { + s->append(c); + ++i; + } + } + pic->append(new PictureLiteral(s)); + } else if (c == ',' || c == '-' || c == ':' || + c == '/' || c == '.' || c == ' ') { + s = new GString(); + s->append(c); + pic->append(new PictureLiteral(s)); + } else if (c == 'A' || c == 'X' || c == 'O' || c == '0' || c == '9') { + pic->append(new PictureChar()); + } + } + + //--- generate formatted text + + ret = new GString(); + j = 0; + for (i = 0; i < pic->getLength(); ++i) { + node = (PictureNode *)pic->get(i); + if (node->isLiteral()) { + ret->append(((PictureLiteral *)node)->s); + } else if (node->isChar()) { + // if there are more chars in the picture than in the value, + // Adobe renders the value as-is, without picture formatting + if (j >= value->getLength()) { + delete ret; + ret = value->copy(); + break; + } + ret->append(value->getChar(j)); + ++j; + } + } + deleteGList(pic, PictureNode); + + return ret; +} + +GBool AcroFormField::isValidInt(GString *s, int start, int len) { + int i; + + for (i = 0; i < len; ++i) { + if (!(start + i < s->getLength() && + s->getChar(start + i) >= '0' && + s->getChar(start + i) <= '9')) { + return gFalse; + } + } + return gTrue; +} + +int AcroFormField::convertInt(GString *s, int start, int len) { + char c; + int x, i; + + x = 0; + for (i = 0; i < len && start + i < s->getLength(); ++i) { + c = s->getChar(start + i); + if (c < '0' || c > '9') { + break; + } + x = x * 10 + (c - '0'); + } + return x; +} diff --git a/xpdf/AcroForm.h b/xpdf/AcroForm.h new file mode 100644 index 0000000..7678d46 --- /dev/null +++ b/xpdf/AcroForm.h @@ -0,0 +1,169 @@ +//======================================================================== +// +// AcroForm.h +// +// Copyright 2012 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef ACROFORM_H +#define ACROFORM_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +class TextString; +class Gfx; +class GfxFont; +class GfxFontDict; +class AcroFormField; +class XFAScanner; +class XFAField; +class XFAFieldBarcodeInfo; + +//------------------------------------------------------------------------ + +class AcroForm { +public: + + static AcroForm *load(PDFDoc *docA, Catalog *catalog, Object *acroFormObjA); + + ~AcroForm(); + + const char *getType(); + + void draw(int pageNum, Gfx *gfx, GBool printing); + + int getNumFields(); + AcroFormField *getField(int idx); + AcroFormField *findField(int pg, double x, double y); + int findFieldIdx(int pg, double x, double y); + +private: + + AcroForm(PDFDoc *docA, Object *acroFormObjA); + void buildAnnotPageList(Catalog *catalog); + int lookupAnnotPage(Object *annotRef); + void scanField(Object *fieldRef); + + PDFDoc *doc; + Object acroFormObj; + GBool needAppearances; + GList *annotPages; // [AcroFormAnnotPage] + GList *fields; // [AcroFormField] + XFAScanner *xfaScanner; + GBool isStaticXFA; + + friend class AcroFormField; +}; + +//------------------------------------------------------------------------ + +enum AcroFormFieldType { + acroFormFieldPushbutton, + acroFormFieldRadioButton, + acroFormFieldCheckbox, + acroFormFieldFileSelect, + acroFormFieldMultilineText, + acroFormFieldText, + acroFormFieldBarcode, + acroFormFieldComboBox, + acroFormFieldListBox, + acroFormFieldSignature +}; + +class AcroFormField { +public: + + static AcroFormField *load(AcroForm *acroFormA, Object *fieldRefA); + + ~AcroFormField(); + + int getPageNum(); + const char *getType(); + Unicode *getName(int *length); + Unicode *getValue(int *length); + void getBBox(double *llx, double *lly, double *urx, double *ury); + void getFont(Ref *fontID, double *fontSize); + void getColor(double *red, double *green, double *blue); + int getMaxLen(); + + Object *getResources(Object *res); + + AcroFormFieldType getAcroFormFieldType() { return type; } + Object *getFieldRef(Object *ref); + Object *getValueObj(Object *val); + Object *getParentRef(Object *parent); + GBool getTypeFromParent() { return typeFromParent; } + +private: + + AcroFormField(AcroForm *acroFormA, Object *fieldRefA, Object *fieldObjA, + AcroFormFieldType typeA, TextString *nameA, + Guint flagsA, GBool typeFromParentA, XFAField *xfaFieldA); + Ref findFontName(char *fontTag); + void draw(int pageNum, Gfx *gfx, GBool printing); + void drawAnnot(int pageNum, Gfx *gfx, GBool printing, + Object *annotRef, Object *annotObj); + void drawExistingAppearance(Gfx *gfx, Dict *annot, + double xMin, double yMin, + double xMax, double yMax); + void drawNewAppearance(Gfx *gfx, Dict *annot, + double xMin, double yMin, + double xMax, double yMax); + void setColor(Array *a, GBool fill, int adjust, GString *appearBuf); + void drawText(GString *text, GString *da, GfxFontDict *fontDict, + GBool multiline, int comb, int quadding, int vAlign, + GBool txField, GBool forceZapfDingbats, int rot, + double x, double y, double width, double height, + double border, GBool whiteBackground, GString *appearBuf); + void drawListBox(GString **text, GBool *selection, + int nOptions, int topIdx, + GString *da, GfxFontDict *fontDict, + GBool quadding, double xMin, double yMin, + double xMax, double yMax, double border, + GString *appearBuf); + void getNextLine(GString *text, int start, + GfxFont *font, double fontSize, double wMax, + int *end, double *width, int *next); + void drawCircle(double cx, double cy, double r, const char *cmd, + GString *appearBuf); + void drawCircleTopLeft(double cx, double cy, double r, + GString *appearBuf); + void drawCircleBottomRight(double cx, double cy, double r, + GString *appearBuf); + void drawBarcode(GString *value, GString *da, GfxFontDict *fontDict, int rot, + double xMin, double yMin, double xMax, double yMax, + XFAFieldBarcodeInfo *barcodeInfo, GString *appearBuf); + GList *tokenize(GString *s); + Object *getAnnotObj(Object *annotObj); + Object *getAnnotResources(Dict *annot, Object *res); + void buildDefaultResourceDict(Object *dr); + Object *fieldLookup(const char *key, Object *obj); + Object *fieldLookup(Dict *dict, const char *key, Object *obj); + Unicode *utf8ToUnicode(GString *s, int *unicodeLength); + GString *unicodeToLatin1(Unicode *u, int unicodeLength); + GBool unicodeStringEqual(Unicode *u, int unicodeLength, GString *s); + GBool unicodeStringEqual(Unicode *u, int unicodeLength, const char *s); + GString *pictureFormatDateTime(GString *value, GString *picture); + GString *pictureFormatNumber(GString *value, GString *picture); + GString *pictureFormatText(GString *value, GString *picture); + GBool isValidInt(GString *s, int start, int len); + int convertInt(GString *s, int start, int len); + + AcroForm *acroForm; + Object fieldRef; + Object fieldObj; + AcroFormFieldType type; + TextString *name; + Guint flags; + GBool typeFromParent; + XFAField *xfaField; + + friend class AcroForm; +}; + +#endif diff --git a/xpdf/Annot.cc b/xpdf/Annot.cc new file mode 100644 index 0000000..82ef600 --- /dev/null +++ b/xpdf/Annot.cc @@ -0,0 +1,1448 @@ +//======================================================================== +// +// Annot.cc +// +// Copyright 2000-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include +#include "gmem.h" +#include "gmempp.h" +#include "GList.h" +#include "Error.h" +#include "Object.h" +#include "Catalog.h" +#include "Gfx.h" +#include "GfxFont.h" +#include "Lexer.h" +#include "PDFDoc.h" +#include "OptionalContent.h" +#include "AcroForm.h" +#include "BuiltinFontTables.h" +#include "FontEncodingTables.h" +#include "Annot.h" + +// the MSVC math.h doesn't define this +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +//------------------------------------------------------------------------ + +#define annotFlagHidden 0x0002 +#define annotFlagPrint 0x0004 +#define annotFlagNoView 0x0020 + +// distance of Bezier control point from center for circle approximation +// = (4 * (sqrt(2) - 1) / 3) * r +#define bezierCircle 0.55228475 + +#define lineEndSize1 6 +#define lineEndSize2 10 +#define lineArrowAngle (M_PI / 6) + +//------------------------------------------------------------------------ +// AnnotBorderStyle +//------------------------------------------------------------------------ + +AnnotBorderStyle::AnnotBorderStyle(AnnotBorderType typeA, double widthA, + double *dashA, int dashLengthA, + double *colorA, int nColorCompsA) { + type = typeA; + width = widthA; + dash = dashA; + dashLength = dashLengthA; + color[0] = colorA[0]; + color[1] = colorA[1]; + color[2] = colorA[2]; + color[3] = colorA[3]; + nColorComps = nColorCompsA; +} + +AnnotBorderStyle::~AnnotBorderStyle() { + if (dash) { + gfree(dash); + } +} + +//------------------------------------------------------------------------ +// Annot +//------------------------------------------------------------------------ + +Annot::Annot(PDFDoc *docA, Dict *dict, Ref *refA) { + Object apObj, asObj, obj1, obj2, obj3; + AnnotBorderType borderType; + double borderWidth; + double *borderDash; + int borderDashLength; + double borderColor[4]; + int nBorderColorComps; + double t; + int i; + + ok = gTrue; + doc = docA; + xref = doc->getXRef(); + ref = *refA; + type = NULL; + appearanceState = NULL; + appearBuf = NULL; + borderStyle = NULL; + + //----- parse the type + + if (dict->lookup("Subtype", &obj1)->isName()) { + type = new GString(obj1.getName()); + } + obj1.free(); + + //----- parse the rectangle + + if (dict->lookup("Rect", &obj1)->isArray() && + obj1.arrayGetLength() == 4) { + xMin = yMin = xMax = yMax = 0; + if (obj1.arrayGet(0, &obj2)->isNum()) { + xMin = obj2.getNum(); + } + obj2.free(); + if (obj1.arrayGet(1, &obj2)->isNum()) { + yMin = obj2.getNum(); + } + obj2.free(); + if (obj1.arrayGet(2, &obj2)->isNum()) { + xMax = obj2.getNum(); + } + obj2.free(); + if (obj1.arrayGet(3, &obj2)->isNum()) { + yMax = obj2.getNum(); + } + obj2.free(); + if (xMin > xMax) { + t = xMin; xMin = xMax; xMax = t; + } + if (yMin > yMax) { + t = yMin; yMin = yMax; yMax = t; + } + } else { + error(errSyntaxError, -1, "Bad bounding box for annotation"); + ok = gFalse; + } + obj1.free(); + + //----- parse the flags + + if (dict->lookup("F", &obj1)->isInt()) { + flags = obj1.getInt(); + } else { + flags = 0; + } + obj1.free(); + + //----- parse the border style + + borderType = annotBorderSolid; + borderWidth = 1; + borderDash = NULL; + borderDashLength = 0; + nBorderColorComps = 3; + borderColor[0] = 0; + borderColor[1] = 0; + borderColor[2] = 1; + borderColor[3] = 0; + if (dict->lookup("BS", &obj1)->isDict()) { + if (obj1.dictLookup("S", &obj2)->isName()) { + if (obj2.isName("S")) { + borderType = annotBorderSolid; + } else if (obj2.isName("D")) { + borderType = annotBorderDashed; + } else if (obj2.isName("B")) { + borderType = annotBorderBeveled; + } else if (obj2.isName("I")) { + borderType = annotBorderInset; + } else if (obj2.isName("U")) { + borderType = annotBorderUnderlined; + } + } + obj2.free(); + if (obj1.dictLookup("W", &obj2)->isNum()) { + borderWidth = obj2.getNum(); + } + obj2.free(); + if (obj1.dictLookup("D", &obj2)->isArray()) { + borderDashLength = obj2.arrayGetLength(); + borderDash = (double *)gmallocn(borderDashLength, sizeof(double)); + for (i = 0; i < borderDashLength; ++i) { + if (obj2.arrayGet(i, &obj3)->isNum()) { + borderDash[i] = obj3.getNum(); + } else { + borderDash[i] = 1; + } + obj3.free(); + } + } + obj2.free(); + } else { + obj1.free(); + if (dict->lookup("Border", &obj1)->isArray()) { + if (obj1.arrayGetLength() >= 3) { + if (obj1.arrayGet(2, &obj2)->isNum()) { + borderWidth = obj2.getNum(); + } + obj2.free(); + if (obj1.arrayGetLength() >= 4) { + if (obj1.arrayGet(3, &obj2)->isArray()) { + borderType = annotBorderDashed; + borderDashLength = obj2.arrayGetLength(); + borderDash = (double *)gmallocn(borderDashLength, sizeof(double)); + for (i = 0; i < borderDashLength; ++i) { + if (obj2.arrayGet(i, &obj3)->isNum()) { + borderDash[i] = obj3.getNum(); + } else { + borderDash[i] = 1; + } + obj3.free(); + } + } else { + // Adobe draws no border at all if the last element is of + // the wrong type. + borderWidth = 0; + } + obj2.free(); + } + } else { + // an empty Border array also means "no border" + borderWidth = 0; + } + } + } + obj1.free(); + // Acrobat ignores borders with unreasonable widths + if (borderWidth > 1 && (borderWidth > xMax - xMin || + borderWidth > yMax - yMin)) { + borderWidth = 0; + } + if (dict->lookup("C", &obj1)->isArray() && + (obj1.arrayGetLength() == 1 || + obj1.arrayGetLength() == 3 || + obj1.arrayGetLength() == 4)) { + nBorderColorComps = obj1.arrayGetLength(); + for (i = 0; i < nBorderColorComps; ++i) { + if (obj1.arrayGet(i, &obj2)->isNum()) { + borderColor[i] = obj2.getNum(); + } else { + borderColor[i] = 0; + } + obj2.free(); + } + } + obj1.free(); + borderStyle = new AnnotBorderStyle(borderType, borderWidth, + borderDash, borderDashLength, + borderColor, nBorderColorComps); + + //----- get the appearance state + + dict->lookup("AP", &apObj); + dict->lookup("AS", &asObj); + if (asObj.isName()) { + appearanceState = new GString(asObj.getName()); + } else if (apObj.isDict()) { + apObj.dictLookup("N", &obj1); + if (obj1.isDict() && obj1.dictGetLength() == 1) { + appearanceState = new GString(obj1.dictGetKey(0)); + } + obj1.free(); + } + if (!appearanceState) { + appearanceState = new GString("Off"); + } + asObj.free(); + + //----- get the annotation appearance + + if (apObj.isDict()) { + apObj.dictLookup("N", &obj1); + apObj.dictLookupNF("N", &obj2); + if (obj1.isDict()) { + if (obj1.dictLookupNF(appearanceState->getCString(), &obj3)->isRef()) { + obj3.copy(&appearance); + } + obj3.free(); + } else if (obj2.isRef()) { + obj2.copy(&appearance); + } + obj1.free(); + obj2.free(); + } + apObj.free(); + + //----- get the optional content entry + + dict->lookupNF("OC", &ocObj); +} + +Annot::~Annot() { + if (type) { + delete type; + } + if (appearanceState) { + delete appearanceState; + } + appearance.free(); + if (appearBuf) { + delete appearBuf; + } + if (borderStyle) { + delete borderStyle; + } + ocObj.free(); +} + +void Annot::generateAnnotAppearance() { + Object obj; + + appearance.fetch(doc->getXRef(), &obj); + if (!obj.isStream()) { + if (type) { + if (!type->cmp("Line")) { + generateLineAppearance(); + } else if (!type->cmp("PolyLine")) { + generatePolyLineAppearance(); + } else if (!type->cmp("Polygon")) { + generatePolygonAppearance(); + } else if (!type->cmp("FreeText")) { + generateFreeTextAppearance(); + } + } + } + obj.free(); +} + +//~ this doesn't draw the caption +void Annot::generateLineAppearance() { + Object annotObj, gfxStateDict, appearDict, obj1, obj2; + MemStream *appearStream; + double x1, y1, x2, y2, dx, dy, len, w; + double lx1, ly1, lx2, ly2; + double tx1, ty1, tx2, ty2; + double ax1, ay1, ax2, ay2; + double bx1, by1, bx2, by2; + double leaderLen, leaderExtLen, leaderOffLen; + AnnotLineEndType lineEnd1, lineEnd2; + GBool fill; + + if (!getObject(&annotObj)->isDict()) { + annotObj.free(); + return; + } + + appearBuf = new GString(); + + //----- check for transparency + if (annotObj.dictLookup("CA", &obj1)->isNum()) { + gfxStateDict.initDict(doc->getXRef()); + gfxStateDict.dictAdd(copyString("ca"), obj1.copy(&obj2)); + appearBuf->append("/GS1 gs\n"); + } + obj1.free(); + + //----- set line style, colors + setLineStyle(borderStyle, &w); + setStrokeColor(borderStyle->getColor(), borderStyle->getNumColorComps()); + fill = gFalse; + if (annotObj.dictLookup("IC", &obj1)->isArray()) { + if (setFillColor(&obj1)) { + fill = gTrue; + } + } + obj1.free(); + + //----- get line properties + if (annotObj.dictLookup("L", &obj1)->isArray() && + obj1.arrayGetLength() == 4) { + if (obj1.arrayGet(0, &obj2)->isNum()) { + x1 = obj2.getNum(); + } else { + obj2.free(); + obj1.free(); + goto err1; + } + obj2.free(); + if (obj1.arrayGet(1, &obj2)->isNum()) { + y1 = obj2.getNum(); + } else { + obj2.free(); + obj1.free(); + goto err1; + } + obj2.free(); + if (obj1.arrayGet(2, &obj2)->isNum()) { + x2 = obj2.getNum(); + } else { + obj2.free(); + obj1.free(); + goto err1; + } + obj2.free(); + if (obj1.arrayGet(3, &obj2)->isNum()) { + y2 = obj2.getNum(); + } else { + obj2.free(); + obj1.free(); + goto err1; + } + obj2.free(); + } else { + obj1.free(); + goto err1; + } + obj1.free(); + lineEnd1 = lineEnd2 = annotLineEndNone; + if (annotObj.dictLookup("LE", &obj1)->isArray() && + obj1.arrayGetLength() == 2) { + lineEnd1 = parseLineEndType(obj1.arrayGet(0, &obj2)); + obj2.free(); + lineEnd2 = parseLineEndType(obj1.arrayGet(1, &obj2)); + obj2.free(); + } + obj1.free(); + if (annotObj.dictLookup("LL", &obj1)->isNum()) { + leaderLen = obj1.getNum(); + } else { + leaderLen = 0; + } + obj1.free(); + if (annotObj.dictLookup("LLE", &obj1)->isNum()) { + leaderExtLen = obj1.getNum(); + } else { + leaderExtLen = 0; + } + obj1.free(); + if (annotObj.dictLookup("LLO", &obj1)->isNum()) { + leaderOffLen = obj1.getNum(); + } else { + leaderOffLen = 0; + } + obj1.free(); + + //----- compute positions + x1 -= xMin; + y1 -= yMin; + x2 -= xMin; + y2 -= yMin; + dx = x2 - x1; + dy = y2 - y1; + len = sqrt(dx*dx + dy*dy); + if (len > 0) { + dx /= len; + dy /= len; + } + if (leaderLen != 0) { + ax1 = x1 + leaderOffLen * dy; + ay1 = y1 - leaderOffLen * dx; + lx1 = ax1 + leaderLen * dy; + ly1 = ay1 - leaderLen * dx; + bx1 = lx1 + leaderExtLen * dy; + by1 = ly1 - leaderExtLen * dx; + ax2 = x2 + leaderOffLen * dy; + ay2 = y2 - leaderOffLen * dx; + lx2 = ax2 + leaderLen * dy; + ly2 = ay2 - leaderLen * dx; + bx2 = lx2 + leaderExtLen * dy; + by2 = ly2 - leaderExtLen * dx; + } else { + lx1 = x1; + ly1 = y1; + lx2 = x2; + ly2 = y2; + ax1 = ay1 = ax2 = ay2 = 0; // make gcc happy + bx1 = by1 = bx2 = by2 = 0; + } + adjustLineEndpoint(lineEnd1, lx1, ly1, dx, dy, w, &tx1, &ty1); + adjustLineEndpoint(lineEnd2, lx2, ly2, -dx, -dy, w, &tx2, &ty2); + + //----- draw leaders + if (leaderLen != 0) { + appearBuf->appendf("{0:.4f} {1:.4f} m {2:.4f} {3:.4f} l\n", + ax1, ay1, bx1, by1); + appearBuf->appendf("{0:.4f} {1:.4f} m {2:.4f} {3:.4f} l\n", + ax2, ay2 , bx2, by2); + } + + //----- draw the line + appearBuf->appendf("{0:.4f} {1:.4f} m {2:.4f} {3:.4f} l\n", + tx1, ty1, tx2, ty2); + appearBuf->append("S\n"); + + //----- draw the arrows + if (borderStyle->getType() == annotBorderDashed) { + appearBuf->append("[] 0 d\n"); + } + drawLineArrow(lineEnd1, lx1, ly1, dx, dy, w, fill); + drawLineArrow(lineEnd2, lx2, ly2, -dx, -dy, w, fill); + + //----- build the appearance stream dictionary + appearDict.initDict(doc->getXRef()); + appearDict.dictAdd(copyString("Length"), + obj1.initInt(appearBuf->getLength())); + appearDict.dictAdd(copyString("Subtype"), obj1.initName("Form")); + obj1.initArray(doc->getXRef()); + obj1.arrayAdd(obj2.initReal(0)); + obj1.arrayAdd(obj2.initReal(0)); + obj1.arrayAdd(obj2.initReal(xMax - xMin)); + obj1.arrayAdd(obj2.initReal(yMax - yMin)); + appearDict.dictAdd(copyString("BBox"), &obj1); + if (gfxStateDict.isDict()) { + obj1.initDict(doc->getXRef()); + obj2.initDict(doc->getXRef()); + obj2.dictAdd(copyString("GS1"), &gfxStateDict); + obj1.dictAdd(copyString("ExtGState"), &obj2); + appearDict.dictAdd(copyString("Resources"), &obj1); + } + + //----- build the appearance stream + appearStream = new MemStream(appearBuf->getCString(), 0, + appearBuf->getLength(), &appearDict); + appearance.free(); + appearance.initStream(appearStream); + + err1: + annotObj.free(); +} + +//~ this doesn't handle line ends (arrows) +void Annot::generatePolyLineAppearance() { + Object annotObj, gfxStateDict, appearDict, obj1, obj2; + MemStream *appearStream; + double x1, y1, w; + int i; + + if (!getObject(&annotObj)->isDict()) { + annotObj.free(); + return; + } + + appearBuf = new GString(); + + //----- check for transparency + if (annotObj.dictLookup("CA", &obj1)->isNum()) { + gfxStateDict.initDict(doc->getXRef()); + gfxStateDict.dictAdd(copyString("ca"), obj1.copy(&obj2)); + appearBuf->append("/GS1 gs\n"); + } + obj1.free(); + + //----- set line style, colors + setLineStyle(borderStyle, &w); + setStrokeColor(borderStyle->getColor(), borderStyle->getNumColorComps()); + // fill = gFalse; + // if (annotObj.dictLookup("IC", &obj1)->isArray()) { + // if (setFillColor(&obj1)) { + // fill = gTrue; + // } + // } + // obj1.free(); + + //----- draw line + if (!annotObj.dictLookup("Vertices", &obj1)->isArray()) { + obj1.free(); + goto err1; + } + for (i = 0; i+1 < obj1.arrayGetLength(); i += 2) { + if (!obj1.arrayGet(i, &obj2)->isNum()) { + obj2.free(); + obj1.free(); + goto err1; + } + x1 = obj2.getNum(); + obj2.free(); + if (!obj1.arrayGet(i+1, &obj2)->isNum()) { + obj2.free(); + obj1.free(); + goto err1; + } + y1 = obj2.getNum(); + obj2.free(); + x1 -= xMin; + y1 -= yMin; + if (i == 0) { + appearBuf->appendf("{0:.4f} {1:.4f} m\n", x1, y1); + } else { + appearBuf->appendf("{0:.4f} {1:.4f} l\n", x1, y1); + } + } + appearBuf->append("S\n"); + obj1.free(); + + //----- build the appearance stream dictionary + appearDict.initDict(doc->getXRef()); + appearDict.dictAdd(copyString("Length"), + obj1.initInt(appearBuf->getLength())); + appearDict.dictAdd(copyString("Subtype"), obj1.initName("Form")); + obj1.initArray(doc->getXRef()); + obj1.arrayAdd(obj2.initReal(0)); + obj1.arrayAdd(obj2.initReal(0)); + obj1.arrayAdd(obj2.initReal(xMax - xMin)); + obj1.arrayAdd(obj2.initReal(yMax - yMin)); + appearDict.dictAdd(copyString("BBox"), &obj1); + if (gfxStateDict.isDict()) { + obj1.initDict(doc->getXRef()); + obj2.initDict(doc->getXRef()); + obj2.dictAdd(copyString("GS1"), &gfxStateDict); + obj1.dictAdd(copyString("ExtGState"), &obj2); + appearDict.dictAdd(copyString("Resources"), &obj1); + } + + //----- build the appearance stream + appearStream = new MemStream(appearBuf->getCString(), 0, + appearBuf->getLength(), &appearDict); + appearance.free(); + appearance.initStream(appearStream); + + err1: + annotObj.free(); +} + +void Annot::generatePolygonAppearance() { + Object annotObj, gfxStateDict, appearDict, obj1, obj2; + MemStream *appearStream; + double x1, y1; + int i; + + if (!getObject(&annotObj)->isDict()) { + annotObj.free(); + return; + } + + appearBuf = new GString(); + + //----- check for transparency + if (annotObj.dictLookup("CA", &obj1)->isNum()) { + gfxStateDict.initDict(doc->getXRef()); + gfxStateDict.dictAdd(copyString("ca"), obj1.copy(&obj2)); + appearBuf->append("/GS1 gs\n"); + } + obj1.free(); + + //----- set fill color + if (!annotObj.dictLookup("IC", &obj1)->isArray() || + !setFillColor(&obj1)) { + obj1.free(); + goto err1; + } + obj1.free(); + + //----- fill polygon + if (!annotObj.dictLookup("Vertices", &obj1)->isArray()) { + obj1.free(); + goto err1; + } + for (i = 0; i+1 < obj1.arrayGetLength(); i += 2) { + if (!obj1.arrayGet(i, &obj2)->isNum()) { + obj2.free(); + obj1.free(); + goto err1; + } + x1 = obj2.getNum(); + obj2.free(); + if (!obj1.arrayGet(i+1, &obj2)->isNum()) { + obj2.free(); + obj1.free(); + goto err1; + } + y1 = obj2.getNum(); + obj2.free(); + x1 -= xMin; + y1 -= yMin; + if (i == 0) { + appearBuf->appendf("{0:.4f} {1:.4f} m\n", x1, y1); + } else { + appearBuf->appendf("{0:.4f} {1:.4f} l\n", x1, y1); + } + } + appearBuf->append("f\n"); + obj1.free(); + + //----- build the appearance stream dictionary + appearDict.initDict(doc->getXRef()); + appearDict.dictAdd(copyString("Length"), + obj1.initInt(appearBuf->getLength())); + appearDict.dictAdd(copyString("Subtype"), obj1.initName("Form")); + obj1.initArray(doc->getXRef()); + obj1.arrayAdd(obj2.initReal(0)); + obj1.arrayAdd(obj2.initReal(0)); + obj1.arrayAdd(obj2.initReal(xMax - xMin)); + obj1.arrayAdd(obj2.initReal(yMax - yMin)); + appearDict.dictAdd(copyString("BBox"), &obj1); + if (gfxStateDict.isDict()) { + obj1.initDict(doc->getXRef()); + obj2.initDict(doc->getXRef()); + obj2.dictAdd(copyString("GS1"), &gfxStateDict); + obj1.dictAdd(copyString("ExtGState"), &obj2); + appearDict.dictAdd(copyString("Resources"), &obj1); + } + + //----- build the appearance stream + appearStream = new MemStream(appearBuf->getCString(), 0, + appearBuf->getLength(), &appearDict); + appearance.free(); + appearance.initStream(appearStream); + + err1: + annotObj.free(); +} + +//~ this doesn't handle rich text +//~ this doesn't handle the callout +//~ this doesn't handle the RD field +void Annot::generateFreeTextAppearance() { + Object annotObj, gfxStateDict, appearDict, obj1, obj2; + Object resources, gsResources, fontResources, defaultFont; + GString *text, *da; + double lineWidth; + int quadding, rot; + MemStream *appearStream; + + if (!getObject(&annotObj)->isDict()) { + annotObj.free(); + return; + } + + appearBuf = new GString(); + + //----- check for transparency + if (annotObj.dictLookup("CA", &obj1)->isNum()) { + gfxStateDict.initDict(doc->getXRef()); + gfxStateDict.dictAdd(copyString("ca"), obj1.copy(&obj2)); + appearBuf->append("/GS1 gs\n"); + } + obj1.free(); + + //----- draw the text + if (annotObj.dictLookup("Contents", &obj1)->isString()) { + text = obj1.getString()->copy(); + } else { + text = new GString(); + } + obj1.free(); + if (annotObj.dictLookup("Q", &obj1)->isInt()) { + quadding = obj1.getInt(); + } else { + quadding = 0; + } + obj1.free(); + if (annotObj.dictLookup("DA", &obj1)->isString()) { + da = obj1.getString()->copy(); + } else { + da = new GString(); + } + obj1.free(); + // the "Rotate" field is not defined in the PDF spec, but Acrobat + // looks at it + if (annotObj.dictLookup("Rotate", &obj1)->isInt()) { + rot = obj1.getInt(); + } else { + rot = 0; + } + obj1.free(); + drawText(text, da, quadding, 0, rot); + delete text; + delete da; + + //----- draw the border + if (borderStyle->getWidth() != 0) { + setLineStyle(borderStyle, &lineWidth); + appearBuf->appendf("{0:.4f} {1:.4f} {2:.4f} {3:.4f} re s\n", + 0.5 * lineWidth, 0.5 * lineWidth, + xMax - xMin - lineWidth, yMax - yMin - lineWidth); + } + + //----- build the appearance stream dictionary + appearDict.initDict(doc->getXRef()); + appearDict.dictAdd(copyString("Length"), + obj1.initInt(appearBuf->getLength())); + appearDict.dictAdd(copyString("Subtype"), obj1.initName("Form")); + obj1.initArray(doc->getXRef()); + obj1.arrayAdd(obj2.initReal(0)); + obj1.arrayAdd(obj2.initReal(0)); + obj1.arrayAdd(obj2.initReal(xMax - xMin)); + obj1.arrayAdd(obj2.initReal(yMax - yMin)); + appearDict.dictAdd(copyString("BBox"), &obj1); + resources.initDict(doc->getXRef()); + defaultFont.initDict(doc->getXRef()); + defaultFont.dictAdd(copyString("Type"), obj1.initName("Font")); + defaultFont.dictAdd(copyString("Subtype"), obj1.initName("Type1")); + defaultFont.dictAdd(copyString("BaseFont"), obj1.initName("Helvetica")); + defaultFont.dictAdd(copyString("Encoding"), obj1.initName("WinAnsiEncoding")); + fontResources.initDict(doc->getXRef()); + fontResources.dictAdd(copyString("xpdf_default_font"), &defaultFont); + resources.dictAdd(copyString("Font"), &fontResources); + if (gfxStateDict.isDict()) { + gsResources.initDict(doc->getXRef()); + gsResources.dictAdd(copyString("GS1"), &gfxStateDict); + resources.dictAdd(copyString("ExtGState"), &gsResources); + } + appearDict.dictAdd(copyString("Resources"), &resources); + + //----- build the appearance stream + appearStream = new MemStream(appearBuf->getCString(), 0, + appearBuf->getLength(), &appearDict); + appearance.free(); + appearance.initStream(appearStream); + + annotObj.free(); +} + +void Annot::setLineStyle(AnnotBorderStyle *bs, double *lineWidth) { + double *dash; + double w; + int dashLength, i; + + if ((w = borderStyle->getWidth()) <= 0) { + w = 0.1; + } + *lineWidth = w; + appearBuf->appendf("{0:.4f} w\n", w); + // this treats beveled/inset/underline as solid + if (borderStyle->getType() == annotBorderDashed) { + borderStyle->getDash(&dash, &dashLength); + appearBuf->append("["); + for (i = 0; i < dashLength; ++i) { + appearBuf->appendf(" {0:.4f}", dash[i]); + } + appearBuf->append("] 0 d\n"); + } + appearBuf->append("0 j\n0 J\n"); +} + +void Annot::setStrokeColor(double *color, int nComps) { + switch (nComps) { + case 0: + appearBuf->append("0 G\n"); + break; + case 1: + appearBuf->appendf("{0:.2f} G\n", color[0]); + break; + case 3: + appearBuf->appendf("{0:.2f} {1:.2f} {2:.2f} RG\n", + color[0], color[1], color[2]); + break; + case 4: + appearBuf->appendf("{0:.2f} {1:.2f} {2:.2f} {3:.2f} K\n", + color[0], color[1], color[2], color[3]); + break; + } +} + +GBool Annot::setFillColor(Object *colorObj) { + Object obj; + double color[4]; + int i; + + if (!colorObj->isArray()) { + return gFalse; + } + for (i = 0; i < colorObj->arrayGetLength() && i < 4; ++i) { + if (colorObj->arrayGet(i, &obj)->isNum()) { + color[i] = obj.getNum(); + } else { + color[i] = 0; + } + obj.free(); + } + switch (colorObj->arrayGetLength()) { + case 1: + appearBuf->appendf("{0:.2f} g\n", color[0]); + return gTrue; + case 3: + appearBuf->appendf("{0:.2f} {1:.2f} {2:.2f} rg\n", + color[0], color[1], color[2]); + return gTrue; + case 4: + appearBuf->appendf("{0:.2f} {1:.2f} {2:.2f} {3:.3f} k\n", + color[0], color[1], + color[2], color[3]); + return gTrue; + } + return gFalse; +} + +AnnotLineEndType Annot::parseLineEndType(Object *obj) { + if (obj->isName("None")) { + return annotLineEndNone; + } else if (obj->isName("Square")) { + return annotLineEndSquare; + } else if (obj->isName("Circle")) { + return annotLineEndCircle; + } else if (obj->isName("Diamond")) { + return annotLineEndDiamond; + } else if (obj->isName("OpenArrow")) { + return annotLineEndOpenArrow; + } else if (obj->isName("ClosedArrow")) { + return annotLineEndClosedArrow; + } else if (obj->isName("Butt")) { + return annotLineEndButt; + } else if (obj->isName("ROpenArrow")) { + return annotLineEndROpenArrow; + } else if (obj->isName("RClosedArrow")) { + return annotLineEndRClosedArrow; + } else if (obj->isName("Slash")) { + return annotLineEndSlash; + } else { + return annotLineEndNone; + } +} + +void Annot::adjustLineEndpoint(AnnotLineEndType lineEnd, + double x, double y, double dx, double dy, + double w, double *tx, double *ty) { + switch (lineEnd) { + case annotLineEndNone: + w = 0; + break; + case annotLineEndSquare: + w *= lineEndSize1; + break; + case annotLineEndCircle: + w *= lineEndSize1; + break; + case annotLineEndDiamond: + w *= lineEndSize1; + break; + case annotLineEndOpenArrow: + w = 0; + break; + case annotLineEndClosedArrow: + w *= lineEndSize2 * cos(lineArrowAngle); + break; + case annotLineEndButt: + w = 0; + break; + case annotLineEndROpenArrow: + w *= lineEndSize2 * cos(lineArrowAngle); + break; + case annotLineEndRClosedArrow: + w *= lineEndSize2 * cos(lineArrowAngle); + break; + case annotLineEndSlash: + w = 0; + break; + } + *tx = x + w * dx; + *ty = y + w * dy; +} + +void Annot::drawLineArrow(AnnotLineEndType lineEnd, + double x, double y, double dx, double dy, + double w, GBool fill) { + switch (lineEnd) { + case annotLineEndNone: + break; + case annotLineEndSquare: + w *= lineEndSize1; + appearBuf->appendf("{0:.4f} {1:.4f} m\n", + x + w*dx + 0.5*w*dy, + y + w*dy - 0.5*w*dx); + appearBuf->appendf("{0:.4f} {1:.4f} l\n", + x + 0.5*w*dy, + y - 0.5*w*dx); + appearBuf->appendf("{0:.4f} {1:.4f} l\n", + x - 0.5*w*dy, + y + 0.5*w*dx); + appearBuf->appendf("{0:.4f} {1:.4f} l\n", + x + w*dx - 0.5*w*dy, + y + w*dy + 0.5*w*dx); + appearBuf->append(fill ? "b\n" : "s\n"); + break; + case annotLineEndCircle: + w *= lineEndSize1; + drawCircle(x + 0.5*w*dx, y + 0.5*w*dy, 0.5*w, fill ? "b" : "s"); + break; + case annotLineEndDiamond: + w *= lineEndSize1; + appearBuf->appendf("{0:.4f} {1:.4f} m\n", x, y); + appearBuf->appendf("{0:.4f} {1:.4f} l\n", + x + 0.5*w*dx - 0.5*w*dy, + y + 0.5*w*dy + 0.5*w*dx); + appearBuf->appendf("{0:.4f} {1:.4f} l\n", + x + w*dx, + y + w*dy); + appearBuf->appendf("{0:.4f} {1:.4f} l\n", + x + 0.5*w*dx + 0.5*w*dy, + y + 0.5*w*dy - 0.5*w*dx); + appearBuf->append(fill ? "b\n" : "s\n"); + break; + case annotLineEndOpenArrow: + w *= lineEndSize2; + appearBuf->appendf("{0:.4f} {1:.4f} m\n", + x + w*cos(lineArrowAngle)*dx + w*sin(lineArrowAngle)*dy, + y + w*cos(lineArrowAngle)*dy - w*sin(lineArrowAngle)*dx); + appearBuf->appendf("{0:.4f} {1:.4f} l\n", x, y); + appearBuf->appendf("{0:.4f} {1:.4f} l\n", + x + w*cos(lineArrowAngle)*dx - w*sin(lineArrowAngle)*dy, + y + w*cos(lineArrowAngle)*dy + w*sin(lineArrowAngle)*dx); + appearBuf->append("S\n"); + break; + case annotLineEndClosedArrow: + w *= lineEndSize2; + appearBuf->appendf("{0:.4f} {1:.4f} m\n", + x + w*cos(lineArrowAngle)*dx + w*sin(lineArrowAngle)*dy, + y + w*cos(lineArrowAngle)*dy - w*sin(lineArrowAngle)*dx); + appearBuf->appendf("{0:.4f} {1:.4f} l\n", x, y); + appearBuf->appendf("{0:.4f} {1:.4f} l\n", + x + w*cos(lineArrowAngle)*dx - w*sin(lineArrowAngle)*dy, + y + w*cos(lineArrowAngle)*dy + w*sin(lineArrowAngle)*dx); + appearBuf->append(fill ? "b\n" : "s\n"); + break; + case annotLineEndButt: + w *= lineEndSize1; + appearBuf->appendf("{0:.4f} {1:.4f} m\n", + x + 0.5*w*dy, + y - 0.5*w*dx); + appearBuf->appendf("{0:.4f} {1:.4f} l\n", + x - 0.5*w*dy, + y + 0.5*w*dx); + appearBuf->append("S\n"); + break; + case annotLineEndROpenArrow: + w *= lineEndSize2; + appearBuf->appendf("{0:.4f} {1:.4f} m\n", + x + w*sin(lineArrowAngle)*dy, + y - w*sin(lineArrowAngle)*dx); + appearBuf->appendf("{0:.4f} {1:.4f} l\n", + x + w*cos(lineArrowAngle)*dx, + y + w*cos(lineArrowAngle)*dy); + appearBuf->appendf("{0:.4f} {1:.4f} l\n", + x - w*sin(lineArrowAngle)*dy, + y + w*sin(lineArrowAngle)*dx); + appearBuf->append("S\n"); + break; + case annotLineEndRClosedArrow: + w *= lineEndSize2; + appearBuf->appendf("{0:.4f} {1:.4f} m\n", + x + w*sin(lineArrowAngle)*dy, + y - w*sin(lineArrowAngle)*dx); + appearBuf->appendf("{0:.4f} {1:.4f} l\n", + x + w*cos(lineArrowAngle)*dx, + y + w*cos(lineArrowAngle)*dy); + appearBuf->appendf("{0:.4f} {1:.4f} l\n", + x - w*sin(lineArrowAngle)*dy, + y + w*sin(lineArrowAngle)*dx); + appearBuf->append(fill ? "b\n" : "s\n"); + break; + case annotLineEndSlash: + w *= lineEndSize1; + appearBuf->appendf("{0:.4f} {1:.4f} m\n", + x + 0.5*w*cos(lineArrowAngle)*dy + - 0.5*w*sin(lineArrowAngle)*dx, + y - 0.5*w*cos(lineArrowAngle)*dx + - 0.5*w*sin(lineArrowAngle)*dy); + appearBuf->appendf("{0:.4f} {1:.4f} l\n", + x - 0.5*w*cos(lineArrowAngle)*dy + + 0.5*w*sin(lineArrowAngle)*dx, + y + 0.5*w*cos(lineArrowAngle)*dx + + 0.5*w*sin(lineArrowAngle)*dy); + appearBuf->append("S\n"); + break; + } +} + +// Draw an (approximate) circle of radius centered at (, ). +// is used to draw the circle ("f", "s", or "b"). +void Annot::drawCircle(double cx, double cy, double r, const char *cmd) { + appearBuf->appendf("{0:.4f} {1:.4f} m\n", + cx + r, cy); + appearBuf->appendf("{0:.4f} {1:.4f} {2:.4f} {3:.4f} {4:.4f} {5:.4f} c\n", + cx + r, cy + bezierCircle * r, + cx + bezierCircle * r, cy + r, + cx, cy + r); + appearBuf->appendf("{0:.4f} {1:.4f} {2:.4f} {3:.4f} {4:.4f} {5:.4f} c\n", + cx - bezierCircle * r, cy + r, + cx - r, cy + bezierCircle * r, + cx - r, cy); + appearBuf->appendf("{0:.4f} {1:.4f} {2:.4f} {3:.4f} {4:.4f} {5:.4f} c\n", + cx - r, cy - bezierCircle * r, + cx - bezierCircle * r, cy - r, + cx, cy - r); + appearBuf->appendf("{0:.4f} {1:.4f} {2:.4f} {3:.4f} {4:.4f} {5:.4f} c\n", + cx + bezierCircle * r, cy - r, + cx + r, cy - bezierCircle * r, + cx + r, cy); + appearBuf->appendf("{0:s}\n", cmd); +} + +// Draw the top-left half of an (approximate) circle of radius +// centered at (, ). +void Annot::drawCircleTopLeft(double cx, double cy, double r) { + double r2; + + r2 = r / sqrt(2.0); + appearBuf->appendf("{0:.4f} {1:.4f} m\n", + cx + r2, cy + r2); + appearBuf->appendf("{0:.4f} {1:.4f} {2:.4f} {3:.4f} {4:.4f} {5:.4f} c\n", + cx + (1 - bezierCircle) * r2, + cy + (1 + bezierCircle) * r2, + cx - (1 - bezierCircle) * r2, + cy + (1 + bezierCircle) * r2, + cx - r2, + cy + r2); + appearBuf->appendf("{0:.4f} {1:.4f} {2:.4f} {3:.4f} {4:.4f} {5:.4f} c\n", + cx - (1 + bezierCircle) * r2, + cy + (1 - bezierCircle) * r2, + cx - (1 + bezierCircle) * r2, + cy - (1 - bezierCircle) * r2, + cx - r2, + cy - r2); + appearBuf->append("S\n"); +} + +// Draw the bottom-right half of an (approximate) circle of radius +// centered at (, ). +void Annot::drawCircleBottomRight(double cx, double cy, double r) { + double r2; + + r2 = r / sqrt(2.0); + appearBuf->appendf("{0:.4f} {1:.4f} m\n", + cx - r2, cy - r2); + appearBuf->appendf("{0:.4f} {1:.4f} {2:.4f} {3:.4f} {4:.4f} {5:.4f} c\n", + cx - (1 - bezierCircle) * r2, + cy - (1 + bezierCircle) * r2, + cx + (1 - bezierCircle) * r2, + cy - (1 + bezierCircle) * r2, + cx + r2, + cy - r2); + appearBuf->appendf("{0:.4f} {1:.4f} {2:.4f} {3:.4f} {4:.4f} {5:.4f} c\n", + cx + (1 + bezierCircle) * r2, + cy - (1 - bezierCircle) * r2, + cx + (1 + bezierCircle) * r2, + cy + (1 - bezierCircle) * r2, + cx + r2, + cy + r2); + appearBuf->append("S\n"); +} + +void Annot::drawText(GString *text, GString *da, int quadding, double margin, + int rot) { + GString *text2, *tok; + GList *daToks; + const char *charName; + double dx, dy, fontSize, fontSize2, x, y, w; + Gushort charWidth; + int tfPos, tmPos, i, j, c; + + // 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) { + daToks = new GList(); + i = 0; + while (i < da->getLength()) { + while (i < da->getLength() && Lexer::isSpace(da->getChar(i))) { + ++i; + } + if (i < da->getLength()) { + for (j = i + 1; + j < da->getLength() && !Lexer::isSpace(da->getChar(j)); + ++j) ; + daToks->append(new GString(da, i, j - i)); + i = j; + } + } + for (i = 2; i < daToks->getLength(); ++i) { + if (i >= 2 && !((GString *)daToks->get(i))->cmp("Tf")) { + tfPos = i - 2; + } else if (i >= 6 && !((GString *)daToks->get(i))->cmp("Tm")) { + tmPos = i - 6; + } + } + } else { + daToks = NULL; + } + + // get the font and font size + fontSize = 0; + if (tfPos >= 0) { + //~ where do we look up the font? + tok = (GString *)daToks->get(tfPos); + tok->clear(); + tok->append("/xpdf_default_font"); + tok = (GString *)daToks->get(tfPos + 1); + fontSize = atof(tok->getCString()); + } else { + error(errSyntaxError, -1, + "Missing 'Tf' operator in annotation's DA string"); + daToks->append(new GString("/xpdf_default_font")); + daToks->append(new GString("10")); + daToks->append(new GString("Tf")); + } + + // setup + appearBuf->append("q\n"); + if (rot == 90) { + appearBuf->appendf("0 1 -1 0 {0:.4f} 0 cm\n", xMax - xMin); + dx = yMax - yMin; + dy = xMax - xMin; + } else if (rot == 180) { + appearBuf->appendf("-1 0 0 -1 {0:.4f} {1:.4f} cm\n", + xMax - xMin, yMax - yMin); + dx = xMax - yMax; + dy = yMax - yMin; + } else if (rot == 270) { + appearBuf->appendf("0 -1 1 0 0 {0:.4f} cm\n", yMax - yMin); + dx = yMax - yMin; + dy = xMax - xMin; + } else { // assume rot == 0 + dx = xMax - xMin; + dy = yMax - yMin; + } + appearBuf->append("BT\n"); + + // compute string width + //~ this assumes we're substituting Helvetica/WinAnsiEncoding for everything + w = 0; + for (i = 0; i < text2->getLength(); ++i) { + charName = winAnsiEncoding[text->getChar(i) & 0xff]; + if (charName && builtinFonts[4].widths->getWidth(charName, &charWidth)) { + w += charWidth; + } else { + w += 0.5; + } + } + + // compute font autosize + if (fontSize == 0) { + fontSize = dy - 2 * margin; + fontSize2 = (dx - 2 * margin) / w; + if (fontSize2 < fontSize) { + fontSize = fontSize2; + } + fontSize = floor(fontSize); + if (tfPos >= 0) { + tok = (GString *)daToks->get(tfPos + 1); + tok->clear(); + tok->appendf("{0:.4f}", fontSize); + } + } + + // compute text start position + w *= fontSize; + switch (quadding) { + case 0: + default: + x = margin + 2; + break; + case 1: + x = (dx - w) / 2; + break; + case 2: + x = dx - margin - 2 - w; + break; + } + y = 0.5 * dy - 0.4 * fontSize; + + // set the font matrix + if (tmPos >= 0) { + tok = (GString *)daToks->get(tmPos + 4); + tok->clear(); + tok->appendf("{0:.4f}", x); + tok = (GString *)daToks->get(tmPos + 5); + tok->clear(); + tok->appendf("{0:.4f}", y); + } + + // write the DA string + if (daToks) { + for (i = 0; i < daToks->getLength(); ++i) { + appearBuf->append((GString *)daToks->get(i))->append(' '); + } + } + + // write the font matrix (if not part of the DA string) + if (tmPos < 0) { + appearBuf->appendf("1 0 0 1 {0:.4f} {1:.4f} Tm\n", x, y); + } + + // write the text string + appearBuf->append('('); + for (i = 0; i < text2->getLength(); ++i) { + c = text2->getChar(i) & 0xff; + if (c == '(' || c == ')' || c == '\\') { + appearBuf->append('\\'); + appearBuf->append((char)c); + } else if (c < 0x20 || c >= 0x80) { + appearBuf->appendf("\\{0:03o}", c); + } else { + appearBuf->append((char)c); + } + } + appearBuf->append(") Tj\n"); + + // cleanup + appearBuf->append("ET\n"); + appearBuf->append("Q\n"); + + if (daToks) { + deleteGList(daToks, GString); + } + if (text2 != text) { + delete text2; + } +} + +void Annot::draw(Gfx *gfx, GBool printing) { + GBool oc, isLink; + + // check the flags + if ((flags & annotFlagHidden) || + (printing && !(flags & annotFlagPrint)) || + (!printing && (flags & annotFlagNoView))) { + return; + } + + // check the optional content entry + if (doc->getOptionalContent()->evalOCObject(&ocObj, &oc) && !oc) { + return; + } + + // draw the appearance stream + isLink = type && !type->cmp("Link"); + gfx->drawAnnot(&appearance, isLink ? borderStyle : (AnnotBorderStyle *)NULL, + xMin, yMin, xMax, yMax); +} + +Object *Annot::getObject(Object *obj) { + if (ref.num >= 0) { + xref->fetch(ref.num, ref.gen, obj); + } else { + obj->initNull(); + } + return obj; +} + +//------------------------------------------------------------------------ +// Annots +//------------------------------------------------------------------------ + +Annots::Annots(PDFDoc *docA, Object *annotsObj) { + Annot *annot; + Object obj1, obj2; + Ref ref; + GBool drawWidgetAnnots; + int size; + int i; + + doc = docA; + annots = NULL; + size = 0; + nAnnots = 0; + + if (annotsObj->isArray()) { + // Kludge: some PDF files define an empty AcroForm, but still + // include Widget-type annotations -- in that case, we want to + // draw the widgets (since the form code won't). This really + // ought to look for Widget-type annotations that are not included + // in any form field. + drawWidgetAnnots = !doc->getCatalog()->getForm() || + doc->getCatalog()->getForm()->getNumFields() == 0; + for (i = 0; i < annotsObj->arrayGetLength(); ++i) { + if (annotsObj->arrayGetNF(i, &obj1)->isRef()) { + ref = obj1.getRef(); + obj1.free(); + annotsObj->arrayGet(i, &obj1); + } else { + ref.num = ref.gen = -1; + } + if (obj1.isDict()) { + if (drawWidgetAnnots || + !obj1.dictLookup("Subtype", &obj2)->isName("Widget")) { + annot = new Annot(doc, obj1.getDict(), &ref); + if (annot->isOk()) { + if (nAnnots >= size) { + size += 16; + annots = (Annot **)greallocn(annots, size, sizeof(Annot *)); + } + annots[nAnnots++] = annot; + } else { + delete annot; + } + } + obj2.free(); + } + obj1.free(); + } + } +} + +Annots::~Annots() { + int i; + + for (i = 0; i < nAnnots; ++i) { + delete annots[i]; + } + gfree(annots); +} + +Annot *Annots::find(double x, double y) { + int i; + + for (i = nAnnots - 1; i >= 0; --i) { + if (annots[i]->inRect(x, y)) { + return annots[i]; + } + } + return NULL; +} + +int Annots::findIdx(double x, double y) { + int i; + + for (i = nAnnots - 1; i >= 0; --i) { + if (annots[i]->inRect(x, y)) { + return i; + } + } + return -1; +} + +void Annots::generateAnnotAppearances() { + int i; + + for (i = 0; i < nAnnots; ++i) { + annots[i]->generateAnnotAppearance(); + } +} + +Annot *Annots::findAnnot(Ref *ref) { + int i; + + for (i = 0; i < nAnnots; ++i) { + if (annots[i]->match(ref)) { + return annots[i]; + } + } + return NULL; +} diff --git a/xpdf/Annot.h b/xpdf/Annot.h new file mode 100644 index 0000000..6ba5ff4 --- /dev/null +++ b/xpdf/Annot.h @@ -0,0 +1,185 @@ +//======================================================================== +// +// Annot.h +// +// Copyright 2000-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef ANNOT_H +#define ANNOT_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +class XRef; +class Catalog; +class Gfx; +class GfxFontDict; +class PDFDoc; + +//------------------------------------------------------------------------ +// AnnotBorderStyle +//------------------------------------------------------------------------ + +enum AnnotBorderType { + annotBorderSolid, + annotBorderDashed, + annotBorderBeveled, + annotBorderInset, + annotBorderUnderlined +}; + +class AnnotBorderStyle { +public: + + AnnotBorderStyle(AnnotBorderType typeA, double widthA, + double *dashA, int dashLengthA, + double *colorA, int nColorCompsA); + ~AnnotBorderStyle(); + + AnnotBorderType getType() { return type; } + double getWidth() { return width; } + void getDash(double **dashA, int *dashLengthA) + { *dashA = dash; *dashLengthA = dashLength; } + int getNumColorComps() { return nColorComps; } + double *getColor() { return color; } + +private: + + AnnotBorderType type; + double width; + double *dash; + int dashLength; + double color[4]; + int nColorComps; +}; + +//------------------------------------------------------------------------ + +enum AnnotLineEndType { + annotLineEndNone, + annotLineEndSquare, + annotLineEndCircle, + annotLineEndDiamond, + annotLineEndOpenArrow, + annotLineEndClosedArrow, + annotLineEndButt, + annotLineEndROpenArrow, + annotLineEndRClosedArrow, + annotLineEndSlash +}; + +//------------------------------------------------------------------------ +// Annot +//------------------------------------------------------------------------ + +class Annot { +public: + + 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); + + // Check if point is inside the annotation rectangle. + GBool inRect(double x, double y) + { return xMin <= x && x <= xMax && yMin <= y && y <= yMax; } + + // Get appearance object. + Object *getAppearance(Object *obj) { return appearance.fetch(xref, obj); } + + AnnotBorderStyle *getBorderStyle() { return borderStyle; } + + GBool match(Ref *refA) + { return ref.num == refA->num && ref.gen == refA->gen; } + + void generateAnnotAppearance(); + +private: + + void generateLineAppearance(); + void generatePolyLineAppearance(); + void generatePolygonAppearance(); + void generateFreeTextAppearance(); + void setLineStyle(AnnotBorderStyle *bs, double *lineWidth); + void setStrokeColor(double *color, int nComps); + GBool setFillColor(Object *colorObj); + AnnotLineEndType parseLineEndType(Object *obj); + void adjustLineEndpoint(AnnotLineEndType lineEnd, + double x, double y, double dx, double dy, + double w, double *tx, double *ty); + void drawLineArrow(AnnotLineEndType lineEnd, + double x, double y, double dx, double dy, + double w, GBool fill); + void drawCircle(double cx, double cy, double r, const char *cmd); + void drawCircleTopLeft(double cx, double cy, double r); + void drawCircleBottomRight(double cx, double cy, double r); + void drawText(GString *text, GString *da, int quadding, double margin, + int rot); + + 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; + double xMin, yMin, // annotation rectangle + xMax, yMax; + Guint flags; + AnnotBorderStyle *borderStyle; + Object ocObj; // optional content entry + GBool ok; +}; + +//------------------------------------------------------------------------ +// Annots +//------------------------------------------------------------------------ + +class Annots { +public: + + // Build a list of Annot objects. + Annots(PDFDoc *docA, Object *annotsObj); + + ~Annots(); + + // Iterate through list of annotations. + int getNumAnnots() { return nAnnots; } + Annot *getAnnot(int i) { return annots[i]; } + + // If point , is in an annotation, return the associated + // annotation; else return NULL. + Annot *find(double x, double y); + int findIdx(double x, double y); + + // Generate an appearance stream for any non-form-field annotation + // that is missing it. + void generateAnnotAppearances(); + +private: + + void scanFieldAppearances(Dict *node, Ref *ref, Dict *parent, + Dict *acroForm); + + Annot *findAnnot(Ref *ref); + + PDFDoc *doc; + Annot **annots; + int nAnnots; +}; + +#endif diff --git a/xpdf/Array.cc b/xpdf/Array.cc new file mode 100644 index 0000000..2bf948e --- /dev/null +++ b/xpdf/Array.cc @@ -0,0 +1,74 @@ +//======================================================================== +// +// Array.cc +// +// Copyright 1996-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include +#include "gmem.h" +#include "gmempp.h" +#include "Object.h" +#include "Array.h" + +//------------------------------------------------------------------------ +// Array +//------------------------------------------------------------------------ + +Array::Array(XRef *xrefA) { + xref = xrefA; + elems = NULL; + size = length = 0; + ref = 1; +} + +Array::~Array() { + int i; + + for (i = 0; i < length; ++i) + elems[i].free(); + gfree(elems); +} + +void Array::add(Object *elem) { + if (length == size) { + if (length == 0) { + size = 8; + } else { + size *= 2; + } + elems = (Object *)greallocn(elems, size, sizeof(Object)); + } + elems[length] = *elem; + ++length; +} + +Object *Array::get(int i, Object *obj, int recursion) { + if (i < 0 || i >= length) { +#ifdef DEBUG_MEM + abort(); +#else + return obj->initNull(); +#endif + } + return elems[i].fetch(xref, obj, recursion); +} + +Object *Array::getNF(int i, Object *obj) { + if (i < 0 || i >= length) { +#ifdef DEBUG_MEM + abort(); +#else + return obj->initNull(); +#endif + } + return elems[i].copy(obj); +} diff --git a/xpdf/Array.h b/xpdf/Array.h new file mode 100644 index 0000000..8d10ead --- /dev/null +++ b/xpdf/Array.h @@ -0,0 +1,70 @@ +//======================================================================== +// +// Array.h +// +// Copyright 1996-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef ARRAY_H +#define ARRAY_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#if MULTITHREADED +#include "GMutex.h" +#endif +#include "Object.h" + +class XRef; + +//------------------------------------------------------------------------ +// Array +//------------------------------------------------------------------------ + +class Array { +public: + + // Constructor. + Array(XRef *xrefA); + + // Destructor. + ~Array(); + + // Reference counting. +#if MULTITHREADED + long incRef() { return gAtomicIncrement(&ref); } + long decRef() { return gAtomicDecrement(&ref); } +#else + long incRef() { return ++ref; } + long decRef() { return --ref; } +#endif + + // Get number of elements. + int getLength() { return length; } + + // Add an element. + void add(Object *elem); + + // Accessors. + Object *get(int i, Object *obj, int recursion = 0); + Object *getNF(int i, Object *obj); + +private: + + XRef *xref; // the xref table for this PDF file + Object *elems; // array of elements + int size; // size of array + int length; // number of elements in array +#if MULTITHREADED + GAtomicCounter ref; // reference count +#else + long ref; // reference count +#endif +}; + +#endif diff --git a/xpdf/BuiltinFont.cc b/xpdf/BuiltinFont.cc new file mode 100644 index 0000000..d2f875e --- /dev/null +++ b/xpdf/BuiltinFont.cc @@ -0,0 +1,67 @@ +//======================================================================== +// +// BuiltinFont.cc +// +// Copyright 2001-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include +#include "gmem.h" +#include "gmempp.h" +#include "FontEncodingTables.h" +#include "BuiltinFont.h" + +//------------------------------------------------------------------------ + +BuiltinFontWidths::BuiltinFontWidths(BuiltinFontWidth *widths, int sizeA) { + int i, h; + + size = sizeA; + tab = (BuiltinFontWidth **)gmallocn(size, sizeof(BuiltinFontWidth *)); + for (i = 0; i < size; ++i) { + tab[i] = NULL; + } + for (i = 0; i < sizeA; ++i) { + h = hash(widths[i].name); + widths[i].next = tab[h]; + tab[h] = &widths[i]; + } +} + +BuiltinFontWidths::~BuiltinFontWidths() { + gfree(tab); +} + +GBool BuiltinFontWidths::getWidth(const char *name, Gushort *width) { + int h; + BuiltinFontWidth *p; + + h = hash(name); + for (p = tab[h]; p; p = p->next) { + if (!strcmp(p->name, name)) { + *width = p->width; + return gTrue; + } + } + *width = 0; + return gFalse; +} + +int BuiltinFontWidths::hash(const char *name) { + const char *p; + unsigned int h; + + h = 0; + for (p = name; *p; ++p) { + h = 17 * h + (int)(*p & 0xff); + } + return (int)(h % size); +} diff --git a/xpdf/BuiltinFont.h b/xpdf/BuiltinFont.h new file mode 100644 index 0000000..f24cbf9 --- /dev/null +++ b/xpdf/BuiltinFont.h @@ -0,0 +1,58 @@ +//======================================================================== +// +// BuiltinFont.h +// +// Copyright 2001-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef BUILTINFONT_H +#define BUILTINFONT_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "gtypes.h" + +struct BuiltinFont; +class BuiltinFontWidths; + +//------------------------------------------------------------------------ + +struct BuiltinFont { + const char *name; + const char **defaultBaseEnc; + short missingWidth; + short ascent; + short descent; + short bbox[4]; + BuiltinFontWidths *widths; +}; + +//------------------------------------------------------------------------ + +struct BuiltinFontWidth { + const char *name; + Gushort width; + BuiltinFontWidth *next; +}; + +class BuiltinFontWidths { +public: + + BuiltinFontWidths(BuiltinFontWidth *widths, int sizeA); + ~BuiltinFontWidths(); + GBool getWidth(const char *name, Gushort *width); + +private: + + int hash(const char *name); + + BuiltinFontWidth **tab; + int size; +}; + +#endif diff --git a/xpdf/BuiltinFontTables.cc b/xpdf/BuiltinFontTables.cc new file mode 100644 index 0000000..51a468c --- /dev/null +++ b/xpdf/BuiltinFontTables.cc @@ -0,0 +1,4285 @@ +//======================================================================== +// +// BuiltinFontTables.cc +// +// Copyright 2001-2017 Glyph & Cog, LLC +// +//======================================================================== + +#include +#include +#include "gmempp.h" +#include "FontEncodingTables.h" +#include "BuiltinFontTables.h" + +static BuiltinFontWidth courierWidthsTab[] = { + { "odieresis", 600, NULL }, + { "M", 600, NULL }, + { "Ograve", 600, NULL }, + { "T", 600, NULL }, + { "amacron", 600, NULL }, + { "Ncommaaccent", 600, NULL }, + { "numbersign", 600, NULL }, + { "emacron", 600, NULL }, + { "divide", 600, NULL }, + { "fl", 600, NULL }, + { "E", 600, NULL }, + { "quotedblbase", 600, NULL }, + { "guillemotleft", 600, NULL }, + { "endash", 600, NULL }, + { "w", 600, NULL }, + { "twosuperior", 600, NULL }, + { "eth", 600, NULL }, + { "space", 600, NULL }, + { "Thorn", 600, NULL }, + { "ecaron", 600, NULL }, + { "brokenbar", 600, NULL }, + { "Aogonek", 600, NULL }, + { "commaaccent", 600, NULL }, + { "W", 600, NULL }, + { "bracketright", 600, NULL }, + { "germandbls", 600, NULL }, + { "Ugrave", 600, NULL }, + { "thorn", 600, NULL }, + { "zero", 600, NULL }, + { "udieresis", 600, NULL }, + { "period", 600, NULL }, + { "scedilla", 600, NULL }, + { "Ccedilla", 600, NULL }, + { "Igrave", 600, NULL }, + { "Ocircumflex", 600, NULL }, + { "F", 600, NULL }, + { "Uring", 600, NULL }, + { "perthousand", 600, NULL }, + { "Edotaccent", 600, NULL }, + { "acircumflex", 600, NULL }, + { "G", 600, NULL }, + { "circumflex", 600, NULL }, + { "Zcaron", 600, NULL }, + { "ogonek", 600, NULL }, + { "idieresis", 600, NULL }, + { "cent", 600, NULL }, + { "ae", 600, NULL }, + { "less", 600, NULL }, + { "ocircumflex", 600, NULL }, + { "minus", 600, NULL }, + { "four", 600, NULL }, + { "dollar", 600, NULL }, + { "Tcommaaccent", 600, NULL }, + { "dotaccent", 600, NULL }, + { "Nacute", 600, NULL }, + { "v", 600, NULL }, + { "Kcommaaccent", 600, NULL }, + { "imacron", 600, NULL }, + { "rcommaaccent", 600, NULL }, + { "tilde", 600, NULL }, + { "underscore", 600, NULL }, + { "racute", 600, NULL }, + { "mu", 600, NULL }, + { "D", 600, NULL }, + { "Ccaron", 600, NULL }, + { "j", 600, NULL }, + { "hungarumlaut", 600, NULL }, + { "Y", 600, NULL }, + { "yen", 600, NULL }, + { "ccaron", 600, NULL }, + { "lessequal", 600, NULL }, + { "Ucircumflex", 600, NULL }, + { "Omacron", 600, NULL }, + { "quotesinglbase", 600, NULL }, + { "Scedilla", 600, NULL }, + { "grave", 600, NULL }, + { "parenleft", 600, NULL }, + { "nine", 600, NULL }, + { "currency", 600, NULL }, + { "radical", 600, NULL }, + { "Ntilde", 600, NULL }, + { "p", 600, NULL }, + { "dotlessi", 600, NULL }, + { "cedilla", 600, NULL }, + { "Idotaccent", 600, NULL }, + { "plusminus", 600, NULL }, + { "Eth", 600, NULL }, + { "quotedblright", 600, NULL }, + { "ccedilla", 600, NULL }, + { "colon", 600, NULL }, + { "g", 600, NULL }, + { "oe", 600, NULL }, + { "Odieresis", 600, NULL }, + { "five", 600, NULL }, + { "asciicircum", 600, NULL }, + { "X", 600, NULL }, + { "emdash", 600, NULL }, + { "Egrave", 600, NULL }, + { "aogonek", 600, NULL }, + { "ring", 600, NULL }, + { "Dcaron", 600, NULL }, + { "ecircumflex", 600, NULL }, + { "Z", 600, NULL }, + { "breve", 600, NULL }, + { "Amacron", 600, NULL }, + { "zcaron", 600, NULL }, + { "paragraph", 600, NULL }, + { "lcaron", 600, NULL }, + { "Ydieresis", 600, NULL }, + { "aring", 600, NULL }, + { "iogonek", 600, NULL }, + { "florin", 600, NULL }, + { "Euro", 600, NULL }, + { "Scaron", 600, NULL }, + { "degree", 600, NULL }, + { "section", 600, NULL }, + { "K", 600, NULL }, + { "Aacute", 600, NULL }, + { "Scommaaccent", 600, NULL }, + { "b", 600, NULL }, + { "greater", 600, NULL }, + { "asterisk", 600, NULL }, + { "scommaaccent", 600, NULL }, + { "Emacron", 600, NULL }, + { "onesuperior", 600, NULL }, + { "percent", 600, NULL }, + { "o", 600, NULL }, + { "icircumflex", 600, NULL }, + { "iacute", 600, NULL }, + { "e", 600, NULL }, + { "Imacron", 600, NULL }, + { "abreve", 600, NULL }, + { "N", 600, NULL }, + { "equal", 600, NULL }, + { "dagger", 600, NULL }, + { "u", 600, NULL }, + { "C", 600, NULL }, + { "l", 600, NULL }, + { "q", 600, NULL }, + { "quoteleft", 600, NULL }, + { "registered", 600, NULL }, + { "Gcommaaccent", 600, NULL }, + { "Racute", 600, NULL }, + { "k", 600, NULL }, + { "copyright", 600, NULL }, + { "onehalf", 600, NULL }, + { "lcommaaccent", 600, NULL }, + { "uhungarumlaut", 600, NULL }, + { "gbreve", 600, NULL }, + { "n", 600, NULL }, + { "Ecaron", 600, NULL }, + { "zdotaccent", 600, NULL }, + { "threesuperior", 600, NULL }, + { "Uacute", 600, NULL }, + { "Zacute", 600, NULL }, + { "atilde", 600, NULL }, + { "fraction", 600, NULL }, + { "Adieresis", 600, NULL }, + { "Sacute", 600, NULL }, + { "asciitilde", 600, NULL }, + { "lacute", 600, NULL }, + { "Uogonek", 600, NULL }, + { "caron", 600, NULL }, + { "Lslash", 600, NULL }, + { "sterling", 600, NULL }, + { "H", 600, NULL }, + { "at", 600, NULL }, + { "greaterequal", 600, NULL }, + { "J", 600, NULL }, + { "threequarters", 600, NULL }, + { "ohungarumlaut", 600, NULL }, + { "Ecircumflex", 600, NULL }, + { "L", 600, NULL }, + { "Agrave", 600, NULL }, + { "exclam", 600, NULL }, + { "AE", 600, NULL }, + { "notequal", 600, NULL }, + { "oslash", 600, NULL }, + { "Acircumflex", 600, NULL }, + { "ograve", 600, NULL }, + { "Rcommaaccent", 600, NULL }, + { "Lacute", 600, NULL }, + { "Idieresis", 600, NULL }, + { "sacute", 600, NULL }, + { "f", 600, NULL }, + { "gcommaaccent", 600, NULL }, + { "bracketleft", 600, NULL }, + { "Ohungarumlaut", 600, NULL }, + { "otilde", 600, NULL }, + { "parenright", 600, NULL }, + { "questiondown", 600, NULL }, + { "Lcaron", 600, NULL }, + { "ordmasculine", 600, NULL }, + { "backslash", 600, NULL }, + { "Eogonek", 600, NULL }, + { "macron", 600, NULL }, + { "three", 600, NULL }, + { "slash", 600, NULL }, + { "r", 600, NULL }, + { "ucircumflex", 600, NULL }, + { "zacute", 600, NULL }, + { "Umacron", 600, NULL }, + { "adieresis", 600, NULL }, + { "ncaron", 600, NULL }, + { "V", 600, NULL }, + { "lozenge", 600, NULL }, + { "exclamdown", 600, NULL }, + { "Q", 600, NULL }, + { "uogonek", 600, NULL }, + { "quoteright", 600, NULL }, + { "guilsinglright", 600, NULL }, + { "semicolon", 600, NULL }, + { "egrave", 600, NULL }, + { "s", 600, NULL }, + { "uring", 600, NULL }, + { "z", 600, NULL }, + { "Uhungarumlaut", 600, NULL }, + { "I", 600, NULL }, + { "one", 600, NULL }, + { "eight", 600, NULL }, + { "periodcentered", 600, NULL }, + { "d", 600, NULL }, + { "c", 600, NULL }, + { "agrave", 600, NULL }, + { "ellipsis", 600, NULL }, + { "Aring", 600, NULL }, + { "t", 600, NULL }, + { "quotedbl", 600, NULL }, + { "Oacute", 600, NULL }, + { "edotaccent", 600, NULL }, + { "six", 600, NULL }, + { "lslash", 600, NULL }, + { "P", 600, NULL }, + { "i", 600, NULL }, + { "multiply", 600, NULL }, + { "bar", 600, NULL }, + { "quotesingle", 600, NULL }, + { "acute", 600, NULL }, + { "braceright", 600, NULL }, + { "braceleft", 600, NULL }, + { "onequarter", 600, NULL }, + { "Atilde", 600, NULL }, + { "Edieresis", 600, NULL }, + { "oacute", 600, NULL }, + { "Yacute", 600, NULL }, + { "daggerdbl", 600, NULL }, + { "ncommaaccent", 600, NULL }, + { "logicalnot", 600, NULL }, + { "tcommaaccent", 600, NULL }, + { "Dcroat", 600, NULL }, + { "cacute", 600, NULL }, + { "tcaron", 600, NULL }, + { "rcaron", 600, NULL }, + { "Iogonek", 600, NULL }, + { "y", 600, NULL }, + { "edieresis", 600, NULL }, + { "x", 600, NULL }, + { "Ncaron", 600, NULL }, + { "OE", 600, NULL }, + { "m", 600, NULL }, + { "U", 600, NULL }, + { "partialdiff", 600, NULL }, + { "dcroat", 600, NULL }, + { "igrave", 600, NULL }, + { "summation", 600, NULL }, + { "question", 600, NULL }, + { "A", 600, NULL }, + { "Cacute", 600, NULL }, + { "h", 600, NULL }, + { "guilsinglleft", 600, NULL }, + { "plus", 600, NULL }, + { "Otilde", 600, NULL }, + { "umacron", 600, NULL }, + { "Tcaron", 600, NULL }, + { "aacute", 600, NULL }, + { "B", 600, NULL }, + { "R", 600, NULL }, + { "ydieresis", 600, NULL }, + { "Rcaron", 600, NULL }, + { "kcommaaccent", 600, NULL }, + { "yacute", 600, NULL }, + { "dcaron", 600, NULL }, + { "ugrave", 600, NULL }, + { "a", 600, NULL }, + { "hyphen", 600, NULL }, + { "Oslash", 600, NULL }, + { "comma", 600, NULL }, + { "Delta", 600, NULL }, + { "omacron", 600, NULL }, + { "Gbreve", 600, NULL }, + { "S", 600, NULL }, + { "quotedblleft", 600, NULL }, + { "ordfeminine", 600, NULL }, + { "ampersand", 600, NULL }, + { "trademark", 600, NULL }, + { "Lcommaaccent", 600, NULL }, + { "ntilde", 600, NULL }, + { "fi", 600, NULL }, + { "dieresis", 600, NULL }, + { "Eacute", 600, NULL }, + { "nacute", 600, NULL }, + { "O", 600, NULL }, + { "Icircumflex", 600, NULL }, + { "Udieresis", 600, NULL }, + { "Abreve", 600, NULL }, + { "Iacute", 600, NULL }, + { "uacute", 600, NULL }, + { "two", 600, NULL }, + { "seven", 600, NULL }, + { "scaron", 600, NULL }, + { "guillemotright", 600, NULL }, + { "bullet", 600, NULL }, + { "eogonek", 600, NULL }, + { "eacute", 600, NULL }, + { "Zdotaccent", 600, NULL } +}; + +static BuiltinFontWidth courierBoldWidthsTab[] = { + { "t", 600, NULL }, + { "quotedbl", 600, NULL }, + { "Oacute", 600, NULL }, + { "agrave", 600, NULL }, + { "ellipsis", 600, NULL }, + { "Aring", 600, NULL }, + { "eight", 600, NULL }, + { "I", 600, NULL }, + { "one", 600, NULL }, + { "periodcentered", 600, NULL }, + { "c", 600, NULL }, + { "d", 600, NULL }, + { "egrave", 600, NULL }, + { "uring", 600, NULL }, + { "s", 600, NULL }, + { "z", 600, NULL }, + { "Uhungarumlaut", 600, NULL }, + { "uogonek", 600, NULL }, + { "quoteright", 600, NULL }, + { "semicolon", 600, NULL }, + { "guilsinglright", 600, NULL }, + { "Umacron", 600, NULL }, + { "zacute", 600, NULL }, + { "ncaron", 600, NULL }, + { "adieresis", 600, NULL }, + { "lozenge", 600, NULL }, + { "V", 600, NULL }, + { "Q", 600, NULL }, + { "exclamdown", 600, NULL }, + { "three", 600, NULL }, + { "slash", 600, NULL }, + { "r", 600, NULL }, + { "ucircumflex", 600, NULL }, + { "macron", 600, NULL }, + { "Eogonek", 600, NULL }, + { "Lcaron", 600, NULL }, + { "ordmasculine", 600, NULL }, + { "questiondown", 600, NULL }, + { "backslash", 600, NULL }, + { "gcommaaccent", 600, NULL }, + { "Ohungarumlaut", 600, NULL }, + { "bracketleft", 600, NULL }, + { "otilde", 600, NULL }, + { "parenright", 600, NULL }, + { "f", 600, NULL }, + { "Lacute", 600, NULL }, + { "Idieresis", 600, NULL }, + { "sacute", 600, NULL }, + { "Rcommaaccent", 600, NULL }, + { "ograve", 600, NULL }, + { "threequarters", 600, NULL }, + { "J", 600, NULL }, + { "ohungarumlaut", 600, NULL }, + { "Ecircumflex", 600, NULL }, + { "L", 600, NULL }, + { "notequal", 600, NULL }, + { "exclam", 600, NULL }, + { "Agrave", 600, NULL }, + { "AE", 600, NULL }, + { "Acircumflex", 600, NULL }, + { "oslash", 600, NULL }, + { "Uogonek", 600, NULL }, + { "caron", 600, NULL }, + { "Lslash", 600, NULL }, + { "lacute", 600, NULL }, + { "sterling", 600, NULL }, + { "H", 600, NULL }, + { "at", 600, NULL }, + { "greaterequal", 600, NULL }, + { "asciitilde", 600, NULL }, + { "Uacute", 600, NULL }, + { "atilde", 600, NULL }, + { "Zacute", 600, NULL }, + { "fraction", 600, NULL }, + { "Adieresis", 600, NULL }, + { "Sacute", 600, NULL }, + { "scaron", 600, NULL }, + { "guillemotright", 600, NULL }, + { "bullet", 600, NULL }, + { "eogonek", 600, NULL }, + { "eacute", 600, NULL }, + { "Zdotaccent", 600, NULL }, + { "Abreve", 600, NULL }, + { "Udieresis", 600, NULL }, + { "Iacute", 600, NULL }, + { "two", 600, NULL }, + { "uacute", 600, NULL }, + { "seven", 600, NULL }, + { "dieresis", 600, NULL }, + { "Eacute", 600, NULL }, + { "O", 600, NULL }, + { "Icircumflex", 600, NULL }, + { "nacute", 600, NULL }, + { "trademark", 600, NULL }, + { "ampersand", 600, NULL }, + { "Lcommaaccent", 600, NULL }, + { "ntilde", 600, NULL }, + { "fi", 600, NULL }, + { "quotedblleft", 600, NULL }, + { "ordfeminine", 600, NULL }, + { "omacron", 600, NULL }, + { "comma", 600, NULL }, + { "Delta", 600, NULL }, + { "Gbreve", 600, NULL }, + { "S", 600, NULL }, + { "B", 600, NULL }, + { "kcommaaccent", 600, NULL }, + { "Rcaron", 600, NULL }, + { "yacute", 600, NULL }, + { "ydieresis", 600, NULL }, + { "R", 600, NULL }, + { "ugrave", 600, NULL }, + { "dcaron", 600, NULL }, + { "Oslash", 600, NULL }, + { "hyphen", 600, NULL }, + { "a", 600, NULL }, + { "Otilde", 600, NULL }, + { "umacron", 600, NULL }, + { "Tcaron", 600, NULL }, + { "aacute", 600, NULL }, + { "guilsinglleft", 600, NULL }, + { "Cacute", 600, NULL }, + { "h", 600, NULL }, + { "plus", 600, NULL }, + { "igrave", 600, NULL }, + { "dcroat", 600, NULL }, + { "question", 600, NULL }, + { "summation", 600, NULL }, + { "A", 600, NULL }, + { "x", 600, NULL }, + { "edieresis", 600, NULL }, + { "Iogonek", 600, NULL }, + { "y", 600, NULL }, + { "Ncaron", 600, NULL }, + { "m", 600, NULL }, + { "OE", 600, NULL }, + { "partialdiff", 600, NULL }, + { "U", 600, NULL }, + { "ncommaaccent", 600, NULL }, + { "tcommaaccent", 600, NULL }, + { "logicalnot", 600, NULL }, + { "cacute", 600, NULL }, + { "Dcroat", 600, NULL }, + { "tcaron", 600, NULL }, + { "rcaron", 600, NULL }, + { "Atilde", 600, NULL }, + { "Edieresis", 600, NULL }, + { "Yacute", 600, NULL }, + { "oacute", 600, NULL }, + { "daggerdbl", 600, NULL }, + { "braceleft", 600, NULL }, + { "braceright", 600, NULL }, + { "acute", 600, NULL }, + { "onequarter", 600, NULL }, + { "i", 600, NULL }, + { "multiply", 600, NULL }, + { "quotesingle", 600, NULL }, + { "bar", 600, NULL }, + { "six", 600, NULL }, + { "edotaccent", 600, NULL }, + { "lslash", 600, NULL }, + { "P", 600, NULL }, + { "parenleft", 600, NULL }, + { "currency", 600, NULL }, + { "nine", 600, NULL }, + { "quotesinglbase", 600, NULL }, + { "grave", 600, NULL }, + { "Scedilla", 600, NULL }, + { "ccaron", 600, NULL }, + { "Ucircumflex", 600, NULL }, + { "lessequal", 600, NULL }, + { "Omacron", 600, NULL }, + { "hungarumlaut", 600, NULL }, + { "Ccaron", 600, NULL }, + { "j", 600, NULL }, + { "Y", 600, NULL }, + { "yen", 600, NULL }, + { "rcommaaccent", 600, NULL }, + { "Kcommaaccent", 600, NULL }, + { "imacron", 600, NULL }, + { "tilde", 600, NULL }, + { "underscore", 600, NULL }, + { "mu", 600, NULL }, + { "D", 600, NULL }, + { "racute", 600, NULL }, + { "Tcommaaccent", 600, NULL }, + { "dollar", 600, NULL }, + { "Nacute", 600, NULL }, + { "v", 600, NULL }, + { "dotaccent", 600, NULL }, + { "cent", 600, NULL }, + { "ae", 600, NULL }, + { "ocircumflex", 600, NULL }, + { "less", 600, NULL }, + { "minus", 600, NULL }, + { "four", 600, NULL }, + { "circumflex", 600, NULL }, + { "Zcaron", 600, NULL }, + { "ogonek", 600, NULL }, + { "idieresis", 600, NULL }, + { "G", 600, NULL }, + { "F", 600, NULL }, + { "Ocircumflex", 600, NULL }, + { "Uring", 600, NULL }, + { "perthousand", 600, NULL }, + { "Edotaccent", 600, NULL }, + { "acircumflex", 600, NULL }, + { "zero", 600, NULL }, + { "period", 600, NULL }, + { "scedilla", 600, NULL }, + { "udieresis", 600, NULL }, + { "Ccedilla", 600, NULL }, + { "Igrave", 600, NULL }, + { "commaaccent", 600, NULL }, + { "W", 600, NULL }, + { "bracketright", 600, NULL }, + { "Ugrave", 600, NULL }, + { "germandbls", 600, NULL }, + { "thorn", 600, NULL }, + { "w", 600, NULL }, + { "Thorn", 600, NULL }, + { "space", 600, NULL }, + { "eth", 600, NULL }, + { "twosuperior", 600, NULL }, + { "ecaron", 600, NULL }, + { "Aogonek", 600, NULL }, + { "brokenbar", 600, NULL }, + { "fl", 600, NULL }, + { "E", 600, NULL }, + { "quotedblbase", 600, NULL }, + { "guillemotleft", 600, NULL }, + { "endash", 600, NULL }, + { "amacron", 600, NULL }, + { "Ncommaaccent", 600, NULL }, + { "numbersign", 600, NULL }, + { "divide", 600, NULL }, + { "emacron", 600, NULL }, + { "M", 600, NULL }, + { "odieresis", 600, NULL }, + { "Ograve", 600, NULL }, + { "T", 600, NULL }, + { "n", 600, NULL }, + { "Ecaron", 600, NULL }, + { "threesuperior", 600, NULL }, + { "zdotaccent", 600, NULL }, + { "lcommaaccent", 600, NULL }, + { "onehalf", 600, NULL }, + { "gbreve", 600, NULL }, + { "uhungarumlaut", 600, NULL }, + { "Racute", 600, NULL }, + { "k", 600, NULL }, + { "copyright", 600, NULL }, + { "quoteleft", 600, NULL }, + { "registered", 600, NULL }, + { "Gcommaaccent", 600, NULL }, + { "equal", 600, NULL }, + { "dagger", 600, NULL }, + { "N", 600, NULL }, + { "C", 600, NULL }, + { "u", 600, NULL }, + { "q", 600, NULL }, + { "l", 600, NULL }, + { "icircumflex", 600, NULL }, + { "Imacron", 600, NULL }, + { "abreve", 600, NULL }, + { "e", 600, NULL }, + { "iacute", 600, NULL }, + { "percent", 600, NULL }, + { "o", 600, NULL }, + { "greater", 600, NULL }, + { "Emacron", 600, NULL }, + { "asterisk", 600, NULL }, + { "scommaaccent", 600, NULL }, + { "onesuperior", 600, NULL }, + { "K", 600, NULL }, + { "Scommaaccent", 600, NULL }, + { "Aacute", 600, NULL }, + { "b", 600, NULL }, + { "Euro", 600, NULL }, + { "florin", 600, NULL }, + { "iogonek", 600, NULL }, + { "section", 600, NULL }, + { "Scaron", 600, NULL }, + { "degree", 600, NULL }, + { "lcaron", 600, NULL }, + { "paragraph", 600, NULL }, + { "zcaron", 600, NULL }, + { "aring", 600, NULL }, + { "Ydieresis", 600, NULL }, + { "Dcaron", 600, NULL }, + { "Z", 600, NULL }, + { "ecircumflex", 600, NULL }, + { "Amacron", 600, NULL }, + { "breve", 600, NULL }, + { "emdash", 600, NULL }, + { "Egrave", 600, NULL }, + { "aogonek", 600, NULL }, + { "ring", 600, NULL }, + { "Odieresis", 600, NULL }, + { "oe", 600, NULL }, + { "five", 600, NULL }, + { "X", 600, NULL }, + { "asciicircum", 600, NULL }, + { "plusminus", 600, NULL }, + { "Idotaccent", 600, NULL }, + { "cedilla", 600, NULL }, + { "quotedblright", 600, NULL }, + { "Eth", 600, NULL }, + { "colon", 600, NULL }, + { "g", 600, NULL }, + { "ccedilla", 600, NULL }, + { "radical", 600, NULL }, + { "Ntilde", 600, NULL }, + { "dotlessi", 600, NULL }, + { "p", 600, NULL } +}; + +static BuiltinFontWidth courierBoldObliqueWidthsTab[] = { + { "greater", 600, NULL }, + { "asterisk", 600, NULL }, + { "Emacron", 600, NULL }, + { "scommaaccent", 600, NULL }, + { "onesuperior", 600, NULL }, + { "percent", 600, NULL }, + { "o", 600, NULL }, + { "icircumflex", 600, NULL }, + { "iacute", 600, NULL }, + { "e", 600, NULL }, + { "Imacron", 600, NULL }, + { "abreve", 600, NULL }, + { "N", 600, NULL }, + { "equal", 600, NULL }, + { "dagger", 600, NULL }, + { "u", 600, NULL }, + { "C", 600, NULL }, + { "l", 600, NULL }, + { "q", 600, NULL }, + { "quoteleft", 600, NULL }, + { "registered", 600, NULL }, + { "Gcommaaccent", 600, NULL }, + { "Racute", 600, NULL }, + { "k", 600, NULL }, + { "copyright", 600, NULL }, + { "onehalf", 600, NULL }, + { "lcommaaccent", 600, NULL }, + { "uhungarumlaut", 600, NULL }, + { "gbreve", 600, NULL }, + { "n", 600, NULL }, + { "Ecaron", 600, NULL }, + { "zdotaccent", 600, NULL }, + { "threesuperior", 600, NULL }, + { "radical", 600, NULL }, + { "Ntilde", 600, NULL }, + { "p", 600, NULL }, + { "dotlessi", 600, NULL }, + { "cedilla", 600, NULL }, + { "Idotaccent", 600, NULL }, + { "plusminus", 600, NULL }, + { "Eth", 600, NULL }, + { "quotedblright", 600, NULL }, + { "ccedilla", 600, NULL }, + { "g", 600, NULL }, + { "colon", 600, NULL }, + { "oe", 600, NULL }, + { "Odieresis", 600, NULL }, + { "five", 600, NULL }, + { "asciicircum", 600, NULL }, + { "X", 600, NULL }, + { "emdash", 600, NULL }, + { "aogonek", 600, NULL }, + { "Egrave", 600, NULL }, + { "ring", 600, NULL }, + { "Dcaron", 600, NULL }, + { "ecircumflex", 600, NULL }, + { "Z", 600, NULL }, + { "breve", 600, NULL }, + { "Amacron", 600, NULL }, + { "paragraph", 600, NULL }, + { "zcaron", 600, NULL }, + { "lcaron", 600, NULL }, + { "Ydieresis", 600, NULL }, + { "aring", 600, NULL }, + { "iogonek", 600, NULL }, + { "florin", 600, NULL }, + { "Euro", 600, NULL }, + { "Scaron", 600, NULL }, + { "degree", 600, NULL }, + { "section", 600, NULL }, + { "K", 600, NULL }, + { "Aacute", 600, NULL }, + { "Scommaaccent", 600, NULL }, + { "b", 600, NULL }, + { "circumflex", 600, NULL }, + { "Zcaron", 600, NULL }, + { "ogonek", 600, NULL }, + { "idieresis", 600, NULL }, + { "ae", 600, NULL }, + { "cent", 600, NULL }, + { "less", 600, NULL }, + { "ocircumflex", 600, NULL }, + { "minus", 600, NULL }, + { "four", 600, NULL }, + { "Tcommaaccent", 600, NULL }, + { "dollar", 600, NULL }, + { "dotaccent", 600, NULL }, + { "v", 600, NULL }, + { "Nacute", 600, NULL }, + { "Kcommaaccent", 600, NULL }, + { "imacron", 600, NULL }, + { "rcommaaccent", 600, NULL }, + { "tilde", 600, NULL }, + { "underscore", 600, NULL }, + { "racute", 600, NULL }, + { "mu", 600, NULL }, + { "D", 600, NULL }, + { "Ccaron", 600, NULL }, + { "j", 600, NULL }, + { "hungarumlaut", 600, NULL }, + { "Y", 600, NULL }, + { "yen", 600, NULL }, + { "ccaron", 600, NULL }, + { "Ucircumflex", 600, NULL }, + { "lessequal", 600, NULL }, + { "Omacron", 600, NULL }, + { "quotesinglbase", 600, NULL }, + { "Scedilla", 600, NULL }, + { "grave", 600, NULL }, + { "parenleft", 600, NULL }, + { "nine", 600, NULL }, + { "currency", 600, NULL }, + { "odieresis", 600, NULL }, + { "M", 600, NULL }, + { "Ograve", 600, NULL }, + { "T", 600, NULL }, + { "amacron", 600, NULL }, + { "Ncommaaccent", 600, NULL }, + { "numbersign", 600, NULL }, + { "emacron", 600, NULL }, + { "divide", 600, NULL }, + { "fl", 600, NULL }, + { "quotedblbase", 600, NULL }, + { "E", 600, NULL }, + { "guillemotleft", 600, NULL }, + { "endash", 600, NULL }, + { "w", 600, NULL }, + { "eth", 600, NULL }, + { "twosuperior", 600, NULL }, + { "space", 600, NULL }, + { "Thorn", 600, NULL }, + { "ecaron", 600, NULL }, + { "brokenbar", 600, NULL }, + { "Aogonek", 600, NULL }, + { "commaaccent", 600, NULL }, + { "bracketright", 600, NULL }, + { "W", 600, NULL }, + { "germandbls", 600, NULL }, + { "Ugrave", 600, NULL }, + { "thorn", 600, NULL }, + { "zero", 600, NULL }, + { "udieresis", 600, NULL }, + { "scedilla", 600, NULL }, + { "period", 600, NULL }, + { "Ccedilla", 600, NULL }, + { "Igrave", 600, NULL }, + { "F", 600, NULL }, + { "Ocircumflex", 600, NULL }, + { "Uring", 600, NULL }, + { "perthousand", 600, NULL }, + { "Edotaccent", 600, NULL }, + { "acircumflex", 600, NULL }, + { "G", 600, NULL }, + { "Otilde", 600, NULL }, + { "umacron", 600, NULL }, + { "Tcaron", 600, NULL }, + { "aacute", 600, NULL }, + { "B", 600, NULL }, + { "ydieresis", 600, NULL }, + { "R", 600, NULL }, + { "kcommaaccent", 600, NULL }, + { "yacute", 600, NULL }, + { "Rcaron", 600, NULL }, + { "dcaron", 600, NULL }, + { "ugrave", 600, NULL }, + { "a", 600, NULL }, + { "hyphen", 600, NULL }, + { "Oslash", 600, NULL }, + { "comma", 600, NULL }, + { "Delta", 600, NULL }, + { "omacron", 600, NULL }, + { "Gbreve", 600, NULL }, + { "S", 600, NULL }, + { "quotedblleft", 600, NULL }, + { "ordfeminine", 600, NULL }, + { "ampersand", 600, NULL }, + { "trademark", 600, NULL }, + { "Lcommaaccent", 600, NULL }, + { "ntilde", 600, NULL }, + { "fi", 600, NULL }, + { "dieresis", 600, NULL }, + { "Eacute", 600, NULL }, + { "nacute", 600, NULL }, + { "O", 600, NULL }, + { "Icircumflex", 600, NULL }, + { "Udieresis", 600, NULL }, + { "Abreve", 600, NULL }, + { "Iacute", 600, NULL }, + { "uacute", 600, NULL }, + { "two", 600, NULL }, + { "seven", 600, NULL }, + { "scaron", 600, NULL }, + { "guillemotright", 600, NULL }, + { "eogonek", 600, NULL }, + { "eacute", 600, NULL }, + { "bullet", 600, NULL }, + { "Zdotaccent", 600, NULL }, + { "edotaccent", 600, NULL }, + { "six", 600, NULL }, + { "lslash", 600, NULL }, + { "P", 600, NULL }, + { "multiply", 600, NULL }, + { "i", 600, NULL }, + { "bar", 600, NULL }, + { "quotesingle", 600, NULL }, + { "acute", 600, NULL }, + { "braceright", 600, NULL }, + { "braceleft", 600, NULL }, + { "onequarter", 600, NULL }, + { "Atilde", 600, NULL }, + { "Edieresis", 600, NULL }, + { "Yacute", 600, NULL }, + { "oacute", 600, NULL }, + { "daggerdbl", 600, NULL }, + { "ncommaaccent", 600, NULL }, + { "logicalnot", 600, NULL }, + { "tcommaaccent", 600, NULL }, + { "Dcroat", 600, NULL }, + { "cacute", 600, NULL }, + { "rcaron", 600, NULL }, + { "tcaron", 600, NULL }, + { "y", 600, NULL }, + { "Iogonek", 600, NULL }, + { "edieresis", 600, NULL }, + { "x", 600, NULL }, + { "Ncaron", 600, NULL }, + { "OE", 600, NULL }, + { "m", 600, NULL }, + { "U", 600, NULL }, + { "partialdiff", 600, NULL }, + { "dcroat", 600, NULL }, + { "igrave", 600, NULL }, + { "summation", 600, NULL }, + { "question", 600, NULL }, + { "A", 600, NULL }, + { "h", 600, NULL }, + { "Cacute", 600, NULL }, + { "guilsinglleft", 600, NULL }, + { "plus", 600, NULL }, + { "ordmasculine", 600, NULL }, + { "Lcaron", 600, NULL }, + { "backslash", 600, NULL }, + { "questiondown", 600, NULL }, + { "macron", 600, NULL }, + { "Eogonek", 600, NULL }, + { "three", 600, NULL }, + { "slash", 600, NULL }, + { "ucircumflex", 600, NULL }, + { "r", 600, NULL }, + { "zacute", 600, NULL }, + { "Umacron", 600, NULL }, + { "adieresis", 600, NULL }, + { "ncaron", 600, NULL }, + { "V", 600, NULL }, + { "lozenge", 600, NULL }, + { "exclamdown", 600, NULL }, + { "Q", 600, NULL }, + { "quoteright", 600, NULL }, + { "uogonek", 600, NULL }, + { "guilsinglright", 600, NULL }, + { "semicolon", 600, NULL }, + { "egrave", 600, NULL }, + { "s", 600, NULL }, + { "uring", 600, NULL }, + { "Uhungarumlaut", 600, NULL }, + { "z", 600, NULL }, + { "I", 600, NULL }, + { "one", 600, NULL }, + { "eight", 600, NULL }, + { "periodcentered", 600, NULL }, + { "d", 600, NULL }, + { "c", 600, NULL }, + { "agrave", 600, NULL }, + { "ellipsis", 600, NULL }, + { "Aring", 600, NULL }, + { "t", 600, NULL }, + { "quotedbl", 600, NULL }, + { "Oacute", 600, NULL }, + { "Uacute", 600, NULL }, + { "Zacute", 600, NULL }, + { "atilde", 600, NULL }, + { "fraction", 600, NULL }, + { "Adieresis", 600, NULL }, + { "Sacute", 600, NULL }, + { "asciitilde", 600, NULL }, + { "lacute", 600, NULL }, + { "Uogonek", 600, NULL }, + { "Lslash", 600, NULL }, + { "caron", 600, NULL }, + { "sterling", 600, NULL }, + { "H", 600, NULL }, + { "greaterequal", 600, NULL }, + { "at", 600, NULL }, + { "J", 600, NULL }, + { "threequarters", 600, NULL }, + { "ohungarumlaut", 600, NULL }, + { "Ecircumflex", 600, NULL }, + { "L", 600, NULL }, + { "AE", 600, NULL }, + { "Agrave", 600, NULL }, + { "exclam", 600, NULL }, + { "notequal", 600, NULL }, + { "oslash", 600, NULL }, + { "Acircumflex", 600, NULL }, + { "Rcommaaccent", 600, NULL }, + { "ograve", 600, NULL }, + { "Lacute", 600, NULL }, + { "Idieresis", 600, NULL }, + { "sacute", 600, NULL }, + { "f", 600, NULL }, + { "gcommaaccent", 600, NULL }, + { "bracketleft", 600, NULL }, + { "Ohungarumlaut", 600, NULL }, + { "otilde", 600, NULL }, + { "parenright", 600, NULL } +}; + +static BuiltinFontWidth courierObliqueWidthsTab[] = { + { "ecaron", 600, NULL }, + { "brokenbar", 600, NULL }, + { "Aogonek", 600, NULL }, + { "w", 600, NULL }, + { "Thorn", 600, NULL }, + { "space", 600, NULL }, + { "eth", 600, NULL }, + { "twosuperior", 600, NULL }, + { "guillemotleft", 600, NULL }, + { "endash", 600, NULL }, + { "fl", 600, NULL }, + { "E", 600, NULL }, + { "quotedblbase", 600, NULL }, + { "numbersign", 600, NULL }, + { "divide", 600, NULL }, + { "emacron", 600, NULL }, + { "amacron", 600, NULL }, + { "Ncommaaccent", 600, NULL }, + { "T", 600, NULL }, + { "M", 600, NULL }, + { "odieresis", 600, NULL }, + { "Ograve", 600, NULL }, + { "G", 600, NULL }, + { "perthousand", 600, NULL }, + { "Edotaccent", 600, NULL }, + { "acircumflex", 600, NULL }, + { "Ocircumflex", 600, NULL }, + { "F", 600, NULL }, + { "Uring", 600, NULL }, + { "Ccedilla", 600, NULL }, + { "Igrave", 600, NULL }, + { "zero", 600, NULL }, + { "scedilla", 600, NULL }, + { "period", 600, NULL }, + { "udieresis", 600, NULL }, + { "Ugrave", 600, NULL }, + { "germandbls", 600, NULL }, + { "thorn", 600, NULL }, + { "commaaccent", 600, NULL }, + { "W", 600, NULL }, + { "bracketright", 600, NULL }, + { "underscore", 600, NULL }, + { "D", 600, NULL }, + { "mu", 600, NULL }, + { "racute", 600, NULL }, + { "rcommaaccent", 600, NULL }, + { "imacron", 600, NULL }, + { "Kcommaaccent", 600, NULL }, + { "tilde", 600, NULL }, + { "Tcommaaccent", 600, NULL }, + { "dollar", 600, NULL }, + { "v", 600, NULL }, + { "Nacute", 600, NULL }, + { "dotaccent", 600, NULL }, + { "ocircumflex", 600, NULL }, + { "less", 600, NULL }, + { "minus", 600, NULL }, + { "four", 600, NULL }, + { "ae", 600, NULL }, + { "cent", 600, NULL }, + { "ogonek", 600, NULL }, + { "idieresis", 600, NULL }, + { "circumflex", 600, NULL }, + { "Zcaron", 600, NULL }, + { "currency", 600, NULL }, + { "nine", 600, NULL }, + { "parenleft", 600, NULL }, + { "grave", 600, NULL }, + { "Scedilla", 600, NULL }, + { "quotesinglbase", 600, NULL }, + { "lessequal", 600, NULL }, + { "Omacron", 600, NULL }, + { "Ucircumflex", 600, NULL }, + { "ccaron", 600, NULL }, + { "yen", 600, NULL }, + { "Y", 600, NULL }, + { "hungarumlaut", 600, NULL }, + { "Ccaron", 600, NULL }, + { "j", 600, NULL }, + { "aogonek", 600, NULL }, + { "Egrave", 600, NULL }, + { "ring", 600, NULL }, + { "emdash", 600, NULL }, + { "five", 600, NULL }, + { "X", 600, NULL }, + { "asciicircum", 600, NULL }, + { "Odieresis", 600, NULL }, + { "oe", 600, NULL }, + { "colon", 600, NULL }, + { "g", 600, NULL }, + { "ccedilla", 600, NULL }, + { "plusminus", 600, NULL }, + { "cedilla", 600, NULL }, + { "Idotaccent", 600, NULL }, + { "quotedblright", 600, NULL }, + { "Eth", 600, NULL }, + { "dotlessi", 600, NULL }, + { "p", 600, NULL }, + { "radical", 600, NULL }, + { "Ntilde", 600, NULL }, + { "Scommaaccent", 600, NULL }, + { "Aacute", 600, NULL }, + { "b", 600, NULL }, + { "K", 600, NULL }, + { "section", 600, NULL }, + { "degree", 600, NULL }, + { "Scaron", 600, NULL }, + { "Euro", 600, NULL }, + { "florin", 600, NULL }, + { "iogonek", 600, NULL }, + { "lcaron", 600, NULL }, + { "paragraph", 600, NULL }, + { "zcaron", 600, NULL }, + { "aring", 600, NULL }, + { "Ydieresis", 600, NULL }, + { "Amacron", 600, NULL }, + { "breve", 600, NULL }, + { "Dcaron", 600, NULL }, + { "Z", 600, NULL }, + { "ecircumflex", 600, NULL }, + { "q", 600, NULL }, + { "l", 600, NULL }, + { "dagger", 600, NULL }, + { "equal", 600, NULL }, + { "N", 600, NULL }, + { "C", 600, NULL }, + { "u", 600, NULL }, + { "abreve", 600, NULL }, + { "Imacron", 600, NULL }, + { "iacute", 600, NULL }, + { "e", 600, NULL }, + { "icircumflex", 600, NULL }, + { "percent", 600, NULL }, + { "o", 600, NULL }, + { "asterisk", 600, NULL }, + { "Emacron", 600, NULL }, + { "scommaaccent", 600, NULL }, + { "onesuperior", 600, NULL }, + { "greater", 600, NULL }, + { "Ecaron", 600, NULL }, + { "threesuperior", 600, NULL }, + { "zdotaccent", 600, NULL }, + { "n", 600, NULL }, + { "lcommaaccent", 600, NULL }, + { "onehalf", 600, NULL }, + { "gbreve", 600, NULL }, + { "uhungarumlaut", 600, NULL }, + { "k", 600, NULL }, + { "copyright", 600, NULL }, + { "Racute", 600, NULL }, + { "Gcommaaccent", 600, NULL }, + { "quoteleft", 600, NULL }, + { "registered", 600, NULL }, + { "notequal", 600, NULL }, + { "Agrave", 600, NULL }, + { "AE", 600, NULL }, + { "exclam", 600, NULL }, + { "Acircumflex", 600, NULL }, + { "oslash", 600, NULL }, + { "threequarters", 600, NULL }, + { "J", 600, NULL }, + { "Ecircumflex", 600, NULL }, + { "ohungarumlaut", 600, NULL }, + { "L", 600, NULL }, + { "H", 600, NULL }, + { "sterling", 600, NULL }, + { "greaterequal", 600, NULL }, + { "at", 600, NULL }, + { "caron", 600, NULL }, + { "Uogonek", 600, NULL }, + { "Lslash", 600, NULL }, + { "lacute", 600, NULL }, + { "asciitilde", 600, NULL }, + { "fraction", 600, NULL }, + { "Sacute", 600, NULL }, + { "Adieresis", 600, NULL }, + { "Uacute", 600, NULL }, + { "atilde", 600, NULL }, + { "Zacute", 600, NULL }, + { "otilde", 600, NULL }, + { "parenright", 600, NULL }, + { "gcommaaccent", 600, NULL }, + { "Ohungarumlaut", 600, NULL }, + { "bracketleft", 600, NULL }, + { "f", 600, NULL }, + { "Lacute", 600, NULL }, + { "Idieresis", 600, NULL }, + { "sacute", 600, NULL }, + { "Rcommaaccent", 600, NULL }, + { "ograve", 600, NULL }, + { "quoteright", 600, NULL }, + { "uogonek", 600, NULL }, + { "semicolon", 600, NULL }, + { "guilsinglright", 600, NULL }, + { "lozenge", 600, NULL }, + { "V", 600, NULL }, + { "Q", 600, NULL }, + { "exclamdown", 600, NULL }, + { "Umacron", 600, NULL }, + { "zacute", 600, NULL }, + { "ncaron", 600, NULL }, + { "adieresis", 600, NULL }, + { "slash", 600, NULL }, + { "ucircumflex", 600, NULL }, + { "r", 600, NULL }, + { "three", 600, NULL }, + { "Eogonek", 600, NULL }, + { "macron", 600, NULL }, + { "Lcaron", 600, NULL }, + { "ordmasculine", 600, NULL }, + { "backslash", 600, NULL }, + { "questiondown", 600, NULL }, + { "Oacute", 600, NULL }, + { "t", 600, NULL }, + { "quotedbl", 600, NULL }, + { "ellipsis", 600, NULL }, + { "Aring", 600, NULL }, + { "agrave", 600, NULL }, + { "c", 600, NULL }, + { "d", 600, NULL }, + { "one", 600, NULL }, + { "I", 600, NULL }, + { "eight", 600, NULL }, + { "periodcentered", 600, NULL }, + { "z", 600, NULL }, + { "Uhungarumlaut", 600, NULL }, + { "egrave", 600, NULL }, + { "uring", 600, NULL }, + { "s", 600, NULL }, + { "oacute", 600, NULL }, + { "Yacute", 600, NULL }, + { "daggerdbl", 600, NULL }, + { "Atilde", 600, NULL }, + { "Edieresis", 600, NULL }, + { "onequarter", 600, NULL }, + { "braceleft", 600, NULL }, + { "braceright", 600, NULL }, + { "acute", 600, NULL }, + { "quotesingle", 600, NULL }, + { "bar", 600, NULL }, + { "i", 600, NULL }, + { "multiply", 600, NULL }, + { "lslash", 600, NULL }, + { "P", 600, NULL }, + { "six", 600, NULL }, + { "edotaccent", 600, NULL }, + { "guilsinglleft", 600, NULL }, + { "h", 600, NULL }, + { "Cacute", 600, NULL }, + { "plus", 600, NULL }, + { "question", 600, NULL }, + { "summation", 600, NULL }, + { "A", 600, NULL }, + { "igrave", 600, NULL }, + { "dcroat", 600, NULL }, + { "m", 600, NULL }, + { "OE", 600, NULL }, + { "partialdiff", 600, NULL }, + { "U", 600, NULL }, + { "x", 600, NULL }, + { "y", 600, NULL }, + { "Iogonek", 600, NULL }, + { "edieresis", 600, NULL }, + { "Ncaron", 600, NULL }, + { "cacute", 600, NULL }, + { "Dcroat", 600, NULL }, + { "rcaron", 600, NULL }, + { "tcaron", 600, NULL }, + { "ncommaaccent", 600, NULL }, + { "tcommaaccent", 600, NULL }, + { "logicalnot", 600, NULL }, + { "ordfeminine", 600, NULL }, + { "quotedblleft", 600, NULL }, + { "S", 600, NULL }, + { "omacron", 600, NULL }, + { "Delta", 600, NULL }, + { "comma", 600, NULL }, + { "Gbreve", 600, NULL }, + { "ugrave", 600, NULL }, + { "dcaron", 600, NULL }, + { "hyphen", 600, NULL }, + { "Oslash", 600, NULL }, + { "a", 600, NULL }, + { "B", 600, NULL }, + { "Rcaron", 600, NULL }, + { "kcommaaccent", 600, NULL }, + { "yacute", 600, NULL }, + { "ydieresis", 600, NULL }, + { "R", 600, NULL }, + { "aacute", 600, NULL }, + { "umacron", 600, NULL }, + { "Otilde", 600, NULL }, + { "Tcaron", 600, NULL }, + { "eogonek", 600, NULL }, + { "bullet", 600, NULL }, + { "eacute", 600, NULL }, + { "Zdotaccent", 600, NULL }, + { "scaron", 600, NULL }, + { "guillemotright", 600, NULL }, + { "two", 600, NULL }, + { "uacute", 600, NULL }, + { "seven", 600, NULL }, + { "Abreve", 600, NULL }, + { "Udieresis", 600, NULL }, + { "Iacute", 600, NULL }, + { "Icircumflex", 600, NULL }, + { "O", 600, NULL }, + { "nacute", 600, NULL }, + { "dieresis", 600, NULL }, + { "Eacute", 600, NULL }, + { "ntilde", 600, NULL }, + { "fi", 600, NULL }, + { "trademark", 600, NULL }, + { "ampersand", 600, NULL }, + { "Lcommaaccent", 600, NULL } +}; + +static BuiltinFontWidth helveticaWidthsTab[] = { + { "lcommaaccent", 222, NULL }, + { "onehalf", 834, NULL }, + { "uhungarumlaut", 556, NULL }, + { "gbreve", 556, NULL }, + { "n", 556, NULL }, + { "Ecaron", 667, NULL }, + { "threesuperior", 333, NULL }, + { "zdotaccent", 500, NULL }, + { "quoteleft", 222, NULL }, + { "registered", 737, NULL }, + { "Gcommaaccent", 778, NULL }, + { "Racute", 722, NULL }, + { "k", 500, NULL }, + { "copyright", 737, NULL }, + { "icircumflex", 278, NULL }, + { "abreve", 556, NULL }, + { "Imacron", 278, NULL }, + { "iacute", 278, NULL }, + { "e", 556, NULL }, + { "equal", 584, NULL }, + { "dagger", 556, NULL }, + { "N", 722, NULL }, + { "C", 722, NULL }, + { "u", 556, NULL }, + { "q", 556, NULL }, + { "l", 222, NULL }, + { "greater", 584, NULL }, + { "asterisk", 389, NULL }, + { "Emacron", 667, NULL }, + { "scommaaccent", 500, NULL }, + { "onesuperior", 333, NULL }, + { "percent", 889, NULL }, + { "o", 556, NULL }, + { "Euro", 556, NULL }, + { "florin", 556, NULL }, + { "iogonek", 222, NULL }, + { "section", 556, NULL }, + { "Scaron", 667, NULL }, + { "degree", 400, NULL }, + { "K", 667, NULL }, + { "Scommaaccent", 667, NULL }, + { "Aacute", 667, NULL }, + { "b", 556, NULL }, + { "Dcaron", 722, NULL }, + { "Z", 611, NULL }, + { "ecircumflex", 556, NULL }, + { "Amacron", 667, NULL }, + { "breve", 333, NULL }, + { "lcaron", 299, NULL }, + { "paragraph", 537, NULL }, + { "zcaron", 500, NULL }, + { "aring", 556, NULL }, + { "Ydieresis", 667, NULL }, + { "Odieresis", 778, NULL }, + { "oe", 944, NULL }, + { "five", 556, NULL }, + { "X", 667, NULL }, + { "asciicircum", 469, NULL }, + { "emdash", 1000, NULL }, + { "Egrave", 667, NULL }, + { "aogonek", 556, NULL }, + { "ring", 333, NULL }, + { "Ntilde", 722, NULL }, + { "radical", 453, NULL }, + { "dotlessi", 278, NULL }, + { "p", 556, NULL }, + { "plusminus", 584, NULL }, + { "cedilla", 333, NULL }, + { "Idotaccent", 278, NULL }, + { "quotedblright", 333, NULL }, + { "Eth", 722, NULL }, + { "g", 556, NULL }, + { "colon", 278, NULL }, + { "ccedilla", 500, NULL }, + { "quotesinglbase", 222, NULL }, + { "grave", 333, NULL }, + { "Scedilla", 667, NULL }, + { "parenleft", 333, NULL }, + { "currency", 556, NULL }, + { "nine", 556, NULL }, + { "hungarumlaut", 333, NULL }, + { "Ccaron", 722, NULL }, + { "j", 222, NULL }, + { "yen", 556, NULL }, + { "Y", 667, NULL }, + { "ccaron", 500, NULL }, + { "Omacron", 778, NULL }, + { "lessequal", 549, NULL }, + { "Ucircumflex", 722, NULL }, + { "dollar", 556, NULL }, + { "Tcommaaccent", 611, NULL }, + { "Nacute", 722, NULL }, + { "v", 500, NULL }, + { "dotaccent", 333, NULL }, + { "rcommaaccent", 333, NULL }, + { "Kcommaaccent", 667, NULL }, + { "imacron", 278, NULL }, + { "tilde", 333, NULL }, + { "underscore", 556, NULL }, + { "mu", 556, NULL }, + { "D", 722, NULL }, + { "racute", 333, NULL }, + { "circumflex", 333, NULL }, + { "Zcaron", 611, NULL }, + { "ogonek", 333, NULL }, + { "idieresis", 278, NULL }, + { "cent", 556, NULL }, + { "ae", 889, NULL }, + { "ocircumflex", 556, NULL }, + { "less", 584, NULL }, + { "minus", 584, NULL }, + { "four", 556, NULL }, + { "F", 611, NULL }, + { "Ocircumflex", 778, NULL }, + { "Uring", 722, NULL }, + { "Edotaccent", 667, NULL }, + { "perthousand", 1000, NULL }, + { "acircumflex", 556, NULL }, + { "G", 778, NULL }, + { "commaaccent", 250, NULL }, + { "W", 944, NULL }, + { "bracketright", 278, NULL }, + { "Ugrave", 722, NULL }, + { "germandbls", 611, NULL }, + { "thorn", 556, NULL }, + { "zero", 556, NULL }, + { "period", 278, NULL }, + { "scedilla", 500, NULL }, + { "udieresis", 556, NULL }, + { "Ccedilla", 722, NULL }, + { "Igrave", 278, NULL }, + { "fl", 500, NULL }, + { "quotedblbase", 333, NULL }, + { "E", 667, NULL }, + { "endash", 556, NULL }, + { "guillemotleft", 556, NULL }, + { "w", 722, NULL }, + { "space", 278, NULL }, + { "Thorn", 667, NULL }, + { "eth", 556, NULL }, + { "twosuperior", 333, NULL }, + { "ecaron", 556, NULL }, + { "brokenbar", 260, NULL }, + { "Aogonek", 667, NULL }, + { "M", 833, NULL }, + { "odieresis", 556, NULL }, + { "Ograve", 778, NULL }, + { "T", 611, NULL }, + { "amacron", 556, NULL }, + { "Ncommaaccent", 722, NULL }, + { "numbersign", 556, NULL }, + { "divide", 584, NULL }, + { "emacron", 556, NULL }, + { "Abreve", 667, NULL }, + { "Udieresis", 722, NULL }, + { "Iacute", 278, NULL }, + { "two", 556, NULL }, + { "uacute", 556, NULL }, + { "seven", 556, NULL }, + { "scaron", 500, NULL }, + { "guillemotright", 556, NULL }, + { "bullet", 350, NULL }, + { "eogonek", 556, NULL }, + { "eacute", 556, NULL }, + { "Zdotaccent", 611, NULL }, + { "trademark", 1000, NULL }, + { "ampersand", 667, NULL }, + { "Lcommaaccent", 556, NULL }, + { "ntilde", 556, NULL }, + { "fi", 500, NULL }, + { "dieresis", 333, NULL }, + { "Eacute", 667, NULL }, + { "O", 778, NULL }, + { "Icircumflex", 278, NULL }, + { "nacute", 556, NULL }, + { "omacron", 556, NULL }, + { "comma", 278, NULL }, + { "Delta", 612, NULL }, + { "Gbreve", 778, NULL }, + { "S", 667, NULL }, + { "quotedblleft", 333, NULL }, + { "ordfeminine", 370, NULL }, + { "Otilde", 778, NULL }, + { "umacron", 556, NULL }, + { "Tcaron", 611, NULL }, + { "aacute", 556, NULL }, + { "B", 667, NULL }, + { "kcommaaccent", 500, NULL }, + { "Rcaron", 722, NULL }, + { "yacute", 500, NULL }, + { "ydieresis", 500, NULL }, + { "R", 722, NULL }, + { "ugrave", 556, NULL }, + { "dcaron", 643, NULL }, + { "hyphen", 333, NULL }, + { "Oslash", 778, NULL }, + { "a", 556, NULL }, + { "igrave", 278, NULL }, + { "dcroat", 556, NULL }, + { "question", 556, NULL }, + { "summation", 600, NULL }, + { "A", 667, NULL }, + { "guilsinglleft", 333, NULL }, + { "h", 556, NULL }, + { "Cacute", 722, NULL }, + { "plus", 584, NULL }, + { "ncommaaccent", 556, NULL }, + { "tcommaaccent", 278, NULL }, + { "logicalnot", 584, NULL }, + { "cacute", 500, NULL }, + { "Dcroat", 722, NULL }, + { "tcaron", 317, NULL }, + { "rcaron", 333, NULL }, + { "x", 500, NULL }, + { "Iogonek", 278, NULL }, + { "y", 500, NULL }, + { "edieresis", 556, NULL }, + { "Ncaron", 722, NULL }, + { "m", 833, NULL }, + { "OE", 1000, NULL }, + { "U", 722, NULL }, + { "partialdiff", 476, NULL }, + { "braceright", 334, NULL }, + { "braceleft", 334, NULL }, + { "acute", 333, NULL }, + { "onequarter", 834, NULL }, + { "Atilde", 667, NULL }, + { "Edieresis", 667, NULL }, + { "Yacute", 667, NULL }, + { "oacute", 556, NULL }, + { "daggerdbl", 556, NULL }, + { "six", 556, NULL }, + { "edotaccent", 556, NULL }, + { "P", 667, NULL }, + { "lslash", 222, NULL }, + { "multiply", 584, NULL }, + { "i", 222, NULL }, + { "quotesingle", 191, NULL }, + { "bar", 260, NULL }, + { "agrave", 556, NULL }, + { "ellipsis", 1000, NULL }, + { "Aring", 667, NULL }, + { "t", 278, NULL }, + { "quotedbl", 355, NULL }, + { "Oacute", 778, NULL }, + { "egrave", 556, NULL }, + { "uring", 556, NULL }, + { "s", 500, NULL }, + { "Uhungarumlaut", 722, NULL }, + { "z", 500, NULL }, + { "eight", 556, NULL }, + { "I", 278, NULL }, + { "one", 556, NULL }, + { "periodcentered", 278, NULL }, + { "c", 500, NULL }, + { "d", 556, NULL }, + { "zacute", 500, NULL }, + { "Umacron", 722, NULL }, + { "ncaron", 556, NULL }, + { "adieresis", 556, NULL }, + { "lozenge", 471, NULL }, + { "V", 667, NULL }, + { "Q", 778, NULL }, + { "exclamdown", 333, NULL }, + { "quoteright", 222, NULL }, + { "uogonek", 556, NULL }, + { "semicolon", 278, NULL }, + { "guilsinglright", 333, NULL }, + { "Eogonek", 667, NULL }, + { "macron", 333, NULL }, + { "ordmasculine", 365, NULL }, + { "Lcaron", 556, NULL }, + { "backslash", 278, NULL }, + { "questiondown", 611, NULL }, + { "three", 556, NULL }, + { "slash", 278, NULL }, + { "ucircumflex", 556, NULL }, + { "r", 333, NULL }, + { "f", 278, NULL }, + { "gcommaaccent", 556, NULL }, + { "Ohungarumlaut", 778, NULL }, + { "bracketleft", 278, NULL }, + { "otilde", 556, NULL }, + { "parenright", 333, NULL }, + { "Rcommaaccent", 722, NULL }, + { "ograve", 556, NULL }, + { "Lacute", 556, NULL }, + { "sacute", 500, NULL }, + { "Idieresis", 278, NULL }, + { "Uogonek", 722, NULL }, + { "Lslash", 556, NULL }, + { "caron", 333, NULL }, + { "lacute", 222, NULL }, + { "sterling", 556, NULL }, + { "H", 722, NULL }, + { "at", 1015, NULL }, + { "greaterequal", 549, NULL }, + { "threequarters", 834, NULL }, + { "J", 500, NULL }, + { "L", 556, NULL }, + { "ohungarumlaut", 556, NULL }, + { "Ecircumflex", 667, NULL }, + { "notequal", 549, NULL }, + { "exclam", 278, NULL }, + { "Agrave", 667, NULL }, + { "AE", 1000, NULL }, + { "Acircumflex", 667, NULL }, + { "oslash", 611, NULL }, + { "Uacute", 722, NULL }, + { "atilde", 556, NULL }, + { "Zacute", 611, NULL }, + { "fraction", 167, NULL }, + { "Sacute", 667, NULL }, + { "Adieresis", 667, NULL }, + { "asciitilde", 584, NULL } +}; + +static BuiltinFontWidth helveticaBoldWidthsTab[] = { + { "uogonek", 611, NULL }, + { "quoteright", 278, NULL }, + { "guilsinglright", 333, NULL }, + { "semicolon", 333, NULL }, + { "V", 667, NULL }, + { "lozenge", 494, NULL }, + { "exclamdown", 333, NULL }, + { "Q", 778, NULL }, + { "zacute", 500, NULL }, + { "Umacron", 722, NULL }, + { "adieresis", 556, NULL }, + { "ncaron", 611, NULL }, + { "slash", 278, NULL }, + { "r", 389, NULL }, + { "ucircumflex", 611, NULL }, + { "three", 556, NULL }, + { "ordmasculine", 365, NULL }, + { "Lcaron", 611, NULL }, + { "backslash", 278, NULL }, + { "questiondown", 611, NULL }, + { "macron", 333, NULL }, + { "Eogonek", 667, NULL }, + { "Oacute", 778, NULL }, + { "t", 333, NULL }, + { "quotedbl", 474, NULL }, + { "ellipsis", 1000, NULL }, + { "Aring", 722, NULL }, + { "agrave", 556, NULL }, + { "d", 611, NULL }, + { "c", 556, NULL }, + { "I", 278, NULL }, + { "one", 556, NULL }, + { "eight", 556, NULL }, + { "periodcentered", 278, NULL }, + { "z", 500, NULL }, + { "Uhungarumlaut", 722, NULL }, + { "egrave", 556, NULL }, + { "s", 556, NULL }, + { "uring", 611, NULL }, + { "Agrave", 722, NULL }, + { "AE", 1000, NULL }, + { "exclam", 333, NULL }, + { "notequal", 549, NULL }, + { "oslash", 611, NULL }, + { "Acircumflex", 722, NULL }, + { "J", 556, NULL }, + { "threequarters", 834, NULL }, + { "ohungarumlaut", 611, NULL }, + { "L", 611, NULL }, + { "Ecircumflex", 667, NULL }, + { "H", 722, NULL }, + { "sterling", 556, NULL }, + { "greaterequal", 549, NULL }, + { "at", 975, NULL }, + { "lacute", 278, NULL }, + { "Uogonek", 722, NULL }, + { "caron", 333, NULL }, + { "Lslash", 611, NULL }, + { "asciitilde", 584, NULL }, + { "fraction", 167, NULL }, + { "Adieresis", 722, NULL }, + { "Sacute", 667, NULL }, + { "Uacute", 722, NULL }, + { "Zacute", 611, NULL }, + { "atilde", 556, NULL }, + { "otilde", 611, NULL }, + { "parenright", 333, NULL }, + { "gcommaaccent", 611, NULL }, + { "bracketleft", 333, NULL }, + { "Ohungarumlaut", 778, NULL }, + { "f", 333, NULL }, + { "Lacute", 611, NULL }, + { "sacute", 556, NULL }, + { "Idieresis", 278, NULL }, + { "ograve", 611, NULL }, + { "Rcommaaccent", 722, NULL }, + { "ordfeminine", 370, NULL }, + { "quotedblleft", 500, NULL }, + { "S", 667, NULL }, + { "comma", 278, NULL }, + { "Delta", 612, NULL }, + { "omacron", 611, NULL }, + { "Gbreve", 778, NULL }, + { "dcaron", 743, NULL }, + { "ugrave", 611, NULL }, + { "a", 556, NULL }, + { "hyphen", 333, NULL }, + { "Oslash", 778, NULL }, + { "B", 722, NULL }, + { "R", 722, NULL }, + { "ydieresis", 556, NULL }, + { "yacute", 556, NULL }, + { "kcommaaccent", 556, NULL }, + { "Rcaron", 722, NULL }, + { "aacute", 556, NULL }, + { "Otilde", 778, NULL }, + { "umacron", 611, NULL }, + { "Tcaron", 611, NULL }, + { "bullet", 350, NULL }, + { "eogonek", 556, NULL }, + { "eacute", 556, NULL }, + { "Zdotaccent", 611, NULL }, + { "scaron", 556, NULL }, + { "guillemotright", 556, NULL }, + { "uacute", 611, NULL }, + { "two", 556, NULL }, + { "seven", 556, NULL }, + { "Abreve", 722, NULL }, + { "Udieresis", 722, NULL }, + { "Iacute", 278, NULL }, + { "nacute", 611, NULL }, + { "O", 778, NULL }, + { "Icircumflex", 278, NULL }, + { "dieresis", 333, NULL }, + { "Eacute", 667, NULL }, + { "ntilde", 611, NULL }, + { "fi", 611, NULL }, + { "ampersand", 722, NULL }, + { "trademark", 1000, NULL }, + { "Lcommaaccent", 611, NULL }, + { "Yacute", 667, NULL }, + { "oacute", 611, NULL }, + { "daggerdbl", 556, NULL }, + { "Atilde", 722, NULL }, + { "Edieresis", 667, NULL }, + { "onequarter", 834, NULL }, + { "acute", 333, NULL }, + { "braceright", 389, NULL }, + { "braceleft", 389, NULL }, + { "quotesingle", 238, NULL }, + { "bar", 280, NULL }, + { "i", 278, NULL }, + { "multiply", 584, NULL }, + { "lslash", 278, NULL }, + { "P", 667, NULL }, + { "edotaccent", 556, NULL }, + { "six", 556, NULL }, + { "Cacute", 722, NULL }, + { "h", 611, NULL }, + { "guilsinglleft", 333, NULL }, + { "plus", 584, NULL }, + { "summation", 600, NULL }, + { "question", 611, NULL }, + { "A", 722, NULL }, + { "dcroat", 611, NULL }, + { "igrave", 278, NULL }, + { "OE", 1000, NULL }, + { "m", 889, NULL }, + { "U", 722, NULL }, + { "partialdiff", 494, NULL }, + { "y", 556, NULL }, + { "Iogonek", 278, NULL }, + { "edieresis", 556, NULL }, + { "x", 556, NULL }, + { "Ncaron", 722, NULL }, + { "Dcroat", 722, NULL }, + { "cacute", 556, NULL }, + { "tcaron", 389, NULL }, + { "rcaron", 389, NULL }, + { "ncommaaccent", 611, NULL }, + { "logicalnot", 584, NULL }, + { "tcommaaccent", 333, NULL }, + { "underscore", 556, NULL }, + { "racute", 389, NULL }, + { "D", 722, NULL }, + { "mu", 611, NULL }, + { "Kcommaaccent", 722, NULL }, + { "imacron", 278, NULL }, + { "rcommaaccent", 389, NULL }, + { "tilde", 333, NULL }, + { "dollar", 556, NULL }, + { "Tcommaaccent", 611, NULL }, + { "dotaccent", 333, NULL }, + { "Nacute", 722, NULL }, + { "v", 556, NULL }, + { "less", 584, NULL }, + { "ocircumflex", 611, NULL }, + { "four", 556, NULL }, + { "minus", 584, NULL }, + { "ae", 889, NULL }, + { "cent", 556, NULL }, + { "ogonek", 333, NULL }, + { "idieresis", 278, NULL }, + { "circumflex", 333, NULL }, + { "Zcaron", 611, NULL }, + { "nine", 556, NULL }, + { "currency", 556, NULL }, + { "parenleft", 333, NULL }, + { "Scedilla", 667, NULL }, + { "grave", 333, NULL }, + { "quotesinglbase", 278, NULL }, + { "Ucircumflex", 722, NULL }, + { "lessequal", 549, NULL }, + { "Omacron", 778, NULL }, + { "ccaron", 556, NULL }, + { "Y", 667, NULL }, + { "yen", 556, NULL }, + { "Ccaron", 722, NULL }, + { "j", 278, NULL }, + { "hungarumlaut", 333, NULL }, + { "ecaron", 556, NULL }, + { "brokenbar", 280, NULL }, + { "Aogonek", 722, NULL }, + { "w", 778, NULL }, + { "twosuperior", 333, NULL }, + { "eth", 611, NULL }, + { "Thorn", 667, NULL }, + { "space", 278, NULL }, + { "guillemotleft", 556, NULL }, + { "endash", 556, NULL }, + { "fl", 611, NULL }, + { "E", 667, NULL }, + { "quotedblbase", 500, NULL }, + { "numbersign", 556, NULL }, + { "emacron", 556, NULL }, + { "divide", 584, NULL }, + { "amacron", 556, NULL }, + { "Ncommaaccent", 722, NULL }, + { "T", 611, NULL }, + { "odieresis", 611, NULL }, + { "M", 833, NULL }, + { "Ograve", 778, NULL }, + { "G", 778, NULL }, + { "perthousand", 1000, NULL }, + { "Edotaccent", 667, NULL }, + { "acircumflex", 556, NULL }, + { "F", 611, NULL }, + { "Ocircumflex", 778, NULL }, + { "Uring", 722, NULL }, + { "Ccedilla", 722, NULL }, + { "Igrave", 278, NULL }, + { "zero", 556, NULL }, + { "udieresis", 611, NULL }, + { "period", 278, NULL }, + { "scedilla", 556, NULL }, + { "germandbls", 611, NULL }, + { "Ugrave", 722, NULL }, + { "thorn", 611, NULL }, + { "commaaccent", 250, NULL }, + { "W", 944, NULL }, + { "bracketright", 333, NULL }, + { "l", 278, NULL }, + { "q", 611, NULL }, + { "N", 722, NULL }, + { "dagger", 556, NULL }, + { "equal", 584, NULL }, + { "u", 611, NULL }, + { "C", 722, NULL }, + { "iacute", 278, NULL }, + { "e", 556, NULL }, + { "Imacron", 278, NULL }, + { "abreve", 556, NULL }, + { "icircumflex", 278, NULL }, + { "percent", 889, NULL }, + { "o", 611, NULL }, + { "asterisk", 389, NULL }, + { "Emacron", 667, NULL }, + { "scommaaccent", 556, NULL }, + { "onesuperior", 333, NULL }, + { "greater", 584, NULL }, + { "Ecaron", 667, NULL }, + { "zdotaccent", 500, NULL }, + { "threesuperior", 333, NULL }, + { "n", 611, NULL }, + { "dbldaggerumlaut", 556, NULL }, + { "onehalf", 834, NULL }, + { "lcommaaccent", 278, NULL }, + { "uhungarumlaut", 611, NULL }, + { "gbreve", 611, NULL }, + { "k", 556, NULL }, + { "copyright", 737, NULL }, + { "Racute", 722, NULL }, + { "Gcommaaccent", 778, NULL }, + { "quoteleft", 278, NULL }, + { "registered", 737, NULL }, + { "aogonek", 556, NULL }, + { "Egrave", 667, NULL }, + { "ring", 333, NULL }, + { "emdash", 1000, NULL }, + { "five", 556, NULL }, + { "asciicircum", 584, NULL }, + { "X", 667, NULL }, + { "oe", 944, NULL }, + { "Odieresis", 778, NULL }, + { "ccedilla", 556, NULL }, + { "g", 611, NULL }, + { "colon", 333, NULL }, + { "Idotaccent", 278, NULL }, + { "cedilla", 333, NULL }, + { "plusminus", 584, NULL }, + { "Eth", 722, NULL }, + { "quotedblright", 500, NULL }, + { "p", 611, NULL }, + { "dotlessi", 278, NULL }, + { "radical", 549, NULL }, + { "Ntilde", 722, NULL }, + { "Aacute", 722, NULL }, + { "Scommaaccent", 667, NULL }, + { "b", 611, NULL }, + { "K", 722, NULL }, + { "Scaron", 667, NULL }, + { "degree", 400, NULL }, + { "section", 556, NULL }, + { "florin", 556, NULL }, + { "iogonek", 278, NULL }, + { "Euro", 556, NULL }, + { "paragraph", 556, NULL }, + { "zcaron", 500, NULL }, + { "lcaron", 400, NULL }, + { "Ydieresis", 667, NULL }, + { "aring", 556, NULL }, + { "breve", 333, NULL }, + { "Amacron", 722, NULL }, + { "Dcaron", 722, NULL }, + { "ecircumflex", 556, NULL }, + { "Z", 611, NULL } +}; + +static BuiltinFontWidth helveticaBoldObliqueWidthsTab[] = { + { "divide", 584, NULL }, + { "emacron", 556, NULL }, + { "numbersign", 556, NULL }, + { "Ncommaaccent", 722, NULL }, + { "amacron", 556, NULL }, + { "T", 611, NULL }, + { "Ograve", 778, NULL }, + { "M", 833, NULL }, + { "odieresis", 611, NULL }, + { "Aogonek", 722, NULL }, + { "brokenbar", 280, NULL }, + { "ecaron", 556, NULL }, + { "Thorn", 667, NULL }, + { "space", 278, NULL }, + { "twosuperior", 333, NULL }, + { "eth", 611, NULL }, + { "w", 778, NULL }, + { "endash", 556, NULL }, + { "guillemotleft", 556, NULL }, + { "E", 667, NULL }, + { "quotedblbase", 500, NULL }, + { "fl", 611, NULL }, + { "Igrave", 278, NULL }, + { "Ccedilla", 722, NULL }, + { "period", 278, NULL }, + { "scedilla", 556, NULL }, + { "udieresis", 611, NULL }, + { "zero", 556, NULL }, + { "thorn", 611, NULL }, + { "Ugrave", 722, NULL }, + { "germandbls", 611, NULL }, + { "bracketright", 333, NULL }, + { "W", 944, NULL }, + { "commaaccent", 250, NULL }, + { "G", 778, NULL }, + { "acircumflex", 556, NULL }, + { "Edotaccent", 667, NULL }, + { "perthousand", 1000, NULL }, + { "Uring", 722, NULL }, + { "F", 611, NULL }, + { "Ocircumflex", 778, NULL }, + { "minus", 584, NULL }, + { "four", 556, NULL }, + { "ocircumflex", 611, NULL }, + { "less", 584, NULL }, + { "ae", 889, NULL }, + { "cent", 556, NULL }, + { "idieresis", 278, NULL }, + { "ogonek", 333, NULL }, + { "Zcaron", 611, NULL }, + { "circumflex", 333, NULL }, + { "D", 722, NULL }, + { "mu", 611, NULL }, + { "racute", 389, NULL }, + { "underscore", 556, NULL }, + { "tilde", 333, NULL }, + { "rcommaaccent", 389, NULL }, + { "Kcommaaccent", 722, NULL }, + { "imacron", 278, NULL }, + { "Nacute", 722, NULL }, + { "v", 556, NULL }, + { "dotaccent", 333, NULL }, + { "Tcommaaccent", 611, NULL }, + { "dollar", 556, NULL }, + { "lessequal", 549, NULL }, + { "Ucircumflex", 722, NULL }, + { "Omacron", 778, NULL }, + { "ccaron", 556, NULL }, + { "yen", 556, NULL }, + { "Y", 667, NULL }, + { "hungarumlaut", 333, NULL }, + { "Ccaron", 722, NULL }, + { "j", 278, NULL }, + { "currency", 556, NULL }, + { "nine", 556, NULL }, + { "parenleft", 333, NULL }, + { "grave", 333, NULL }, + { "Scedilla", 667, NULL }, + { "quotesinglbase", 278, NULL }, + { "g", 611, NULL }, + { "colon", 333, NULL }, + { "ccedilla", 556, NULL }, + { "quotedblright", 500, NULL }, + { "Eth", 722, NULL }, + { "plusminus", 584, NULL }, + { "cedilla", 333, NULL }, + { "Idotaccent", 278, NULL }, + { "dotlessi", 278, NULL }, + { "p", 611, NULL }, + { "Ntilde", 722, NULL }, + { "radical", 549, NULL }, + { "ring", 333, NULL }, + { "Egrave", 667, NULL }, + { "aogonek", 556, NULL }, + { "emdash", 1000, NULL }, + { "X", 667, NULL }, + { "asciicircum", 584, NULL }, + { "five", 556, NULL }, + { "Odieresis", 778, NULL }, + { "oe", 944, NULL }, + { "aring", 556, NULL }, + { "Ydieresis", 667, NULL }, + { "lcaron", 400, NULL }, + { "zcaron", 500, NULL }, + { "paragraph", 556, NULL }, + { "Amacron", 722, NULL }, + { "breve", 333, NULL }, + { "Z", 611, NULL }, + { "ecircumflex", 556, NULL }, + { "Dcaron", 722, NULL }, + { "b", 611, NULL }, + { "Scommaaccent", 667, NULL }, + { "Aacute", 722, NULL }, + { "K", 722, NULL }, + { "section", 556, NULL }, + { "Scaron", 667, NULL }, + { "degree", 400, NULL }, + { "Euro", 556, NULL }, + { "florin", 556, NULL }, + { "iogonek", 278, NULL }, + { "o", 611, NULL }, + { "percent", 889, NULL }, + { "onesuperior", 333, NULL }, + { "scommaaccent", 556, NULL }, + { "Emacron", 667, NULL }, + { "asterisk", 389, NULL }, + { "greater", 584, NULL }, + { "q", 611, NULL }, + { "l", 278, NULL }, + { "C", 722, NULL }, + { "u", 611, NULL }, + { "dagger", 556, NULL }, + { "equal", 584, NULL }, + { "N", 722, NULL }, + { "Imacron", 278, NULL }, + { "abreve", 556, NULL }, + { "iacute", 278, NULL }, + { "e", 556, NULL }, + { "icircumflex", 278, NULL }, + { "copyright", 737, NULL }, + { "k", 556, NULL }, + { "Racute", 722, NULL }, + { "Gcommaaccent", 778, NULL }, + { "registered", 737, NULL }, + { "quoteleft", 278, NULL }, + { "threesuperior", 333, NULL }, + { "zdotaccent", 500, NULL }, + { "Ecaron", 667, NULL }, + { "n", 611, NULL }, + { "gbreve", 611, NULL }, + { "uhungarumlaut", 611, NULL }, + { "lcommaaccent", 278, NULL }, + { "onehalf", 834, NULL }, + { "asciitilde", 584, NULL }, + { "Adieresis", 722, NULL }, + { "Sacute", 667, NULL }, + { "fraction", 167, NULL }, + { "atilde", 556, NULL }, + { "Zacute", 611, NULL }, + { "Uacute", 722, NULL }, + { "Acircumflex", 722, NULL }, + { "oslash", 611, NULL }, + { "notequal", 549, NULL }, + { "AE", 1000, NULL }, + { "Agrave", 722, NULL }, + { "exclam", 333, NULL }, + { "L", 611, NULL }, + { "ohungarumlaut", 611, NULL }, + { "Ecircumflex", 667, NULL }, + { "threequarters", 834, NULL }, + { "J", 556, NULL }, + { "greaterequal", 549, NULL }, + { "at", 975, NULL }, + { "sterling", 556, NULL }, + { "H", 722, NULL }, + { "Lslash", 611, NULL }, + { "Uogonek", 722, NULL }, + { "caron", 333, NULL }, + { "lacute", 278, NULL }, + { "sacute", 556, NULL }, + { "Idieresis", 278, NULL }, + { "Lacute", 611, NULL }, + { "Rcommaaccent", 722, NULL }, + { "ograve", 611, NULL }, + { "parenright", 333, NULL }, + { "otilde", 611, NULL }, + { "Ohungarumlaut", 778, NULL }, + { "bracketleft", 333, NULL }, + { "gcommaaccent", 611, NULL }, + { "f", 333, NULL }, + { "r", 389, NULL }, + { "ucircumflex", 611, NULL }, + { "slash", 278, NULL }, + { "three", 556, NULL }, + { "Eogonek", 667, NULL }, + { "macron", 333, NULL }, + { "Lcaron", 611, NULL }, + { "ordmasculine", 365, NULL }, + { "backslash", 278, NULL }, + { "questiondown", 611, NULL }, + { "semicolon", 333, NULL }, + { "guilsinglright", 333, NULL }, + { "uogonek", 611, NULL }, + { "quoteright", 278, NULL }, + { "Q", 778, NULL }, + { "exclamdown", 333, NULL }, + { "lozenge", 494, NULL }, + { "V", 667, NULL }, + { "ncaron", 611, NULL }, + { "adieresis", 556, NULL }, + { "zacute", 500, NULL }, + { "Umacron", 722, NULL }, + { "c", 556, NULL }, + { "d", 611, NULL }, + { "periodcentered", 278, NULL }, + { "eight", 556, NULL }, + { "I", 278, NULL }, + { "one", 556, NULL }, + { "Uhungarumlaut", 722, NULL }, + { "z", 500, NULL }, + { "uring", 611, NULL }, + { "s", 556, NULL }, + { "egrave", 556, NULL }, + { "Oacute", 778, NULL }, + { "quotedbl", 474, NULL }, + { "t", 333, NULL }, + { "Aring", 722, NULL }, + { "ellipsis", 1000, NULL }, + { "agrave", 556, NULL }, + { "bar", 280, NULL }, + { "quotesingle", 238, NULL }, + { "multiply", 584, NULL }, + { "i", 278, NULL }, + { "P", 667, NULL }, + { "lslash", 278, NULL }, + { "six", 556, NULL }, + { "edotaccent", 556, NULL }, + { "daggerdbl", 556, NULL }, + { "Yacute", 667, NULL }, + { "oacute", 611, NULL }, + { "Edieresis", 667, NULL }, + { "Atilde", 722, NULL }, + { "onequarter", 834, NULL }, + { "braceright", 389, NULL }, + { "braceleft", 389, NULL }, + { "acute", 333, NULL }, + { "partialdiff", 494, NULL }, + { "U", 722, NULL }, + { "m", 889, NULL }, + { "OE", 1000, NULL }, + { "Ncaron", 722, NULL }, + { "x", 556, NULL }, + { "edieresis", 556, NULL }, + { "Iogonek", 278, NULL }, + { "y", 556, NULL }, + { "tcaron", 389, NULL }, + { "rcaron", 389, NULL }, + { "cacute", 556, NULL }, + { "Dcroat", 722, NULL }, + { "tcommaaccent", 333, NULL }, + { "logicalnot", 584, NULL }, + { "ncommaaccent", 611, NULL }, + { "plus", 584, NULL }, + { "guilsinglleft", 333, NULL }, + { "h", 611, NULL }, + { "Cacute", 722, NULL }, + { "A", 722, NULL }, + { "question", 611, NULL }, + { "summation", 600, NULL }, + { "igrave", 278, NULL }, + { "dcroat", 611, NULL }, + { "Oslash", 778, NULL }, + { "hyphen", 333, NULL }, + { "a", 556, NULL }, + { "ugrave", 611, NULL }, + { "dcaron", 743, NULL }, + { "Rcaron", 722, NULL }, + { "kcommaaccent", 556, NULL }, + { "yacute", 556, NULL }, + { "ydieresis", 556, NULL }, + { "R", 722, NULL }, + { "B", 722, NULL }, + { "aacute", 556, NULL }, + { "Tcaron", 611, NULL }, + { "Otilde", 778, NULL }, + { "umacron", 611, NULL }, + { "ordfeminine", 370, NULL }, + { "quotedblleft", 500, NULL }, + { "S", 667, NULL }, + { "Gbreve", 778, NULL }, + { "omacron", 611, NULL }, + { "Delta", 612, NULL }, + { "comma", 278, NULL }, + { "O", 778, NULL }, + { "Icircumflex", 278, NULL }, + { "nacute", 611, NULL }, + { "Eacute", 667, NULL }, + { "dieresis", 333, NULL }, + { "fi", 611, NULL }, + { "ntilde", 611, NULL }, + { "Lcommaaccent", 611, NULL }, + { "trademark", 1000, NULL }, + { "ampersand", 722, NULL }, + { "Zdotaccent", 611, NULL }, + { "bullet", 350, NULL }, + { "eogonek", 556, NULL }, + { "eacute", 556, NULL }, + { "guillemotright", 556, NULL }, + { "scaron", 556, NULL }, + { "seven", 556, NULL }, + { "two", 556, NULL }, + { "uacute", 611, NULL }, + { "Iacute", 278, NULL }, + { "Udieresis", 722, NULL }, + { "Abreve", 722, NULL } +}; + +static BuiltinFontWidth helveticaObliqueWidthsTab[] = { + { "dieresis", 333, NULL }, + { "Eacute", 667, NULL }, + { "Icircumflex", 278, NULL }, + { "O", 778, NULL }, + { "nacute", 556, NULL }, + { "trademark", 1000, NULL }, + { "ampersand", 667, NULL }, + { "Lcommaaccent", 556, NULL }, + { "ntilde", 556, NULL }, + { "fi", 500, NULL }, + { "scaron", 500, NULL }, + { "guillemotright", 556, NULL }, + { "eacute", 556, NULL }, + { "eogonek", 556, NULL }, + { "bullet", 350, NULL }, + { "Zdotaccent", 611, NULL }, + { "Abreve", 667, NULL }, + { "Udieresis", 722, NULL }, + { "Iacute", 278, NULL }, + { "two", 556, NULL }, + { "uacute", 556, NULL }, + { "seven", 556, NULL }, + { "B", 667, NULL }, + { "Rcaron", 722, NULL }, + { "kcommaaccent", 500, NULL }, + { "yacute", 500, NULL }, + { "R", 722, NULL }, + { "ydieresis", 500, NULL }, + { "ugrave", 556, NULL }, + { "dcaron", 643, NULL }, + { "Oslash", 778, NULL }, + { "hyphen", 333, NULL }, + { "a", 556, NULL }, + { "umacron", 556, NULL }, + { "Otilde", 778, NULL }, + { "Tcaron", 611, NULL }, + { "aacute", 556, NULL }, + { "quotedblleft", 333, NULL }, + { "ordfeminine", 370, NULL }, + { "omacron", 556, NULL }, + { "Delta", 612, NULL }, + { "comma", 278, NULL }, + { "Gbreve", 778, NULL }, + { "S", 667, NULL }, + { "x", 500, NULL }, + { "y", 500, NULL }, + { "Iogonek", 278, NULL }, + { "edieresis", 556, NULL }, + { "Ncaron", 722, NULL }, + { "m", 833, NULL }, + { "OE", 1000, NULL }, + { "partialdiff", 476, NULL }, + { "U", 722, NULL }, + { "ncommaaccent", 556, NULL }, + { "tcommaaccent", 278, NULL }, + { "logicalnot", 584, NULL }, + { "cacute", 500, NULL }, + { "Dcroat", 722, NULL }, + { "tcaron", 317, NULL }, + { "rcaron", 333, NULL }, + { "guilsinglleft", 333, NULL }, + { "Cacute", 722, NULL }, + { "h", 556, NULL }, + { "plus", 584, NULL }, + { "igrave", 278, NULL }, + { "dcroat", 556, NULL }, + { "question", 556, NULL }, + { "summation", 600, NULL }, + { "A", 667, NULL }, + { "multiply", 584, NULL }, + { "i", 222, NULL }, + { "quotesingle", 191, NULL }, + { "bar", 260, NULL }, + { "six", 556, NULL }, + { "edotaccent", 556, NULL }, + { "lslash", 222, NULL }, + { "P", 667, NULL }, + { "Atilde", 667, NULL }, + { "Edieresis", 667, NULL }, + { "oacute", 556, NULL }, + { "Yacute", 667, NULL }, + { "daggerdbl", 556, NULL }, + { "braceleft", 334, NULL }, + { "braceright", 334, NULL }, + { "acute", 333, NULL }, + { "onequarter", 834, NULL }, + { "one", 556, NULL }, + { "I", 278, NULL }, + { "eight", 556, NULL }, + { "periodcentered", 278, NULL }, + { "c", 500, NULL }, + { "d", 556, NULL }, + { "egrave", 556, NULL }, + { "uring", 556, NULL }, + { "s", 500, NULL }, + { "Uhungarumlaut", 722, NULL }, + { "z", 500, NULL }, + { "t", 278, NULL }, + { "quotedbl", 355, NULL }, + { "Oacute", 778, NULL }, + { "agrave", 556, NULL }, + { "ellipsis", 1000, NULL }, + { "Aring", 667, NULL }, + { "three", 556, NULL }, + { "slash", 278, NULL }, + { "ucircumflex", 556, NULL }, + { "r", 333, NULL }, + { "macron", 333, NULL }, + { "Eogonek", 667, NULL }, + { "Lcaron", 556, NULL }, + { "questiondown", 611, NULL }, + { "ordmasculine", 365, NULL }, + { "backslash", 278, NULL }, + { "uogonek", 556, NULL }, + { "quoteright", 222, NULL }, + { "semicolon", 278, NULL }, + { "guilsinglright", 333, NULL }, + { "Umacron", 722, NULL }, + { "zacute", 500, NULL }, + { "ncaron", 556, NULL }, + { "adieresis", 556, NULL }, + { "lozenge", 471, NULL }, + { "V", 667, NULL }, + { "Q", 778, NULL }, + { "exclamdown", 333, NULL }, + { "Lacute", 556, NULL }, + { "sacute", 500, NULL }, + { "Idieresis", 278, NULL }, + { "ograve", 556, NULL }, + { "Rcommaaccent", 722, NULL }, + { "gcommaaccent", 556, NULL }, + { "Ohungarumlaut", 778, NULL }, + { "bracketleft", 278, NULL }, + { "otilde", 556, NULL }, + { "parenright", 333, NULL }, + { "f", 278, NULL }, + { "asciitilde", 584, NULL }, + { "Uacute", 722, NULL }, + { "atilde", 556, NULL }, + { "Zacute", 611, NULL }, + { "fraction", 167, NULL }, + { "Sacute", 667, NULL }, + { "Adieresis", 667, NULL }, + { "threequarters", 834, NULL }, + { "J", 500, NULL }, + { "ohungarumlaut", 556, NULL }, + { "Ecircumflex", 667, NULL }, + { "L", 556, NULL }, + { "notequal", 549, NULL }, + { "exclam", 278, NULL }, + { "Agrave", 667, NULL }, + { "AE", 1000, NULL }, + { "Acircumflex", 667, NULL }, + { "oslash", 611, NULL }, + { "Uogonek", 722, NULL }, + { "caron", 333, NULL }, + { "Lslash", 556, NULL }, + { "lacute", 222, NULL }, + { "sterling", 556, NULL }, + { "H", 722, NULL }, + { "at", 1015, NULL }, + { "greaterequal", 549, NULL }, + { "Racute", 722, NULL }, + { "k", 500, NULL }, + { "copyright", 737, NULL }, + { "quoteleft", 222, NULL }, + { "registered", 737, NULL }, + { "Gcommaaccent", 778, NULL }, + { "n", 556, NULL }, + { "Ecaron", 667, NULL }, + { "threesuperior", 333, NULL }, + { "zdotaccent", 500, NULL }, + { "lcommaaccent", 222, NULL }, + { "onehalf", 834, NULL }, + { "gbreve", 556, NULL }, + { "uhungarumlaut", 556, NULL }, + { "percent", 889, NULL }, + { "o", 556, NULL }, + { "greater", 584, NULL }, + { "asterisk", 389, NULL }, + { "Emacron", 667, NULL }, + { "scommaaccent", 500, NULL }, + { "onesuperior", 333, NULL }, + { "dagger", 556, NULL }, + { "equal", 584, NULL }, + { "N", 722, NULL }, + { "C", 722, NULL }, + { "u", 556, NULL }, + { "q", 556, NULL }, + { "l", 222, NULL }, + { "icircumflex", 278, NULL }, + { "Imacron", 278, NULL }, + { "abreve", 556, NULL }, + { "iacute", 278, NULL }, + { "e", 556, NULL }, + { "lcaron", 299, NULL }, + { "paragraph", 537, NULL }, + { "zcaron", 500, NULL }, + { "aring", 556, NULL }, + { "Ydieresis", 667, NULL }, + { "Dcaron", 722, NULL }, + { "Z", 611, NULL }, + { "ecircumflex", 556, NULL }, + { "Amacron", 667, NULL }, + { "breve", 333, NULL }, + { "K", 667, NULL }, + { "Scommaaccent", 667, NULL }, + { "Aacute", 667, NULL }, + { "b", 556, NULL }, + { "Euro", 556, NULL }, + { "iogonek", 222, NULL }, + { "florin", 556, NULL }, + { "section", 556, NULL }, + { "Scaron", 667, NULL }, + { "degree", 400, NULL }, + { "plusminus", 584, NULL }, + { "cedilla", 333, NULL }, + { "Idotaccent", 278, NULL }, + { "quotedblright", 333, NULL }, + { "Eth", 722, NULL }, + { "colon", 278, NULL }, + { "g", 556, NULL }, + { "ccedilla", 500, NULL }, + { "Ntilde", 722, NULL }, + { "radical", 453, NULL }, + { "dotlessi", 278, NULL }, + { "p", 556, NULL }, + { "emdash", 1000, NULL }, + { "aogonek", 556, NULL }, + { "Egrave", 667, NULL }, + { "ring", 333, NULL }, + { "Odieresis", 778, NULL }, + { "oe", 944, NULL }, + { "five", 556, NULL }, + { "X", 667, NULL }, + { "asciicircum", 469, NULL }, + { "ccaron", 500, NULL }, + { "Omacron", 778, NULL }, + { "lessequal", 549, NULL }, + { "Ucircumflex", 722, NULL }, + { "hungarumlaut", 333, NULL }, + { "j", 222, NULL }, + { "Ccaron", 722, NULL }, + { "yen", 556, NULL }, + { "Y", 667, NULL }, + { "parenleft", 333, NULL }, + { "currency", 556, NULL }, + { "nine", 556, NULL }, + { "quotesinglbase", 222, NULL }, + { "grave", 333, NULL }, + { "Scedilla", 667, NULL }, + { "ae", 889, NULL }, + { "cent", 556, NULL }, + { "ocircumflex", 556, NULL }, + { "less", 584, NULL }, + { "minus", 584, NULL }, + { "four", 556, NULL }, + { "circumflex", 333, NULL }, + { "Zcaron", 611, NULL }, + { "ogonek", 333, NULL }, + { "idieresis", 278, NULL }, + { "rcommaaccent", 333, NULL }, + { "Kcommaaccent", 667, NULL }, + { "imacron", 278, NULL }, + { "tilde", 333, NULL }, + { "underscore", 556, NULL }, + { "D", 722, NULL }, + { "mu", 556, NULL }, + { "racute", 333, NULL }, + { "Tcommaaccent", 611, NULL }, + { "dollar", 556, NULL }, + { "v", 500, NULL }, + { "Nacute", 722, NULL }, + { "dotaccent", 333, NULL }, + { "zero", 556, NULL }, + { "scedilla", 500, NULL }, + { "period", 278, NULL }, + { "udieresis", 556, NULL }, + { "Ccedilla", 722, NULL }, + { "Igrave", 278, NULL }, + { "commaaccent", 250, NULL }, + { "W", 944, NULL }, + { "bracketright", 278, NULL }, + { "Ugrave", 722, NULL }, + { "germandbls", 611, NULL }, + { "thorn", 556, NULL }, + { "G", 778, NULL }, + { "Ocircumflex", 778, NULL }, + { "F", 611, NULL }, + { "Uring", 722, NULL }, + { "perthousand", 1000, NULL }, + { "Edotaccent", 667, NULL }, + { "acircumflex", 556, NULL }, + { "amacron", 556, NULL }, + { "Ncommaaccent", 722, NULL }, + { "numbersign", 556, NULL }, + { "divide", 584, NULL }, + { "emacron", 556, NULL }, + { "M", 833, NULL }, + { "odieresis", 556, NULL }, + { "Ograve", 778, NULL }, + { "T", 611, NULL }, + { "w", 722, NULL }, + { "Thorn", 667, NULL }, + { "space", 278, NULL }, + { "twosuperior", 333, NULL }, + { "eth", 556, NULL }, + { "ecaron", 556, NULL }, + { "brokenbar", 260, NULL }, + { "Aogonek", 667, NULL }, + { "fl", 500, NULL }, + { "E", 667, NULL }, + { "quotedblbase", 333, NULL }, + { "guillemotleft", 556, NULL }, + { "endash", 556, NULL } +}; + +static BuiltinFontWidth symbolWidthsTab[] = { + { "copyrightsans", 790, NULL }, + { "Upsilon", 690, NULL }, + { "sigma", 603, NULL }, + { "kappa", 549, NULL }, + { "circleplus", 768, NULL }, + { "degree", 400, NULL }, + { "florin", 500, NULL }, + { "Euro", 750, NULL }, + { "phi1", 603, NULL }, + { "club", 753, NULL }, + { "radicalex", 500, NULL }, + { "theta", 521, NULL }, + { "Upsilon1", 620, NULL }, + { "radical", 549, NULL }, + { "angle", 768, NULL }, + { "colon", 278, NULL }, + { "plusminus", 549, NULL }, + { "five", 500, NULL }, + { "weierstrass", 987, NULL }, + { "gamma", 411, NULL }, + { "theta1", 631, NULL }, + { "Zeta", 611, NULL }, + { "angleleft", 329, NULL }, + { "copyrightserif", 790, NULL }, + { "logicaland", 603, NULL }, + { "arrowvertex", 603, NULL }, + { "arrowleft", 987, NULL }, + { "Omicron", 722, NULL }, + { "propersubset", 713, NULL }, + { "equivalence", 549, NULL }, + { "circlemultiply", 768, NULL }, + { "greater", 549, NULL }, + { "minute", 247, NULL }, + { "integral", 274, NULL }, + { "percent", 833, NULL }, + { "omega", 686, NULL }, + { "Beta", 667, NULL }, + { "equal", 549, NULL }, + { "therefore", 863, NULL }, + { "braceleftmid", 494, NULL }, + { "parenrighttp", 384, NULL }, + { "bracketright", 333, NULL }, + { "omicron", 549, NULL }, + { "Epsilon", 611, NULL }, + { "Nu", 722, NULL }, + { "zero", 500, NULL }, + { "period", 250, NULL }, + { "Gamma", 603, NULL }, + { "product", 823, NULL }, + { "arrowboth", 1042, NULL }, + { "Ifraktur", 686, NULL }, + { "infinity", 713, NULL }, + { "heart", 753, NULL }, + { "parenrightex", 384, NULL }, + { "arrowdown", 603, NULL }, + { "bracketleftbt", 384, NULL }, + { "logicalor", 603, NULL }, + { "numbersign", 500, NULL }, + { "divide", 549, NULL }, + { "nu", 521, NULL }, + { "spade", 753, NULL }, + { "rho", 549, NULL }, + { "Sigma", 592, NULL }, + { "integralex", 686, NULL }, + { "space", 250, NULL }, + { "reflexsuperset", 713, NULL }, + { "alpha", 631, NULL }, + { "parenleftex", 384, NULL }, + { "lessequal", 549, NULL }, + { "second", 411, NULL }, + { "integraltp", 686, NULL }, + { "approxequal", 549, NULL }, + { "existential", 549, NULL }, + { "diamond", 753, NULL }, + { "phi", 521, NULL }, + { "nine", 500, NULL }, + { "Iota", 333, NULL }, + { "parenleft", 333, NULL }, + { "tau", 439, NULL }, + { "Tau", 611, NULL }, + { "less", 549, NULL }, + { "Eta", 722, NULL }, + { "minus", 549, NULL }, + { "four", 500, NULL }, + { "bracketleftex", 384, NULL }, + { "arrowdblboth", 1042, NULL }, + { "arrowup", 603, NULL }, + { "arrowright", 987, NULL }, + { "integralbt", 686, NULL }, + { "similar", 549, NULL }, + { "underscore", 500, NULL }, + { "dotmath", 250, NULL }, + { "mu", 576, NULL }, + { "trademarkserif", 890, NULL }, + { "Chi", 722, NULL }, + { "angleright", 329, NULL }, + { "logicalnot", 713, NULL }, + { "parenlefttp", 384, NULL }, + { "partialdiff", 494, NULL }, + { "arrowdblright", 987, NULL }, + { "summation", 713, NULL }, + { "question", 444, NULL }, + { "apple", 790, NULL }, + { "plus", 549, NULL }, + { "epsilon", 439, NULL }, + { "reflexsubset", 713, NULL }, + { "six", 500, NULL }, + { "arrowdbldown", 603, NULL }, + { "Omega", 768, NULL }, + { "bar", 200, NULL }, + { "multiply", 549, NULL }, + { "braceright", 480, NULL }, + { "braceleft", 480, NULL }, + { "braceleftbt", 494, NULL }, + { "delta", 494, NULL }, + { "arrowdblleft", 987, NULL }, + { "ampersand", 778, NULL }, + { "arrowdblup", 603, NULL }, + { "aleph", 823, NULL }, + { "two", 500, NULL }, + { "bracerighttp", 494, NULL }, + { "seven", 500, NULL }, + { "propersuperset", 713, NULL }, + { "bullet", 460, NULL }, + { "perpendicular", 658, NULL }, + { "Lambda", 686, NULL }, + { "parenrightbt", 384, NULL }, + { "bracerightmid", 494, NULL }, + { "comma", 250, NULL }, + { "Delta", 612, NULL }, + { "bracerightbt", 494, NULL }, + { "union", 768, NULL }, + { "arrowhorizex", 1000, NULL }, + { "omega1", 713, NULL }, + { "proportional", 713, NULL }, + { "sigma1", 439, NULL }, + { "carriagereturn", 658, NULL }, + { "suchthat", 439, NULL }, + { "notelement", 713, NULL }, + { "beta", 549, NULL }, + { "parenright", 333, NULL }, + { "bracketleft", 333, NULL }, + { "fraction", 167, NULL }, + { "Xi", 645, NULL }, + { "pi", 549, NULL }, + { "braceex", 494, NULL }, + { "bracketlefttp", 384, NULL }, + { "notsubset", 713, NULL }, + { "asteriskmath", 500, NULL }, + { "greaterequal", 549, NULL }, + { "emptyset", 823, NULL }, + { "bracketrightex", 384, NULL }, + { "gradient", 713, NULL }, + { "exclam", 333, NULL }, + { "notequal", 549, NULL }, + { "congruent", 549, NULL }, + { "Pi", 768, NULL }, + { "Theta", 741, NULL }, + { "Rfraktur", 795, NULL }, + { "bracketrighttp", 384, NULL }, + { "parenleftbt", 384, NULL }, + { "universal", 713, NULL }, + { "upsilon", 576, NULL }, + { "psi", 686, NULL }, + { "eight", 500, NULL }, + { "one", 500, NULL }, + { "Kappa", 722, NULL }, + { "ellipsis", 1000, NULL }, + { "chi", 549, NULL }, + { "trademarksans", 786, NULL }, + { "Rho", 556, NULL }, + { "Alpha", 722, NULL }, + { "bracketrightbt", 384, NULL }, + { "intersection", 768, NULL }, + { "xi", 493, NULL }, + { "slash", 278, NULL }, + { "registerserif", 790, NULL }, + { "iota", 329, NULL }, + { "Psi", 795, NULL }, + { "three", 500, NULL }, + { "lozenge", 494, NULL }, + { "Phi", 763, NULL }, + { "zeta", 494, NULL }, + { "lambda", 549, NULL }, + { "Mu", 889, NULL }, + { "bracelefttp", 494, NULL }, + { "eta", 603, NULL }, + { "registersans", 790, NULL }, + { "element", 713, NULL }, + { "semicolon", 278, NULL } +}; + +static BuiltinFontWidth timesBoldWidthsTab[] = { + { "cacute", 444, NULL }, + { "Dcroat", 722, NULL }, + { "tcaron", 416, NULL }, + { "rcaron", 444, NULL }, + { "ncommaaccent", 556, NULL }, + { "tcommaaccent", 333, NULL }, + { "logicalnot", 570, NULL }, + { "m", 833, NULL }, + { "OE", 1000, NULL }, + { "partialdiff", 494, NULL }, + { "U", 722, NULL }, + { "x", 500, NULL }, + { "y", 500, NULL }, + { "Iogonek", 389, NULL }, + { "edieresis", 444, NULL }, + { "Ncaron", 722, NULL }, + { "question", 500, NULL }, + { "summation", 600, NULL }, + { "A", 722, NULL }, + { "igrave", 278, NULL }, + { "dcroat", 556, NULL }, + { "guilsinglleft", 333, NULL }, + { "h", 556, NULL }, + { "Cacute", 722, NULL }, + { "plus", 570, NULL }, + { "P", 611, NULL }, + { "lslash", 278, NULL }, + { "six", 500, NULL }, + { "edotaccent", 444, NULL }, + { "bar", 220, NULL }, + { "quotesingle", 278, NULL }, + { "multiply", 570, NULL }, + { "i", 278, NULL }, + { "onequarter", 750, NULL }, + { "braceright", 394, NULL }, + { "braceleft", 394, NULL }, + { "acute", 333, NULL }, + { "oacute", 500, NULL }, + { "Yacute", 722, NULL }, + { "daggerdbl", 500, NULL }, + { "Atilde", 722, NULL }, + { "Edieresis", 667, NULL }, + { "ntilde", 556, NULL }, + { "fi", 556, NULL }, + { "trademark", 1000, NULL }, + { "ampersand", 833, NULL }, + { "Lcommaaccent", 667, NULL }, + { "O", 778, NULL }, + { "Icircumflex", 389, NULL }, + { "nacute", 556, NULL }, + { "dieresis", 333, NULL }, + { "Eacute", 667, NULL }, + { "two", 500, NULL }, + { "uacute", 556, NULL }, + { "seven", 500, NULL }, + { "Udieresis", 722, NULL }, + { "Abreve", 722, NULL }, + { "Iacute", 389, NULL }, + { "bullet", 350, NULL }, + { "eogonek", 444, NULL }, + { "eacute", 444, NULL }, + { "Zdotaccent", 667, NULL }, + { "scaron", 389, NULL }, + { "guillemotright", 500, NULL }, + { "aacute", 500, NULL }, + { "Otilde", 778, NULL }, + { "umacron", 556, NULL }, + { "Tcaron", 667, NULL }, + { "ugrave", 556, NULL }, + { "dcaron", 672, NULL }, + { "hyphen", 333, NULL }, + { "Oslash", 778, NULL }, + { "a", 500, NULL }, + { "B", 667, NULL }, + { "yacute", 500, NULL }, + { "kcommaaccent", 556, NULL }, + { "Rcaron", 722, NULL }, + { "R", 722, NULL }, + { "ydieresis", 500, NULL }, + { "S", 556, NULL }, + { "omacron", 500, NULL }, + { "comma", 250, NULL }, + { "Delta", 612, NULL }, + { "Gbreve", 778, NULL }, + { "ordfeminine", 300, NULL }, + { "quotedblleft", 500, NULL }, + { "Rcommaaccent", 722, NULL }, + { "ograve", 500, NULL }, + { "Lacute", 667, NULL }, + { "Idieresis", 389, NULL }, + { "sacute", 389, NULL }, + { "f", 333, NULL }, + { "otilde", 500, NULL }, + { "parenright", 333, NULL }, + { "gcommaaccent", 500, NULL }, + { "Ohungarumlaut", 778, NULL }, + { "bracketleft", 333, NULL }, + { "fraction", 167, NULL }, + { "Sacute", 556, NULL }, + { "Adieresis", 722, NULL }, + { "Uacute", 722, NULL }, + { "atilde", 500, NULL }, + { "Zacute", 667, NULL }, + { "asciitilde", 520, NULL }, + { "H", 778, NULL }, + { "sterling", 500, NULL }, + { "greaterequal", 549, NULL }, + { "at", 930, NULL }, + { "Lslash", 667, NULL }, + { "Uogonek", 722, NULL }, + { "caron", 333, NULL }, + { "lacute", 278, NULL }, + { "notequal", 549, NULL }, + { "Agrave", 722, NULL }, + { "AE", 1000, NULL }, + { "exclam", 333, NULL }, + { "Acircumflex", 722, NULL }, + { "oslash", 500, NULL }, + { "threequarters", 750, NULL }, + { "J", 500, NULL }, + { "ohungarumlaut", 500, NULL }, + { "Ecircumflex", 667, NULL }, + { "L", 667, NULL }, + { "z", 444, NULL }, + { "Uhungarumlaut", 722, NULL }, + { "egrave", 444, NULL }, + { "uring", 556, NULL }, + { "s", 389, NULL }, + { "c", 444, NULL }, + { "d", 556, NULL }, + { "eight", 500, NULL }, + { "I", 389, NULL }, + { "one", 500, NULL }, + { "periodcentered", 250, NULL }, + { "ellipsis", 1000, NULL }, + { "Aring", 722, NULL }, + { "agrave", 500, NULL }, + { "Oacute", 778, NULL }, + { "t", 333, NULL }, + { "quotedbl", 555, NULL }, + { "Eogonek", 667, NULL }, + { "macron", 333, NULL }, + { "Lcaron", 667, NULL }, + { "ordmasculine", 330, NULL }, + { "questiondown", 500, NULL }, + { "backslash", 278, NULL }, + { "slash", 278, NULL }, + { "r", 444, NULL }, + { "ucircumflex", 556, NULL }, + { "three", 500, NULL }, + { "lozenge", 494, NULL }, + { "V", 722, NULL }, + { "Q", 778, NULL }, + { "exclamdown", 333, NULL }, + { "Umacron", 722, NULL }, + { "zacute", 444, NULL }, + { "ncaron", 556, NULL }, + { "adieresis", 500, NULL }, + { "quoteright", 333, NULL }, + { "uogonek", 556, NULL }, + { "semicolon", 333, NULL }, + { "guilsinglright", 333, NULL }, + { "Amacron", 722, NULL }, + { "breve", 333, NULL }, + { "Dcaron", 722, NULL }, + { "Z", 667, NULL }, + { "ecircumflex", 444, NULL }, + { "lcaron", 394, NULL }, + { "paragraph", 540, NULL }, + { "zcaron", 444, NULL }, + { "aring", 500, NULL }, + { "Ydieresis", 722, NULL }, + { "section", 500, NULL }, + { "Scaron", 556, NULL }, + { "degree", 400, NULL }, + { "Euro", 500, NULL }, + { "florin", 500, NULL }, + { "iogonek", 278, NULL }, + { "Scommaaccent", 556, NULL }, + { "Aacute", 722, NULL }, + { "b", 556, NULL }, + { "K", 778, NULL }, + { "dotlessi", 278, NULL }, + { "p", 556, NULL }, + { "Ntilde", 722, NULL }, + { "radical", 549, NULL }, + { "g", 500, NULL }, + { "colon", 333, NULL }, + { "ccedilla", 444, NULL }, + { "plusminus", 570, NULL }, + { "cedilla", 333, NULL }, + { "Idotaccent", 389, NULL }, + { "quotedblright", 500, NULL }, + { "Eth", 722, NULL }, + { "five", 500, NULL }, + { "X", 722, NULL }, + { "asciicircum", 581, NULL }, + { "Odieresis", 778, NULL }, + { "oe", 722, NULL }, + { "aogonek", 500, NULL }, + { "Egrave", 667, NULL }, + { "ring", 333, NULL }, + { "emdash", 1000, NULL }, + { "Gcommaaccent", 778, NULL }, + { "quoteleft", 333, NULL }, + { "registered", 747, NULL }, + { "k", 556, NULL }, + { "copyright", 747, NULL }, + { "Racute", 722, NULL }, + { "lcommaaccent", 278, NULL }, + { "onehalf", 750, NULL }, + { "uhungarumlaut", 556, NULL }, + { "gbreve", 500, NULL }, + { "Ecaron", 667, NULL }, + { "threesuperior", 300, NULL }, + { "zdotaccent", 444, NULL }, + { "n", 556, NULL }, + { "Emacron", 667, NULL }, + { "asterisk", 500, NULL }, + { "scommaaccent", 389, NULL }, + { "onesuperior", 300, NULL }, + { "greater", 570, NULL }, + { "percent", 1000, NULL }, + { "o", 500, NULL }, + { "abreve", 500, NULL }, + { "Imacron", 389, NULL }, + { "iacute", 278, NULL }, + { "e", 444, NULL }, + { "icircumflex", 278, NULL }, + { "q", 556, NULL }, + { "l", 278, NULL }, + { "dagger", 500, NULL }, + { "equal", 570, NULL }, + { "N", 722, NULL }, + { "C", 722, NULL }, + { "u", 556, NULL }, + { "Ugrave", 722, NULL }, + { "germandbls", 556, NULL }, + { "thorn", 556, NULL }, + { "commaaccent", 250, NULL }, + { "bracketright", 333, NULL }, + { "W", 1000, NULL }, + { "Ccedilla", 722, NULL }, + { "Igrave", 389, NULL }, + { "zero", 500, NULL }, + { "period", 250, NULL }, + { "scedilla", 389, NULL }, + { "udieresis", 556, NULL }, + { "perthousand", 1000, NULL }, + { "Edotaccent", 667, NULL }, + { "acircumflex", 500, NULL }, + { "Ocircumflex", 778, NULL }, + { "F", 611, NULL }, + { "Uring", 722, NULL }, + { "G", 778, NULL }, + { "T", 667, NULL }, + { "M", 944, NULL }, + { "odieresis", 500, NULL }, + { "Ograve", 778, NULL }, + { "numbersign", 500, NULL }, + { "divide", 570, NULL }, + { "emacron", 444, NULL }, + { "amacron", 500, NULL }, + { "Ncommaaccent", 722, NULL }, + { "endash", 500, NULL }, + { "guillemotleft", 500, NULL }, + { "fl", 556, NULL }, + { "E", 667, NULL }, + { "quotedblbase", 500, NULL }, + { "ecaron", 444, NULL }, + { "Aogonek", 722, NULL }, + { "brokenbar", 220, NULL }, + { "w", 722, NULL }, + { "Thorn", 611, NULL }, + { "space", 250, NULL }, + { "eth", 500, NULL }, + { "twosuperior", 300, NULL }, + { "Y", 722, NULL }, + { "yen", 500, NULL }, + { "hungarumlaut", 333, NULL }, + { "Ccaron", 722, NULL }, + { "j", 333, NULL }, + { "Omacron", 778, NULL }, + { "lessequal", 549, NULL }, + { "Ucircumflex", 722, NULL }, + { "ccaron", 444, NULL }, + { "grave", 333, NULL }, + { "Scedilla", 556, NULL }, + { "quotesinglbase", 333, NULL }, + { "currency", 500, NULL }, + { "nine", 500, NULL }, + { "parenleft", 333, NULL }, + { "ogonek", 333, NULL }, + { "idieresis", 278, NULL }, + { "circumflex", 333, NULL }, + { "Zcaron", 667, NULL }, + { "ocircumflex", 500, NULL }, + { "less", 570, NULL }, + { "minus", 570, NULL }, + { "four", 500, NULL }, + { "ae", 722, NULL }, + { "cent", 500, NULL }, + { "Tcommaaccent", 667, NULL }, + { "dollar", 500, NULL }, + { "v", 500, NULL }, + { "Nacute", 722, NULL }, + { "dotaccent", 333, NULL }, + { "underscore", 500, NULL }, + { "D", 722, NULL }, + { "mu", 556, NULL }, + { "racute", 444, NULL }, + { "rcommaaccent", 444, NULL }, + { "imacron", 278, NULL }, + { "Kcommaaccent", 778, NULL }, + { "tilde", 333, NULL } +}; + +static BuiltinFontWidth timesBoldItalicWidthsTab[] = { + { "M", 889, NULL }, + { "odieresis", 500, NULL }, + { "Ograve", 722, NULL }, + { "T", 611, NULL }, + { "amacron", 500, NULL }, + { "Ncommaaccent", 722, NULL }, + { "numbersign", 500, NULL }, + { "divide", 570, NULL }, + { "emacron", 444, NULL }, + { "fl", 556, NULL }, + { "E", 667, NULL }, + { "quotedblbase", 500, NULL }, + { "endash", 500, NULL }, + { "guillemotleft", 500, NULL }, + { "w", 667, NULL }, + { "Thorn", 611, NULL }, + { "space", 250, NULL }, + { "eth", 500, NULL }, + { "twosuperior", 300, NULL }, + { "ecaron", 444, NULL }, + { "Aogonek", 667, NULL }, + { "brokenbar", 220, NULL }, + { "commaaccent", 250, NULL }, + { "bracketright", 333, NULL }, + { "W", 889, NULL }, + { "Ugrave", 722, NULL }, + { "germandbls", 500, NULL }, + { "thorn", 500, NULL }, + { "zero", 500, NULL }, + { "period", 250, NULL }, + { "scedilla", 389, NULL }, + { "udieresis", 556, NULL }, + { "Ccedilla", 667, NULL }, + { "Igrave", 389, NULL }, + { "Ocircumflex", 722, NULL }, + { "F", 667, NULL }, + { "Uring", 722, NULL }, + { "Edotaccent", 667, NULL }, + { "perthousand", 1000, NULL }, + { "acircumflex", 500, NULL }, + { "G", 722, NULL }, + { "circumflex", 333, NULL }, + { "Zcaron", 611, NULL }, + { "ogonek", 333, NULL }, + { "idieresis", 278, NULL }, + { "ae", 722, NULL }, + { "cent", 500, NULL }, + { "ocircumflex", 500, NULL }, + { "less", 570, NULL }, + { "minus", 606, NULL }, + { "four", 500, NULL }, + { "dollar", 500, NULL }, + { "Tcommaaccent", 611, NULL }, + { "v", 444, NULL }, + { "Nacute", 722, NULL }, + { "dotaccent", 333, NULL }, + { "rcommaaccent", 389, NULL }, + { "Kcommaaccent", 667, NULL }, + { "imacron", 278, NULL }, + { "tilde", 333, NULL }, + { "underscore", 500, NULL }, + { "mu", 576, NULL }, + { "D", 722, NULL }, + { "racute", 389, NULL }, + { "hungarumlaut", 333, NULL }, + { "j", 278, NULL }, + { "Ccaron", 667, NULL }, + { "yen", 500, NULL }, + { "Y", 611, NULL }, + { "ccaron", 444, NULL }, + { "lessequal", 549, NULL }, + { "Ucircumflex", 722, NULL }, + { "Omacron", 722, NULL }, + { "quotesinglbase", 333, NULL }, + { "grave", 333, NULL }, + { "Scedilla", 556, NULL }, + { "parenleft", 333, NULL }, + { "currency", 500, NULL }, + { "nine", 500, NULL }, + { "Ntilde", 722, NULL }, + { "radical", 549, NULL }, + { "dotlessi", 278, NULL }, + { "p", 500, NULL }, + { "plusminus", 570, NULL }, + { "Idotaccent", 389, NULL }, + { "cedilla", 333, NULL }, + { "quotedblright", 500, NULL }, + { "Eth", 722, NULL }, + { "colon", 333, NULL }, + { "g", 500, NULL }, + { "ccedilla", 444, NULL }, + { "Odieresis", 722, NULL }, + { "oe", 722, NULL }, + { "five", 500, NULL }, + { "X", 667, NULL }, + { "asciicircum", 570, NULL }, + { "emdash", 1000, NULL }, + { "aogonek", 500, NULL }, + { "Egrave", 667, NULL }, + { "ring", 333, NULL }, + { "Dcaron", 722, NULL }, + { "Z", 611, NULL }, + { "ecircumflex", 444, NULL }, + { "Amacron", 667, NULL }, + { "breve", 333, NULL }, + { "lcaron", 382, NULL }, + { "paragraph", 500, NULL }, + { "zcaron", 389, NULL }, + { "aring", 500, NULL }, + { "Ydieresis", 611, NULL }, + { "Euro", 500, NULL }, + { "iogonek", 278, NULL }, + { "florin", 500, NULL }, + { "section", 500, NULL }, + { "Scaron", 556, NULL }, + { "degree", 400, NULL }, + { "K", 667, NULL }, + { "Scommaaccent", 556, NULL }, + { "Aacute", 667, NULL }, + { "b", 500, NULL }, + { "greater", 570, NULL }, + { "asterisk", 500, NULL }, + { "Emacron", 667, NULL }, + { "scommaaccent", 389, NULL }, + { "onesuperior", 300, NULL }, + { "percent", 833, NULL }, + { "o", 500, NULL }, + { "icircumflex", 278, NULL }, + { "abreve", 500, NULL }, + { "Imacron", 389, NULL }, + { "e", 444, NULL }, + { "iacute", 278, NULL }, + { "dagger", 500, NULL }, + { "equal", 570, NULL }, + { "N", 722, NULL }, + { "C", 667, NULL }, + { "u", 556, NULL }, + { "q", 500, NULL }, + { "l", 278, NULL }, + { "quoteleft", 333, NULL }, + { "registered", 747, NULL }, + { "Gcommaaccent", 722, NULL }, + { "Racute", 667, NULL }, + { "k", 500, NULL }, + { "copyright", 747, NULL }, + { "lcommaaccent", 278, NULL }, + { "onehalf", 750, NULL }, + { "gbreve", 500, NULL }, + { "uhungarumlaut", 556, NULL }, + { "n", 556, NULL }, + { "Ecaron", 667, NULL }, + { "threesuperior", 300, NULL }, + { "zdotaccent", 389, NULL }, + { "Uacute", 722, NULL }, + { "atilde", 500, NULL }, + { "Zacute", 611, NULL }, + { "fraction", 167, NULL }, + { "Sacute", 556, NULL }, + { "Adieresis", 667, NULL }, + { "asciitilde", 570, NULL }, + { "Uogonek", 722, NULL }, + { "Lslash", 611, NULL }, + { "caron", 333, NULL }, + { "lacute", 278, NULL }, + { "H", 778, NULL }, + { "sterling", 500, NULL }, + { "greaterequal", 549, NULL }, + { "at", 832, NULL }, + { "threequarters", 750, NULL }, + { "J", 500, NULL }, + { "ohungarumlaut", 500, NULL }, + { "Ecircumflex", 667, NULL }, + { "L", 611, NULL }, + { "notequal", 549, NULL }, + { "Agrave", 667, NULL }, + { "exclam", 389, NULL }, + { "AE", 944, NULL }, + { "Acircumflex", 667, NULL }, + { "oslash", 500, NULL }, + { "ograve", 500, NULL }, + { "Rcommaaccent", 667, NULL }, + { "Lacute", 611, NULL }, + { "sacute", 389, NULL }, + { "Idieresis", 389, NULL }, + { "f", 333, NULL }, + { "gcommaaccent", 500, NULL }, + { "Ohungarumlaut", 722, NULL }, + { "bracketleft", 333, NULL }, + { "otilde", 500, NULL }, + { "parenright", 333, NULL }, + { "Eogonek", 667, NULL }, + { "macron", 333, NULL }, + { "backslash", 278, NULL }, + { "Lcaron", 611, NULL }, + { "ordmasculine", 300, NULL }, + { "questiondown", 500, NULL }, + { "three", 500, NULL }, + { "slash", 278, NULL }, + { "r", 389, NULL }, + { "ucircumflex", 556, NULL }, + { "zacute", 389, NULL }, + { "Umacron", 722, NULL }, + { "ncaron", 556, NULL }, + { "adieresis", 500, NULL }, + { "lozenge", 494, NULL }, + { "V", 667, NULL }, + { "Q", 722, NULL }, + { "exclamdown", 389, NULL }, + { "quoteright", 333, NULL }, + { "uogonek", 556, NULL }, + { "semicolon", 333, NULL }, + { "guilsinglright", 333, NULL }, + { "egrave", 444, NULL }, + { "uring", 556, NULL }, + { "s", 389, NULL }, + { "z", 389, NULL }, + { "Uhungarumlaut", 722, NULL }, + { "one", 500, NULL }, + { "I", 389, NULL }, + { "eight", 500, NULL }, + { "periodcentered", 250, NULL }, + { "c", 444, NULL }, + { "d", 500, NULL }, + { "agrave", 500, NULL }, + { "ellipsis", 1000, NULL }, + { "Aring", 667, NULL }, + { "t", 278, NULL }, + { "quotedbl", 555, NULL }, + { "Oacute", 722, NULL }, + { "six", 500, NULL }, + { "edotaccent", 444, NULL }, + { "lslash", 278, NULL }, + { "P", 611, NULL }, + { "i", 278, NULL }, + { "multiply", 570, NULL }, + { "bar", 220, NULL }, + { "quotesingle", 278, NULL }, + { "braceleft", 348, NULL }, + { "braceright", 348, NULL }, + { "acute", 333, NULL }, + { "onequarter", 750, NULL }, + { "Atilde", 667, NULL }, + { "Edieresis", 667, NULL }, + { "oacute", 500, NULL }, + { "Yacute", 611, NULL }, + { "daggerdbl", 500, NULL }, + { "ncommaaccent", 556, NULL }, + { "tcommaaccent", 278, NULL }, + { "logicalnot", 606, NULL }, + { "cacute", 444, NULL }, + { "Dcroat", 722, NULL }, + { "tcaron", 366, NULL }, + { "rcaron", 389, NULL }, + { "x", 500, NULL }, + { "Iogonek", 389, NULL }, + { "edieresis", 444, NULL }, + { "y", 444, NULL }, + { "Ncaron", 722, NULL }, + { "m", 778, NULL }, + { "OE", 944, NULL }, + { "U", 722, NULL }, + { "partialdiff", 494, NULL }, + { "igrave", 278, NULL }, + { "dcroat", 500, NULL }, + { "question", 500, NULL }, + { "summation", 600, NULL }, + { "A", 667, NULL }, + { "guilsinglleft", 333, NULL }, + { "Cacute", 667, NULL }, + { "h", 556, NULL }, + { "plus", 570, NULL }, + { "Otilde", 722, NULL }, + { "umacron", 556, NULL }, + { "Tcaron", 611, NULL }, + { "aacute", 500, NULL }, + { "B", 667, NULL }, + { "kcommaaccent", 500, NULL }, + { "Rcaron", 667, NULL }, + { "yacute", 444, NULL }, + { "ydieresis", 444, NULL }, + { "R", 667, NULL }, + { "ugrave", 556, NULL }, + { "dcaron", 608, NULL }, + { "Oslash", 722, NULL }, + { "hyphen", 333, NULL }, + { "a", 500, NULL }, + { "omacron", 500, NULL }, + { "Delta", 612, NULL }, + { "comma", 250, NULL }, + { "Gbreve", 722, NULL }, + { "S", 556, NULL }, + { "quotedblleft", 500, NULL }, + { "ordfeminine", 266, NULL }, + { "trademark", 1000, NULL }, + { "ampersand", 778, NULL }, + { "Lcommaaccent", 611, NULL }, + { "ntilde", 556, NULL }, + { "fi", 556, NULL }, + { "dieresis", 333, NULL }, + { "Eacute", 667, NULL }, + { "O", 722, NULL }, + { "Icircumflex", 389, NULL }, + { "nacute", 556, NULL }, + { "Abreve", 667, NULL }, + { "Udieresis", 722, NULL }, + { "Iacute", 389, NULL }, + { "two", 500, NULL }, + { "uacute", 556, NULL }, + { "seven", 500, NULL }, + { "scaron", 389, NULL }, + { "guillemotright", 500, NULL }, + { "bullet", 350, NULL }, + { "eogonek", 444, NULL }, + { "eacute", 444, NULL }, + { "Zdotaccent", 611, NULL } +}; + +static BuiltinFontWidth timesItalicWidthsTab[] = { + { "quoteright", 333, NULL }, + { "uogonek", 500, NULL }, + { "semicolon", 333, NULL }, + { "guilsinglright", 333, NULL }, + { "Umacron", 722, NULL }, + { "zacute", 389, NULL }, + { "ncaron", 500, NULL }, + { "adieresis", 500, NULL }, + { "lozenge", 471, NULL }, + { "V", 611, NULL }, + { "Q", 722, NULL }, + { "exclamdown", 389, NULL }, + { "three", 500, NULL }, + { "slash", 278, NULL }, + { "r", 389, NULL }, + { "ucircumflex", 500, NULL }, + { "Eogonek", 611, NULL }, + { "macron", 333, NULL }, + { "ordmasculine", 310, NULL }, + { "Lcaron", 611, NULL }, + { "questiondown", 500, NULL }, + { "backslash", 278, NULL }, + { "t", 278, NULL }, + { "quotedbl", 420, NULL }, + { "Oacute", 722, NULL }, + { "agrave", 500, NULL }, + { "ellipsis", 889, NULL }, + { "Aring", 611, NULL }, + { "I", 333, NULL }, + { "one", 500, NULL }, + { "eight", 500, NULL }, + { "periodcentered", 250, NULL }, + { "c", 444, NULL }, + { "d", 500, NULL }, + { "egrave", 444, NULL }, + { "uring", 500, NULL }, + { "s", 389, NULL }, + { "Uhungarumlaut", 722, NULL }, + { "z", 389, NULL }, + { "threequarters", 750, NULL }, + { "J", 444, NULL }, + { "ohungarumlaut", 500, NULL }, + { "Ecircumflex", 611, NULL }, + { "L", 556, NULL }, + { "notequal", 549, NULL }, + { "Agrave", 611, NULL }, + { "AE", 889, NULL }, + { "exclam", 333, NULL }, + { "Acircumflex", 611, NULL }, + { "oslash", 500, NULL }, + { "caron", 333, NULL }, + { "Uogonek", 722, NULL }, + { "Lslash", 556, NULL }, + { "lacute", 278, NULL }, + { "H", 722, NULL }, + { "sterling", 500, NULL }, + { "at", 920, NULL }, + { "greaterequal", 549, NULL }, + { "asciitilde", 541, NULL }, + { "Uacute", 722, NULL }, + { "atilde", 500, NULL }, + { "Zacute", 556, NULL }, + { "fraction", 167, NULL }, + { "Adieresis", 611, NULL }, + { "Sacute", 500, NULL }, + { "gcommaaccent", 500, NULL }, + { "Ohungarumlaut", 722, NULL }, + { "bracketleft", 389, NULL }, + { "otilde", 500, NULL }, + { "parenright", 333, NULL }, + { "f", 278, NULL }, + { "Lacute", 556, NULL }, + { "sacute", 389, NULL }, + { "Idieresis", 333, NULL }, + { "ograve", 500, NULL }, + { "Rcommaaccent", 611, NULL }, + { "quotedblleft", 556, NULL }, + { "ordfeminine", 276, NULL }, + { "omacron", 500, NULL }, + { "Delta", 612, NULL }, + { "comma", 250, NULL }, + { "Gbreve", 722, NULL }, + { "S", 500, NULL }, + { "B", 611, NULL }, + { "kcommaaccent", 444, NULL }, + { "yacute", 444, NULL }, + { "Rcaron", 611, NULL }, + { "R", 611, NULL }, + { "ydieresis", 444, NULL }, + { "ugrave", 500, NULL }, + { "dcaron", 544, NULL }, + { "Oslash", 722, NULL }, + { "hyphen", 333, NULL }, + { "a", 500, NULL }, + { "umacron", 500, NULL }, + { "Otilde", 722, NULL }, + { "Tcaron", 556, NULL }, + { "aacute", 500, NULL }, + { "scaron", 389, NULL }, + { "guillemotright", 500, NULL }, + { "eogonek", 444, NULL }, + { "bullet", 350, NULL }, + { "eacute", 444, NULL }, + { "Zdotaccent", 556, NULL }, + { "Udieresis", 722, NULL }, + { "Abreve", 611, NULL }, + { "Iacute", 333, NULL }, + { "two", 500, NULL }, + { "uacute", 500, NULL }, + { "seven", 500, NULL }, + { "dieresis", 333, NULL }, + { "Eacute", 611, NULL }, + { "O", 722, NULL }, + { "Icircumflex", 333, NULL }, + { "nacute", 500, NULL }, + { "trademark", 980, NULL }, + { "ampersand", 778, NULL }, + { "Lcommaaccent", 556, NULL }, + { "ntilde", 500, NULL }, + { "fi", 500, NULL }, + { "Atilde", 611, NULL }, + { "Edieresis", 611, NULL }, + { "Yacute", 556, NULL }, + { "oacute", 500, NULL }, + { "daggerdbl", 500, NULL }, + { "braceleft", 400, NULL }, + { "braceright", 400, NULL }, + { "acute", 333, NULL }, + { "onequarter", 750, NULL }, + { "multiply", 675, NULL }, + { "i", 278, NULL }, + { "bar", 275, NULL }, + { "quotesingle", 214, NULL }, + { "six", 500, NULL }, + { "edotaccent", 444, NULL }, + { "P", 611, NULL }, + { "lslash", 278, NULL }, + { "guilsinglleft", 333, NULL }, + { "h", 500, NULL }, + { "Cacute", 667, NULL }, + { "plus", 675, NULL }, + { "igrave", 278, NULL }, + { "dcroat", 500, NULL }, + { "question", 500, NULL }, + { "summation", 600, NULL }, + { "A", 611, NULL }, + { "x", 444, NULL }, + { "Iogonek", 333, NULL }, + { "y", 444, NULL }, + { "edieresis", 444, NULL }, + { "Ncaron", 667, NULL }, + { "m", 722, NULL }, + { "OE", 944, NULL }, + { "U", 722, NULL }, + { "partialdiff", 476, NULL }, + { "ncommaaccent", 500, NULL }, + { "tcommaaccent", 278, NULL }, + { "logicalnot", 675, NULL }, + { "cacute", 444, NULL }, + { "Dcroat", 722, NULL }, + { "tcaron", 300, NULL }, + { "rcaron", 389, NULL }, + { "rcommaaccent", 389, NULL }, + { "Kcommaaccent", 667, NULL }, + { "imacron", 278, NULL }, + { "tilde", 333, NULL }, + { "underscore", 500, NULL }, + { "mu", 500, NULL }, + { "D", 722, NULL }, + { "racute", 389, NULL }, + { "Tcommaaccent", 556, NULL }, + { "dollar", 500, NULL }, + { "v", 444, NULL }, + { "Nacute", 667, NULL }, + { "dotaccent", 333, NULL }, + { "ae", 667, NULL }, + { "cent", 500, NULL }, + { "ocircumflex", 500, NULL }, + { "less", 675, NULL }, + { "four", 500, NULL }, + { "minus", 675, NULL }, + { "circumflex", 333, NULL }, + { "Zcaron", 556, NULL }, + { "ogonek", 333, NULL }, + { "idieresis", 278, NULL }, + { "parenleft", 333, NULL }, + { "currency", 500, NULL }, + { "nine", 500, NULL }, + { "quotesinglbase", 333, NULL }, + { "grave", 333, NULL }, + { "Scedilla", 500, NULL }, + { "ccaron", 444, NULL }, + { "lessequal", 549, NULL }, + { "Omacron", 722, NULL }, + { "Ucircumflex", 722, NULL }, + { "hungarumlaut", 333, NULL }, + { "j", 278, NULL }, + { "Ccaron", 667, NULL }, + { "Y", 556, NULL }, + { "yen", 500, NULL }, + { "w", 667, NULL }, + { "space", 250, NULL }, + { "Thorn", 611, NULL }, + { "eth", 500, NULL }, + { "twosuperior", 300, NULL }, + { "ecaron", 444, NULL }, + { "brokenbar", 275, NULL }, + { "Aogonek", 611, NULL }, + { "fl", 500, NULL }, + { "quotedblbase", 556, NULL }, + { "E", 611, NULL }, + { "endash", 500, NULL }, + { "guillemotleft", 500, NULL }, + { "amacron", 500, NULL }, + { "Ncommaaccent", 667, NULL }, + { "numbersign", 500, NULL }, + { "divide", 675, NULL }, + { "emacron", 444, NULL }, + { "M", 833, NULL }, + { "odieresis", 500, NULL }, + { "Ograve", 722, NULL }, + { "T", 556, NULL }, + { "G", 722, NULL }, + { "F", 611, NULL }, + { "Ocircumflex", 722, NULL }, + { "Uring", 722, NULL }, + { "Edotaccent", 611, NULL }, + { "perthousand", 1000, NULL }, + { "acircumflex", 500, NULL }, + { "zero", 500, NULL }, + { "period", 250, NULL }, + { "scedilla", 389, NULL }, + { "udieresis", 500, NULL }, + { "Ccedilla", 667, NULL }, + { "Igrave", 333, NULL }, + { "commaaccent", 250, NULL }, + { "bracketright", 389, NULL }, + { "W", 833, NULL }, + { "Ugrave", 722, NULL }, + { "germandbls", 500, NULL }, + { "thorn", 500, NULL }, + { "dagger", 500, NULL }, + { "equal", 675, NULL }, + { "N", 667, NULL }, + { "C", 667, NULL }, + { "u", 500, NULL }, + { "q", 500, NULL }, + { "l", 278, NULL }, + { "icircumflex", 278, NULL }, + { "abreve", 500, NULL }, + { "Imacron", 333, NULL }, + { "iacute", 278, NULL }, + { "e", 444, NULL }, + { "percent", 833, NULL }, + { "o", 500, NULL }, + { "greater", 675, NULL }, + { "Emacron", 611, NULL }, + { "scommaaccent", 389, NULL }, + { "asterisk", 500, NULL }, + { "onesuperior", 300, NULL }, + { "n", 500, NULL }, + { "Ecaron", 611, NULL }, + { "threesuperior", 300, NULL }, + { "zdotaccent", 389, NULL }, + { "lcommaaccent", 278, NULL }, + { "onehalf", 750, NULL }, + { "gbreve", 500, NULL }, + { "uhungarumlaut", 500, NULL }, + { "Racute", 611, NULL }, + { "k", 444, NULL }, + { "copyright", 760, NULL }, + { "quoteleft", 333, NULL }, + { "registered", 760, NULL }, + { "Gcommaaccent", 722, NULL }, + { "emdash", 889, NULL }, + { "aogonek", 500, NULL }, + { "Egrave", 611, NULL }, + { "ring", 333, NULL }, + { "Odieresis", 722, NULL }, + { "oe", 667, NULL }, + { "five", 500, NULL }, + { "X", 611, NULL }, + { "asciicircum", 422, NULL }, + { "plusminus", 675, NULL }, + { "Idotaccent", 333, NULL }, + { "cedilla", 333, NULL }, + { "quotedblright", 556, NULL }, + { "Eth", 722, NULL }, + { "g", 500, NULL }, + { "colon", 333, NULL }, + { "ccedilla", 444, NULL }, + { "Ntilde", 667, NULL }, + { "radical", 453, NULL }, + { "dotlessi", 278, NULL }, + { "p", 500, NULL }, + { "K", 667, NULL }, + { "Scommaaccent", 500, NULL }, + { "Aacute", 611, NULL }, + { "b", 500, NULL }, + { "Euro", 500, NULL }, + { "iogonek", 278, NULL }, + { "florin", 500, NULL }, + { "section", 500, NULL }, + { "Scaron", 500, NULL }, + { "degree", 400, NULL }, + { "lcaron", 300, NULL }, + { "paragraph", 523, NULL }, + { "zcaron", 389, NULL }, + { "aring", 500, NULL }, + { "Ydieresis", 556, NULL }, + { "Dcaron", 722, NULL }, + { "Z", 556, NULL }, + { "ecircumflex", 444, NULL }, + { "Amacron", 611, NULL }, + { "breve", 333, NULL } +}; + +static BuiltinFontWidth timesRomanWidthsTab[] = { + { "greaterequal", 549, NULL }, + { "at", 921, NULL }, + { "sterling", 500, NULL }, + { "H", 722, NULL }, + { "caron", 333, NULL }, + { "Uogonek", 722, NULL }, + { "Lslash", 611, NULL }, + { "lacute", 278, NULL }, + { "Acircumflex", 722, NULL }, + { "oslash", 500, NULL }, + { "notequal", 549, NULL }, + { "Agrave", 722, NULL }, + { "AE", 889, NULL }, + { "exclam", 333, NULL }, + { "ohungarumlaut", 500, NULL }, + { "L", 611, NULL }, + { "Ecircumflex", 611, NULL }, + { "threequarters", 750, NULL }, + { "J", 389, NULL }, + { "Sacute", 556, NULL }, + { "Adieresis", 722, NULL }, + { "fraction", 167, NULL }, + { "atilde", 444, NULL }, + { "Zacute", 611, NULL }, + { "Uacute", 722, NULL }, + { "asciitilde", 541, NULL }, + { "f", 333, NULL }, + { "parenright", 333, NULL }, + { "otilde", 500, NULL }, + { "Ohungarumlaut", 722, NULL }, + { "bracketleft", 333, NULL }, + { "gcommaaccent", 500, NULL }, + { "Rcommaaccent", 667, NULL }, + { "ograve", 500, NULL }, + { "sacute", 389, NULL }, + { "Idieresis", 333, NULL }, + { "Lacute", 611, NULL }, + { "Q", 722, NULL }, + { "exclamdown", 333, NULL }, + { "lozenge", 471, NULL }, + { "V", 722, NULL }, + { "ncaron", 500, NULL }, + { "adieresis", 444, NULL }, + { "zacute", 444, NULL }, + { "Umacron", 722, NULL }, + { "semicolon", 278, NULL }, + { "guilsinglright", 333, NULL }, + { "quoteright", 333, NULL }, + { "uogonek", 500, NULL }, + { "Eogonek", 611, NULL }, + { "macron", 333, NULL }, + { "ordmasculine", 310, NULL }, + { "Lcaron", 611, NULL }, + { "backslash", 278, NULL }, + { "questiondown", 444, NULL }, + { "ucircumflex", 500, NULL }, + { "r", 333, NULL }, + { "slash", 278, NULL }, + { "three", 500, NULL }, + { "Aring", 722, NULL }, + { "ellipsis", 1000, NULL }, + { "agrave", 444, NULL }, + { "Oacute", 722, NULL }, + { "quotedbl", 408, NULL }, + { "t", 278, NULL }, + { "Uhungarumlaut", 722, NULL }, + { "z", 444, NULL }, + { "uring", 500, NULL }, + { "s", 389, NULL }, + { "egrave", 444, NULL }, + { "c", 444, NULL }, + { "d", 500, NULL }, + { "periodcentered", 250, NULL }, + { "I", 333, NULL }, + { "eight", 500, NULL }, + { "one", 500, NULL }, + { "onequarter", 750, NULL }, + { "braceright", 480, NULL }, + { "braceleft", 480, NULL }, + { "acute", 333, NULL }, + { "daggerdbl", 500, NULL }, + { "oacute", 500, NULL }, + { "Yacute", 722, NULL }, + { "Edieresis", 611, NULL }, + { "Atilde", 722, NULL }, + { "P", 556, NULL }, + { "lslash", 278, NULL }, + { "six", 500, NULL }, + { "edotaccent", 444, NULL }, + { "quotesingle", 180, NULL }, + { "bar", 200, NULL }, + { "i", 278, NULL }, + { "multiply", 564, NULL }, + { "A", 722, NULL }, + { "question", 444, NULL }, + { "summation", 600, NULL }, + { "igrave", 278, NULL }, + { "dcroat", 500, NULL }, + { "plus", 564, NULL }, + { "guilsinglleft", 333, NULL }, + { "h", 500, NULL }, + { "Cacute", 667, NULL }, + { "rcaron", 333, NULL }, + { "tcaron", 326, NULL }, + { "cacute", 444, NULL }, + { "Dcroat", 722, NULL }, + { "tcommaaccent", 278, NULL }, + { "logicalnot", 564, NULL }, + { "ncommaaccent", 500, NULL }, + { "partialdiff", 476, NULL }, + { "U", 722, NULL }, + { "m", 778, NULL }, + { "OE", 889, NULL }, + { "Ncaron", 722, NULL }, + { "x", 500, NULL }, + { "edieresis", 444, NULL }, + { "Iogonek", 333, NULL }, + { "y", 500, NULL }, + { "S", 556, NULL }, + { "Gbreve", 722, NULL }, + { "omacron", 500, NULL }, + { "comma", 250, NULL }, + { "Delta", 612, NULL }, + { "ordfeminine", 276, NULL }, + { "quotedblleft", 444, NULL }, + { "aacute", 444, NULL }, + { "Tcaron", 611, NULL }, + { "Otilde", 722, NULL }, + { "umacron", 500, NULL }, + { "Oslash", 722, NULL }, + { "hyphen", 333, NULL }, + { "a", 444, NULL }, + { "ugrave", 500, NULL }, + { "dcaron", 588, NULL }, + { "yacute", 500, NULL }, + { "kcommaaccent", 500, NULL }, + { "Rcaron", 667, NULL }, + { "R", 667, NULL }, + { "ydieresis", 500, NULL }, + { "B", 667, NULL }, + { "seven", 500, NULL }, + { "two", 500, NULL }, + { "uacute", 500, NULL }, + { "Iacute", 333, NULL }, + { "Abreve", 722, NULL }, + { "Udieresis", 722, NULL }, + { "Zdotaccent", 611, NULL }, + { "eacute", 444, NULL }, + { "eogonek", 444, NULL }, + { "bullet", 350, NULL }, + { "guillemotright", 500, NULL }, + { "scaron", 389, NULL }, + { "fi", 556, NULL }, + { "ntilde", 500, NULL }, + { "Lcommaaccent", 611, NULL }, + { "trademark", 980, NULL }, + { "ampersand", 778, NULL }, + { "O", 722, NULL }, + { "Icircumflex", 333, NULL }, + { "nacute", 500, NULL }, + { "Eacute", 611, NULL }, + { "dieresis", 333, NULL }, + { "endash", 500, NULL }, + { "guillemotleft", 500, NULL }, + { "E", 611, NULL }, + { "quotedblbase", 444, NULL }, + { "fl", 556, NULL }, + { "brokenbar", 200, NULL }, + { "Aogonek", 722, NULL }, + { "ecaron", 444, NULL }, + { "Thorn", 556, NULL }, + { "space", 250, NULL }, + { "twosuperior", 300, NULL }, + { "eth", 500, NULL }, + { "w", 722, NULL }, + { "T", 611, NULL }, + { "Ograve", 722, NULL }, + { "M", 889, NULL }, + { "odieresis", 500, NULL }, + { "divide", 564, NULL }, + { "emacron", 444, NULL }, + { "numbersign", 500, NULL }, + { "Ncommaaccent", 722, NULL }, + { "amacron", 444, NULL }, + { "acircumflex", 444, NULL }, + { "Edotaccent", 611, NULL }, + { "perthousand", 1000, NULL }, + { "Uring", 722, NULL }, + { "Ocircumflex", 722, NULL }, + { "F", 556, NULL }, + { "G", 722, NULL }, + { "thorn", 500, NULL }, + { "Ugrave", 722, NULL }, + { "germandbls", 500, NULL }, + { "bracketright", 333, NULL }, + { "W", 944, NULL }, + { "commaaccent", 250, NULL }, + { "Igrave", 333, NULL }, + { "Ccedilla", 667, NULL }, + { "period", 250, NULL }, + { "scedilla", 389, NULL }, + { "udieresis", 500, NULL }, + { "zero", 500, NULL }, + { "v", 500, NULL }, + { "Nacute", 722, NULL }, + { "dotaccent", 333, NULL }, + { "Tcommaaccent", 611, NULL }, + { "dollar", 500, NULL }, + { "mu", 500, NULL }, + { "D", 722, NULL }, + { "racute", 333, NULL }, + { "underscore", 500, NULL }, + { "tilde", 333, NULL }, + { "rcommaaccent", 333, NULL }, + { "Kcommaaccent", 722, NULL }, + { "imacron", 278, NULL }, + { "idieresis", 278, NULL }, + { "ogonek", 333, NULL }, + { "Zcaron", 611, NULL }, + { "circumflex", 333, NULL }, + { "four", 500, NULL }, + { "minus", 564, NULL }, + { "ocircumflex", 500, NULL }, + { "less", 564, NULL }, + { "cent", 500, NULL }, + { "ae", 667, NULL }, + { "grave", 333, NULL }, + { "Scedilla", 556, NULL }, + { "quotesinglbase", 333, NULL }, + { "currency", 500, NULL }, + { "nine", 500, NULL }, + { "parenleft", 333, NULL }, + { "yen", 500, NULL }, + { "Y", 722, NULL }, + { "hungarumlaut", 333, NULL }, + { "Ccaron", 667, NULL }, + { "j", 278, NULL }, + { "lessequal", 549, NULL }, + { "Ucircumflex", 722, NULL }, + { "Omacron", 722, NULL }, + { "ccaron", 444, NULL }, + { "X", 722, NULL }, + { "asciicircum", 469, NULL }, + { "five", 500, NULL }, + { "Odieresis", 722, NULL }, + { "oe", 722, NULL }, + { "ring", 333, NULL }, + { "Egrave", 611, NULL }, + { "aogonek", 444, NULL }, + { "emdash", 1000, NULL }, + { "dotlessi", 278, NULL }, + { "p", 500, NULL }, + { "radical", 453, NULL }, + { "Ntilde", 722, NULL }, + { "g", 500, NULL }, + { "colon", 278, NULL }, + { "ccedilla", 444, NULL }, + { "quotedblright", 444, NULL }, + { "Eth", 722, NULL }, + { "plusminus", 564, NULL }, + { "Idotaccent", 333, NULL }, + { "cedilla", 333, NULL }, + { "section", 500, NULL }, + { "Scaron", 556, NULL }, + { "degree", 400, NULL }, + { "Euro", 500, NULL }, + { "florin", 500, NULL }, + { "iogonek", 278, NULL }, + { "b", 500, NULL }, + { "Scommaaccent", 556, NULL }, + { "Aacute", 722, NULL }, + { "K", 722, NULL }, + { "Amacron", 722, NULL }, + { "breve", 333, NULL }, + { "Z", 611, NULL }, + { "ecircumflex", 444, NULL }, + { "Dcaron", 722, NULL }, + { "aring", 444, NULL }, + { "Ydieresis", 722, NULL }, + { "lcaron", 344, NULL }, + { "paragraph", 453, NULL }, + { "zcaron", 444, NULL }, + { "Imacron", 333, NULL }, + { "abreve", 444, NULL }, + { "e", 444, NULL }, + { "iacute", 278, NULL }, + { "icircumflex", 278, NULL }, + { "q", 500, NULL }, + { "l", 278, NULL }, + { "C", 667, NULL }, + { "u", 500, NULL }, + { "dagger", 500, NULL }, + { "equal", 564, NULL }, + { "N", 722, NULL }, + { "onesuperior", 300, NULL }, + { "asterisk", 500, NULL }, + { "Emacron", 611, NULL }, + { "scommaaccent", 389, NULL }, + { "greater", 564, NULL }, + { "o", 500, NULL }, + { "percent", 833, NULL }, + { "gbreve", 500, NULL }, + { "uhungarumlaut", 500, NULL }, + { "lcommaaccent", 278, NULL }, + { "onehalf", 750, NULL }, + { "threesuperior", 300, NULL }, + { "zdotaccent", 444, NULL }, + { "Ecaron", 611, NULL }, + { "n", 500, NULL }, + { "Gcommaaccent", 722, NULL }, + { "registered", 760, NULL }, + { "quoteleft", 333, NULL }, + { "copyright", 760, NULL }, + { "k", 500, NULL }, + { "Racute", 667, NULL } +}; + +static BuiltinFontWidth zapfDingbatsWidthsTab[] = { + { "a198", 888, NULL }, + { "a107", 760, NULL }, + { "a167", 927, NULL }, + { "a97", 392, NULL }, + { "a137", 788, NULL }, + { "a175", 930, NULL }, + { "a55", 708, NULL }, + { "a206", 410, NULL }, + { "a146", 788, NULL }, + { "a27", 759, NULL }, + { "a71", 791, NULL }, + { "a79", 784, NULL }, + { "a136", 788, NULL }, + { "a43", 923, NULL }, + { "a131", 788, NULL }, + { "a154", 788, NULL }, + { "a123", 788, NULL }, + { "a8", 537, NULL }, + { "a87", 234, NULL }, + { "a72", 873, NULL }, + { "a199", 867, NULL }, + { "a151", 788, NULL }, + { "a99", 668, NULL }, + { "a126", 788, NULL }, + { "a46", 749, NULL }, + { "a34", 794, NULL }, + { "a186", 967, NULL }, + { "a102", 544, NULL }, + { "a205", 509, NULL }, + { "a62", 707, NULL }, + { "a140", 788, NULL }, + { "a90", 390, NULL }, + { "a98", 392, NULL }, + { "a9", 577, NULL }, + { "a178", 883, NULL }, + { "a26", 760, NULL }, + { "a40", 833, NULL }, + { "a125", 788, NULL }, + { "a101", 732, NULL }, + { "a103", 544, NULL }, + { "a150", 788, NULL }, + { "a57", 701, NULL }, + { "a18", 974, NULL }, + { "a184", 946, NULL }, + { "space", 278, NULL }, + { "a74", 762, NULL }, + { "a168", 928, NULL }, + { "a147", 788, NULL }, + { "a187", 831, NULL }, + { "a110", 694, NULL }, + { "a143", 788, NULL }, + { "a36", 823, NULL }, + { "a41", 816, NULL }, + { "a86", 410, NULL }, + { "a164", 458, NULL }, + { "a152", 788, NULL }, + { "a163", 1016, NULL }, + { "a3", 980, NULL }, + { "a160", 894, NULL }, + { "a166", 918, NULL }, + { "a117", 690, NULL }, + { "a83", 277, NULL }, + { "a29", 786, NULL }, + { "a22", 761, NULL }, + { "a112", 776, NULL }, + { "a133", 788, NULL }, + { "a156", 788, NULL }, + { "a200", 696, NULL }, + { "a81", 438, NULL }, + { "a106", 667, NULL }, + { "a100", 668, NULL }, + { "a132", 788, NULL }, + { "a95", 334, NULL }, + { "a37", 789, NULL }, + { "a58", 826, NULL }, + { "a191", 918, NULL }, + { "a56", 682, NULL }, + { "a70", 785, NULL }, + { "a157", 788, NULL }, + { "a171", 873, NULL }, + { "a188", 873, NULL }, + { "a47", 790, NULL }, + { "a14", 855, NULL }, + { "a23", 571, NULL }, + { "a2", 961, NULL }, + { "a77", 892, NULL }, + { "a105", 911, NULL }, + { "a25", 763, NULL }, + { "a202", 974, NULL }, + { "a61", 789, NULL }, + { "a10", 692, NULL }, + { "a44", 744, NULL }, + { "a159", 788, NULL }, + { "a48", 792, NULL }, + { "a124", 788, NULL }, + { "a190", 970, NULL }, + { "a20", 846, NULL }, + { "a185", 865, NULL }, + { "a16", 933, NULL }, + { "a11", 960, NULL }, + { "a134", 788, NULL }, + { "a108", 760, NULL }, + { "a28", 754, NULL }, + { "a149", 788, NULL }, + { "a172", 828, NULL }, + { "a1", 974, NULL }, + { "a144", 788, NULL }, + { "a92", 276, NULL }, + { "a66", 786, NULL }, + { "a189", 927, NULL }, + { "a54", 707, NULL }, + { "a59", 815, NULL }, + { "a13", 549, NULL }, + { "a4", 719, NULL }, + { "a82", 138, NULL }, + { "a109", 626, NULL }, + { "a170", 834, NULL }, + { "a201", 874, NULL }, + { "a204", 759, NULL }, + { "a39", 823, NULL }, + { "a197", 771, NULL }, + { "a49", 695, NULL }, + { "a139", 788, NULL }, + { "a96", 334, NULL }, + { "a7", 552, NULL }, + { "a183", 760, NULL }, + { "a118", 791, NULL }, + { "a155", 788, NULL }, + { "a148", 788, NULL }, + { "a73", 761, NULL }, + { "a75", 759, NULL }, + { "a76", 892, NULL }, + { "a135", 788, NULL }, + { "a177", 463, NULL }, + { "a104", 910, NULL }, + { "a88", 234, NULL }, + { "a142", 788, NULL }, + { "a179", 836, NULL }, + { "a17", 945, NULL }, + { "a203", 762, NULL }, + { "a141", 788, NULL }, + { "a31", 788, NULL }, + { "a129", 788, NULL }, + { "a35", 816, NULL }, + { "a182", 874, NULL }, + { "a15", 911, NULL }, + { "a38", 841, NULL }, + { "a169", 928, NULL }, + { "a67", 787, NULL }, + { "a45", 723, NULL }, + { "a93", 317, NULL }, + { "a195", 888, NULL }, + { "a68", 713, NULL }, + { "a6", 494, NULL }, + { "a24", 677, NULL }, + { "a21", 762, NULL }, + { "a192", 748, NULL }, + { "a138", 788, NULL }, + { "a65", 689, NULL }, + { "a84", 415, NULL }, + { "a52", 792, NULL }, + { "a32", 790, NULL }, + { "a33", 793, NULL }, + { "a60", 789, NULL }, + { "a130", 788, NULL }, + { "a180", 867, NULL }, + { "a78", 788, NULL }, + { "a42", 831, NULL }, + { "a196", 748, NULL }, + { "a111", 595, NULL }, + { "a53", 759, NULL }, + { "a161", 838, NULL }, + { "a94", 317, NULL }, + { "a85", 509, NULL }, + { "a51", 768, NULL }, + { "a181", 696, NULL }, + { "a176", 931, NULL }, + { "a50", 776, NULL }, + { "a173", 924, NULL }, + { "a153", 788, NULL }, + { "a120", 788, NULL }, + { "a122", 788, NULL }, + { "a193", 836, NULL }, + { "a165", 924, NULL }, + { "a19", 755, NULL }, + { "a30", 788, NULL }, + { "a89", 390, NULL }, + { "a158", 788, NULL }, + { "a145", 788, NULL }, + { "a121", 788, NULL }, + { "a194", 771, NULL }, + { "a64", 696, NULL }, + { "a127", 788, NULL }, + { "a174", 917, NULL }, + { "a69", 791, NULL }, + { "a128", 788, NULL }, + { "a91", 276, NULL }, + { "a63", 687, NULL }, + { "a5", 789, NULL }, + { "a119", 790, NULL }, + { "a12", 939, NULL }, + { "a162", 924, NULL } +}; + +BuiltinFont builtinFonts[] = { + { "Courier", standardEncoding, 600, 629, -157, { -23, -250, 715, 805}, NULL }, + { "Courier-Bold", standardEncoding, 600, 629, -157, {-113, -250, 749, 801}, NULL }, + { "Courier-BoldOblique", standardEncoding, 600, 629, -157, { -57, -250, 869, 801}, NULL }, + { "Courier-Oblique", standardEncoding, 600, 629, -157, { -27, -250, 849, 805}, NULL }, + { "Helvetica", standardEncoding, 0, 718, -207, {-166, -225, 1000, 931}, NULL }, + { "Helvetica-Bold", standardEncoding, 0, 718, -207, {-170, -228, 1003, 962}, NULL }, + { "Helvetica-BoldOblique", standardEncoding, 0, 718, -207, {-174, -228, 1114, 962}, NULL }, + { "Helvetica-Oblique", standardEncoding, 0, 718, -207, {-170, -225, 1116, 931}, NULL }, + { "Symbol", symbolEncoding, 0, 1010, -293, {-180, -293, 1090, 1010}, NULL }, + { "Times-Bold", standardEncoding, 0, 683, -217, {-168, -218, 1000, 935}, NULL }, + { "Times-BoldItalic", standardEncoding, 0, 683, -217, {-200, -218, 996, 921}, NULL }, + { "Times-Italic", standardEncoding, 0, 683, -217, {-169, -217, 1010, 883}, NULL }, + { "Times-Roman", standardEncoding, 0, 683, -217, {-168, -218, 1000, 898}, NULL }, + { "ZapfDingbats", zapfDingbatsEncoding, 0, 820, -143, { -1, -143, 981, 820}, NULL } +}; + +BuiltinFont *builtinFontSubst[] = { + &builtinFonts[0], + &builtinFonts[3], + &builtinFonts[1], + &builtinFonts[2], + &builtinFonts[4], + &builtinFonts[7], + &builtinFonts[5], + &builtinFonts[6], + &builtinFonts[12], + &builtinFonts[11], + &builtinFonts[9], + &builtinFonts[10] +}; + +void initBuiltinFontTables() { + builtinFonts[0].widths = new BuiltinFontWidths(courierWidthsTab, 315); + builtinFonts[1].widths = new BuiltinFontWidths(courierBoldWidthsTab, 315); + builtinFonts[2].widths = new BuiltinFontWidths(courierBoldObliqueWidthsTab, 315); + builtinFonts[3].widths = new BuiltinFontWidths(courierObliqueWidthsTab, 315); + builtinFonts[4].widths = new BuiltinFontWidths(helveticaWidthsTab, 315); + builtinFonts[5].widths = new BuiltinFontWidths(helveticaBoldWidthsTab, 316); + builtinFonts[6].widths = new BuiltinFontWidths(helveticaBoldObliqueWidthsTab, 315); + builtinFonts[7].widths = new BuiltinFontWidths(helveticaObliqueWidthsTab, 315); + builtinFonts[8].widths = new BuiltinFontWidths(symbolWidthsTab, 190); + builtinFonts[9].widths = new BuiltinFontWidths(timesBoldWidthsTab, 315); + builtinFonts[10].widths = new BuiltinFontWidths(timesBoldItalicWidthsTab, 315); + builtinFonts[11].widths = new BuiltinFontWidths(timesItalicWidthsTab, 315); + builtinFonts[12].widths = new BuiltinFontWidths(timesRomanWidthsTab, 315); + builtinFonts[13].widths = new BuiltinFontWidths(zapfDingbatsWidthsTab, 202); +} + +void freeBuiltinFontTables() { + int i; + + for (i = 0; i < 14; ++i) { + delete builtinFonts[i].widths; + } +} diff --git a/xpdf/BuiltinFontTables.h b/xpdf/BuiltinFontTables.h new file mode 100644 index 0000000..eb45549 --- /dev/null +++ b/xpdf/BuiltinFontTables.h @@ -0,0 +1,23 @@ +//======================================================================== +// +// BuiltinFontTables.h +// +// Copyright 2001-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef BUILTINFONTTABLES_H +#define BUILTINFONTTABLES_H + +#include "BuiltinFont.h" + +#define nBuiltinFonts 14 +#define nBuiltinFontSubsts 12 + +extern BuiltinFont builtinFonts[nBuiltinFonts]; +extern BuiltinFont *builtinFontSubst[nBuiltinFontSubsts]; + +extern void initBuiltinFontTables(); +extern void freeBuiltinFontTables(); + +#endif diff --git a/xpdf/CMakeFiles/CMakeDirectoryInformation.cmake b/xpdf/CMakeFiles/CMakeDirectoryInformation.cmake new file mode 100644 index 0000000..aef4d6c --- /dev/null +++ b/xpdf/CMakeFiles/CMakeDirectoryInformation.cmake @@ -0,0 +1,16 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +# Relative path conversion top directories. +set(CMAKE_RELATIVE_PATH_TOP_SOURCE "/home/calvin/src/xpdf-4.04") +set(CMAKE_RELATIVE_PATH_TOP_BINARY "/home/calvin/src/xpdf-4.04") + +# Force unix paths in dependencies. +set(CMAKE_FORCE_UNIX_PATHS 1) + + +# The C and CXX include file regular expressions for this directory. +set(CMAKE_C_INCLUDE_REGEX_SCAN "^.*$") +set(CMAKE_C_INCLUDE_REGEX_COMPLAIN "^$") +set(CMAKE_CXX_INCLUDE_REGEX_SCAN ${CMAKE_C_INCLUDE_REGEX_SCAN}) +set(CMAKE_CXX_INCLUDE_REGEX_COMPLAIN ${CMAKE_C_INCLUDE_REGEX_COMPLAIN}) diff --git a/xpdf/CMakeFiles/pdfdetach.dir/CXX.includecache b/xpdf/CMakeFiles/pdfdetach.dir/CXX.includecache new file mode 100644 index 0000000..473b199 --- /dev/null +++ b/xpdf/CMakeFiles/pdfdetach.dir/CXX.includecache @@ -0,0 +1,244 @@ +#IncludeRegexLine: ^[ ]*[#%][ ]*(include|import)[ ]*[<"]([^">]+)([">]) + +#IncludeRegexScan: ^.*$ + +#IncludeRegexComplain: ^$ + +#IncludeRegexTransform: + +/home/calvin/src/xpdf-4.04/xpdf/Array.h +aconf.h +- +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h + +/home/calvin/src/xpdf-4.04/xpdf/Catalog.h +aconf.h +- +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h +CharTypes.h +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + +/home/calvin/src/xpdf-4.04/xpdf/Dict.h +aconf.h +- +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h + +/home/calvin/src/xpdf-4.04/xpdf/Error.h +aconf.h +- +stdio.h +- +config.h +/home/calvin/src/xpdf-4.04/xpdf/config.h +gfile.h +/home/calvin/src/xpdf-4.04/xpdf/gfile.h + +/home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h +aconf.h +- +stdio.h +- +windows.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +CharTypes.h +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h + +/home/calvin/src/xpdf-4.04/xpdf/Object.h +aconf.h +- +stdio.h +- +string.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +gmem.h +/home/calvin/src/xpdf-4.04/xpdf/gmem.h +gfile.h +/home/calvin/src/xpdf-4.04/xpdf/gfile.h +GString.h +/home/calvin/src/xpdf-4.04/xpdf/GString.h +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h +Array.h +/home/calvin/src/xpdf-4.04/xpdf/Array.h +Dict.h +/home/calvin/src/xpdf-4.04/xpdf/Dict.h +Stream.h +/home/calvin/src/xpdf-4.04/xpdf/Stream.h + +/home/calvin/src/xpdf-4.04/xpdf/PDFDoc.h +aconf.h +- +stdio.h +- +XRef.h +/home/calvin/src/xpdf-4.04/xpdf/XRef.h +Catalog.h +/home/calvin/src/xpdf-4.04/xpdf/Catalog.h +Page.h +/home/calvin/src/xpdf-4.04/xpdf/Page.h + +/home/calvin/src/xpdf-4.04/xpdf/Page.h +aconf.h +- +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h + +/home/calvin/src/xpdf-4.04/xpdf/Stream.h +aconf.h +- +stdio.h +- +jpeglib.h +- +setjmp.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +gfile.h +/home/calvin/src/xpdf-4.04/xpdf/gfile.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h + +/home/calvin/src/xpdf-4.04/xpdf/UTF8.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +GString.h +/home/calvin/src/xpdf-4.04/xpdf/GString.h +CharTypes.h +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + +/home/calvin/src/xpdf-4.04/xpdf/UnicodeMap.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +CharTypes.h +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h + +/home/calvin/src/xpdf-4.04/xpdf/XRef.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +gfile.h +/home/calvin/src/xpdf-4.04/xpdf/gfile.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h + +/home/calvin/src/xpdf-4.04/xpdf/config.h + +/home/calvin/src/xpdf-4.04/xpdf/pdfdetach.cc +aconf.h +- +stdio.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +gmem.h +/home/calvin/src/xpdf-4.04/xpdf/gmem.h +gmempp.h +/home/calvin/src/xpdf-4.04/xpdf/gmempp.h +parseargs.h +/home/calvin/src/xpdf-4.04/xpdf/parseargs.h +GlobalParams.h +/home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h +PDFDoc.h +/home/calvin/src/xpdf-4.04/xpdf/PDFDoc.h +CharTypes.h +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h +UnicodeMap.h +/home/calvin/src/xpdf-4.04/xpdf/UnicodeMap.h +UTF8.h +/home/calvin/src/xpdf-4.04/xpdf/UTF8.h +Error.h +/home/calvin/src/xpdf-4.04/xpdf/Error.h +config.h +/home/calvin/src/xpdf-4.04/xpdf/config.h + +aconf.h +aconf2.h +- + +aconf2.h +AvailabilityMacros.h +- + +goo/GMutex.h +aconf.h +- +windows.h +- +intrin.h +- +pthread.h +- + +goo/GString.h +aconf.h +- +limits.h +- +stdarg.h +- +gtypes.h +goo/gtypes.h + +goo/gfile.h +aconf.h +- +stdio.h +- +stdlib.h +- +stddef.h +- +sys/stat.h +- +win32lib.h +- +windows.h +- +unistd.h +- +sys/types.h +- +gtypes.h +goo/gtypes.h + +goo/gmem.h +stdio.h +- +aconf.h +- + +goo/gmempp.h +stdlib.h +- + +goo/gtypes.h + +goo/parseargs.h +gtypes.h +goo/gtypes.h + diff --git a/xpdf/CMakeFiles/pdfdetach.dir/DependInfo.cmake b/xpdf/CMakeFiles/pdfdetach.dir/DependInfo.cmake new file mode 100644 index 0000000..10917a8 --- /dev/null +++ b/xpdf/CMakeFiles/pdfdetach.dir/DependInfo.cmake @@ -0,0 +1,26 @@ +# The set of languages for which implicit dependencies are needed: +set(CMAKE_DEPENDS_LANGUAGES + "CXX" + ) +# The set of files for implicit dependencies of each language: +set(CMAKE_DEPENDS_CHECK_CXX + "/home/calvin/src/xpdf-4.04/xpdf/pdfdetach.cc" "/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/pdfdetach.dir/pdfdetach.cc.o" + ) +set(CMAKE_CXX_COMPILER_ID "GNU") + +# The include file search paths: +set(CMAKE_CXX_TARGET_INCLUDE_PATH + "." + "goo" + "fofi" + "splash" + ) + +# Targets to which this target links. +set(CMAKE_TARGET_LINKED_INFO_FILES + "/home/calvin/src/xpdf-4.04/goo/CMakeFiles/goo.dir/DependInfo.cmake" + "/home/calvin/src/xpdf-4.04/fofi/CMakeFiles/fofi.dir/DependInfo.cmake" + ) + +# Fortran module output directory. +set(CMAKE_Fortran_TARGET_MODULE_DIR "") diff --git a/xpdf/CMakeFiles/pdfdetach.dir/build.make b/xpdf/CMakeFiles/pdfdetach.dir/build.make new file mode 100644 index 0000000..7f43ae6 --- /dev/null +++ b/xpdf/CMakeFiles/pdfdetach.dir/build.make @@ -0,0 +1,206 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +# Delete rule output on recipe failure. +.DELETE_ON_ERROR: + + +#============================================================================= +# Special targets provided by cmake. + +# Disable implicit rules so canonical targets will work. +.SUFFIXES: + + +# Disable VCS-based implicit rules. +% : %,v + + +# Disable VCS-based implicit rules. +% : RCS/% + + +# Disable VCS-based implicit rules. +% : RCS/%,v + + +# Disable VCS-based implicit rules. +% : SCCS/s.% + + +# Disable VCS-based implicit rules. +% : s.% + + +.SUFFIXES: .hpux_make_needs_suffix_list + + +# Command-line flag to silence nested $(MAKE). +$(VERBOSE)MAKESILENT = -s + +#Suppress display of executed commands. +$(VERBOSE).SILENT: + +# A target that is always out of date. +cmake_force: + +.PHONY : cmake_force + +#============================================================================= +# Set environment variables for the build. + +# The shell in which to execute make rules. +SHELL = /bin/sh + +# The CMake executable. +CMAKE_COMMAND = /usr/bin/cmake + +# The command to remove a file. +RM = /usr/bin/cmake -E rm -f + +# Escaping for special characters. +EQUALS = = + +# The top-level source directory on which CMake was run. +CMAKE_SOURCE_DIR = /home/calvin/src/xpdf-4.04 + +# The top-level build directory on which CMake was run. +CMAKE_BINARY_DIR = /home/calvin/src/xpdf-4.04 + +# Include any dependencies generated for this target. +include xpdf/CMakeFiles/pdfdetach.dir/depend.make + +# Include the progress variables for this target. +include xpdf/CMakeFiles/pdfdetach.dir/progress.make + +# Include the compile flags for this target's objects. +include xpdf/CMakeFiles/pdfdetach.dir/flags.make + +xpdf/CMakeFiles/pdfdetach.dir/pdfdetach.cc.o: xpdf/CMakeFiles/pdfdetach.dir/flags.make +xpdf/CMakeFiles/pdfdetach.dir/pdfdetach.cc.o: xpdf/pdfdetach.cc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_1) "Building CXX object xpdf/CMakeFiles/pdfdetach.dir/pdfdetach.cc.o" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/pdfdetach.dir/pdfdetach.cc.o -c /home/calvin/src/xpdf-4.04/xpdf/pdfdetach.cc + +xpdf/CMakeFiles/pdfdetach.dir/pdfdetach.cc.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/pdfdetach.dir/pdfdetach.cc.i" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf/pdfdetach.cc > CMakeFiles/pdfdetach.dir/pdfdetach.cc.i + +xpdf/CMakeFiles/pdfdetach.dir/pdfdetach.cc.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/pdfdetach.dir/pdfdetach.cc.s" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf/pdfdetach.cc -o CMakeFiles/pdfdetach.dir/pdfdetach.cc.s + +# Object files for target pdfdetach +pdfdetach_OBJECTS = \ +"CMakeFiles/pdfdetach.dir/pdfdetach.cc.o" + +# External object files for target pdfdetach +pdfdetach_EXTERNAL_OBJECTS = \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/AcroForm.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Annot.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Array.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFont.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFontTables.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Catalog.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/CharCodeToUnicode.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/CMap.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Decrypt.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Dict.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Error.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/FontEncodingTables.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Function.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Gfx.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/GfxFont.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/GfxState.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/GlobalParams.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/JArithmeticDecoder.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/JBIG2Stream.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/JPXStream.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Lexer.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Link.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/NameToCharCode.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Object.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/OptionalContent.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Outline.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/OutputDev.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Page.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Parser.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/PDF417Barcode.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/PDFDoc.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/PDFDocEncoding.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/PSTokenizer.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Stream.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/TextString.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/UnicodeMap.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/UnicodeRemapping.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/UnicodeTypeTable.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/UTF8.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/XFAScanner.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/XRef.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Zoox.cc.o" + +xpdf/pdfdetach: xpdf/CMakeFiles/pdfdetach.dir/pdfdetach.cc.o +xpdf/pdfdetach: xpdf/CMakeFiles/xpdf_objs.dir/AcroForm.cc.o +xpdf/pdfdetach: xpdf/CMakeFiles/xpdf_objs.dir/Annot.cc.o +xpdf/pdfdetach: xpdf/CMakeFiles/xpdf_objs.dir/Array.cc.o +xpdf/pdfdetach: xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFont.cc.o +xpdf/pdfdetach: xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFontTables.cc.o +xpdf/pdfdetach: xpdf/CMakeFiles/xpdf_objs.dir/Catalog.cc.o +xpdf/pdfdetach: xpdf/CMakeFiles/xpdf_objs.dir/CharCodeToUnicode.cc.o +xpdf/pdfdetach: xpdf/CMakeFiles/xpdf_objs.dir/CMap.cc.o +xpdf/pdfdetach: xpdf/CMakeFiles/xpdf_objs.dir/Decrypt.cc.o +xpdf/pdfdetach: xpdf/CMakeFiles/xpdf_objs.dir/Dict.cc.o +xpdf/pdfdetach: xpdf/CMakeFiles/xpdf_objs.dir/Error.cc.o +xpdf/pdfdetach: xpdf/CMakeFiles/xpdf_objs.dir/FontEncodingTables.cc.o +xpdf/pdfdetach: xpdf/CMakeFiles/xpdf_objs.dir/Function.cc.o +xpdf/pdfdetach: xpdf/CMakeFiles/xpdf_objs.dir/Gfx.cc.o +xpdf/pdfdetach: xpdf/CMakeFiles/xpdf_objs.dir/GfxFont.cc.o +xpdf/pdfdetach: xpdf/CMakeFiles/xpdf_objs.dir/GfxState.cc.o +xpdf/pdfdetach: xpdf/CMakeFiles/xpdf_objs.dir/GlobalParams.cc.o +xpdf/pdfdetach: xpdf/CMakeFiles/xpdf_objs.dir/JArithmeticDecoder.cc.o +xpdf/pdfdetach: xpdf/CMakeFiles/xpdf_objs.dir/JBIG2Stream.cc.o +xpdf/pdfdetach: xpdf/CMakeFiles/xpdf_objs.dir/JPXStream.cc.o +xpdf/pdfdetach: xpdf/CMakeFiles/xpdf_objs.dir/Lexer.cc.o +xpdf/pdfdetach: xpdf/CMakeFiles/xpdf_objs.dir/Link.cc.o +xpdf/pdfdetach: xpdf/CMakeFiles/xpdf_objs.dir/NameToCharCode.cc.o +xpdf/pdfdetach: xpdf/CMakeFiles/xpdf_objs.dir/Object.cc.o +xpdf/pdfdetach: xpdf/CMakeFiles/xpdf_objs.dir/OptionalContent.cc.o +xpdf/pdfdetach: xpdf/CMakeFiles/xpdf_objs.dir/Outline.cc.o +xpdf/pdfdetach: xpdf/CMakeFiles/xpdf_objs.dir/OutputDev.cc.o +xpdf/pdfdetach: xpdf/CMakeFiles/xpdf_objs.dir/Page.cc.o +xpdf/pdfdetach: xpdf/CMakeFiles/xpdf_objs.dir/Parser.cc.o +xpdf/pdfdetach: xpdf/CMakeFiles/xpdf_objs.dir/PDF417Barcode.cc.o +xpdf/pdfdetach: xpdf/CMakeFiles/xpdf_objs.dir/PDFDoc.cc.o +xpdf/pdfdetach: xpdf/CMakeFiles/xpdf_objs.dir/PDFDocEncoding.cc.o +xpdf/pdfdetach: xpdf/CMakeFiles/xpdf_objs.dir/PSTokenizer.cc.o +xpdf/pdfdetach: xpdf/CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.o +xpdf/pdfdetach: xpdf/CMakeFiles/xpdf_objs.dir/Stream.cc.o +xpdf/pdfdetach: xpdf/CMakeFiles/xpdf_objs.dir/TextString.cc.o +xpdf/pdfdetach: xpdf/CMakeFiles/xpdf_objs.dir/UnicodeMap.cc.o +xpdf/pdfdetach: xpdf/CMakeFiles/xpdf_objs.dir/UnicodeRemapping.cc.o +xpdf/pdfdetach: xpdf/CMakeFiles/xpdf_objs.dir/UnicodeTypeTable.cc.o +xpdf/pdfdetach: xpdf/CMakeFiles/xpdf_objs.dir/UTF8.cc.o +xpdf/pdfdetach: xpdf/CMakeFiles/xpdf_objs.dir/XFAScanner.cc.o +xpdf/pdfdetach: xpdf/CMakeFiles/xpdf_objs.dir/XRef.cc.o +xpdf/pdfdetach: xpdf/CMakeFiles/xpdf_objs.dir/Zoox.cc.o +xpdf/pdfdetach: xpdf/CMakeFiles/pdfdetach.dir/build.make +xpdf/pdfdetach: goo/libgoo.a +xpdf/pdfdetach: fofi/libfofi.a +xpdf/pdfdetach: /usr/lib/x86_64-linux-gnu/libfontconfig.so +xpdf/pdfdetach: xpdf/CMakeFiles/pdfdetach.dir/link.txt + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --bold --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_2) "Linking CXX executable pdfdetach" + cd /home/calvin/src/xpdf-4.04/xpdf && $(CMAKE_COMMAND) -E cmake_link_script CMakeFiles/pdfdetach.dir/link.txt --verbose=$(VERBOSE) + +# Rule to build all files generated by this target. +xpdf/CMakeFiles/pdfdetach.dir/build: xpdf/pdfdetach + +.PHONY : xpdf/CMakeFiles/pdfdetach.dir/build + +xpdf/CMakeFiles/pdfdetach.dir/clean: + cd /home/calvin/src/xpdf-4.04/xpdf && $(CMAKE_COMMAND) -P CMakeFiles/pdfdetach.dir/cmake_clean.cmake +.PHONY : xpdf/CMakeFiles/pdfdetach.dir/clean + +xpdf/CMakeFiles/pdfdetach.dir/depend: + cd /home/calvin/src/xpdf-4.04 && $(CMAKE_COMMAND) -E cmake_depends "Unix Makefiles" /home/calvin/src/xpdf-4.04 /home/calvin/src/xpdf-4.04/xpdf /home/calvin/src/xpdf-4.04 /home/calvin/src/xpdf-4.04/xpdf /home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/pdfdetach.dir/DependInfo.cmake --color=$(COLOR) +.PHONY : xpdf/CMakeFiles/pdfdetach.dir/depend + diff --git a/xpdf/CMakeFiles/pdfdetach.dir/cmake_clean.cmake b/xpdf/CMakeFiles/pdfdetach.dir/cmake_clean.cmake new file mode 100644 index 0000000..acc7f7e --- /dev/null +++ b/xpdf/CMakeFiles/pdfdetach.dir/cmake_clean.cmake @@ -0,0 +1,10 @@ +file(REMOVE_RECURSE + "CMakeFiles/pdfdetach.dir/pdfdetach.cc.o" + "pdfdetach" + "pdfdetach.pdb" +) + +# Per-language clean rules from dependency scanning. +foreach(lang CXX) + include(CMakeFiles/pdfdetach.dir/cmake_clean_${lang}.cmake OPTIONAL) +endforeach() diff --git a/xpdf/CMakeFiles/pdfdetach.dir/depend.internal b/xpdf/CMakeFiles/pdfdetach.dir/depend.internal new file mode 100644 index 0000000..8a397a0 --- /dev/null +++ b/xpdf/CMakeFiles/pdfdetach.dir/depend.internal @@ -0,0 +1,28 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +xpdf/CMakeFiles/pdfdetach.dir/pdfdetach.cc.o + /home/calvin/src/xpdf-4.04/xpdf/Array.h + /home/calvin/src/xpdf-4.04/xpdf/Catalog.h + /home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + /home/calvin/src/xpdf-4.04/xpdf/Dict.h + /home/calvin/src/xpdf-4.04/xpdf/Error.h + /home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h + /home/calvin/src/xpdf-4.04/xpdf/Object.h + /home/calvin/src/xpdf-4.04/xpdf/PDFDoc.h + /home/calvin/src/xpdf-4.04/xpdf/Page.h + /home/calvin/src/xpdf-4.04/xpdf/Stream.h + /home/calvin/src/xpdf-4.04/xpdf/UTF8.h + /home/calvin/src/xpdf-4.04/xpdf/UnicodeMap.h + /home/calvin/src/xpdf-4.04/xpdf/XRef.h + /home/calvin/src/xpdf-4.04/xpdf/config.h + /home/calvin/src/xpdf-4.04/xpdf/pdfdetach.cc + aconf.h + aconf2.h + goo/GMutex.h + goo/GString.h + goo/gfile.h + goo/gmem.h + goo/gmempp.h + goo/gtypes.h + goo/parseargs.h diff --git a/xpdf/CMakeFiles/pdfdetach.dir/depend.make b/xpdf/CMakeFiles/pdfdetach.dir/depend.make new file mode 100644 index 0000000..c59e324 --- /dev/null +++ b/xpdf/CMakeFiles/pdfdetach.dir/depend.make @@ -0,0 +1,28 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +xpdf/CMakeFiles/pdfdetach.dir/pdfdetach.cc.o: xpdf/Array.h +xpdf/CMakeFiles/pdfdetach.dir/pdfdetach.cc.o: xpdf/Catalog.h +xpdf/CMakeFiles/pdfdetach.dir/pdfdetach.cc.o: xpdf/CharTypes.h +xpdf/CMakeFiles/pdfdetach.dir/pdfdetach.cc.o: xpdf/Dict.h +xpdf/CMakeFiles/pdfdetach.dir/pdfdetach.cc.o: xpdf/Error.h +xpdf/CMakeFiles/pdfdetach.dir/pdfdetach.cc.o: xpdf/GlobalParams.h +xpdf/CMakeFiles/pdfdetach.dir/pdfdetach.cc.o: xpdf/Object.h +xpdf/CMakeFiles/pdfdetach.dir/pdfdetach.cc.o: xpdf/PDFDoc.h +xpdf/CMakeFiles/pdfdetach.dir/pdfdetach.cc.o: xpdf/Page.h +xpdf/CMakeFiles/pdfdetach.dir/pdfdetach.cc.o: xpdf/Stream.h +xpdf/CMakeFiles/pdfdetach.dir/pdfdetach.cc.o: xpdf/UTF8.h +xpdf/CMakeFiles/pdfdetach.dir/pdfdetach.cc.o: xpdf/UnicodeMap.h +xpdf/CMakeFiles/pdfdetach.dir/pdfdetach.cc.o: xpdf/XRef.h +xpdf/CMakeFiles/pdfdetach.dir/pdfdetach.cc.o: xpdf/config.h +xpdf/CMakeFiles/pdfdetach.dir/pdfdetach.cc.o: xpdf/pdfdetach.cc +xpdf/CMakeFiles/pdfdetach.dir/pdfdetach.cc.o: aconf.h +xpdf/CMakeFiles/pdfdetach.dir/pdfdetach.cc.o: aconf2.h +xpdf/CMakeFiles/pdfdetach.dir/pdfdetach.cc.o: goo/GMutex.h +xpdf/CMakeFiles/pdfdetach.dir/pdfdetach.cc.o: goo/GString.h +xpdf/CMakeFiles/pdfdetach.dir/pdfdetach.cc.o: goo/gfile.h +xpdf/CMakeFiles/pdfdetach.dir/pdfdetach.cc.o: goo/gmem.h +xpdf/CMakeFiles/pdfdetach.dir/pdfdetach.cc.o: goo/gmempp.h +xpdf/CMakeFiles/pdfdetach.dir/pdfdetach.cc.o: goo/gtypes.h +xpdf/CMakeFiles/pdfdetach.dir/pdfdetach.cc.o: goo/parseargs.h + diff --git a/xpdf/CMakeFiles/pdfdetach.dir/flags.make b/xpdf/CMakeFiles/pdfdetach.dir/flags.make new file mode 100644 index 0000000..300fa3e --- /dev/null +++ b/xpdf/CMakeFiles/pdfdetach.dir/flags.make @@ -0,0 +1,10 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +# compile CXX with /usr/bin/c++ +CXX_DEFINES = + +CXX_INCLUDES = -I/home/calvin/src/xpdf-4.04 -I/home/calvin/src/xpdf-4.04/goo -I/home/calvin/src/xpdf-4.04/fofi -I/home/calvin/src/xpdf-4.04/splash + +CXX_FLAGS = + diff --git a/xpdf/CMakeFiles/pdfdetach.dir/link.txt b/xpdf/CMakeFiles/pdfdetach.dir/link.txt new file mode 100644 index 0000000..b46d9bf --- /dev/null +++ b/xpdf/CMakeFiles/pdfdetach.dir/link.txt @@ -0,0 +1 @@ +/usr/bin/c++ -rdynamic CMakeFiles/pdfdetach.dir/pdfdetach.cc.o CMakeFiles/xpdf_objs.dir/AcroForm.cc.o CMakeFiles/xpdf_objs.dir/Annot.cc.o CMakeFiles/xpdf_objs.dir/Array.cc.o CMakeFiles/xpdf_objs.dir/BuiltinFont.cc.o CMakeFiles/xpdf_objs.dir/BuiltinFontTables.cc.o CMakeFiles/xpdf_objs.dir/Catalog.cc.o CMakeFiles/xpdf_objs.dir/CharCodeToUnicode.cc.o CMakeFiles/xpdf_objs.dir/CMap.cc.o CMakeFiles/xpdf_objs.dir/Decrypt.cc.o CMakeFiles/xpdf_objs.dir/Dict.cc.o CMakeFiles/xpdf_objs.dir/Error.cc.o CMakeFiles/xpdf_objs.dir/FontEncodingTables.cc.o CMakeFiles/xpdf_objs.dir/Function.cc.o CMakeFiles/xpdf_objs.dir/Gfx.cc.o CMakeFiles/xpdf_objs.dir/GfxFont.cc.o CMakeFiles/xpdf_objs.dir/GfxState.cc.o CMakeFiles/xpdf_objs.dir/GlobalParams.cc.o CMakeFiles/xpdf_objs.dir/JArithmeticDecoder.cc.o CMakeFiles/xpdf_objs.dir/JBIG2Stream.cc.o CMakeFiles/xpdf_objs.dir/JPXStream.cc.o CMakeFiles/xpdf_objs.dir/Lexer.cc.o CMakeFiles/xpdf_objs.dir/Link.cc.o CMakeFiles/xpdf_objs.dir/NameToCharCode.cc.o CMakeFiles/xpdf_objs.dir/Object.cc.o CMakeFiles/xpdf_objs.dir/OptionalContent.cc.o CMakeFiles/xpdf_objs.dir/Outline.cc.o CMakeFiles/xpdf_objs.dir/OutputDev.cc.o CMakeFiles/xpdf_objs.dir/Page.cc.o CMakeFiles/xpdf_objs.dir/Parser.cc.o CMakeFiles/xpdf_objs.dir/PDF417Barcode.cc.o CMakeFiles/xpdf_objs.dir/PDFDoc.cc.o CMakeFiles/xpdf_objs.dir/PDFDocEncoding.cc.o CMakeFiles/xpdf_objs.dir/PSTokenizer.cc.o CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.o CMakeFiles/xpdf_objs.dir/Stream.cc.o CMakeFiles/xpdf_objs.dir/TextString.cc.o CMakeFiles/xpdf_objs.dir/UnicodeMap.cc.o CMakeFiles/xpdf_objs.dir/UnicodeRemapping.cc.o CMakeFiles/xpdf_objs.dir/UnicodeTypeTable.cc.o CMakeFiles/xpdf_objs.dir/UTF8.cc.o CMakeFiles/xpdf_objs.dir/XFAScanner.cc.o CMakeFiles/xpdf_objs.dir/XRef.cc.o CMakeFiles/xpdf_objs.dir/Zoox.cc.o -o pdfdetach ../goo/libgoo.a ../fofi/libfofi.a -lfontconfig -lpthread diff --git a/xpdf/CMakeFiles/pdfdetach.dir/pdfdetach.cc.o b/xpdf/CMakeFiles/pdfdetach.dir/pdfdetach.cc.o new file mode 100644 index 0000000..c6c7289 Binary files /dev/null and b/xpdf/CMakeFiles/pdfdetach.dir/pdfdetach.cc.o differ diff --git a/xpdf/CMakeFiles/pdfdetach.dir/progress.make b/xpdf/CMakeFiles/pdfdetach.dir/progress.make new file mode 100644 index 0000000..d92f75a --- /dev/null +++ b/xpdf/CMakeFiles/pdfdetach.dir/progress.make @@ -0,0 +1,3 @@ +CMAKE_PROGRESS_1 = 13 +CMAKE_PROGRESS_2 = 14 + diff --git a/xpdf/CMakeFiles/pdffonts.dir/CXX.includecache b/xpdf/CMakeFiles/pdffonts.dir/CXX.includecache new file mode 100644 index 0000000..1cdfc75 --- /dev/null +++ b/xpdf/CMakeFiles/pdffonts.dir/CXX.includecache @@ -0,0 +1,258 @@ +#IncludeRegexLine: ^[ ]*[#%][ ]*(include|import)[ ]*[<"]([^">]+)([">]) + +#IncludeRegexScan: ^.*$ + +#IncludeRegexComplain: ^$ + +#IncludeRegexTransform: + +/home/calvin/src/xpdf-4.04/xpdf/AcroForm.h +aconf.h +- + +/home/calvin/src/xpdf-4.04/xpdf/Annot.h +aconf.h +- + +/home/calvin/src/xpdf-4.04/xpdf/Array.h +aconf.h +- +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h + +/home/calvin/src/xpdf-4.04/xpdf/Catalog.h +aconf.h +- +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h +CharTypes.h +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + +/home/calvin/src/xpdf-4.04/xpdf/Dict.h +aconf.h +- +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h + +/home/calvin/src/xpdf-4.04/xpdf/Error.h +aconf.h +- +stdio.h +- +config.h +/home/calvin/src/xpdf-4.04/xpdf/config.h +gfile.h +/home/calvin/src/xpdf-4.04/xpdf/gfile.h + +/home/calvin/src/xpdf-4.04/xpdf/GfxFont.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +GString.h +/home/calvin/src/xpdf-4.04/xpdf/GString.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h +CharTypes.h +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + +/home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h +aconf.h +- +stdio.h +- +windows.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +CharTypes.h +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h + +/home/calvin/src/xpdf-4.04/xpdf/Object.h +aconf.h +- +stdio.h +- +string.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +gmem.h +/home/calvin/src/xpdf-4.04/xpdf/gmem.h +gfile.h +/home/calvin/src/xpdf-4.04/xpdf/gfile.h +GString.h +/home/calvin/src/xpdf-4.04/xpdf/GString.h +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h +Array.h +/home/calvin/src/xpdf-4.04/xpdf/Array.h +Dict.h +/home/calvin/src/xpdf-4.04/xpdf/Dict.h +Stream.h +/home/calvin/src/xpdf-4.04/xpdf/Stream.h + +/home/calvin/src/xpdf-4.04/xpdf/PDFDoc.h +aconf.h +- +stdio.h +- +XRef.h +/home/calvin/src/xpdf-4.04/xpdf/XRef.h +Catalog.h +/home/calvin/src/xpdf-4.04/xpdf/Catalog.h +Page.h +/home/calvin/src/xpdf-4.04/xpdf/Page.h + +/home/calvin/src/xpdf-4.04/xpdf/Page.h +aconf.h +- +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h + +/home/calvin/src/xpdf-4.04/xpdf/Stream.h +aconf.h +- +stdio.h +- +jpeglib.h +- +setjmp.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +gfile.h +/home/calvin/src/xpdf-4.04/xpdf/gfile.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h + +/home/calvin/src/xpdf-4.04/xpdf/XRef.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +gfile.h +/home/calvin/src/xpdf-4.04/xpdf/gfile.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h + +/home/calvin/src/xpdf-4.04/xpdf/config.h + +/home/calvin/src/xpdf-4.04/xpdf/pdffonts.cc +aconf.h +- +stdio.h +- +stdlib.h +- +stddef.h +- +string.h +- +math.h +- +limits.h +- +gmem.h +/home/calvin/src/xpdf-4.04/xpdf/gmem.h +gmempp.h +/home/calvin/src/xpdf-4.04/xpdf/gmempp.h +parseargs.h +/home/calvin/src/xpdf-4.04/xpdf/parseargs.h +GString.h +/home/calvin/src/xpdf-4.04/xpdf/GString.h +GlobalParams.h +/home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h +Error.h +/home/calvin/src/xpdf-4.04/xpdf/Error.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h +Dict.h +/home/calvin/src/xpdf-4.04/xpdf/Dict.h +GfxFont.h +/home/calvin/src/xpdf-4.04/xpdf/GfxFont.h +Annot.h +/home/calvin/src/xpdf-4.04/xpdf/Annot.h +AcroForm.h +/home/calvin/src/xpdf-4.04/xpdf/AcroForm.h +PDFDoc.h +/home/calvin/src/xpdf-4.04/xpdf/PDFDoc.h +config.h +/home/calvin/src/xpdf-4.04/xpdf/config.h + +aconf.h +aconf2.h +- + +aconf2.h +AvailabilityMacros.h +- + +goo/GMutex.h +aconf.h +- +windows.h +- +intrin.h +- +pthread.h +- + +goo/GString.h +aconf.h +- +limits.h +- +stdarg.h +- +gtypes.h +goo/gtypes.h + +goo/gfile.h +aconf.h +- +stdio.h +- +stdlib.h +- +stddef.h +- +sys/stat.h +- +win32lib.h +- +windows.h +- +unistd.h +- +sys/types.h +- +gtypes.h +goo/gtypes.h + +goo/gmem.h +stdio.h +- +aconf.h +- + +goo/gmempp.h +stdlib.h +- + +goo/gtypes.h + +goo/parseargs.h +gtypes.h +goo/gtypes.h + diff --git a/xpdf/CMakeFiles/pdffonts.dir/DependInfo.cmake b/xpdf/CMakeFiles/pdffonts.dir/DependInfo.cmake new file mode 100644 index 0000000..71b911b --- /dev/null +++ b/xpdf/CMakeFiles/pdffonts.dir/DependInfo.cmake @@ -0,0 +1,26 @@ +# The set of languages for which implicit dependencies are needed: +set(CMAKE_DEPENDS_LANGUAGES + "CXX" + ) +# The set of files for implicit dependencies of each language: +set(CMAKE_DEPENDS_CHECK_CXX + "/home/calvin/src/xpdf-4.04/xpdf/pdffonts.cc" "/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/pdffonts.dir/pdffonts.cc.o" + ) +set(CMAKE_CXX_COMPILER_ID "GNU") + +# The include file search paths: +set(CMAKE_CXX_TARGET_INCLUDE_PATH + "." + "goo" + "fofi" + "splash" + ) + +# Targets to which this target links. +set(CMAKE_TARGET_LINKED_INFO_FILES + "/home/calvin/src/xpdf-4.04/goo/CMakeFiles/goo.dir/DependInfo.cmake" + "/home/calvin/src/xpdf-4.04/fofi/CMakeFiles/fofi.dir/DependInfo.cmake" + ) + +# Fortran module output directory. +set(CMAKE_Fortran_TARGET_MODULE_DIR "") diff --git a/xpdf/CMakeFiles/pdffonts.dir/build.make b/xpdf/CMakeFiles/pdffonts.dir/build.make new file mode 100644 index 0000000..c22c919 --- /dev/null +++ b/xpdf/CMakeFiles/pdffonts.dir/build.make @@ -0,0 +1,206 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +# Delete rule output on recipe failure. +.DELETE_ON_ERROR: + + +#============================================================================= +# Special targets provided by cmake. + +# Disable implicit rules so canonical targets will work. +.SUFFIXES: + + +# Disable VCS-based implicit rules. +% : %,v + + +# Disable VCS-based implicit rules. +% : RCS/% + + +# Disable VCS-based implicit rules. +% : RCS/%,v + + +# Disable VCS-based implicit rules. +% : SCCS/s.% + + +# Disable VCS-based implicit rules. +% : s.% + + +.SUFFIXES: .hpux_make_needs_suffix_list + + +# Command-line flag to silence nested $(MAKE). +$(VERBOSE)MAKESILENT = -s + +#Suppress display of executed commands. +$(VERBOSE).SILENT: + +# A target that is always out of date. +cmake_force: + +.PHONY : cmake_force + +#============================================================================= +# Set environment variables for the build. + +# The shell in which to execute make rules. +SHELL = /bin/sh + +# The CMake executable. +CMAKE_COMMAND = /usr/bin/cmake + +# The command to remove a file. +RM = /usr/bin/cmake -E rm -f + +# Escaping for special characters. +EQUALS = = + +# The top-level source directory on which CMake was run. +CMAKE_SOURCE_DIR = /home/calvin/src/xpdf-4.04 + +# The top-level build directory on which CMake was run. +CMAKE_BINARY_DIR = /home/calvin/src/xpdf-4.04 + +# Include any dependencies generated for this target. +include xpdf/CMakeFiles/pdffonts.dir/depend.make + +# Include the progress variables for this target. +include xpdf/CMakeFiles/pdffonts.dir/progress.make + +# Include the compile flags for this target's objects. +include xpdf/CMakeFiles/pdffonts.dir/flags.make + +xpdf/CMakeFiles/pdffonts.dir/pdffonts.cc.o: xpdf/CMakeFiles/pdffonts.dir/flags.make +xpdf/CMakeFiles/pdffonts.dir/pdffonts.cc.o: xpdf/pdffonts.cc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_1) "Building CXX object xpdf/CMakeFiles/pdffonts.dir/pdffonts.cc.o" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/pdffonts.dir/pdffonts.cc.o -c /home/calvin/src/xpdf-4.04/xpdf/pdffonts.cc + +xpdf/CMakeFiles/pdffonts.dir/pdffonts.cc.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/pdffonts.dir/pdffonts.cc.i" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf/pdffonts.cc > CMakeFiles/pdffonts.dir/pdffonts.cc.i + +xpdf/CMakeFiles/pdffonts.dir/pdffonts.cc.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/pdffonts.dir/pdffonts.cc.s" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf/pdffonts.cc -o CMakeFiles/pdffonts.dir/pdffonts.cc.s + +# Object files for target pdffonts +pdffonts_OBJECTS = \ +"CMakeFiles/pdffonts.dir/pdffonts.cc.o" + +# External object files for target pdffonts +pdffonts_EXTERNAL_OBJECTS = \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/AcroForm.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Annot.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Array.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFont.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFontTables.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Catalog.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/CharCodeToUnicode.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/CMap.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Decrypt.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Dict.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Error.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/FontEncodingTables.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Function.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Gfx.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/GfxFont.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/GfxState.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/GlobalParams.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/JArithmeticDecoder.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/JBIG2Stream.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/JPXStream.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Lexer.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Link.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/NameToCharCode.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Object.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/OptionalContent.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Outline.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/OutputDev.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Page.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Parser.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/PDF417Barcode.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/PDFDoc.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/PDFDocEncoding.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/PSTokenizer.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Stream.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/TextString.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/UnicodeMap.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/UnicodeRemapping.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/UnicodeTypeTable.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/UTF8.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/XFAScanner.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/XRef.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Zoox.cc.o" + +xpdf/pdffonts: xpdf/CMakeFiles/pdffonts.dir/pdffonts.cc.o +xpdf/pdffonts: xpdf/CMakeFiles/xpdf_objs.dir/AcroForm.cc.o +xpdf/pdffonts: xpdf/CMakeFiles/xpdf_objs.dir/Annot.cc.o +xpdf/pdffonts: xpdf/CMakeFiles/xpdf_objs.dir/Array.cc.o +xpdf/pdffonts: xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFont.cc.o +xpdf/pdffonts: xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFontTables.cc.o +xpdf/pdffonts: xpdf/CMakeFiles/xpdf_objs.dir/Catalog.cc.o +xpdf/pdffonts: xpdf/CMakeFiles/xpdf_objs.dir/CharCodeToUnicode.cc.o +xpdf/pdffonts: xpdf/CMakeFiles/xpdf_objs.dir/CMap.cc.o +xpdf/pdffonts: xpdf/CMakeFiles/xpdf_objs.dir/Decrypt.cc.o +xpdf/pdffonts: xpdf/CMakeFiles/xpdf_objs.dir/Dict.cc.o +xpdf/pdffonts: xpdf/CMakeFiles/xpdf_objs.dir/Error.cc.o +xpdf/pdffonts: xpdf/CMakeFiles/xpdf_objs.dir/FontEncodingTables.cc.o +xpdf/pdffonts: xpdf/CMakeFiles/xpdf_objs.dir/Function.cc.o +xpdf/pdffonts: xpdf/CMakeFiles/xpdf_objs.dir/Gfx.cc.o +xpdf/pdffonts: xpdf/CMakeFiles/xpdf_objs.dir/GfxFont.cc.o +xpdf/pdffonts: xpdf/CMakeFiles/xpdf_objs.dir/GfxState.cc.o +xpdf/pdffonts: xpdf/CMakeFiles/xpdf_objs.dir/GlobalParams.cc.o +xpdf/pdffonts: xpdf/CMakeFiles/xpdf_objs.dir/JArithmeticDecoder.cc.o +xpdf/pdffonts: xpdf/CMakeFiles/xpdf_objs.dir/JBIG2Stream.cc.o +xpdf/pdffonts: xpdf/CMakeFiles/xpdf_objs.dir/JPXStream.cc.o +xpdf/pdffonts: xpdf/CMakeFiles/xpdf_objs.dir/Lexer.cc.o +xpdf/pdffonts: xpdf/CMakeFiles/xpdf_objs.dir/Link.cc.o +xpdf/pdffonts: xpdf/CMakeFiles/xpdf_objs.dir/NameToCharCode.cc.o +xpdf/pdffonts: xpdf/CMakeFiles/xpdf_objs.dir/Object.cc.o +xpdf/pdffonts: xpdf/CMakeFiles/xpdf_objs.dir/OptionalContent.cc.o +xpdf/pdffonts: xpdf/CMakeFiles/xpdf_objs.dir/Outline.cc.o +xpdf/pdffonts: xpdf/CMakeFiles/xpdf_objs.dir/OutputDev.cc.o +xpdf/pdffonts: xpdf/CMakeFiles/xpdf_objs.dir/Page.cc.o +xpdf/pdffonts: xpdf/CMakeFiles/xpdf_objs.dir/Parser.cc.o +xpdf/pdffonts: xpdf/CMakeFiles/xpdf_objs.dir/PDF417Barcode.cc.o +xpdf/pdffonts: xpdf/CMakeFiles/xpdf_objs.dir/PDFDoc.cc.o +xpdf/pdffonts: xpdf/CMakeFiles/xpdf_objs.dir/PDFDocEncoding.cc.o +xpdf/pdffonts: xpdf/CMakeFiles/xpdf_objs.dir/PSTokenizer.cc.o +xpdf/pdffonts: xpdf/CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.o +xpdf/pdffonts: xpdf/CMakeFiles/xpdf_objs.dir/Stream.cc.o +xpdf/pdffonts: xpdf/CMakeFiles/xpdf_objs.dir/TextString.cc.o +xpdf/pdffonts: xpdf/CMakeFiles/xpdf_objs.dir/UnicodeMap.cc.o +xpdf/pdffonts: xpdf/CMakeFiles/xpdf_objs.dir/UnicodeRemapping.cc.o +xpdf/pdffonts: xpdf/CMakeFiles/xpdf_objs.dir/UnicodeTypeTable.cc.o +xpdf/pdffonts: xpdf/CMakeFiles/xpdf_objs.dir/UTF8.cc.o +xpdf/pdffonts: xpdf/CMakeFiles/xpdf_objs.dir/XFAScanner.cc.o +xpdf/pdffonts: xpdf/CMakeFiles/xpdf_objs.dir/XRef.cc.o +xpdf/pdffonts: xpdf/CMakeFiles/xpdf_objs.dir/Zoox.cc.o +xpdf/pdffonts: xpdf/CMakeFiles/pdffonts.dir/build.make +xpdf/pdffonts: goo/libgoo.a +xpdf/pdffonts: fofi/libfofi.a +xpdf/pdffonts: /usr/lib/x86_64-linux-gnu/libfontconfig.so +xpdf/pdffonts: xpdf/CMakeFiles/pdffonts.dir/link.txt + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --bold --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_2) "Linking CXX executable pdffonts" + cd /home/calvin/src/xpdf-4.04/xpdf && $(CMAKE_COMMAND) -E cmake_link_script CMakeFiles/pdffonts.dir/link.txt --verbose=$(VERBOSE) + +# Rule to build all files generated by this target. +xpdf/CMakeFiles/pdffonts.dir/build: xpdf/pdffonts + +.PHONY : xpdf/CMakeFiles/pdffonts.dir/build + +xpdf/CMakeFiles/pdffonts.dir/clean: + cd /home/calvin/src/xpdf-4.04/xpdf && $(CMAKE_COMMAND) -P CMakeFiles/pdffonts.dir/cmake_clean.cmake +.PHONY : xpdf/CMakeFiles/pdffonts.dir/clean + +xpdf/CMakeFiles/pdffonts.dir/depend: + cd /home/calvin/src/xpdf-4.04 && $(CMAKE_COMMAND) -E cmake_depends "Unix Makefiles" /home/calvin/src/xpdf-4.04 /home/calvin/src/xpdf-4.04/xpdf /home/calvin/src/xpdf-4.04 /home/calvin/src/xpdf-4.04/xpdf /home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/pdffonts.dir/DependInfo.cmake --color=$(COLOR) +.PHONY : xpdf/CMakeFiles/pdffonts.dir/depend + diff --git a/xpdf/CMakeFiles/pdffonts.dir/cmake_clean.cmake b/xpdf/CMakeFiles/pdffonts.dir/cmake_clean.cmake new file mode 100644 index 0000000..82c52af --- /dev/null +++ b/xpdf/CMakeFiles/pdffonts.dir/cmake_clean.cmake @@ -0,0 +1,10 @@ +file(REMOVE_RECURSE + "CMakeFiles/pdffonts.dir/pdffonts.cc.o" + "pdffonts" + "pdffonts.pdb" +) + +# Per-language clean rules from dependency scanning. +foreach(lang CXX) + include(CMakeFiles/pdffonts.dir/cmake_clean_${lang}.cmake OPTIONAL) +endforeach() diff --git a/xpdf/CMakeFiles/pdffonts.dir/depend.internal b/xpdf/CMakeFiles/pdffonts.dir/depend.internal new file mode 100644 index 0000000..87297d2 --- /dev/null +++ b/xpdf/CMakeFiles/pdffonts.dir/depend.internal @@ -0,0 +1,29 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +xpdf/CMakeFiles/pdffonts.dir/pdffonts.cc.o + /home/calvin/src/xpdf-4.04/xpdf/AcroForm.h + /home/calvin/src/xpdf-4.04/xpdf/Annot.h + /home/calvin/src/xpdf-4.04/xpdf/Array.h + /home/calvin/src/xpdf-4.04/xpdf/Catalog.h + /home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + /home/calvin/src/xpdf-4.04/xpdf/Dict.h + /home/calvin/src/xpdf-4.04/xpdf/Error.h + /home/calvin/src/xpdf-4.04/xpdf/GfxFont.h + /home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h + /home/calvin/src/xpdf-4.04/xpdf/Object.h + /home/calvin/src/xpdf-4.04/xpdf/PDFDoc.h + /home/calvin/src/xpdf-4.04/xpdf/Page.h + /home/calvin/src/xpdf-4.04/xpdf/Stream.h + /home/calvin/src/xpdf-4.04/xpdf/XRef.h + /home/calvin/src/xpdf-4.04/xpdf/config.h + /home/calvin/src/xpdf-4.04/xpdf/pdffonts.cc + aconf.h + aconf2.h + goo/GMutex.h + goo/GString.h + goo/gfile.h + goo/gmem.h + goo/gmempp.h + goo/gtypes.h + goo/parseargs.h diff --git a/xpdf/CMakeFiles/pdffonts.dir/depend.make b/xpdf/CMakeFiles/pdffonts.dir/depend.make new file mode 100644 index 0000000..c76284e --- /dev/null +++ b/xpdf/CMakeFiles/pdffonts.dir/depend.make @@ -0,0 +1,29 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +xpdf/CMakeFiles/pdffonts.dir/pdffonts.cc.o: xpdf/AcroForm.h +xpdf/CMakeFiles/pdffonts.dir/pdffonts.cc.o: xpdf/Annot.h +xpdf/CMakeFiles/pdffonts.dir/pdffonts.cc.o: xpdf/Array.h +xpdf/CMakeFiles/pdffonts.dir/pdffonts.cc.o: xpdf/Catalog.h +xpdf/CMakeFiles/pdffonts.dir/pdffonts.cc.o: xpdf/CharTypes.h +xpdf/CMakeFiles/pdffonts.dir/pdffonts.cc.o: xpdf/Dict.h +xpdf/CMakeFiles/pdffonts.dir/pdffonts.cc.o: xpdf/Error.h +xpdf/CMakeFiles/pdffonts.dir/pdffonts.cc.o: xpdf/GfxFont.h +xpdf/CMakeFiles/pdffonts.dir/pdffonts.cc.o: xpdf/GlobalParams.h +xpdf/CMakeFiles/pdffonts.dir/pdffonts.cc.o: xpdf/Object.h +xpdf/CMakeFiles/pdffonts.dir/pdffonts.cc.o: xpdf/PDFDoc.h +xpdf/CMakeFiles/pdffonts.dir/pdffonts.cc.o: xpdf/Page.h +xpdf/CMakeFiles/pdffonts.dir/pdffonts.cc.o: xpdf/Stream.h +xpdf/CMakeFiles/pdffonts.dir/pdffonts.cc.o: xpdf/XRef.h +xpdf/CMakeFiles/pdffonts.dir/pdffonts.cc.o: xpdf/config.h +xpdf/CMakeFiles/pdffonts.dir/pdffonts.cc.o: xpdf/pdffonts.cc +xpdf/CMakeFiles/pdffonts.dir/pdffonts.cc.o: aconf.h +xpdf/CMakeFiles/pdffonts.dir/pdffonts.cc.o: aconf2.h +xpdf/CMakeFiles/pdffonts.dir/pdffonts.cc.o: goo/GMutex.h +xpdf/CMakeFiles/pdffonts.dir/pdffonts.cc.o: goo/GString.h +xpdf/CMakeFiles/pdffonts.dir/pdffonts.cc.o: goo/gfile.h +xpdf/CMakeFiles/pdffonts.dir/pdffonts.cc.o: goo/gmem.h +xpdf/CMakeFiles/pdffonts.dir/pdffonts.cc.o: goo/gmempp.h +xpdf/CMakeFiles/pdffonts.dir/pdffonts.cc.o: goo/gtypes.h +xpdf/CMakeFiles/pdffonts.dir/pdffonts.cc.o: goo/parseargs.h + diff --git a/xpdf/CMakeFiles/pdffonts.dir/flags.make b/xpdf/CMakeFiles/pdffonts.dir/flags.make new file mode 100644 index 0000000..300fa3e --- /dev/null +++ b/xpdf/CMakeFiles/pdffonts.dir/flags.make @@ -0,0 +1,10 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +# compile CXX with /usr/bin/c++ +CXX_DEFINES = + +CXX_INCLUDES = -I/home/calvin/src/xpdf-4.04 -I/home/calvin/src/xpdf-4.04/goo -I/home/calvin/src/xpdf-4.04/fofi -I/home/calvin/src/xpdf-4.04/splash + +CXX_FLAGS = + diff --git a/xpdf/CMakeFiles/pdffonts.dir/link.txt b/xpdf/CMakeFiles/pdffonts.dir/link.txt new file mode 100644 index 0000000..318951c --- /dev/null +++ b/xpdf/CMakeFiles/pdffonts.dir/link.txt @@ -0,0 +1 @@ +/usr/bin/c++ -rdynamic CMakeFiles/pdffonts.dir/pdffonts.cc.o CMakeFiles/xpdf_objs.dir/AcroForm.cc.o CMakeFiles/xpdf_objs.dir/Annot.cc.o CMakeFiles/xpdf_objs.dir/Array.cc.o CMakeFiles/xpdf_objs.dir/BuiltinFont.cc.o CMakeFiles/xpdf_objs.dir/BuiltinFontTables.cc.o CMakeFiles/xpdf_objs.dir/Catalog.cc.o CMakeFiles/xpdf_objs.dir/CharCodeToUnicode.cc.o CMakeFiles/xpdf_objs.dir/CMap.cc.o CMakeFiles/xpdf_objs.dir/Decrypt.cc.o CMakeFiles/xpdf_objs.dir/Dict.cc.o CMakeFiles/xpdf_objs.dir/Error.cc.o CMakeFiles/xpdf_objs.dir/FontEncodingTables.cc.o CMakeFiles/xpdf_objs.dir/Function.cc.o CMakeFiles/xpdf_objs.dir/Gfx.cc.o CMakeFiles/xpdf_objs.dir/GfxFont.cc.o CMakeFiles/xpdf_objs.dir/GfxState.cc.o CMakeFiles/xpdf_objs.dir/GlobalParams.cc.o CMakeFiles/xpdf_objs.dir/JArithmeticDecoder.cc.o CMakeFiles/xpdf_objs.dir/JBIG2Stream.cc.o CMakeFiles/xpdf_objs.dir/JPXStream.cc.o CMakeFiles/xpdf_objs.dir/Lexer.cc.o CMakeFiles/xpdf_objs.dir/Link.cc.o CMakeFiles/xpdf_objs.dir/NameToCharCode.cc.o CMakeFiles/xpdf_objs.dir/Object.cc.o CMakeFiles/xpdf_objs.dir/OptionalContent.cc.o CMakeFiles/xpdf_objs.dir/Outline.cc.o CMakeFiles/xpdf_objs.dir/OutputDev.cc.o CMakeFiles/xpdf_objs.dir/Page.cc.o CMakeFiles/xpdf_objs.dir/Parser.cc.o CMakeFiles/xpdf_objs.dir/PDF417Barcode.cc.o CMakeFiles/xpdf_objs.dir/PDFDoc.cc.o CMakeFiles/xpdf_objs.dir/PDFDocEncoding.cc.o CMakeFiles/xpdf_objs.dir/PSTokenizer.cc.o CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.o CMakeFiles/xpdf_objs.dir/Stream.cc.o CMakeFiles/xpdf_objs.dir/TextString.cc.o CMakeFiles/xpdf_objs.dir/UnicodeMap.cc.o CMakeFiles/xpdf_objs.dir/UnicodeRemapping.cc.o CMakeFiles/xpdf_objs.dir/UnicodeTypeTable.cc.o CMakeFiles/xpdf_objs.dir/UTF8.cc.o CMakeFiles/xpdf_objs.dir/XFAScanner.cc.o CMakeFiles/xpdf_objs.dir/XRef.cc.o CMakeFiles/xpdf_objs.dir/Zoox.cc.o -o pdffonts ../goo/libgoo.a ../fofi/libfofi.a -lfontconfig -lpthread diff --git a/xpdf/CMakeFiles/pdffonts.dir/pdffonts.cc.o b/xpdf/CMakeFiles/pdffonts.dir/pdffonts.cc.o new file mode 100644 index 0000000..2161738 Binary files /dev/null and b/xpdf/CMakeFiles/pdffonts.dir/pdffonts.cc.o differ diff --git a/xpdf/CMakeFiles/pdffonts.dir/progress.make b/xpdf/CMakeFiles/pdffonts.dir/progress.make new file mode 100644 index 0000000..52b6d64 --- /dev/null +++ b/xpdf/CMakeFiles/pdffonts.dir/progress.make @@ -0,0 +1,3 @@ +CMAKE_PROGRESS_1 = +CMAKE_PROGRESS_2 = 15 + diff --git a/xpdf/CMakeFiles/pdfimages.dir/CXX.includecache b/xpdf/CMakeFiles/pdfimages.dir/CXX.includecache new file mode 100644 index 0000000..cc7f66b --- /dev/null +++ b/xpdf/CMakeFiles/pdfimages.dir/CXX.includecache @@ -0,0 +1,306 @@ +#IncludeRegexLine: ^[ ]*[#%][ ]*(include|import)[ ]*[<"]([^">]+)([">]) + +#IncludeRegexScan: ^.*$ + +#IncludeRegexComplain: ^$ + +#IncludeRegexTransform: + +/home/calvin/src/xpdf-4.04/xpdf/Array.h +aconf.h +- +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h + +/home/calvin/src/xpdf-4.04/xpdf/Catalog.h +aconf.h +- +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h +CharTypes.h +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + +/home/calvin/src/xpdf-4.04/xpdf/Dict.h +aconf.h +- +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h + +/home/calvin/src/xpdf-4.04/xpdf/Error.h +aconf.h +- +stdio.h +- +config.h +/home/calvin/src/xpdf-4.04/xpdf/config.h +gfile.h +/home/calvin/src/xpdf-4.04/xpdf/gfile.h + +/home/calvin/src/xpdf-4.04/xpdf/Function.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h + +/home/calvin/src/xpdf-4.04/xpdf/GfxState.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h +Function.h +/home/calvin/src/xpdf-4.04/xpdf/Function.h + +/home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h +aconf.h +- +stdio.h +- +windows.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +CharTypes.h +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h + +/home/calvin/src/xpdf-4.04/xpdf/ImageOutputDev.cc +aconf.h +- +stdio.h +- +stdlib.h +- +stddef.h +- +ctype.h +- +math.h +- +gmem.h +/home/calvin/src/xpdf-4.04/xpdf/gmem.h +gmempp.h +/home/calvin/src/xpdf-4.04/xpdf/gmempp.h +config.h +/home/calvin/src/xpdf-4.04/xpdf/config.h +Error.h +/home/calvin/src/xpdf-4.04/xpdf/Error.h +GfxState.h +/home/calvin/src/xpdf-4.04/xpdf/GfxState.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h +Stream.h +/home/calvin/src/xpdf-4.04/xpdf/Stream.h +ImageOutputDev.h +/home/calvin/src/xpdf-4.04/xpdf/ImageOutputDev.h + +/home/calvin/src/xpdf-4.04/xpdf/ImageOutputDev.h +aconf.h +- +stdio.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +OutputDev.h +/home/calvin/src/xpdf-4.04/xpdf/OutputDev.h + +/home/calvin/src/xpdf-4.04/xpdf/Object.h +aconf.h +- +stdio.h +- +string.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +gmem.h +/home/calvin/src/xpdf-4.04/xpdf/gmem.h +gfile.h +/home/calvin/src/xpdf-4.04/xpdf/gfile.h +GString.h +/home/calvin/src/xpdf-4.04/xpdf/GString.h +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h +Array.h +/home/calvin/src/xpdf-4.04/xpdf/Array.h +Dict.h +/home/calvin/src/xpdf-4.04/xpdf/Dict.h +Stream.h +/home/calvin/src/xpdf-4.04/xpdf/Stream.h + +/home/calvin/src/xpdf-4.04/xpdf/OutputDev.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +CharTypes.h +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + +/home/calvin/src/xpdf-4.04/xpdf/PDFDoc.h +aconf.h +- +stdio.h +- +XRef.h +/home/calvin/src/xpdf-4.04/xpdf/XRef.h +Catalog.h +/home/calvin/src/xpdf-4.04/xpdf/Catalog.h +Page.h +/home/calvin/src/xpdf-4.04/xpdf/Page.h + +/home/calvin/src/xpdf-4.04/xpdf/Page.h +aconf.h +- +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h + +/home/calvin/src/xpdf-4.04/xpdf/Stream.h +aconf.h +- +stdio.h +- +jpeglib.h +- +setjmp.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +gfile.h +/home/calvin/src/xpdf-4.04/xpdf/gfile.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h + +/home/calvin/src/xpdf-4.04/xpdf/XRef.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +gfile.h +/home/calvin/src/xpdf-4.04/xpdf/gfile.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h + +/home/calvin/src/xpdf-4.04/xpdf/config.h + +/home/calvin/src/xpdf-4.04/xpdf/pdfimages.cc +aconf.h +- +stdio.h +- +stdlib.h +- +stddef.h +- +string.h +- +gmem.h +/home/calvin/src/xpdf-4.04/xpdf/gmem.h +gmempp.h +/home/calvin/src/xpdf-4.04/xpdf/gmempp.h +parseargs.h +/home/calvin/src/xpdf-4.04/xpdf/parseargs.h +GString.h +/home/calvin/src/xpdf-4.04/xpdf/GString.h +GlobalParams.h +/home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h +Stream.h +/home/calvin/src/xpdf-4.04/xpdf/Stream.h +Array.h +/home/calvin/src/xpdf-4.04/xpdf/Array.h +Dict.h +/home/calvin/src/xpdf-4.04/xpdf/Dict.h +XRef.h +/home/calvin/src/xpdf-4.04/xpdf/XRef.h +Catalog.h +/home/calvin/src/xpdf-4.04/xpdf/Catalog.h +Page.h +/home/calvin/src/xpdf-4.04/xpdf/Page.h +PDFDoc.h +/home/calvin/src/xpdf-4.04/xpdf/PDFDoc.h +ImageOutputDev.h +/home/calvin/src/xpdf-4.04/xpdf/ImageOutputDev.h +Error.h +/home/calvin/src/xpdf-4.04/xpdf/Error.h +config.h +/home/calvin/src/xpdf-4.04/xpdf/config.h + +aconf.h +aconf2.h +- + +aconf2.h +AvailabilityMacros.h +- + +goo/GMutex.h +aconf.h +- +windows.h +- +intrin.h +- +pthread.h +- + +goo/GString.h +aconf.h +- +limits.h +- +stdarg.h +- +gtypes.h +goo/gtypes.h + +goo/gfile.h +aconf.h +- +stdio.h +- +stdlib.h +- +stddef.h +- +sys/stat.h +- +win32lib.h +- +windows.h +- +unistd.h +- +sys/types.h +- +gtypes.h +goo/gtypes.h + +goo/gmem.h +stdio.h +- +aconf.h +- + +goo/gmempp.h +stdlib.h +- + +goo/gtypes.h + +goo/parseargs.h +gtypes.h +goo/gtypes.h + diff --git a/xpdf/CMakeFiles/pdfimages.dir/DependInfo.cmake b/xpdf/CMakeFiles/pdfimages.dir/DependInfo.cmake new file mode 100644 index 0000000..34942d2 --- /dev/null +++ b/xpdf/CMakeFiles/pdfimages.dir/DependInfo.cmake @@ -0,0 +1,27 @@ +# The set of languages for which implicit dependencies are needed: +set(CMAKE_DEPENDS_LANGUAGES + "CXX" + ) +# The set of files for implicit dependencies of each language: +set(CMAKE_DEPENDS_CHECK_CXX + "/home/calvin/src/xpdf-4.04/xpdf/ImageOutputDev.cc" "/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/pdfimages.dir/ImageOutputDev.cc.o" + "/home/calvin/src/xpdf-4.04/xpdf/pdfimages.cc" "/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/pdfimages.dir/pdfimages.cc.o" + ) +set(CMAKE_CXX_COMPILER_ID "GNU") + +# The include file search paths: +set(CMAKE_CXX_TARGET_INCLUDE_PATH + "." + "goo" + "fofi" + "splash" + ) + +# Targets to which this target links. +set(CMAKE_TARGET_LINKED_INFO_FILES + "/home/calvin/src/xpdf-4.04/goo/CMakeFiles/goo.dir/DependInfo.cmake" + "/home/calvin/src/xpdf-4.04/fofi/CMakeFiles/fofi.dir/DependInfo.cmake" + ) + +# Fortran module output directory. +set(CMAKE_Fortran_TARGET_MODULE_DIR "") diff --git a/xpdf/CMakeFiles/pdfimages.dir/ImageOutputDev.cc.o b/xpdf/CMakeFiles/pdfimages.dir/ImageOutputDev.cc.o new file mode 100644 index 0000000..d465f74 Binary files /dev/null and b/xpdf/CMakeFiles/pdfimages.dir/ImageOutputDev.cc.o differ diff --git a/xpdf/CMakeFiles/pdfimages.dir/build.make b/xpdf/CMakeFiles/pdfimages.dir/build.make new file mode 100644 index 0000000..f42d0b3 --- /dev/null +++ b/xpdf/CMakeFiles/pdfimages.dir/build.make @@ -0,0 +1,221 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +# Delete rule output on recipe failure. +.DELETE_ON_ERROR: + + +#============================================================================= +# Special targets provided by cmake. + +# Disable implicit rules so canonical targets will work. +.SUFFIXES: + + +# Disable VCS-based implicit rules. +% : %,v + + +# Disable VCS-based implicit rules. +% : RCS/% + + +# Disable VCS-based implicit rules. +% : RCS/%,v + + +# Disable VCS-based implicit rules. +% : SCCS/s.% + + +# Disable VCS-based implicit rules. +% : s.% + + +.SUFFIXES: .hpux_make_needs_suffix_list + + +# Command-line flag to silence nested $(MAKE). +$(VERBOSE)MAKESILENT = -s + +#Suppress display of executed commands. +$(VERBOSE).SILENT: + +# A target that is always out of date. +cmake_force: + +.PHONY : cmake_force + +#============================================================================= +# Set environment variables for the build. + +# The shell in which to execute make rules. +SHELL = /bin/sh + +# The CMake executable. +CMAKE_COMMAND = /usr/bin/cmake + +# The command to remove a file. +RM = /usr/bin/cmake -E rm -f + +# Escaping for special characters. +EQUALS = = + +# The top-level source directory on which CMake was run. +CMAKE_SOURCE_DIR = /home/calvin/src/xpdf-4.04 + +# The top-level build directory on which CMake was run. +CMAKE_BINARY_DIR = /home/calvin/src/xpdf-4.04 + +# Include any dependencies generated for this target. +include xpdf/CMakeFiles/pdfimages.dir/depend.make + +# Include the progress variables for this target. +include xpdf/CMakeFiles/pdfimages.dir/progress.make + +# Include the compile flags for this target's objects. +include xpdf/CMakeFiles/pdfimages.dir/flags.make + +xpdf/CMakeFiles/pdfimages.dir/ImageOutputDev.cc.o: xpdf/CMakeFiles/pdfimages.dir/flags.make +xpdf/CMakeFiles/pdfimages.dir/ImageOutputDev.cc.o: xpdf/ImageOutputDev.cc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_1) "Building CXX object xpdf/CMakeFiles/pdfimages.dir/ImageOutputDev.cc.o" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/pdfimages.dir/ImageOutputDev.cc.o -c /home/calvin/src/xpdf-4.04/xpdf/ImageOutputDev.cc + +xpdf/CMakeFiles/pdfimages.dir/ImageOutputDev.cc.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/pdfimages.dir/ImageOutputDev.cc.i" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf/ImageOutputDev.cc > CMakeFiles/pdfimages.dir/ImageOutputDev.cc.i + +xpdf/CMakeFiles/pdfimages.dir/ImageOutputDev.cc.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/pdfimages.dir/ImageOutputDev.cc.s" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf/ImageOutputDev.cc -o CMakeFiles/pdfimages.dir/ImageOutputDev.cc.s + +xpdf/CMakeFiles/pdfimages.dir/pdfimages.cc.o: xpdf/CMakeFiles/pdfimages.dir/flags.make +xpdf/CMakeFiles/pdfimages.dir/pdfimages.cc.o: xpdf/pdfimages.cc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_2) "Building CXX object xpdf/CMakeFiles/pdfimages.dir/pdfimages.cc.o" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/pdfimages.dir/pdfimages.cc.o -c /home/calvin/src/xpdf-4.04/xpdf/pdfimages.cc + +xpdf/CMakeFiles/pdfimages.dir/pdfimages.cc.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/pdfimages.dir/pdfimages.cc.i" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf/pdfimages.cc > CMakeFiles/pdfimages.dir/pdfimages.cc.i + +xpdf/CMakeFiles/pdfimages.dir/pdfimages.cc.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/pdfimages.dir/pdfimages.cc.s" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf/pdfimages.cc -o CMakeFiles/pdfimages.dir/pdfimages.cc.s + +# Object files for target pdfimages +pdfimages_OBJECTS = \ +"CMakeFiles/pdfimages.dir/ImageOutputDev.cc.o" \ +"CMakeFiles/pdfimages.dir/pdfimages.cc.o" + +# External object files for target pdfimages +pdfimages_EXTERNAL_OBJECTS = \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/AcroForm.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Annot.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Array.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFont.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFontTables.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Catalog.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/CharCodeToUnicode.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/CMap.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Decrypt.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Dict.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Error.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/FontEncodingTables.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Function.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Gfx.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/GfxFont.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/GfxState.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/GlobalParams.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/JArithmeticDecoder.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/JBIG2Stream.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/JPXStream.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Lexer.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Link.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/NameToCharCode.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Object.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/OptionalContent.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Outline.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/OutputDev.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Page.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Parser.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/PDF417Barcode.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/PDFDoc.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/PDFDocEncoding.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/PSTokenizer.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Stream.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/TextString.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/UnicodeMap.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/UnicodeRemapping.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/UnicodeTypeTable.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/UTF8.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/XFAScanner.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/XRef.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Zoox.cc.o" + +xpdf/pdfimages: xpdf/CMakeFiles/pdfimages.dir/ImageOutputDev.cc.o +xpdf/pdfimages: xpdf/CMakeFiles/pdfimages.dir/pdfimages.cc.o +xpdf/pdfimages: xpdf/CMakeFiles/xpdf_objs.dir/AcroForm.cc.o +xpdf/pdfimages: xpdf/CMakeFiles/xpdf_objs.dir/Annot.cc.o +xpdf/pdfimages: xpdf/CMakeFiles/xpdf_objs.dir/Array.cc.o +xpdf/pdfimages: xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFont.cc.o +xpdf/pdfimages: xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFontTables.cc.o +xpdf/pdfimages: xpdf/CMakeFiles/xpdf_objs.dir/Catalog.cc.o +xpdf/pdfimages: xpdf/CMakeFiles/xpdf_objs.dir/CharCodeToUnicode.cc.o +xpdf/pdfimages: xpdf/CMakeFiles/xpdf_objs.dir/CMap.cc.o +xpdf/pdfimages: xpdf/CMakeFiles/xpdf_objs.dir/Decrypt.cc.o +xpdf/pdfimages: xpdf/CMakeFiles/xpdf_objs.dir/Dict.cc.o +xpdf/pdfimages: xpdf/CMakeFiles/xpdf_objs.dir/Error.cc.o +xpdf/pdfimages: xpdf/CMakeFiles/xpdf_objs.dir/FontEncodingTables.cc.o +xpdf/pdfimages: xpdf/CMakeFiles/xpdf_objs.dir/Function.cc.o +xpdf/pdfimages: xpdf/CMakeFiles/xpdf_objs.dir/Gfx.cc.o +xpdf/pdfimages: xpdf/CMakeFiles/xpdf_objs.dir/GfxFont.cc.o +xpdf/pdfimages: xpdf/CMakeFiles/xpdf_objs.dir/GfxState.cc.o +xpdf/pdfimages: xpdf/CMakeFiles/xpdf_objs.dir/GlobalParams.cc.o +xpdf/pdfimages: xpdf/CMakeFiles/xpdf_objs.dir/JArithmeticDecoder.cc.o +xpdf/pdfimages: xpdf/CMakeFiles/xpdf_objs.dir/JBIG2Stream.cc.o +xpdf/pdfimages: xpdf/CMakeFiles/xpdf_objs.dir/JPXStream.cc.o +xpdf/pdfimages: xpdf/CMakeFiles/xpdf_objs.dir/Lexer.cc.o +xpdf/pdfimages: xpdf/CMakeFiles/xpdf_objs.dir/Link.cc.o +xpdf/pdfimages: xpdf/CMakeFiles/xpdf_objs.dir/NameToCharCode.cc.o +xpdf/pdfimages: xpdf/CMakeFiles/xpdf_objs.dir/Object.cc.o +xpdf/pdfimages: xpdf/CMakeFiles/xpdf_objs.dir/OptionalContent.cc.o +xpdf/pdfimages: xpdf/CMakeFiles/xpdf_objs.dir/Outline.cc.o +xpdf/pdfimages: xpdf/CMakeFiles/xpdf_objs.dir/OutputDev.cc.o +xpdf/pdfimages: xpdf/CMakeFiles/xpdf_objs.dir/Page.cc.o +xpdf/pdfimages: xpdf/CMakeFiles/xpdf_objs.dir/Parser.cc.o +xpdf/pdfimages: xpdf/CMakeFiles/xpdf_objs.dir/PDF417Barcode.cc.o +xpdf/pdfimages: xpdf/CMakeFiles/xpdf_objs.dir/PDFDoc.cc.o +xpdf/pdfimages: xpdf/CMakeFiles/xpdf_objs.dir/PDFDocEncoding.cc.o +xpdf/pdfimages: xpdf/CMakeFiles/xpdf_objs.dir/PSTokenizer.cc.o +xpdf/pdfimages: xpdf/CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.o +xpdf/pdfimages: xpdf/CMakeFiles/xpdf_objs.dir/Stream.cc.o +xpdf/pdfimages: xpdf/CMakeFiles/xpdf_objs.dir/TextString.cc.o +xpdf/pdfimages: xpdf/CMakeFiles/xpdf_objs.dir/UnicodeMap.cc.o +xpdf/pdfimages: xpdf/CMakeFiles/xpdf_objs.dir/UnicodeRemapping.cc.o +xpdf/pdfimages: xpdf/CMakeFiles/xpdf_objs.dir/UnicodeTypeTable.cc.o +xpdf/pdfimages: xpdf/CMakeFiles/xpdf_objs.dir/UTF8.cc.o +xpdf/pdfimages: xpdf/CMakeFiles/xpdf_objs.dir/XFAScanner.cc.o +xpdf/pdfimages: xpdf/CMakeFiles/xpdf_objs.dir/XRef.cc.o +xpdf/pdfimages: xpdf/CMakeFiles/xpdf_objs.dir/Zoox.cc.o +xpdf/pdfimages: xpdf/CMakeFiles/pdfimages.dir/build.make +xpdf/pdfimages: goo/libgoo.a +xpdf/pdfimages: fofi/libfofi.a +xpdf/pdfimages: /usr/lib/x86_64-linux-gnu/libfontconfig.so +xpdf/pdfimages: xpdf/CMakeFiles/pdfimages.dir/link.txt + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --bold --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_3) "Linking CXX executable pdfimages" + cd /home/calvin/src/xpdf-4.04/xpdf && $(CMAKE_COMMAND) -E cmake_link_script CMakeFiles/pdfimages.dir/link.txt --verbose=$(VERBOSE) + +# Rule to build all files generated by this target. +xpdf/CMakeFiles/pdfimages.dir/build: xpdf/pdfimages + +.PHONY : xpdf/CMakeFiles/pdfimages.dir/build + +xpdf/CMakeFiles/pdfimages.dir/clean: + cd /home/calvin/src/xpdf-4.04/xpdf && $(CMAKE_COMMAND) -P CMakeFiles/pdfimages.dir/cmake_clean.cmake +.PHONY : xpdf/CMakeFiles/pdfimages.dir/clean + +xpdf/CMakeFiles/pdfimages.dir/depend: + cd /home/calvin/src/xpdf-4.04 && $(CMAKE_COMMAND) -E cmake_depends "Unix Makefiles" /home/calvin/src/xpdf-4.04 /home/calvin/src/xpdf-4.04/xpdf /home/calvin/src/xpdf-4.04 /home/calvin/src/xpdf-4.04/xpdf /home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/pdfimages.dir/DependInfo.cmake --color=$(COLOR) +.PHONY : xpdf/CMakeFiles/pdfimages.dir/depend + diff --git a/xpdf/CMakeFiles/pdfimages.dir/cmake_clean.cmake b/xpdf/CMakeFiles/pdfimages.dir/cmake_clean.cmake new file mode 100644 index 0000000..6bda113 --- /dev/null +++ b/xpdf/CMakeFiles/pdfimages.dir/cmake_clean.cmake @@ -0,0 +1,11 @@ +file(REMOVE_RECURSE + "CMakeFiles/pdfimages.dir/ImageOutputDev.cc.o" + "CMakeFiles/pdfimages.dir/pdfimages.cc.o" + "pdfimages" + "pdfimages.pdb" +) + +# Per-language clean rules from dependency scanning. +foreach(lang CXX) + include(CMakeFiles/pdfimages.dir/cmake_clean_${lang}.cmake OPTIONAL) +endforeach() diff --git a/xpdf/CMakeFiles/pdfimages.dir/depend.internal b/xpdf/CMakeFiles/pdfimages.dir/depend.internal new file mode 100644 index 0000000..109934a --- /dev/null +++ b/xpdf/CMakeFiles/pdfimages.dir/depend.internal @@ -0,0 +1,49 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +xpdf/CMakeFiles/pdfimages.dir/ImageOutputDev.cc.o + /home/calvin/src/xpdf-4.04/xpdf/Array.h + /home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + /home/calvin/src/xpdf-4.04/xpdf/Dict.h + /home/calvin/src/xpdf-4.04/xpdf/Error.h + /home/calvin/src/xpdf-4.04/xpdf/Function.h + /home/calvin/src/xpdf-4.04/xpdf/GfxState.h + /home/calvin/src/xpdf-4.04/xpdf/ImageOutputDev.cc + /home/calvin/src/xpdf-4.04/xpdf/ImageOutputDev.h + /home/calvin/src/xpdf-4.04/xpdf/Object.h + /home/calvin/src/xpdf-4.04/xpdf/OutputDev.h + /home/calvin/src/xpdf-4.04/xpdf/Stream.h + /home/calvin/src/xpdf-4.04/xpdf/config.h + aconf.h + aconf2.h + goo/GMutex.h + goo/GString.h + goo/gfile.h + goo/gmem.h + goo/gmempp.h + goo/gtypes.h +xpdf/CMakeFiles/pdfimages.dir/pdfimages.cc.o + /home/calvin/src/xpdf-4.04/xpdf/Array.h + /home/calvin/src/xpdf-4.04/xpdf/Catalog.h + /home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + /home/calvin/src/xpdf-4.04/xpdf/Dict.h + /home/calvin/src/xpdf-4.04/xpdf/Error.h + /home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h + /home/calvin/src/xpdf-4.04/xpdf/ImageOutputDev.h + /home/calvin/src/xpdf-4.04/xpdf/Object.h + /home/calvin/src/xpdf-4.04/xpdf/OutputDev.h + /home/calvin/src/xpdf-4.04/xpdf/PDFDoc.h + /home/calvin/src/xpdf-4.04/xpdf/Page.h + /home/calvin/src/xpdf-4.04/xpdf/Stream.h + /home/calvin/src/xpdf-4.04/xpdf/XRef.h + /home/calvin/src/xpdf-4.04/xpdf/config.h + /home/calvin/src/xpdf-4.04/xpdf/pdfimages.cc + aconf.h + aconf2.h + goo/GMutex.h + goo/GString.h + goo/gfile.h + goo/gmem.h + goo/gmempp.h + goo/gtypes.h + goo/parseargs.h diff --git a/xpdf/CMakeFiles/pdfimages.dir/depend.make b/xpdf/CMakeFiles/pdfimages.dir/depend.make new file mode 100644 index 0000000..35157f2 --- /dev/null +++ b/xpdf/CMakeFiles/pdfimages.dir/depend.make @@ -0,0 +1,49 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +xpdf/CMakeFiles/pdfimages.dir/ImageOutputDev.cc.o: xpdf/Array.h +xpdf/CMakeFiles/pdfimages.dir/ImageOutputDev.cc.o: xpdf/CharTypes.h +xpdf/CMakeFiles/pdfimages.dir/ImageOutputDev.cc.o: xpdf/Dict.h +xpdf/CMakeFiles/pdfimages.dir/ImageOutputDev.cc.o: xpdf/Error.h +xpdf/CMakeFiles/pdfimages.dir/ImageOutputDev.cc.o: xpdf/Function.h +xpdf/CMakeFiles/pdfimages.dir/ImageOutputDev.cc.o: xpdf/GfxState.h +xpdf/CMakeFiles/pdfimages.dir/ImageOutputDev.cc.o: xpdf/ImageOutputDev.cc +xpdf/CMakeFiles/pdfimages.dir/ImageOutputDev.cc.o: xpdf/ImageOutputDev.h +xpdf/CMakeFiles/pdfimages.dir/ImageOutputDev.cc.o: xpdf/Object.h +xpdf/CMakeFiles/pdfimages.dir/ImageOutputDev.cc.o: xpdf/OutputDev.h +xpdf/CMakeFiles/pdfimages.dir/ImageOutputDev.cc.o: xpdf/Stream.h +xpdf/CMakeFiles/pdfimages.dir/ImageOutputDev.cc.o: xpdf/config.h +xpdf/CMakeFiles/pdfimages.dir/ImageOutputDev.cc.o: aconf.h +xpdf/CMakeFiles/pdfimages.dir/ImageOutputDev.cc.o: aconf2.h +xpdf/CMakeFiles/pdfimages.dir/ImageOutputDev.cc.o: goo/GMutex.h +xpdf/CMakeFiles/pdfimages.dir/ImageOutputDev.cc.o: goo/GString.h +xpdf/CMakeFiles/pdfimages.dir/ImageOutputDev.cc.o: goo/gfile.h +xpdf/CMakeFiles/pdfimages.dir/ImageOutputDev.cc.o: goo/gmem.h +xpdf/CMakeFiles/pdfimages.dir/ImageOutputDev.cc.o: goo/gmempp.h +xpdf/CMakeFiles/pdfimages.dir/ImageOutputDev.cc.o: goo/gtypes.h + +xpdf/CMakeFiles/pdfimages.dir/pdfimages.cc.o: xpdf/Array.h +xpdf/CMakeFiles/pdfimages.dir/pdfimages.cc.o: xpdf/Catalog.h +xpdf/CMakeFiles/pdfimages.dir/pdfimages.cc.o: xpdf/CharTypes.h +xpdf/CMakeFiles/pdfimages.dir/pdfimages.cc.o: xpdf/Dict.h +xpdf/CMakeFiles/pdfimages.dir/pdfimages.cc.o: xpdf/Error.h +xpdf/CMakeFiles/pdfimages.dir/pdfimages.cc.o: xpdf/GlobalParams.h +xpdf/CMakeFiles/pdfimages.dir/pdfimages.cc.o: xpdf/ImageOutputDev.h +xpdf/CMakeFiles/pdfimages.dir/pdfimages.cc.o: xpdf/Object.h +xpdf/CMakeFiles/pdfimages.dir/pdfimages.cc.o: xpdf/OutputDev.h +xpdf/CMakeFiles/pdfimages.dir/pdfimages.cc.o: xpdf/PDFDoc.h +xpdf/CMakeFiles/pdfimages.dir/pdfimages.cc.o: xpdf/Page.h +xpdf/CMakeFiles/pdfimages.dir/pdfimages.cc.o: xpdf/Stream.h +xpdf/CMakeFiles/pdfimages.dir/pdfimages.cc.o: xpdf/XRef.h +xpdf/CMakeFiles/pdfimages.dir/pdfimages.cc.o: xpdf/config.h +xpdf/CMakeFiles/pdfimages.dir/pdfimages.cc.o: xpdf/pdfimages.cc +xpdf/CMakeFiles/pdfimages.dir/pdfimages.cc.o: aconf.h +xpdf/CMakeFiles/pdfimages.dir/pdfimages.cc.o: aconf2.h +xpdf/CMakeFiles/pdfimages.dir/pdfimages.cc.o: goo/GMutex.h +xpdf/CMakeFiles/pdfimages.dir/pdfimages.cc.o: goo/GString.h +xpdf/CMakeFiles/pdfimages.dir/pdfimages.cc.o: goo/gfile.h +xpdf/CMakeFiles/pdfimages.dir/pdfimages.cc.o: goo/gmem.h +xpdf/CMakeFiles/pdfimages.dir/pdfimages.cc.o: goo/gmempp.h +xpdf/CMakeFiles/pdfimages.dir/pdfimages.cc.o: goo/gtypes.h +xpdf/CMakeFiles/pdfimages.dir/pdfimages.cc.o: goo/parseargs.h + diff --git a/xpdf/CMakeFiles/pdfimages.dir/flags.make b/xpdf/CMakeFiles/pdfimages.dir/flags.make new file mode 100644 index 0000000..300fa3e --- /dev/null +++ b/xpdf/CMakeFiles/pdfimages.dir/flags.make @@ -0,0 +1,10 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +# compile CXX with /usr/bin/c++ +CXX_DEFINES = + +CXX_INCLUDES = -I/home/calvin/src/xpdf-4.04 -I/home/calvin/src/xpdf-4.04/goo -I/home/calvin/src/xpdf-4.04/fofi -I/home/calvin/src/xpdf-4.04/splash + +CXX_FLAGS = + diff --git a/xpdf/CMakeFiles/pdfimages.dir/link.txt b/xpdf/CMakeFiles/pdfimages.dir/link.txt new file mode 100644 index 0000000..dc20425 --- /dev/null +++ b/xpdf/CMakeFiles/pdfimages.dir/link.txt @@ -0,0 +1 @@ +/usr/bin/c++ -rdynamic CMakeFiles/pdfimages.dir/ImageOutputDev.cc.o CMakeFiles/pdfimages.dir/pdfimages.cc.o CMakeFiles/xpdf_objs.dir/AcroForm.cc.o CMakeFiles/xpdf_objs.dir/Annot.cc.o CMakeFiles/xpdf_objs.dir/Array.cc.o CMakeFiles/xpdf_objs.dir/BuiltinFont.cc.o CMakeFiles/xpdf_objs.dir/BuiltinFontTables.cc.o CMakeFiles/xpdf_objs.dir/Catalog.cc.o CMakeFiles/xpdf_objs.dir/CharCodeToUnicode.cc.o CMakeFiles/xpdf_objs.dir/CMap.cc.o CMakeFiles/xpdf_objs.dir/Decrypt.cc.o CMakeFiles/xpdf_objs.dir/Dict.cc.o CMakeFiles/xpdf_objs.dir/Error.cc.o CMakeFiles/xpdf_objs.dir/FontEncodingTables.cc.o CMakeFiles/xpdf_objs.dir/Function.cc.o CMakeFiles/xpdf_objs.dir/Gfx.cc.o CMakeFiles/xpdf_objs.dir/GfxFont.cc.o CMakeFiles/xpdf_objs.dir/GfxState.cc.o CMakeFiles/xpdf_objs.dir/GlobalParams.cc.o CMakeFiles/xpdf_objs.dir/JArithmeticDecoder.cc.o CMakeFiles/xpdf_objs.dir/JBIG2Stream.cc.o CMakeFiles/xpdf_objs.dir/JPXStream.cc.o CMakeFiles/xpdf_objs.dir/Lexer.cc.o CMakeFiles/xpdf_objs.dir/Link.cc.o CMakeFiles/xpdf_objs.dir/NameToCharCode.cc.o CMakeFiles/xpdf_objs.dir/Object.cc.o CMakeFiles/xpdf_objs.dir/OptionalContent.cc.o CMakeFiles/xpdf_objs.dir/Outline.cc.o CMakeFiles/xpdf_objs.dir/OutputDev.cc.o CMakeFiles/xpdf_objs.dir/Page.cc.o CMakeFiles/xpdf_objs.dir/Parser.cc.o CMakeFiles/xpdf_objs.dir/PDF417Barcode.cc.o CMakeFiles/xpdf_objs.dir/PDFDoc.cc.o CMakeFiles/xpdf_objs.dir/PDFDocEncoding.cc.o CMakeFiles/xpdf_objs.dir/PSTokenizer.cc.o CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.o CMakeFiles/xpdf_objs.dir/Stream.cc.o CMakeFiles/xpdf_objs.dir/TextString.cc.o CMakeFiles/xpdf_objs.dir/UnicodeMap.cc.o CMakeFiles/xpdf_objs.dir/UnicodeRemapping.cc.o CMakeFiles/xpdf_objs.dir/UnicodeTypeTable.cc.o CMakeFiles/xpdf_objs.dir/UTF8.cc.o CMakeFiles/xpdf_objs.dir/XFAScanner.cc.o CMakeFiles/xpdf_objs.dir/XRef.cc.o CMakeFiles/xpdf_objs.dir/Zoox.cc.o -o pdfimages ../goo/libgoo.a ../fofi/libfofi.a -lfontconfig -lpthread diff --git a/xpdf/CMakeFiles/pdfimages.dir/pdfimages.cc.o b/xpdf/CMakeFiles/pdfimages.dir/pdfimages.cc.o new file mode 100644 index 0000000..826918c Binary files /dev/null and b/xpdf/CMakeFiles/pdfimages.dir/pdfimages.cc.o differ diff --git a/xpdf/CMakeFiles/pdfimages.dir/progress.make b/xpdf/CMakeFiles/pdfimages.dir/progress.make new file mode 100644 index 0000000..481f9e9 --- /dev/null +++ b/xpdf/CMakeFiles/pdfimages.dir/progress.make @@ -0,0 +1,4 @@ +CMAKE_PROGRESS_1 = 16 +CMAKE_PROGRESS_2 = 17 +CMAKE_PROGRESS_3 = + diff --git a/xpdf/CMakeFiles/pdfinfo.dir/CXX.includecache b/xpdf/CMakeFiles/pdfinfo.dir/CXX.includecache new file mode 100644 index 0000000..d7f688f --- /dev/null +++ b/xpdf/CMakeFiles/pdfinfo.dir/CXX.includecache @@ -0,0 +1,288 @@ +#IncludeRegexLine: ^[ ]*[#%][ ]*(include|import)[ ]*[<"]([^">]+)([">]) + +#IncludeRegexScan: ^.*$ + +#IncludeRegexComplain: ^$ + +#IncludeRegexTransform: + +/home/calvin/src/xpdf-4.04/xpdf/Array.h +aconf.h +- +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h + +/home/calvin/src/xpdf-4.04/xpdf/Catalog.h +aconf.h +- +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h +CharTypes.h +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + +/home/calvin/src/xpdf-4.04/xpdf/Dict.h +aconf.h +- +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h + +/home/calvin/src/xpdf-4.04/xpdf/Error.h +aconf.h +- +stdio.h +- +config.h +/home/calvin/src/xpdf-4.04/xpdf/config.h +gfile.h +/home/calvin/src/xpdf-4.04/xpdf/gfile.h + +/home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h +aconf.h +- +stdio.h +- +windows.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +CharTypes.h +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h + +/home/calvin/src/xpdf-4.04/xpdf/Object.h +aconf.h +- +stdio.h +- +string.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +gmem.h +/home/calvin/src/xpdf-4.04/xpdf/gmem.h +gfile.h +/home/calvin/src/xpdf-4.04/xpdf/gfile.h +GString.h +/home/calvin/src/xpdf-4.04/xpdf/GString.h +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h +Array.h +/home/calvin/src/xpdf-4.04/xpdf/Array.h +Dict.h +/home/calvin/src/xpdf-4.04/xpdf/Dict.h +Stream.h +/home/calvin/src/xpdf-4.04/xpdf/Stream.h + +/home/calvin/src/xpdf-4.04/xpdf/PDFDoc.h +aconf.h +- +stdio.h +- +XRef.h +/home/calvin/src/xpdf-4.04/xpdf/XRef.h +Catalog.h +/home/calvin/src/xpdf-4.04/xpdf/Catalog.h +Page.h +/home/calvin/src/xpdf-4.04/xpdf/Page.h + +/home/calvin/src/xpdf-4.04/xpdf/Page.h +aconf.h +- +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h + +/home/calvin/src/xpdf-4.04/xpdf/Stream.h +aconf.h +- +stdio.h +- +jpeglib.h +- +setjmp.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +gfile.h +/home/calvin/src/xpdf-4.04/xpdf/gfile.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h + +/home/calvin/src/xpdf-4.04/xpdf/TextString.h +aconf.h +- +CharTypes.h +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + +/home/calvin/src/xpdf-4.04/xpdf/UTF8.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +GString.h +/home/calvin/src/xpdf-4.04/xpdf/GString.h +CharTypes.h +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + +/home/calvin/src/xpdf-4.04/xpdf/UnicodeMap.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +CharTypes.h +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h + +/home/calvin/src/xpdf-4.04/xpdf/XRef.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +gfile.h +/home/calvin/src/xpdf-4.04/xpdf/gfile.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h + +/home/calvin/src/xpdf-4.04/xpdf/Zoox.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h + +/home/calvin/src/xpdf-4.04/xpdf/config.h + +/home/calvin/src/xpdf-4.04/xpdf/pdfinfo.cc +aconf.h +- +stdio.h +- +stdlib.h +- +stddef.h +- +string.h +- +time.h +- +math.h +- +ctype.h +- +gmem.h +/home/calvin/src/xpdf-4.04/xpdf/gmem.h +gmempp.h +/home/calvin/src/xpdf-4.04/xpdf/gmempp.h +parseargs.h +/home/calvin/src/xpdf-4.04/xpdf/parseargs.h +GString.h +/home/calvin/src/xpdf-4.04/xpdf/GString.h +gfile.h +/home/calvin/src/xpdf-4.04/xpdf/gfile.h +GlobalParams.h +/home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h +Stream.h +/home/calvin/src/xpdf-4.04/xpdf/Stream.h +Array.h +/home/calvin/src/xpdf-4.04/xpdf/Array.h +Dict.h +/home/calvin/src/xpdf-4.04/xpdf/Dict.h +XRef.h +/home/calvin/src/xpdf-4.04/xpdf/XRef.h +Catalog.h +/home/calvin/src/xpdf-4.04/xpdf/Catalog.h +Page.h +/home/calvin/src/xpdf-4.04/xpdf/Page.h +PDFDoc.h +/home/calvin/src/xpdf-4.04/xpdf/PDFDoc.h +CharTypes.h +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h +UnicodeMap.h +/home/calvin/src/xpdf-4.04/xpdf/UnicodeMap.h +TextString.h +/home/calvin/src/xpdf-4.04/xpdf/TextString.h +UTF8.h +/home/calvin/src/xpdf-4.04/xpdf/UTF8.h +Zoox.h +/home/calvin/src/xpdf-4.04/xpdf/Zoox.h +Error.h +/home/calvin/src/xpdf-4.04/xpdf/Error.h +config.h +/home/calvin/src/xpdf-4.04/xpdf/config.h + +aconf.h +aconf2.h +- + +aconf2.h +AvailabilityMacros.h +- + +goo/GMutex.h +aconf.h +- +windows.h +- +intrin.h +- +pthread.h +- + +goo/GString.h +aconf.h +- +limits.h +- +stdarg.h +- +gtypes.h +goo/gtypes.h + +goo/gfile.h +aconf.h +- +stdio.h +- +stdlib.h +- +stddef.h +- +sys/stat.h +- +win32lib.h +- +windows.h +- +unistd.h +- +sys/types.h +- +gtypes.h +goo/gtypes.h + +goo/gmem.h +stdio.h +- +aconf.h +- + +goo/gmempp.h +stdlib.h +- + +goo/gtypes.h + +goo/parseargs.h +gtypes.h +goo/gtypes.h + diff --git a/xpdf/CMakeFiles/pdfinfo.dir/DependInfo.cmake b/xpdf/CMakeFiles/pdfinfo.dir/DependInfo.cmake new file mode 100644 index 0000000..683fdd0 --- /dev/null +++ b/xpdf/CMakeFiles/pdfinfo.dir/DependInfo.cmake @@ -0,0 +1,26 @@ +# The set of languages for which implicit dependencies are needed: +set(CMAKE_DEPENDS_LANGUAGES + "CXX" + ) +# The set of files for implicit dependencies of each language: +set(CMAKE_DEPENDS_CHECK_CXX + "/home/calvin/src/xpdf-4.04/xpdf/pdfinfo.cc" "/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/pdfinfo.dir/pdfinfo.cc.o" + ) +set(CMAKE_CXX_COMPILER_ID "GNU") + +# The include file search paths: +set(CMAKE_CXX_TARGET_INCLUDE_PATH + "." + "goo" + "fofi" + "splash" + ) + +# Targets to which this target links. +set(CMAKE_TARGET_LINKED_INFO_FILES + "/home/calvin/src/xpdf-4.04/goo/CMakeFiles/goo.dir/DependInfo.cmake" + "/home/calvin/src/xpdf-4.04/fofi/CMakeFiles/fofi.dir/DependInfo.cmake" + ) + +# Fortran module output directory. +set(CMAKE_Fortran_TARGET_MODULE_DIR "") diff --git a/xpdf/CMakeFiles/pdfinfo.dir/build.make b/xpdf/CMakeFiles/pdfinfo.dir/build.make new file mode 100644 index 0000000..3b0b55e --- /dev/null +++ b/xpdf/CMakeFiles/pdfinfo.dir/build.make @@ -0,0 +1,206 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +# Delete rule output on recipe failure. +.DELETE_ON_ERROR: + + +#============================================================================= +# Special targets provided by cmake. + +# Disable implicit rules so canonical targets will work. +.SUFFIXES: + + +# Disable VCS-based implicit rules. +% : %,v + + +# Disable VCS-based implicit rules. +% : RCS/% + + +# Disable VCS-based implicit rules. +% : RCS/%,v + + +# Disable VCS-based implicit rules. +% : SCCS/s.% + + +# Disable VCS-based implicit rules. +% : s.% + + +.SUFFIXES: .hpux_make_needs_suffix_list + + +# Command-line flag to silence nested $(MAKE). +$(VERBOSE)MAKESILENT = -s + +#Suppress display of executed commands. +$(VERBOSE).SILENT: + +# A target that is always out of date. +cmake_force: + +.PHONY : cmake_force + +#============================================================================= +# Set environment variables for the build. + +# The shell in which to execute make rules. +SHELL = /bin/sh + +# The CMake executable. +CMAKE_COMMAND = /usr/bin/cmake + +# The command to remove a file. +RM = /usr/bin/cmake -E rm -f + +# Escaping for special characters. +EQUALS = = + +# The top-level source directory on which CMake was run. +CMAKE_SOURCE_DIR = /home/calvin/src/xpdf-4.04 + +# The top-level build directory on which CMake was run. +CMAKE_BINARY_DIR = /home/calvin/src/xpdf-4.04 + +# Include any dependencies generated for this target. +include xpdf/CMakeFiles/pdfinfo.dir/depend.make + +# Include the progress variables for this target. +include xpdf/CMakeFiles/pdfinfo.dir/progress.make + +# Include the compile flags for this target's objects. +include xpdf/CMakeFiles/pdfinfo.dir/flags.make + +xpdf/CMakeFiles/pdfinfo.dir/pdfinfo.cc.o: xpdf/CMakeFiles/pdfinfo.dir/flags.make +xpdf/CMakeFiles/pdfinfo.dir/pdfinfo.cc.o: xpdf/pdfinfo.cc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_1) "Building CXX object xpdf/CMakeFiles/pdfinfo.dir/pdfinfo.cc.o" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/pdfinfo.dir/pdfinfo.cc.o -c /home/calvin/src/xpdf-4.04/xpdf/pdfinfo.cc + +xpdf/CMakeFiles/pdfinfo.dir/pdfinfo.cc.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/pdfinfo.dir/pdfinfo.cc.i" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf/pdfinfo.cc > CMakeFiles/pdfinfo.dir/pdfinfo.cc.i + +xpdf/CMakeFiles/pdfinfo.dir/pdfinfo.cc.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/pdfinfo.dir/pdfinfo.cc.s" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf/pdfinfo.cc -o CMakeFiles/pdfinfo.dir/pdfinfo.cc.s + +# Object files for target pdfinfo +pdfinfo_OBJECTS = \ +"CMakeFiles/pdfinfo.dir/pdfinfo.cc.o" + +# External object files for target pdfinfo +pdfinfo_EXTERNAL_OBJECTS = \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/AcroForm.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Annot.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Array.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFont.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFontTables.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Catalog.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/CharCodeToUnicode.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/CMap.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Decrypt.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Dict.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Error.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/FontEncodingTables.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Function.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Gfx.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/GfxFont.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/GfxState.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/GlobalParams.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/JArithmeticDecoder.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/JBIG2Stream.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/JPXStream.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Lexer.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Link.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/NameToCharCode.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Object.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/OptionalContent.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Outline.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/OutputDev.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Page.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Parser.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/PDF417Barcode.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/PDFDoc.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/PDFDocEncoding.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/PSTokenizer.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Stream.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/TextString.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/UnicodeMap.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/UnicodeRemapping.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/UnicodeTypeTable.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/UTF8.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/XFAScanner.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/XRef.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Zoox.cc.o" + +xpdf/pdfinfo: xpdf/CMakeFiles/pdfinfo.dir/pdfinfo.cc.o +xpdf/pdfinfo: xpdf/CMakeFiles/xpdf_objs.dir/AcroForm.cc.o +xpdf/pdfinfo: xpdf/CMakeFiles/xpdf_objs.dir/Annot.cc.o +xpdf/pdfinfo: xpdf/CMakeFiles/xpdf_objs.dir/Array.cc.o +xpdf/pdfinfo: xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFont.cc.o +xpdf/pdfinfo: xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFontTables.cc.o +xpdf/pdfinfo: xpdf/CMakeFiles/xpdf_objs.dir/Catalog.cc.o +xpdf/pdfinfo: xpdf/CMakeFiles/xpdf_objs.dir/CharCodeToUnicode.cc.o +xpdf/pdfinfo: xpdf/CMakeFiles/xpdf_objs.dir/CMap.cc.o +xpdf/pdfinfo: xpdf/CMakeFiles/xpdf_objs.dir/Decrypt.cc.o +xpdf/pdfinfo: xpdf/CMakeFiles/xpdf_objs.dir/Dict.cc.o +xpdf/pdfinfo: xpdf/CMakeFiles/xpdf_objs.dir/Error.cc.o +xpdf/pdfinfo: xpdf/CMakeFiles/xpdf_objs.dir/FontEncodingTables.cc.o +xpdf/pdfinfo: xpdf/CMakeFiles/xpdf_objs.dir/Function.cc.o +xpdf/pdfinfo: xpdf/CMakeFiles/xpdf_objs.dir/Gfx.cc.o +xpdf/pdfinfo: xpdf/CMakeFiles/xpdf_objs.dir/GfxFont.cc.o +xpdf/pdfinfo: xpdf/CMakeFiles/xpdf_objs.dir/GfxState.cc.o +xpdf/pdfinfo: xpdf/CMakeFiles/xpdf_objs.dir/GlobalParams.cc.o +xpdf/pdfinfo: xpdf/CMakeFiles/xpdf_objs.dir/JArithmeticDecoder.cc.o +xpdf/pdfinfo: xpdf/CMakeFiles/xpdf_objs.dir/JBIG2Stream.cc.o +xpdf/pdfinfo: xpdf/CMakeFiles/xpdf_objs.dir/JPXStream.cc.o +xpdf/pdfinfo: xpdf/CMakeFiles/xpdf_objs.dir/Lexer.cc.o +xpdf/pdfinfo: xpdf/CMakeFiles/xpdf_objs.dir/Link.cc.o +xpdf/pdfinfo: xpdf/CMakeFiles/xpdf_objs.dir/NameToCharCode.cc.o +xpdf/pdfinfo: xpdf/CMakeFiles/xpdf_objs.dir/Object.cc.o +xpdf/pdfinfo: xpdf/CMakeFiles/xpdf_objs.dir/OptionalContent.cc.o +xpdf/pdfinfo: xpdf/CMakeFiles/xpdf_objs.dir/Outline.cc.o +xpdf/pdfinfo: xpdf/CMakeFiles/xpdf_objs.dir/OutputDev.cc.o +xpdf/pdfinfo: xpdf/CMakeFiles/xpdf_objs.dir/Page.cc.o +xpdf/pdfinfo: xpdf/CMakeFiles/xpdf_objs.dir/Parser.cc.o +xpdf/pdfinfo: xpdf/CMakeFiles/xpdf_objs.dir/PDF417Barcode.cc.o +xpdf/pdfinfo: xpdf/CMakeFiles/xpdf_objs.dir/PDFDoc.cc.o +xpdf/pdfinfo: xpdf/CMakeFiles/xpdf_objs.dir/PDFDocEncoding.cc.o +xpdf/pdfinfo: xpdf/CMakeFiles/xpdf_objs.dir/PSTokenizer.cc.o +xpdf/pdfinfo: xpdf/CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.o +xpdf/pdfinfo: xpdf/CMakeFiles/xpdf_objs.dir/Stream.cc.o +xpdf/pdfinfo: xpdf/CMakeFiles/xpdf_objs.dir/TextString.cc.o +xpdf/pdfinfo: xpdf/CMakeFiles/xpdf_objs.dir/UnicodeMap.cc.o +xpdf/pdfinfo: xpdf/CMakeFiles/xpdf_objs.dir/UnicodeRemapping.cc.o +xpdf/pdfinfo: xpdf/CMakeFiles/xpdf_objs.dir/UnicodeTypeTable.cc.o +xpdf/pdfinfo: xpdf/CMakeFiles/xpdf_objs.dir/UTF8.cc.o +xpdf/pdfinfo: xpdf/CMakeFiles/xpdf_objs.dir/XFAScanner.cc.o +xpdf/pdfinfo: xpdf/CMakeFiles/xpdf_objs.dir/XRef.cc.o +xpdf/pdfinfo: xpdf/CMakeFiles/xpdf_objs.dir/Zoox.cc.o +xpdf/pdfinfo: xpdf/CMakeFiles/pdfinfo.dir/build.make +xpdf/pdfinfo: goo/libgoo.a +xpdf/pdfinfo: fofi/libfofi.a +xpdf/pdfinfo: /usr/lib/x86_64-linux-gnu/libfontconfig.so +xpdf/pdfinfo: xpdf/CMakeFiles/pdfinfo.dir/link.txt + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --bold --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_2) "Linking CXX executable pdfinfo" + cd /home/calvin/src/xpdf-4.04/xpdf && $(CMAKE_COMMAND) -E cmake_link_script CMakeFiles/pdfinfo.dir/link.txt --verbose=$(VERBOSE) + +# Rule to build all files generated by this target. +xpdf/CMakeFiles/pdfinfo.dir/build: xpdf/pdfinfo + +.PHONY : xpdf/CMakeFiles/pdfinfo.dir/build + +xpdf/CMakeFiles/pdfinfo.dir/clean: + cd /home/calvin/src/xpdf-4.04/xpdf && $(CMAKE_COMMAND) -P CMakeFiles/pdfinfo.dir/cmake_clean.cmake +.PHONY : xpdf/CMakeFiles/pdfinfo.dir/clean + +xpdf/CMakeFiles/pdfinfo.dir/depend: + cd /home/calvin/src/xpdf-4.04 && $(CMAKE_COMMAND) -E cmake_depends "Unix Makefiles" /home/calvin/src/xpdf-4.04 /home/calvin/src/xpdf-4.04/xpdf /home/calvin/src/xpdf-4.04 /home/calvin/src/xpdf-4.04/xpdf /home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/pdfinfo.dir/DependInfo.cmake --color=$(COLOR) +.PHONY : xpdf/CMakeFiles/pdfinfo.dir/depend + diff --git a/xpdf/CMakeFiles/pdfinfo.dir/cmake_clean.cmake b/xpdf/CMakeFiles/pdfinfo.dir/cmake_clean.cmake new file mode 100644 index 0000000..419ea5d --- /dev/null +++ b/xpdf/CMakeFiles/pdfinfo.dir/cmake_clean.cmake @@ -0,0 +1,10 @@ +file(REMOVE_RECURSE + "CMakeFiles/pdfinfo.dir/pdfinfo.cc.o" + "pdfinfo" + "pdfinfo.pdb" +) + +# Per-language clean rules from dependency scanning. +foreach(lang CXX) + include(CMakeFiles/pdfinfo.dir/cmake_clean_${lang}.cmake OPTIONAL) +endforeach() diff --git a/xpdf/CMakeFiles/pdfinfo.dir/depend.internal b/xpdf/CMakeFiles/pdfinfo.dir/depend.internal new file mode 100644 index 0000000..a7e7251 --- /dev/null +++ b/xpdf/CMakeFiles/pdfinfo.dir/depend.internal @@ -0,0 +1,30 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +xpdf/CMakeFiles/pdfinfo.dir/pdfinfo.cc.o + /home/calvin/src/xpdf-4.04/xpdf/Array.h + /home/calvin/src/xpdf-4.04/xpdf/Catalog.h + /home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + /home/calvin/src/xpdf-4.04/xpdf/Dict.h + /home/calvin/src/xpdf-4.04/xpdf/Error.h + /home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h + /home/calvin/src/xpdf-4.04/xpdf/Object.h + /home/calvin/src/xpdf-4.04/xpdf/PDFDoc.h + /home/calvin/src/xpdf-4.04/xpdf/Page.h + /home/calvin/src/xpdf-4.04/xpdf/Stream.h + /home/calvin/src/xpdf-4.04/xpdf/TextString.h + /home/calvin/src/xpdf-4.04/xpdf/UTF8.h + /home/calvin/src/xpdf-4.04/xpdf/UnicodeMap.h + /home/calvin/src/xpdf-4.04/xpdf/XRef.h + /home/calvin/src/xpdf-4.04/xpdf/Zoox.h + /home/calvin/src/xpdf-4.04/xpdf/config.h + /home/calvin/src/xpdf-4.04/xpdf/pdfinfo.cc + aconf.h + aconf2.h + goo/GMutex.h + goo/GString.h + goo/gfile.h + goo/gmem.h + goo/gmempp.h + goo/gtypes.h + goo/parseargs.h diff --git a/xpdf/CMakeFiles/pdfinfo.dir/depend.make b/xpdf/CMakeFiles/pdfinfo.dir/depend.make new file mode 100644 index 0000000..83bc6a9 --- /dev/null +++ b/xpdf/CMakeFiles/pdfinfo.dir/depend.make @@ -0,0 +1,30 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +xpdf/CMakeFiles/pdfinfo.dir/pdfinfo.cc.o: xpdf/Array.h +xpdf/CMakeFiles/pdfinfo.dir/pdfinfo.cc.o: xpdf/Catalog.h +xpdf/CMakeFiles/pdfinfo.dir/pdfinfo.cc.o: xpdf/CharTypes.h +xpdf/CMakeFiles/pdfinfo.dir/pdfinfo.cc.o: xpdf/Dict.h +xpdf/CMakeFiles/pdfinfo.dir/pdfinfo.cc.o: xpdf/Error.h +xpdf/CMakeFiles/pdfinfo.dir/pdfinfo.cc.o: xpdf/GlobalParams.h +xpdf/CMakeFiles/pdfinfo.dir/pdfinfo.cc.o: xpdf/Object.h +xpdf/CMakeFiles/pdfinfo.dir/pdfinfo.cc.o: xpdf/PDFDoc.h +xpdf/CMakeFiles/pdfinfo.dir/pdfinfo.cc.o: xpdf/Page.h +xpdf/CMakeFiles/pdfinfo.dir/pdfinfo.cc.o: xpdf/Stream.h +xpdf/CMakeFiles/pdfinfo.dir/pdfinfo.cc.o: xpdf/TextString.h +xpdf/CMakeFiles/pdfinfo.dir/pdfinfo.cc.o: xpdf/UTF8.h +xpdf/CMakeFiles/pdfinfo.dir/pdfinfo.cc.o: xpdf/UnicodeMap.h +xpdf/CMakeFiles/pdfinfo.dir/pdfinfo.cc.o: xpdf/XRef.h +xpdf/CMakeFiles/pdfinfo.dir/pdfinfo.cc.o: xpdf/Zoox.h +xpdf/CMakeFiles/pdfinfo.dir/pdfinfo.cc.o: xpdf/config.h +xpdf/CMakeFiles/pdfinfo.dir/pdfinfo.cc.o: xpdf/pdfinfo.cc +xpdf/CMakeFiles/pdfinfo.dir/pdfinfo.cc.o: aconf.h +xpdf/CMakeFiles/pdfinfo.dir/pdfinfo.cc.o: aconf2.h +xpdf/CMakeFiles/pdfinfo.dir/pdfinfo.cc.o: goo/GMutex.h +xpdf/CMakeFiles/pdfinfo.dir/pdfinfo.cc.o: goo/GString.h +xpdf/CMakeFiles/pdfinfo.dir/pdfinfo.cc.o: goo/gfile.h +xpdf/CMakeFiles/pdfinfo.dir/pdfinfo.cc.o: goo/gmem.h +xpdf/CMakeFiles/pdfinfo.dir/pdfinfo.cc.o: goo/gmempp.h +xpdf/CMakeFiles/pdfinfo.dir/pdfinfo.cc.o: goo/gtypes.h +xpdf/CMakeFiles/pdfinfo.dir/pdfinfo.cc.o: goo/parseargs.h + diff --git a/xpdf/CMakeFiles/pdfinfo.dir/flags.make b/xpdf/CMakeFiles/pdfinfo.dir/flags.make new file mode 100644 index 0000000..300fa3e --- /dev/null +++ b/xpdf/CMakeFiles/pdfinfo.dir/flags.make @@ -0,0 +1,10 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +# compile CXX with /usr/bin/c++ +CXX_DEFINES = + +CXX_INCLUDES = -I/home/calvin/src/xpdf-4.04 -I/home/calvin/src/xpdf-4.04/goo -I/home/calvin/src/xpdf-4.04/fofi -I/home/calvin/src/xpdf-4.04/splash + +CXX_FLAGS = + diff --git a/xpdf/CMakeFiles/pdfinfo.dir/link.txt b/xpdf/CMakeFiles/pdfinfo.dir/link.txt new file mode 100644 index 0000000..560eb56 --- /dev/null +++ b/xpdf/CMakeFiles/pdfinfo.dir/link.txt @@ -0,0 +1 @@ +/usr/bin/c++ -rdynamic CMakeFiles/pdfinfo.dir/pdfinfo.cc.o CMakeFiles/xpdf_objs.dir/AcroForm.cc.o CMakeFiles/xpdf_objs.dir/Annot.cc.o CMakeFiles/xpdf_objs.dir/Array.cc.o CMakeFiles/xpdf_objs.dir/BuiltinFont.cc.o CMakeFiles/xpdf_objs.dir/BuiltinFontTables.cc.o CMakeFiles/xpdf_objs.dir/Catalog.cc.o CMakeFiles/xpdf_objs.dir/CharCodeToUnicode.cc.o CMakeFiles/xpdf_objs.dir/CMap.cc.o CMakeFiles/xpdf_objs.dir/Decrypt.cc.o CMakeFiles/xpdf_objs.dir/Dict.cc.o CMakeFiles/xpdf_objs.dir/Error.cc.o CMakeFiles/xpdf_objs.dir/FontEncodingTables.cc.o CMakeFiles/xpdf_objs.dir/Function.cc.o CMakeFiles/xpdf_objs.dir/Gfx.cc.o CMakeFiles/xpdf_objs.dir/GfxFont.cc.o CMakeFiles/xpdf_objs.dir/GfxState.cc.o CMakeFiles/xpdf_objs.dir/GlobalParams.cc.o CMakeFiles/xpdf_objs.dir/JArithmeticDecoder.cc.o CMakeFiles/xpdf_objs.dir/JBIG2Stream.cc.o CMakeFiles/xpdf_objs.dir/JPXStream.cc.o CMakeFiles/xpdf_objs.dir/Lexer.cc.o CMakeFiles/xpdf_objs.dir/Link.cc.o CMakeFiles/xpdf_objs.dir/NameToCharCode.cc.o CMakeFiles/xpdf_objs.dir/Object.cc.o CMakeFiles/xpdf_objs.dir/OptionalContent.cc.o CMakeFiles/xpdf_objs.dir/Outline.cc.o CMakeFiles/xpdf_objs.dir/OutputDev.cc.o CMakeFiles/xpdf_objs.dir/Page.cc.o CMakeFiles/xpdf_objs.dir/Parser.cc.o CMakeFiles/xpdf_objs.dir/PDF417Barcode.cc.o CMakeFiles/xpdf_objs.dir/PDFDoc.cc.o CMakeFiles/xpdf_objs.dir/PDFDocEncoding.cc.o CMakeFiles/xpdf_objs.dir/PSTokenizer.cc.o CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.o CMakeFiles/xpdf_objs.dir/Stream.cc.o CMakeFiles/xpdf_objs.dir/TextString.cc.o CMakeFiles/xpdf_objs.dir/UnicodeMap.cc.o CMakeFiles/xpdf_objs.dir/UnicodeRemapping.cc.o CMakeFiles/xpdf_objs.dir/UnicodeTypeTable.cc.o CMakeFiles/xpdf_objs.dir/UTF8.cc.o CMakeFiles/xpdf_objs.dir/XFAScanner.cc.o CMakeFiles/xpdf_objs.dir/XRef.cc.o CMakeFiles/xpdf_objs.dir/Zoox.cc.o -o pdfinfo ../goo/libgoo.a ../fofi/libfofi.a -lfontconfig -lpthread diff --git a/xpdf/CMakeFiles/pdfinfo.dir/pdfinfo.cc.o b/xpdf/CMakeFiles/pdfinfo.dir/pdfinfo.cc.o new file mode 100644 index 0000000..d2e2fab Binary files /dev/null and b/xpdf/CMakeFiles/pdfinfo.dir/pdfinfo.cc.o differ diff --git a/xpdf/CMakeFiles/pdfinfo.dir/progress.make b/xpdf/CMakeFiles/pdfinfo.dir/progress.make new file mode 100644 index 0000000..2b041ba --- /dev/null +++ b/xpdf/CMakeFiles/pdfinfo.dir/progress.make @@ -0,0 +1,3 @@ +CMAKE_PROGRESS_1 = 18 +CMAKE_PROGRESS_2 = 19 + diff --git a/xpdf/CMakeFiles/pdftohtml.dir/CXX.includecache b/xpdf/CMakeFiles/pdftohtml.dir/CXX.includecache new file mode 100644 index 0000000..2245778 --- /dev/null +++ b/xpdf/CMakeFiles/pdftohtml.dir/CXX.includecache @@ -0,0 +1,734 @@ +#IncludeRegexLine: ^[ ]*[#%][ ]*(include|import)[ ]*[<"]([^">]+)([">]) + +#IncludeRegexScan: ^.*$ + +#IncludeRegexComplain: ^$ + +#IncludeRegexTransform: + +/home/calvin/src/xpdf-4.04/xpdf/AcroForm.h +aconf.h +- + +/home/calvin/src/xpdf-4.04/xpdf/Array.h +aconf.h +- +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h + +/home/calvin/src/xpdf-4.04/xpdf/BuiltinFont.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h + +/home/calvin/src/xpdf-4.04/xpdf/BuiltinFontTables.h +BuiltinFont.h +/home/calvin/src/xpdf-4.04/xpdf/BuiltinFont.h + +/home/calvin/src/xpdf-4.04/xpdf/Catalog.h +aconf.h +- +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h +CharTypes.h +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + +/home/calvin/src/xpdf-4.04/xpdf/CharCodeToUnicode.h +aconf.h +- +CharTypes.h +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h + +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + +/home/calvin/src/xpdf-4.04/xpdf/Dict.h +aconf.h +- +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h + +/home/calvin/src/xpdf-4.04/xpdf/Error.h +aconf.h +- +stdio.h +- +config.h +/home/calvin/src/xpdf-4.04/xpdf/config.h +gfile.h +/home/calvin/src/xpdf-4.04/xpdf/gfile.h + +/home/calvin/src/xpdf-4.04/xpdf/ErrorCodes.h + +/home/calvin/src/xpdf-4.04/xpdf/FontEncodingTables.h + +/home/calvin/src/xpdf-4.04/xpdf/Function.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h + +/home/calvin/src/xpdf-4.04/xpdf/Gfx.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +gfile.h +/home/calvin/src/xpdf-4.04/xpdf/gfile.h +GfxState.h +/home/calvin/src/xpdf-4.04/xpdf/GfxState.h + +/home/calvin/src/xpdf-4.04/xpdf/GfxFont.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +GString.h +/home/calvin/src/xpdf-4.04/xpdf/GString.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h +CharTypes.h +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + +/home/calvin/src/xpdf-4.04/xpdf/GfxState.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h +Function.h +/home/calvin/src/xpdf-4.04/xpdf/Function.h + +/home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h +aconf.h +- +stdio.h +- +windows.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +CharTypes.h +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h + +/home/calvin/src/xpdf-4.04/xpdf/HTMLGen.cc +aconf.h +- +stdlib.h +- +png.h +- +gmem.h +/home/calvin/src/xpdf-4.04/xpdf/gmem.h +gmempp.h +/home/calvin/src/xpdf-4.04/xpdf/gmempp.h +GString.h +/home/calvin/src/xpdf-4.04/xpdf/GString.h +GList.h +/home/calvin/src/xpdf-4.04/xpdf/GList.h +SplashBitmap.h +/home/calvin/src/xpdf-4.04/xpdf/SplashBitmap.h +PDFDoc.h +/home/calvin/src/xpdf-4.04/xpdf/PDFDoc.h +GfxFont.h +/home/calvin/src/xpdf-4.04/xpdf/GfxFont.h +AcroForm.h +/home/calvin/src/xpdf-4.04/xpdf/AcroForm.h +TextOutputDev.h +/home/calvin/src/xpdf-4.04/xpdf/TextOutputDev.h +SplashOutputDev.h +/home/calvin/src/xpdf-4.04/xpdf/SplashOutputDev.h +ErrorCodes.h +/home/calvin/src/xpdf-4.04/xpdf/ErrorCodes.h +WebFont.h +/home/calvin/src/xpdf-4.04/xpdf/WebFont.h +HTMLGen.h +/home/calvin/src/xpdf-4.04/xpdf/HTMLGen.h + +/home/calvin/src/xpdf-4.04/xpdf/HTMLGen.h +aconf.h +- + +/home/calvin/src/xpdf-4.04/xpdf/JPXStream.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h +Stream.h +/home/calvin/src/xpdf-4.04/xpdf/Stream.h + +/home/calvin/src/xpdf-4.04/xpdf/Link.h +aconf.h +- +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h + +/home/calvin/src/xpdf-4.04/xpdf/Object.h +aconf.h +- +stdio.h +- +string.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +gmem.h +/home/calvin/src/xpdf-4.04/xpdf/gmem.h +gfile.h +/home/calvin/src/xpdf-4.04/xpdf/gfile.h +GString.h +/home/calvin/src/xpdf-4.04/xpdf/GString.h +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h +Array.h +/home/calvin/src/xpdf-4.04/xpdf/Array.h +Dict.h +/home/calvin/src/xpdf-4.04/xpdf/Dict.h +Stream.h +/home/calvin/src/xpdf-4.04/xpdf/Stream.h + +/home/calvin/src/xpdf-4.04/xpdf/OutputDev.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +CharTypes.h +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + +/home/calvin/src/xpdf-4.04/xpdf/PDFDoc.h +aconf.h +- +stdio.h +- +XRef.h +/home/calvin/src/xpdf-4.04/xpdf/XRef.h +Catalog.h +/home/calvin/src/xpdf-4.04/xpdf/Catalog.h +Page.h +/home/calvin/src/xpdf-4.04/xpdf/Page.h + +/home/calvin/src/xpdf-4.04/xpdf/Page.h +aconf.h +- +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h + +/home/calvin/src/xpdf-4.04/xpdf/ShadingImage.cc +aconf.h +- +math.h +- +Trace.h +/home/calvin/src/xpdf-4.04/xpdf/Trace.h +GfxState.h +/home/calvin/src/xpdf-4.04/xpdf/GfxState.h +SplashBitmap.h +/home/calvin/src/xpdf-4.04/xpdf/SplashBitmap.h +SplashPattern.h +/home/calvin/src/xpdf-4.04/xpdf/SplashPattern.h +SplashPath.h +/home/calvin/src/xpdf-4.04/xpdf/SplashPath.h +Splash.h +/home/calvin/src/xpdf-4.04/xpdf/Splash.h +ShadingImage.h +/home/calvin/src/xpdf-4.04/xpdf/ShadingImage.h + +/home/calvin/src/xpdf-4.04/xpdf/ShadingImage.h +aconf.h +- +SplashTypes.h +/home/calvin/src/xpdf-4.04/xpdf/SplashTypes.h + +/home/calvin/src/xpdf-4.04/xpdf/SplashOutputDev.cc +aconf.h +- +string.h +- +math.h +- +limits.h +- +gmempp.h +/home/calvin/src/xpdf-4.04/xpdf/gmempp.h +gfile.h +/home/calvin/src/xpdf-4.04/xpdf/gfile.h +Trace.h +/home/calvin/src/xpdf-4.04/xpdf/Trace.h +GlobalParams.h +/home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h +Error.h +/home/calvin/src/xpdf-4.04/xpdf/Error.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h +Gfx.h +/home/calvin/src/xpdf-4.04/xpdf/Gfx.h +GfxFont.h +/home/calvin/src/xpdf-4.04/xpdf/GfxFont.h +ShadingImage.h +/home/calvin/src/xpdf-4.04/xpdf/ShadingImage.h +Link.h +/home/calvin/src/xpdf-4.04/xpdf/Link.h +CharCodeToUnicode.h +/home/calvin/src/xpdf-4.04/xpdf/CharCodeToUnicode.h +FontEncodingTables.h +/home/calvin/src/xpdf-4.04/xpdf/FontEncodingTables.h +BuiltinFont.h +/home/calvin/src/xpdf-4.04/xpdf/BuiltinFont.h +BuiltinFontTables.h +/home/calvin/src/xpdf-4.04/xpdf/BuiltinFontTables.h +FoFiTrueType.h +/home/calvin/src/xpdf-4.04/xpdf/FoFiTrueType.h +FoFiType1C.h +/home/calvin/src/xpdf-4.04/xpdf/FoFiType1C.h +JPXStream.h +/home/calvin/src/xpdf-4.04/xpdf/JPXStream.h +SplashBitmap.h +/home/calvin/src/xpdf-4.04/xpdf/SplashBitmap.h +SplashGlyphBitmap.h +/home/calvin/src/xpdf-4.04/xpdf/SplashGlyphBitmap.h +SplashPattern.h +/home/calvin/src/xpdf-4.04/xpdf/SplashPattern.h +SplashScreen.h +/home/calvin/src/xpdf-4.04/xpdf/SplashScreen.h +SplashPath.h +/home/calvin/src/xpdf-4.04/xpdf/SplashPath.h +SplashState.h +/home/calvin/src/xpdf-4.04/xpdf/SplashState.h +SplashErrorCodes.h +/home/calvin/src/xpdf-4.04/xpdf/SplashErrorCodes.h +SplashFontEngine.h +/home/calvin/src/xpdf-4.04/xpdf/SplashFontEngine.h +SplashFont.h +/home/calvin/src/xpdf-4.04/xpdf/SplashFont.h +SplashFontFile.h +/home/calvin/src/xpdf-4.04/xpdf/SplashFontFile.h +SplashFontFileID.h +/home/calvin/src/xpdf-4.04/xpdf/SplashFontFileID.h +Splash.h +/home/calvin/src/xpdf-4.04/xpdf/Splash.h +SplashOutputDev.h +/home/calvin/src/xpdf-4.04/xpdf/SplashOutputDev.h + +/home/calvin/src/xpdf-4.04/xpdf/SplashOutputDev.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +SplashTypes.h +/home/calvin/src/xpdf-4.04/xpdf/SplashTypes.h +config.h +/home/calvin/src/xpdf-4.04/xpdf/config.h +OutputDev.h +/home/calvin/src/xpdf-4.04/xpdf/OutputDev.h +GfxState.h +/home/calvin/src/xpdf-4.04/xpdf/GfxState.h + +/home/calvin/src/xpdf-4.04/xpdf/Stream.h +aconf.h +- +stdio.h +- +jpeglib.h +- +setjmp.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +gfile.h +/home/calvin/src/xpdf-4.04/xpdf/gfile.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h + +/home/calvin/src/xpdf-4.04/xpdf/TextOutputDev.cc +aconf.h +- +stdio.h +- +stdlib.h +- +stddef.h +- +math.h +- +limits.h +- +ctype.h +- +fcntl.h +- +io.h +- +gmem.h +/home/calvin/src/xpdf-4.04/xpdf/gmem.h +gmempp.h +/home/calvin/src/xpdf-4.04/xpdf/gmempp.h +GString.h +/home/calvin/src/xpdf-4.04/xpdf/GString.h +GList.h +/home/calvin/src/xpdf-4.04/xpdf/GList.h +gfile.h +/home/calvin/src/xpdf-4.04/xpdf/gfile.h +config.h +/home/calvin/src/xpdf-4.04/xpdf/config.h +Error.h +/home/calvin/src/xpdf-4.04/xpdf/Error.h +GlobalParams.h +/home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h +UnicodeMap.h +/home/calvin/src/xpdf-4.04/xpdf/UnicodeMap.h +UnicodeRemapping.h +/home/calvin/src/xpdf-4.04/xpdf/UnicodeRemapping.h +UnicodeTypeTable.h +/home/calvin/src/xpdf-4.04/xpdf/UnicodeTypeTable.h +GfxState.h +/home/calvin/src/xpdf-4.04/xpdf/GfxState.h +Link.h +/home/calvin/src/xpdf-4.04/xpdf/Link.h +TextOutputDev.h +/home/calvin/src/xpdf-4.04/xpdf/TextOutputDev.h + +/home/calvin/src/xpdf-4.04/xpdf/TextOutputDev.h +aconf.h +- +stdio.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +GfxFont.h +/home/calvin/src/xpdf-4.04/xpdf/GfxFont.h +OutputDev.h +/home/calvin/src/xpdf-4.04/xpdf/OutputDev.h + +/home/calvin/src/xpdf-4.04/xpdf/UnicodeMap.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +CharTypes.h +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h + +/home/calvin/src/xpdf-4.04/xpdf/UnicodeRemapping.h +aconf.h +- +CharTypes.h +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + +/home/calvin/src/xpdf-4.04/xpdf/UnicodeTypeTable.h +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h + +/home/calvin/src/xpdf-4.04/xpdf/WebFont.cc +aconf.h +- +gmem.h +/home/calvin/src/xpdf-4.04/xpdf/gmem.h +gmempp.h +/home/calvin/src/xpdf-4.04/xpdf/gmempp.h +GHash.h +/home/calvin/src/xpdf-4.04/xpdf/GHash.h +FoFiTrueType.h +/home/calvin/src/xpdf-4.04/xpdf/FoFiTrueType.h +FoFiType1C.h +/home/calvin/src/xpdf-4.04/xpdf/FoFiType1C.h +CharCodeToUnicode.h +/home/calvin/src/xpdf-4.04/xpdf/CharCodeToUnicode.h +WebFont.h +/home/calvin/src/xpdf-4.04/xpdf/WebFont.h + +/home/calvin/src/xpdf-4.04/xpdf/WebFont.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +FoFiBase.h +/home/calvin/src/xpdf-4.04/xpdf/FoFiBase.h +GfxFont.h +/home/calvin/src/xpdf-4.04/xpdf/GfxFont.h + +/home/calvin/src/xpdf-4.04/xpdf/XRef.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +gfile.h +/home/calvin/src/xpdf-4.04/xpdf/gfile.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h + +/home/calvin/src/xpdf-4.04/xpdf/config.h + +/home/calvin/src/xpdf-4.04/xpdf/pdftohtml.cc +aconf.h +- +stdio.h +- +stdlib.h +- +gmem.h +/home/calvin/src/xpdf-4.04/xpdf/gmem.h +gmempp.h +/home/calvin/src/xpdf-4.04/xpdf/gmempp.h +parseargs.h +/home/calvin/src/xpdf-4.04/xpdf/parseargs.h +gfile.h +/home/calvin/src/xpdf-4.04/xpdf/gfile.h +GString.h +/home/calvin/src/xpdf-4.04/xpdf/GString.h +GlobalParams.h +/home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h +PDFDoc.h +/home/calvin/src/xpdf-4.04/xpdf/PDFDoc.h +HTMLGen.h +/home/calvin/src/xpdf-4.04/xpdf/HTMLGen.h +Error.h +/home/calvin/src/xpdf-4.04/xpdf/Error.h +ErrorCodes.h +/home/calvin/src/xpdf-4.04/xpdf/ErrorCodes.h +config.h +/home/calvin/src/xpdf-4.04/xpdf/config.h + +aconf.h +aconf2.h +- + +aconf2.h +AvailabilityMacros.h +- + +fofi/FoFiBase.h +aconf.h +- +gtypes.h +fofi/gtypes.h + +fofi/FoFiTrueType.h +aconf.h +- +gtypes.h +fofi/gtypes.h +FoFiBase.h +fofi/FoFiBase.h + +fofi/FoFiType1C.h +aconf.h +- +gtypes.h +fofi/gtypes.h +FoFiBase.h +fofi/FoFiBase.h + +goo/FixedPoint.h +aconf.h +- +stdio.h +- +stdlib.h +- +gtypes.h +goo/gtypes.h + +goo/GHash.h +aconf.h +- +gtypes.h +goo/gtypes.h + +goo/GList.h +aconf.h +- +gtypes.h +goo/gtypes.h + +goo/GMutex.h +aconf.h +- +windows.h +- +intrin.h +- +pthread.h +- + +goo/GString.h +aconf.h +- +limits.h +- +stdarg.h +- +gtypes.h +goo/gtypes.h + +goo/Trace.h +aconf.h +- + +goo/gfile.h +aconf.h +- +stdio.h +- +stdlib.h +- +stddef.h +- +sys/stat.h +- +win32lib.h +- +windows.h +- +unistd.h +- +sys/types.h +- +gtypes.h +goo/gtypes.h + +goo/gmem.h +stdio.h +- +aconf.h +- + +goo/gmempp.h +stdlib.h +- + +goo/gtypes.h + +goo/parseargs.h +gtypes.h +goo/gtypes.h + +splash/Splash.h +aconf.h +- +SplashTypes.h +splash/SplashTypes.h +SplashClip.h +splash/SplashClip.h + +splash/SplashBitmap.h +aconf.h +- +stdio.h +- +limits.h +- +stdint.h +- +SplashTypes.h +splash/SplashTypes.h + +splash/SplashClip.h +aconf.h +- +SplashTypes.h +splash/SplashTypes.h +SplashMath.h +splash/SplashMath.h + +splash/SplashErrorCodes.h +aconf.h +- + +splash/SplashFont.h +aconf.h +- +gtypes.h +splash/gtypes.h +SplashTypes.h +splash/SplashTypes.h +SplashMath.h +splash/SplashMath.h + +splash/SplashFontEngine.h +aconf.h +- +gtypes.h +splash/gtypes.h + +splash/SplashFontFile.h +aconf.h +- +gtypes.h +splash/gtypes.h +SplashTypes.h +splash/SplashTypes.h +GMutex.h +splash/GMutex.h + +splash/SplashFontFileID.h +aconf.h +- +gtypes.h +splash/gtypes.h + +splash/SplashGlyphBitmap.h +aconf.h +- +gtypes.h +splash/gtypes.h + +splash/SplashMath.h +aconf.h +- +FixedPoint.h +splash/FixedPoint.h +math.h +- +emmintrin.h +- +SplashTypes.h +splash/SplashTypes.h + +splash/SplashPath.h +aconf.h +- +SplashTypes.h +splash/SplashTypes.h + +splash/SplashPattern.h +aconf.h +- +SplashTypes.h +splash/SplashTypes.h + +splash/SplashScreen.h +aconf.h +- +SplashTypes.h +splash/SplashTypes.h + +splash/SplashState.h +aconf.h +- +SplashTypes.h +splash/SplashTypes.h + +splash/SplashTypes.h +aconf.h +- +gtypes.h +splash/gtypes.h +FixedPoint.h +splash/FixedPoint.h + diff --git a/xpdf/CMakeFiles/pdftohtml.dir/DependInfo.cmake b/xpdf/CMakeFiles/pdftohtml.dir/DependInfo.cmake new file mode 100644 index 0000000..ee4e2cb --- /dev/null +++ b/xpdf/CMakeFiles/pdftohtml.dir/DependInfo.cmake @@ -0,0 +1,32 @@ +# The set of languages for which implicit dependencies are needed: +set(CMAKE_DEPENDS_LANGUAGES + "CXX" + ) +# The set of files for implicit dependencies of each language: +set(CMAKE_DEPENDS_CHECK_CXX + "/home/calvin/src/xpdf-4.04/xpdf/HTMLGen.cc" "/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/pdftohtml.dir/HTMLGen.cc.o" + "/home/calvin/src/xpdf-4.04/xpdf/ShadingImage.cc" "/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/pdftohtml.dir/ShadingImage.cc.o" + "/home/calvin/src/xpdf-4.04/xpdf/SplashOutputDev.cc" "/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/pdftohtml.dir/SplashOutputDev.cc.o" + "/home/calvin/src/xpdf-4.04/xpdf/TextOutputDev.cc" "/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/pdftohtml.dir/TextOutputDev.cc.o" + "/home/calvin/src/xpdf-4.04/xpdf/WebFont.cc" "/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/pdftohtml.dir/WebFont.cc.o" + "/home/calvin/src/xpdf-4.04/xpdf/pdftohtml.cc" "/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/pdftohtml.dir/pdftohtml.cc.o" + ) +set(CMAKE_CXX_COMPILER_ID "GNU") + +# The include file search paths: +set(CMAKE_CXX_TARGET_INCLUDE_PATH + "." + "goo" + "fofi" + "splash" + ) + +# Targets to which this target links. +set(CMAKE_TARGET_LINKED_INFO_FILES + "/home/calvin/src/xpdf-4.04/goo/CMakeFiles/goo.dir/DependInfo.cmake" + "/home/calvin/src/xpdf-4.04/fofi/CMakeFiles/fofi.dir/DependInfo.cmake" + "/home/calvin/src/xpdf-4.04/splash/CMakeFiles/splash.dir/DependInfo.cmake" + ) + +# Fortran module output directory. +set(CMAKE_Fortran_TARGET_MODULE_DIR "") diff --git a/xpdf/CMakeFiles/pdftohtml.dir/HTMLGen.cc.o b/xpdf/CMakeFiles/pdftohtml.dir/HTMLGen.cc.o new file mode 100644 index 0000000..9d6e3ca Binary files /dev/null and b/xpdf/CMakeFiles/pdftohtml.dir/HTMLGen.cc.o differ diff --git a/xpdf/CMakeFiles/pdftohtml.dir/ShadingImage.cc.o b/xpdf/CMakeFiles/pdftohtml.dir/ShadingImage.cc.o new file mode 100644 index 0000000..d53401f Binary files /dev/null and b/xpdf/CMakeFiles/pdftohtml.dir/ShadingImage.cc.o differ diff --git a/xpdf/CMakeFiles/pdftohtml.dir/SplashOutputDev.cc.o b/xpdf/CMakeFiles/pdftohtml.dir/SplashOutputDev.cc.o new file mode 100644 index 0000000..7fdcd23 Binary files /dev/null and b/xpdf/CMakeFiles/pdftohtml.dir/SplashOutputDev.cc.o differ diff --git a/xpdf/CMakeFiles/pdftohtml.dir/TextOutputDev.cc.o b/xpdf/CMakeFiles/pdftohtml.dir/TextOutputDev.cc.o new file mode 100644 index 0000000..ac16080 Binary files /dev/null and b/xpdf/CMakeFiles/pdftohtml.dir/TextOutputDev.cc.o differ diff --git a/xpdf/CMakeFiles/pdftohtml.dir/WebFont.cc.o b/xpdf/CMakeFiles/pdftohtml.dir/WebFont.cc.o new file mode 100644 index 0000000..5c80ce5 Binary files /dev/null and b/xpdf/CMakeFiles/pdftohtml.dir/WebFont.cc.o differ diff --git a/xpdf/CMakeFiles/pdftohtml.dir/build.make b/xpdf/CMakeFiles/pdftohtml.dir/build.make new file mode 100644 index 0000000..c4448eb --- /dev/null +++ b/xpdf/CMakeFiles/pdftohtml.dir/build.make @@ -0,0 +1,285 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +# Delete rule output on recipe failure. +.DELETE_ON_ERROR: + + +#============================================================================= +# Special targets provided by cmake. + +# Disable implicit rules so canonical targets will work. +.SUFFIXES: + + +# Disable VCS-based implicit rules. +% : %,v + + +# Disable VCS-based implicit rules. +% : RCS/% + + +# Disable VCS-based implicit rules. +% : RCS/%,v + + +# Disable VCS-based implicit rules. +% : SCCS/s.% + + +# Disable VCS-based implicit rules. +% : s.% + + +.SUFFIXES: .hpux_make_needs_suffix_list + + +# Command-line flag to silence nested $(MAKE). +$(VERBOSE)MAKESILENT = -s + +#Suppress display of executed commands. +$(VERBOSE).SILENT: + +# A target that is always out of date. +cmake_force: + +.PHONY : cmake_force + +#============================================================================= +# Set environment variables for the build. + +# The shell in which to execute make rules. +SHELL = /bin/sh + +# The CMake executable. +CMAKE_COMMAND = /usr/bin/cmake + +# The command to remove a file. +RM = /usr/bin/cmake -E rm -f + +# Escaping for special characters. +EQUALS = = + +# The top-level source directory on which CMake was run. +CMAKE_SOURCE_DIR = /home/calvin/src/xpdf-4.04 + +# The top-level build directory on which CMake was run. +CMAKE_BINARY_DIR = /home/calvin/src/xpdf-4.04 + +# Include any dependencies generated for this target. +include xpdf/CMakeFiles/pdftohtml.dir/depend.make + +# Include the progress variables for this target. +include xpdf/CMakeFiles/pdftohtml.dir/progress.make + +# Include the compile flags for this target's objects. +include xpdf/CMakeFiles/pdftohtml.dir/flags.make + +xpdf/CMakeFiles/pdftohtml.dir/HTMLGen.cc.o: xpdf/CMakeFiles/pdftohtml.dir/flags.make +xpdf/CMakeFiles/pdftohtml.dir/HTMLGen.cc.o: xpdf/HTMLGen.cc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_1) "Building CXX object xpdf/CMakeFiles/pdftohtml.dir/HTMLGen.cc.o" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/pdftohtml.dir/HTMLGen.cc.o -c /home/calvin/src/xpdf-4.04/xpdf/HTMLGen.cc + +xpdf/CMakeFiles/pdftohtml.dir/HTMLGen.cc.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/pdftohtml.dir/HTMLGen.cc.i" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf/HTMLGen.cc > CMakeFiles/pdftohtml.dir/HTMLGen.cc.i + +xpdf/CMakeFiles/pdftohtml.dir/HTMLGen.cc.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/pdftohtml.dir/HTMLGen.cc.s" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf/HTMLGen.cc -o CMakeFiles/pdftohtml.dir/HTMLGen.cc.s + +xpdf/CMakeFiles/pdftohtml.dir/ShadingImage.cc.o: xpdf/CMakeFiles/pdftohtml.dir/flags.make +xpdf/CMakeFiles/pdftohtml.dir/ShadingImage.cc.o: xpdf/ShadingImage.cc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_2) "Building CXX object xpdf/CMakeFiles/pdftohtml.dir/ShadingImage.cc.o" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/pdftohtml.dir/ShadingImage.cc.o -c /home/calvin/src/xpdf-4.04/xpdf/ShadingImage.cc + +xpdf/CMakeFiles/pdftohtml.dir/ShadingImage.cc.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/pdftohtml.dir/ShadingImage.cc.i" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf/ShadingImage.cc > CMakeFiles/pdftohtml.dir/ShadingImage.cc.i + +xpdf/CMakeFiles/pdftohtml.dir/ShadingImage.cc.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/pdftohtml.dir/ShadingImage.cc.s" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf/ShadingImage.cc -o CMakeFiles/pdftohtml.dir/ShadingImage.cc.s + +xpdf/CMakeFiles/pdftohtml.dir/SplashOutputDev.cc.o: xpdf/CMakeFiles/pdftohtml.dir/flags.make +xpdf/CMakeFiles/pdftohtml.dir/SplashOutputDev.cc.o: xpdf/SplashOutputDev.cc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_3) "Building CXX object xpdf/CMakeFiles/pdftohtml.dir/SplashOutputDev.cc.o" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/pdftohtml.dir/SplashOutputDev.cc.o -c /home/calvin/src/xpdf-4.04/xpdf/SplashOutputDev.cc + +xpdf/CMakeFiles/pdftohtml.dir/SplashOutputDev.cc.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/pdftohtml.dir/SplashOutputDev.cc.i" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf/SplashOutputDev.cc > CMakeFiles/pdftohtml.dir/SplashOutputDev.cc.i + +xpdf/CMakeFiles/pdftohtml.dir/SplashOutputDev.cc.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/pdftohtml.dir/SplashOutputDev.cc.s" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf/SplashOutputDev.cc -o CMakeFiles/pdftohtml.dir/SplashOutputDev.cc.s + +xpdf/CMakeFiles/pdftohtml.dir/TextOutputDev.cc.o: xpdf/CMakeFiles/pdftohtml.dir/flags.make +xpdf/CMakeFiles/pdftohtml.dir/TextOutputDev.cc.o: xpdf/TextOutputDev.cc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_4) "Building CXX object xpdf/CMakeFiles/pdftohtml.dir/TextOutputDev.cc.o" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/pdftohtml.dir/TextOutputDev.cc.o -c /home/calvin/src/xpdf-4.04/xpdf/TextOutputDev.cc + +xpdf/CMakeFiles/pdftohtml.dir/TextOutputDev.cc.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/pdftohtml.dir/TextOutputDev.cc.i" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf/TextOutputDev.cc > CMakeFiles/pdftohtml.dir/TextOutputDev.cc.i + +xpdf/CMakeFiles/pdftohtml.dir/TextOutputDev.cc.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/pdftohtml.dir/TextOutputDev.cc.s" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf/TextOutputDev.cc -o CMakeFiles/pdftohtml.dir/TextOutputDev.cc.s + +xpdf/CMakeFiles/pdftohtml.dir/WebFont.cc.o: xpdf/CMakeFiles/pdftohtml.dir/flags.make +xpdf/CMakeFiles/pdftohtml.dir/WebFont.cc.o: xpdf/WebFont.cc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_5) "Building CXX object xpdf/CMakeFiles/pdftohtml.dir/WebFont.cc.o" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/pdftohtml.dir/WebFont.cc.o -c /home/calvin/src/xpdf-4.04/xpdf/WebFont.cc + +xpdf/CMakeFiles/pdftohtml.dir/WebFont.cc.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/pdftohtml.dir/WebFont.cc.i" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf/WebFont.cc > CMakeFiles/pdftohtml.dir/WebFont.cc.i + +xpdf/CMakeFiles/pdftohtml.dir/WebFont.cc.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/pdftohtml.dir/WebFont.cc.s" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf/WebFont.cc -o CMakeFiles/pdftohtml.dir/WebFont.cc.s + +xpdf/CMakeFiles/pdftohtml.dir/pdftohtml.cc.o: xpdf/CMakeFiles/pdftohtml.dir/flags.make +xpdf/CMakeFiles/pdftohtml.dir/pdftohtml.cc.o: xpdf/pdftohtml.cc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_6) "Building CXX object xpdf/CMakeFiles/pdftohtml.dir/pdftohtml.cc.o" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/pdftohtml.dir/pdftohtml.cc.o -c /home/calvin/src/xpdf-4.04/xpdf/pdftohtml.cc + +xpdf/CMakeFiles/pdftohtml.dir/pdftohtml.cc.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/pdftohtml.dir/pdftohtml.cc.i" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf/pdftohtml.cc > CMakeFiles/pdftohtml.dir/pdftohtml.cc.i + +xpdf/CMakeFiles/pdftohtml.dir/pdftohtml.cc.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/pdftohtml.dir/pdftohtml.cc.s" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf/pdftohtml.cc -o CMakeFiles/pdftohtml.dir/pdftohtml.cc.s + +# Object files for target pdftohtml +pdftohtml_OBJECTS = \ +"CMakeFiles/pdftohtml.dir/HTMLGen.cc.o" \ +"CMakeFiles/pdftohtml.dir/ShadingImage.cc.o" \ +"CMakeFiles/pdftohtml.dir/SplashOutputDev.cc.o" \ +"CMakeFiles/pdftohtml.dir/TextOutputDev.cc.o" \ +"CMakeFiles/pdftohtml.dir/WebFont.cc.o" \ +"CMakeFiles/pdftohtml.dir/pdftohtml.cc.o" + +# External object files for target pdftohtml +pdftohtml_EXTERNAL_OBJECTS = \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/AcroForm.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Annot.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Array.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFont.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFontTables.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Catalog.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/CharCodeToUnicode.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/CMap.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Decrypt.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Dict.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Error.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/FontEncodingTables.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Function.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Gfx.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/GfxFont.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/GfxState.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/GlobalParams.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/JArithmeticDecoder.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/JBIG2Stream.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/JPXStream.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Lexer.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Link.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/NameToCharCode.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Object.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/OptionalContent.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Outline.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/OutputDev.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Page.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Parser.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/PDF417Barcode.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/PDFDoc.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/PDFDocEncoding.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/PSTokenizer.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Stream.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/TextString.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/UnicodeMap.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/UnicodeRemapping.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/UnicodeTypeTable.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/UTF8.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/XFAScanner.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/XRef.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Zoox.cc.o" + +xpdf/pdftohtml: xpdf/CMakeFiles/pdftohtml.dir/HTMLGen.cc.o +xpdf/pdftohtml: xpdf/CMakeFiles/pdftohtml.dir/ShadingImage.cc.o +xpdf/pdftohtml: xpdf/CMakeFiles/pdftohtml.dir/SplashOutputDev.cc.o +xpdf/pdftohtml: xpdf/CMakeFiles/pdftohtml.dir/TextOutputDev.cc.o +xpdf/pdftohtml: xpdf/CMakeFiles/pdftohtml.dir/WebFont.cc.o +xpdf/pdftohtml: xpdf/CMakeFiles/pdftohtml.dir/pdftohtml.cc.o +xpdf/pdftohtml: xpdf/CMakeFiles/xpdf_objs.dir/AcroForm.cc.o +xpdf/pdftohtml: xpdf/CMakeFiles/xpdf_objs.dir/Annot.cc.o +xpdf/pdftohtml: xpdf/CMakeFiles/xpdf_objs.dir/Array.cc.o +xpdf/pdftohtml: xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFont.cc.o +xpdf/pdftohtml: xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFontTables.cc.o +xpdf/pdftohtml: xpdf/CMakeFiles/xpdf_objs.dir/Catalog.cc.o +xpdf/pdftohtml: xpdf/CMakeFiles/xpdf_objs.dir/CharCodeToUnicode.cc.o +xpdf/pdftohtml: xpdf/CMakeFiles/xpdf_objs.dir/CMap.cc.o +xpdf/pdftohtml: xpdf/CMakeFiles/xpdf_objs.dir/Decrypt.cc.o +xpdf/pdftohtml: xpdf/CMakeFiles/xpdf_objs.dir/Dict.cc.o +xpdf/pdftohtml: xpdf/CMakeFiles/xpdf_objs.dir/Error.cc.o +xpdf/pdftohtml: xpdf/CMakeFiles/xpdf_objs.dir/FontEncodingTables.cc.o +xpdf/pdftohtml: xpdf/CMakeFiles/xpdf_objs.dir/Function.cc.o +xpdf/pdftohtml: xpdf/CMakeFiles/xpdf_objs.dir/Gfx.cc.o +xpdf/pdftohtml: xpdf/CMakeFiles/xpdf_objs.dir/GfxFont.cc.o +xpdf/pdftohtml: xpdf/CMakeFiles/xpdf_objs.dir/GfxState.cc.o +xpdf/pdftohtml: xpdf/CMakeFiles/xpdf_objs.dir/GlobalParams.cc.o +xpdf/pdftohtml: xpdf/CMakeFiles/xpdf_objs.dir/JArithmeticDecoder.cc.o +xpdf/pdftohtml: xpdf/CMakeFiles/xpdf_objs.dir/JBIG2Stream.cc.o +xpdf/pdftohtml: xpdf/CMakeFiles/xpdf_objs.dir/JPXStream.cc.o +xpdf/pdftohtml: xpdf/CMakeFiles/xpdf_objs.dir/Lexer.cc.o +xpdf/pdftohtml: xpdf/CMakeFiles/xpdf_objs.dir/Link.cc.o +xpdf/pdftohtml: xpdf/CMakeFiles/xpdf_objs.dir/NameToCharCode.cc.o +xpdf/pdftohtml: xpdf/CMakeFiles/xpdf_objs.dir/Object.cc.o +xpdf/pdftohtml: xpdf/CMakeFiles/xpdf_objs.dir/OptionalContent.cc.o +xpdf/pdftohtml: xpdf/CMakeFiles/xpdf_objs.dir/Outline.cc.o +xpdf/pdftohtml: xpdf/CMakeFiles/xpdf_objs.dir/OutputDev.cc.o +xpdf/pdftohtml: xpdf/CMakeFiles/xpdf_objs.dir/Page.cc.o +xpdf/pdftohtml: xpdf/CMakeFiles/xpdf_objs.dir/Parser.cc.o +xpdf/pdftohtml: xpdf/CMakeFiles/xpdf_objs.dir/PDF417Barcode.cc.o +xpdf/pdftohtml: xpdf/CMakeFiles/xpdf_objs.dir/PDFDoc.cc.o +xpdf/pdftohtml: xpdf/CMakeFiles/xpdf_objs.dir/PDFDocEncoding.cc.o +xpdf/pdftohtml: xpdf/CMakeFiles/xpdf_objs.dir/PSTokenizer.cc.o +xpdf/pdftohtml: xpdf/CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.o +xpdf/pdftohtml: xpdf/CMakeFiles/xpdf_objs.dir/Stream.cc.o +xpdf/pdftohtml: xpdf/CMakeFiles/xpdf_objs.dir/TextString.cc.o +xpdf/pdftohtml: xpdf/CMakeFiles/xpdf_objs.dir/UnicodeMap.cc.o +xpdf/pdftohtml: xpdf/CMakeFiles/xpdf_objs.dir/UnicodeRemapping.cc.o +xpdf/pdftohtml: xpdf/CMakeFiles/xpdf_objs.dir/UnicodeTypeTable.cc.o +xpdf/pdftohtml: xpdf/CMakeFiles/xpdf_objs.dir/UTF8.cc.o +xpdf/pdftohtml: xpdf/CMakeFiles/xpdf_objs.dir/XFAScanner.cc.o +xpdf/pdftohtml: xpdf/CMakeFiles/xpdf_objs.dir/XRef.cc.o +xpdf/pdftohtml: xpdf/CMakeFiles/xpdf_objs.dir/Zoox.cc.o +xpdf/pdftohtml: xpdf/CMakeFiles/pdftohtml.dir/build.make +xpdf/pdftohtml: goo/libgoo.a +xpdf/pdftohtml: fofi/libfofi.a +xpdf/pdftohtml: splash/libsplash.a +xpdf/pdftohtml: /usr/lib/x86_64-linux-gnu/libfreetype.so +xpdf/pdftohtml: /usr/lib/x86_64-linux-gnu/libpng.so +xpdf/pdftohtml: /usr/lib/x86_64-linux-gnu/libz.so +xpdf/pdftohtml: /usr/lib/x86_64-linux-gnu/libfontconfig.so +xpdf/pdftohtml: xpdf/CMakeFiles/pdftohtml.dir/link.txt + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --bold --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_7) "Linking CXX executable pdftohtml" + cd /home/calvin/src/xpdf-4.04/xpdf && $(CMAKE_COMMAND) -E cmake_link_script CMakeFiles/pdftohtml.dir/link.txt --verbose=$(VERBOSE) + +# Rule to build all files generated by this target. +xpdf/CMakeFiles/pdftohtml.dir/build: xpdf/pdftohtml + +.PHONY : xpdf/CMakeFiles/pdftohtml.dir/build + +xpdf/CMakeFiles/pdftohtml.dir/clean: + cd /home/calvin/src/xpdf-4.04/xpdf && $(CMAKE_COMMAND) -P CMakeFiles/pdftohtml.dir/cmake_clean.cmake +.PHONY : xpdf/CMakeFiles/pdftohtml.dir/clean + +xpdf/CMakeFiles/pdftohtml.dir/depend: + cd /home/calvin/src/xpdf-4.04 && $(CMAKE_COMMAND) -E cmake_depends "Unix Makefiles" /home/calvin/src/xpdf-4.04 /home/calvin/src/xpdf-4.04/xpdf /home/calvin/src/xpdf-4.04 /home/calvin/src/xpdf-4.04/xpdf /home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/pdftohtml.dir/DependInfo.cmake --color=$(COLOR) +.PHONY : xpdf/CMakeFiles/pdftohtml.dir/depend + diff --git a/xpdf/CMakeFiles/pdftohtml.dir/cmake_clean.cmake b/xpdf/CMakeFiles/pdftohtml.dir/cmake_clean.cmake new file mode 100644 index 0000000..3e70a80 --- /dev/null +++ b/xpdf/CMakeFiles/pdftohtml.dir/cmake_clean.cmake @@ -0,0 +1,15 @@ +file(REMOVE_RECURSE + "CMakeFiles/pdftohtml.dir/HTMLGen.cc.o" + "CMakeFiles/pdftohtml.dir/ShadingImage.cc.o" + "CMakeFiles/pdftohtml.dir/SplashOutputDev.cc.o" + "CMakeFiles/pdftohtml.dir/TextOutputDev.cc.o" + "CMakeFiles/pdftohtml.dir/WebFont.cc.o" + "CMakeFiles/pdftohtml.dir/pdftohtml.cc.o" + "pdftohtml" + "pdftohtml.pdb" +) + +# Per-language clean rules from dependency scanning. +foreach(lang CXX) + include(CMakeFiles/pdftohtml.dir/cmake_clean_${lang}.cmake OPTIONAL) +endforeach() diff --git a/xpdf/CMakeFiles/pdftohtml.dir/depend.internal b/xpdf/CMakeFiles/pdftohtml.dir/depend.internal new file mode 100644 index 0000000..08a4e12 --- /dev/null +++ b/xpdf/CMakeFiles/pdftohtml.dir/depend.internal @@ -0,0 +1,189 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +xpdf/CMakeFiles/pdftohtml.dir/HTMLGen.cc.o + /home/calvin/src/xpdf-4.04/xpdf/AcroForm.h + /home/calvin/src/xpdf-4.04/xpdf/Array.h + /home/calvin/src/xpdf-4.04/xpdf/Catalog.h + /home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + /home/calvin/src/xpdf-4.04/xpdf/Dict.h + /home/calvin/src/xpdf-4.04/xpdf/ErrorCodes.h + /home/calvin/src/xpdf-4.04/xpdf/Function.h + /home/calvin/src/xpdf-4.04/xpdf/GfxFont.h + /home/calvin/src/xpdf-4.04/xpdf/GfxState.h + /home/calvin/src/xpdf-4.04/xpdf/HTMLGen.cc + /home/calvin/src/xpdf-4.04/xpdf/HTMLGen.h + /home/calvin/src/xpdf-4.04/xpdf/Object.h + /home/calvin/src/xpdf-4.04/xpdf/OutputDev.h + /home/calvin/src/xpdf-4.04/xpdf/PDFDoc.h + /home/calvin/src/xpdf-4.04/xpdf/Page.h + /home/calvin/src/xpdf-4.04/xpdf/SplashOutputDev.h + /home/calvin/src/xpdf-4.04/xpdf/Stream.h + /home/calvin/src/xpdf-4.04/xpdf/TextOutputDev.h + /home/calvin/src/xpdf-4.04/xpdf/WebFont.h + /home/calvin/src/xpdf-4.04/xpdf/XRef.h + /home/calvin/src/xpdf-4.04/xpdf/config.h + aconf.h + aconf2.h + fofi/FoFiBase.h + goo/FixedPoint.h + goo/GList.h + goo/GMutex.h + goo/GString.h + goo/gfile.h + goo/gmem.h + goo/gmempp.h + goo/gtypes.h + splash/SplashBitmap.h + splash/SplashTypes.h +xpdf/CMakeFiles/pdftohtml.dir/ShadingImage.cc.o + /home/calvin/src/xpdf-4.04/xpdf/Array.h + /home/calvin/src/xpdf-4.04/xpdf/Dict.h + /home/calvin/src/xpdf-4.04/xpdf/Function.h + /home/calvin/src/xpdf-4.04/xpdf/GfxState.h + /home/calvin/src/xpdf-4.04/xpdf/Object.h + /home/calvin/src/xpdf-4.04/xpdf/ShadingImage.cc + /home/calvin/src/xpdf-4.04/xpdf/ShadingImage.h + /home/calvin/src/xpdf-4.04/xpdf/Stream.h + aconf.h + aconf2.h + goo/FixedPoint.h + goo/GMutex.h + goo/GString.h + goo/Trace.h + goo/gfile.h + goo/gmem.h + goo/gtypes.h + splash/Splash.h + splash/SplashBitmap.h + splash/SplashClip.h + splash/SplashMath.h + splash/SplashPath.h + splash/SplashPattern.h + splash/SplashTypes.h +xpdf/CMakeFiles/pdftohtml.dir/SplashOutputDev.cc.o + /home/calvin/src/xpdf-4.04/xpdf/Array.h + /home/calvin/src/xpdf-4.04/xpdf/BuiltinFont.h + /home/calvin/src/xpdf-4.04/xpdf/BuiltinFontTables.h + /home/calvin/src/xpdf-4.04/xpdf/CharCodeToUnicode.h + /home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + /home/calvin/src/xpdf-4.04/xpdf/Dict.h + /home/calvin/src/xpdf-4.04/xpdf/Error.h + /home/calvin/src/xpdf-4.04/xpdf/FontEncodingTables.h + /home/calvin/src/xpdf-4.04/xpdf/Function.h + /home/calvin/src/xpdf-4.04/xpdf/Gfx.h + /home/calvin/src/xpdf-4.04/xpdf/GfxFont.h + /home/calvin/src/xpdf-4.04/xpdf/GfxState.h + /home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h + /home/calvin/src/xpdf-4.04/xpdf/JPXStream.h + /home/calvin/src/xpdf-4.04/xpdf/Link.h + /home/calvin/src/xpdf-4.04/xpdf/Object.h + /home/calvin/src/xpdf-4.04/xpdf/OutputDev.h + /home/calvin/src/xpdf-4.04/xpdf/ShadingImage.h + /home/calvin/src/xpdf-4.04/xpdf/SplashOutputDev.cc + /home/calvin/src/xpdf-4.04/xpdf/SplashOutputDev.h + /home/calvin/src/xpdf-4.04/xpdf/Stream.h + /home/calvin/src/xpdf-4.04/xpdf/config.h + aconf.h + aconf2.h + fofi/FoFiBase.h + fofi/FoFiTrueType.h + fofi/FoFiType1C.h + goo/FixedPoint.h + goo/GMutex.h + goo/GString.h + goo/Trace.h + goo/gfile.h + goo/gmem.h + goo/gmempp.h + goo/gtypes.h + splash/Splash.h + splash/SplashBitmap.h + splash/SplashClip.h + splash/SplashErrorCodes.h + splash/SplashFont.h + splash/SplashFontEngine.h + splash/SplashFontFile.h + splash/SplashFontFileID.h + splash/SplashGlyphBitmap.h + splash/SplashMath.h + splash/SplashPath.h + splash/SplashPattern.h + splash/SplashScreen.h + splash/SplashState.h + splash/SplashTypes.h +xpdf/CMakeFiles/pdftohtml.dir/TextOutputDev.cc.o + /home/calvin/src/xpdf-4.04/xpdf/Array.h + /home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + /home/calvin/src/xpdf-4.04/xpdf/Dict.h + /home/calvin/src/xpdf-4.04/xpdf/Error.h + /home/calvin/src/xpdf-4.04/xpdf/Function.h + /home/calvin/src/xpdf-4.04/xpdf/GfxFont.h + /home/calvin/src/xpdf-4.04/xpdf/GfxState.h + /home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h + /home/calvin/src/xpdf-4.04/xpdf/Link.h + /home/calvin/src/xpdf-4.04/xpdf/Object.h + /home/calvin/src/xpdf-4.04/xpdf/OutputDev.h + /home/calvin/src/xpdf-4.04/xpdf/Stream.h + /home/calvin/src/xpdf-4.04/xpdf/TextOutputDev.cc + /home/calvin/src/xpdf-4.04/xpdf/TextOutputDev.h + /home/calvin/src/xpdf-4.04/xpdf/UnicodeMap.h + /home/calvin/src/xpdf-4.04/xpdf/UnicodeRemapping.h + /home/calvin/src/xpdf-4.04/xpdf/UnicodeTypeTable.h + /home/calvin/src/xpdf-4.04/xpdf/config.h + aconf.h + aconf2.h + goo/GList.h + goo/GMutex.h + goo/GString.h + goo/gfile.h + goo/gmem.h + goo/gmempp.h + goo/gtypes.h +xpdf/CMakeFiles/pdftohtml.dir/WebFont.cc.o + /home/calvin/src/xpdf-4.04/xpdf/Array.h + /home/calvin/src/xpdf-4.04/xpdf/CharCodeToUnicode.h + /home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + /home/calvin/src/xpdf-4.04/xpdf/Dict.h + /home/calvin/src/xpdf-4.04/xpdf/GfxFont.h + /home/calvin/src/xpdf-4.04/xpdf/Object.h + /home/calvin/src/xpdf-4.04/xpdf/Stream.h + /home/calvin/src/xpdf-4.04/xpdf/WebFont.cc + /home/calvin/src/xpdf-4.04/xpdf/WebFont.h + aconf.h + aconf2.h + fofi/FoFiBase.h + fofi/FoFiTrueType.h + fofi/FoFiType1C.h + goo/GHash.h + goo/GMutex.h + goo/GString.h + goo/gfile.h + goo/gmem.h + goo/gmempp.h + goo/gtypes.h +xpdf/CMakeFiles/pdftohtml.dir/pdftohtml.cc.o + /home/calvin/src/xpdf-4.04/xpdf/Array.h + /home/calvin/src/xpdf-4.04/xpdf/Catalog.h + /home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + /home/calvin/src/xpdf-4.04/xpdf/Dict.h + /home/calvin/src/xpdf-4.04/xpdf/Error.h + /home/calvin/src/xpdf-4.04/xpdf/ErrorCodes.h + /home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h + /home/calvin/src/xpdf-4.04/xpdf/HTMLGen.h + /home/calvin/src/xpdf-4.04/xpdf/Object.h + /home/calvin/src/xpdf-4.04/xpdf/PDFDoc.h + /home/calvin/src/xpdf-4.04/xpdf/Page.h + /home/calvin/src/xpdf-4.04/xpdf/Stream.h + /home/calvin/src/xpdf-4.04/xpdf/XRef.h + /home/calvin/src/xpdf-4.04/xpdf/config.h + /home/calvin/src/xpdf-4.04/xpdf/pdftohtml.cc + aconf.h + aconf2.h + goo/GMutex.h + goo/GString.h + goo/gfile.h + goo/gmem.h + goo/gmempp.h + goo/gtypes.h + goo/parseargs.h diff --git a/xpdf/CMakeFiles/pdftohtml.dir/depend.make b/xpdf/CMakeFiles/pdftohtml.dir/depend.make new file mode 100644 index 0000000..3bab817 --- /dev/null +++ b/xpdf/CMakeFiles/pdftohtml.dir/depend.make @@ -0,0 +1,189 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +xpdf/CMakeFiles/pdftohtml.dir/HTMLGen.cc.o: xpdf/AcroForm.h +xpdf/CMakeFiles/pdftohtml.dir/HTMLGen.cc.o: xpdf/Array.h +xpdf/CMakeFiles/pdftohtml.dir/HTMLGen.cc.o: xpdf/Catalog.h +xpdf/CMakeFiles/pdftohtml.dir/HTMLGen.cc.o: xpdf/CharTypes.h +xpdf/CMakeFiles/pdftohtml.dir/HTMLGen.cc.o: xpdf/Dict.h +xpdf/CMakeFiles/pdftohtml.dir/HTMLGen.cc.o: xpdf/ErrorCodes.h +xpdf/CMakeFiles/pdftohtml.dir/HTMLGen.cc.o: xpdf/Function.h +xpdf/CMakeFiles/pdftohtml.dir/HTMLGen.cc.o: xpdf/GfxFont.h +xpdf/CMakeFiles/pdftohtml.dir/HTMLGen.cc.o: xpdf/GfxState.h +xpdf/CMakeFiles/pdftohtml.dir/HTMLGen.cc.o: xpdf/HTMLGen.cc +xpdf/CMakeFiles/pdftohtml.dir/HTMLGen.cc.o: xpdf/HTMLGen.h +xpdf/CMakeFiles/pdftohtml.dir/HTMLGen.cc.o: xpdf/Object.h +xpdf/CMakeFiles/pdftohtml.dir/HTMLGen.cc.o: xpdf/OutputDev.h +xpdf/CMakeFiles/pdftohtml.dir/HTMLGen.cc.o: xpdf/PDFDoc.h +xpdf/CMakeFiles/pdftohtml.dir/HTMLGen.cc.o: xpdf/Page.h +xpdf/CMakeFiles/pdftohtml.dir/HTMLGen.cc.o: xpdf/SplashOutputDev.h +xpdf/CMakeFiles/pdftohtml.dir/HTMLGen.cc.o: xpdf/Stream.h +xpdf/CMakeFiles/pdftohtml.dir/HTMLGen.cc.o: xpdf/TextOutputDev.h +xpdf/CMakeFiles/pdftohtml.dir/HTMLGen.cc.o: xpdf/WebFont.h +xpdf/CMakeFiles/pdftohtml.dir/HTMLGen.cc.o: xpdf/XRef.h +xpdf/CMakeFiles/pdftohtml.dir/HTMLGen.cc.o: xpdf/config.h +xpdf/CMakeFiles/pdftohtml.dir/HTMLGen.cc.o: aconf.h +xpdf/CMakeFiles/pdftohtml.dir/HTMLGen.cc.o: aconf2.h +xpdf/CMakeFiles/pdftohtml.dir/HTMLGen.cc.o: fofi/FoFiBase.h +xpdf/CMakeFiles/pdftohtml.dir/HTMLGen.cc.o: goo/FixedPoint.h +xpdf/CMakeFiles/pdftohtml.dir/HTMLGen.cc.o: goo/GList.h +xpdf/CMakeFiles/pdftohtml.dir/HTMLGen.cc.o: goo/GMutex.h +xpdf/CMakeFiles/pdftohtml.dir/HTMLGen.cc.o: goo/GString.h +xpdf/CMakeFiles/pdftohtml.dir/HTMLGen.cc.o: goo/gfile.h +xpdf/CMakeFiles/pdftohtml.dir/HTMLGen.cc.o: goo/gmem.h +xpdf/CMakeFiles/pdftohtml.dir/HTMLGen.cc.o: goo/gmempp.h +xpdf/CMakeFiles/pdftohtml.dir/HTMLGen.cc.o: goo/gtypes.h +xpdf/CMakeFiles/pdftohtml.dir/HTMLGen.cc.o: splash/SplashBitmap.h +xpdf/CMakeFiles/pdftohtml.dir/HTMLGen.cc.o: splash/SplashTypes.h + +xpdf/CMakeFiles/pdftohtml.dir/ShadingImage.cc.o: xpdf/Array.h +xpdf/CMakeFiles/pdftohtml.dir/ShadingImage.cc.o: xpdf/Dict.h +xpdf/CMakeFiles/pdftohtml.dir/ShadingImage.cc.o: xpdf/Function.h +xpdf/CMakeFiles/pdftohtml.dir/ShadingImage.cc.o: xpdf/GfxState.h +xpdf/CMakeFiles/pdftohtml.dir/ShadingImage.cc.o: xpdf/Object.h +xpdf/CMakeFiles/pdftohtml.dir/ShadingImage.cc.o: xpdf/ShadingImage.cc +xpdf/CMakeFiles/pdftohtml.dir/ShadingImage.cc.o: xpdf/ShadingImage.h +xpdf/CMakeFiles/pdftohtml.dir/ShadingImage.cc.o: xpdf/Stream.h +xpdf/CMakeFiles/pdftohtml.dir/ShadingImage.cc.o: aconf.h +xpdf/CMakeFiles/pdftohtml.dir/ShadingImage.cc.o: aconf2.h +xpdf/CMakeFiles/pdftohtml.dir/ShadingImage.cc.o: goo/FixedPoint.h +xpdf/CMakeFiles/pdftohtml.dir/ShadingImage.cc.o: goo/GMutex.h +xpdf/CMakeFiles/pdftohtml.dir/ShadingImage.cc.o: goo/GString.h +xpdf/CMakeFiles/pdftohtml.dir/ShadingImage.cc.o: goo/Trace.h +xpdf/CMakeFiles/pdftohtml.dir/ShadingImage.cc.o: goo/gfile.h +xpdf/CMakeFiles/pdftohtml.dir/ShadingImage.cc.o: goo/gmem.h +xpdf/CMakeFiles/pdftohtml.dir/ShadingImage.cc.o: goo/gtypes.h +xpdf/CMakeFiles/pdftohtml.dir/ShadingImage.cc.o: splash/Splash.h +xpdf/CMakeFiles/pdftohtml.dir/ShadingImage.cc.o: splash/SplashBitmap.h +xpdf/CMakeFiles/pdftohtml.dir/ShadingImage.cc.o: splash/SplashClip.h +xpdf/CMakeFiles/pdftohtml.dir/ShadingImage.cc.o: splash/SplashMath.h +xpdf/CMakeFiles/pdftohtml.dir/ShadingImage.cc.o: splash/SplashPath.h +xpdf/CMakeFiles/pdftohtml.dir/ShadingImage.cc.o: splash/SplashPattern.h +xpdf/CMakeFiles/pdftohtml.dir/ShadingImage.cc.o: splash/SplashTypes.h + +xpdf/CMakeFiles/pdftohtml.dir/SplashOutputDev.cc.o: xpdf/Array.h +xpdf/CMakeFiles/pdftohtml.dir/SplashOutputDev.cc.o: xpdf/BuiltinFont.h +xpdf/CMakeFiles/pdftohtml.dir/SplashOutputDev.cc.o: xpdf/BuiltinFontTables.h +xpdf/CMakeFiles/pdftohtml.dir/SplashOutputDev.cc.o: xpdf/CharCodeToUnicode.h +xpdf/CMakeFiles/pdftohtml.dir/SplashOutputDev.cc.o: xpdf/CharTypes.h +xpdf/CMakeFiles/pdftohtml.dir/SplashOutputDev.cc.o: xpdf/Dict.h +xpdf/CMakeFiles/pdftohtml.dir/SplashOutputDev.cc.o: xpdf/Error.h +xpdf/CMakeFiles/pdftohtml.dir/SplashOutputDev.cc.o: xpdf/FontEncodingTables.h +xpdf/CMakeFiles/pdftohtml.dir/SplashOutputDev.cc.o: xpdf/Function.h +xpdf/CMakeFiles/pdftohtml.dir/SplashOutputDev.cc.o: xpdf/Gfx.h +xpdf/CMakeFiles/pdftohtml.dir/SplashOutputDev.cc.o: xpdf/GfxFont.h +xpdf/CMakeFiles/pdftohtml.dir/SplashOutputDev.cc.o: xpdf/GfxState.h +xpdf/CMakeFiles/pdftohtml.dir/SplashOutputDev.cc.o: xpdf/GlobalParams.h +xpdf/CMakeFiles/pdftohtml.dir/SplashOutputDev.cc.o: xpdf/JPXStream.h +xpdf/CMakeFiles/pdftohtml.dir/SplashOutputDev.cc.o: xpdf/Link.h +xpdf/CMakeFiles/pdftohtml.dir/SplashOutputDev.cc.o: xpdf/Object.h +xpdf/CMakeFiles/pdftohtml.dir/SplashOutputDev.cc.o: xpdf/OutputDev.h +xpdf/CMakeFiles/pdftohtml.dir/SplashOutputDev.cc.o: xpdf/ShadingImage.h +xpdf/CMakeFiles/pdftohtml.dir/SplashOutputDev.cc.o: xpdf/SplashOutputDev.cc +xpdf/CMakeFiles/pdftohtml.dir/SplashOutputDev.cc.o: xpdf/SplashOutputDev.h +xpdf/CMakeFiles/pdftohtml.dir/SplashOutputDev.cc.o: xpdf/Stream.h +xpdf/CMakeFiles/pdftohtml.dir/SplashOutputDev.cc.o: xpdf/config.h +xpdf/CMakeFiles/pdftohtml.dir/SplashOutputDev.cc.o: aconf.h +xpdf/CMakeFiles/pdftohtml.dir/SplashOutputDev.cc.o: aconf2.h +xpdf/CMakeFiles/pdftohtml.dir/SplashOutputDev.cc.o: fofi/FoFiBase.h +xpdf/CMakeFiles/pdftohtml.dir/SplashOutputDev.cc.o: fofi/FoFiTrueType.h +xpdf/CMakeFiles/pdftohtml.dir/SplashOutputDev.cc.o: fofi/FoFiType1C.h +xpdf/CMakeFiles/pdftohtml.dir/SplashOutputDev.cc.o: goo/FixedPoint.h +xpdf/CMakeFiles/pdftohtml.dir/SplashOutputDev.cc.o: goo/GMutex.h +xpdf/CMakeFiles/pdftohtml.dir/SplashOutputDev.cc.o: goo/GString.h +xpdf/CMakeFiles/pdftohtml.dir/SplashOutputDev.cc.o: goo/Trace.h +xpdf/CMakeFiles/pdftohtml.dir/SplashOutputDev.cc.o: goo/gfile.h +xpdf/CMakeFiles/pdftohtml.dir/SplashOutputDev.cc.o: goo/gmem.h +xpdf/CMakeFiles/pdftohtml.dir/SplashOutputDev.cc.o: goo/gmempp.h +xpdf/CMakeFiles/pdftohtml.dir/SplashOutputDev.cc.o: goo/gtypes.h +xpdf/CMakeFiles/pdftohtml.dir/SplashOutputDev.cc.o: splash/Splash.h +xpdf/CMakeFiles/pdftohtml.dir/SplashOutputDev.cc.o: splash/SplashBitmap.h +xpdf/CMakeFiles/pdftohtml.dir/SplashOutputDev.cc.o: splash/SplashClip.h +xpdf/CMakeFiles/pdftohtml.dir/SplashOutputDev.cc.o: splash/SplashErrorCodes.h +xpdf/CMakeFiles/pdftohtml.dir/SplashOutputDev.cc.o: splash/SplashFont.h +xpdf/CMakeFiles/pdftohtml.dir/SplashOutputDev.cc.o: splash/SplashFontEngine.h +xpdf/CMakeFiles/pdftohtml.dir/SplashOutputDev.cc.o: splash/SplashFontFile.h +xpdf/CMakeFiles/pdftohtml.dir/SplashOutputDev.cc.o: splash/SplashFontFileID.h +xpdf/CMakeFiles/pdftohtml.dir/SplashOutputDev.cc.o: splash/SplashGlyphBitmap.h +xpdf/CMakeFiles/pdftohtml.dir/SplashOutputDev.cc.o: splash/SplashMath.h +xpdf/CMakeFiles/pdftohtml.dir/SplashOutputDev.cc.o: splash/SplashPath.h +xpdf/CMakeFiles/pdftohtml.dir/SplashOutputDev.cc.o: splash/SplashPattern.h +xpdf/CMakeFiles/pdftohtml.dir/SplashOutputDev.cc.o: splash/SplashScreen.h +xpdf/CMakeFiles/pdftohtml.dir/SplashOutputDev.cc.o: splash/SplashState.h +xpdf/CMakeFiles/pdftohtml.dir/SplashOutputDev.cc.o: splash/SplashTypes.h + +xpdf/CMakeFiles/pdftohtml.dir/TextOutputDev.cc.o: xpdf/Array.h +xpdf/CMakeFiles/pdftohtml.dir/TextOutputDev.cc.o: xpdf/CharTypes.h +xpdf/CMakeFiles/pdftohtml.dir/TextOutputDev.cc.o: xpdf/Dict.h +xpdf/CMakeFiles/pdftohtml.dir/TextOutputDev.cc.o: xpdf/Error.h +xpdf/CMakeFiles/pdftohtml.dir/TextOutputDev.cc.o: xpdf/Function.h +xpdf/CMakeFiles/pdftohtml.dir/TextOutputDev.cc.o: xpdf/GfxFont.h +xpdf/CMakeFiles/pdftohtml.dir/TextOutputDev.cc.o: xpdf/GfxState.h +xpdf/CMakeFiles/pdftohtml.dir/TextOutputDev.cc.o: xpdf/GlobalParams.h +xpdf/CMakeFiles/pdftohtml.dir/TextOutputDev.cc.o: xpdf/Link.h +xpdf/CMakeFiles/pdftohtml.dir/TextOutputDev.cc.o: xpdf/Object.h +xpdf/CMakeFiles/pdftohtml.dir/TextOutputDev.cc.o: xpdf/OutputDev.h +xpdf/CMakeFiles/pdftohtml.dir/TextOutputDev.cc.o: xpdf/Stream.h +xpdf/CMakeFiles/pdftohtml.dir/TextOutputDev.cc.o: xpdf/TextOutputDev.cc +xpdf/CMakeFiles/pdftohtml.dir/TextOutputDev.cc.o: xpdf/TextOutputDev.h +xpdf/CMakeFiles/pdftohtml.dir/TextOutputDev.cc.o: xpdf/UnicodeMap.h +xpdf/CMakeFiles/pdftohtml.dir/TextOutputDev.cc.o: xpdf/UnicodeRemapping.h +xpdf/CMakeFiles/pdftohtml.dir/TextOutputDev.cc.o: xpdf/UnicodeTypeTable.h +xpdf/CMakeFiles/pdftohtml.dir/TextOutputDev.cc.o: xpdf/config.h +xpdf/CMakeFiles/pdftohtml.dir/TextOutputDev.cc.o: aconf.h +xpdf/CMakeFiles/pdftohtml.dir/TextOutputDev.cc.o: aconf2.h +xpdf/CMakeFiles/pdftohtml.dir/TextOutputDev.cc.o: goo/GList.h +xpdf/CMakeFiles/pdftohtml.dir/TextOutputDev.cc.o: goo/GMutex.h +xpdf/CMakeFiles/pdftohtml.dir/TextOutputDev.cc.o: goo/GString.h +xpdf/CMakeFiles/pdftohtml.dir/TextOutputDev.cc.o: goo/gfile.h +xpdf/CMakeFiles/pdftohtml.dir/TextOutputDev.cc.o: goo/gmem.h +xpdf/CMakeFiles/pdftohtml.dir/TextOutputDev.cc.o: goo/gmempp.h +xpdf/CMakeFiles/pdftohtml.dir/TextOutputDev.cc.o: goo/gtypes.h + +xpdf/CMakeFiles/pdftohtml.dir/WebFont.cc.o: xpdf/Array.h +xpdf/CMakeFiles/pdftohtml.dir/WebFont.cc.o: xpdf/CharCodeToUnicode.h +xpdf/CMakeFiles/pdftohtml.dir/WebFont.cc.o: xpdf/CharTypes.h +xpdf/CMakeFiles/pdftohtml.dir/WebFont.cc.o: xpdf/Dict.h +xpdf/CMakeFiles/pdftohtml.dir/WebFont.cc.o: xpdf/GfxFont.h +xpdf/CMakeFiles/pdftohtml.dir/WebFont.cc.o: xpdf/Object.h +xpdf/CMakeFiles/pdftohtml.dir/WebFont.cc.o: xpdf/Stream.h +xpdf/CMakeFiles/pdftohtml.dir/WebFont.cc.o: xpdf/WebFont.cc +xpdf/CMakeFiles/pdftohtml.dir/WebFont.cc.o: xpdf/WebFont.h +xpdf/CMakeFiles/pdftohtml.dir/WebFont.cc.o: aconf.h +xpdf/CMakeFiles/pdftohtml.dir/WebFont.cc.o: aconf2.h +xpdf/CMakeFiles/pdftohtml.dir/WebFont.cc.o: fofi/FoFiBase.h +xpdf/CMakeFiles/pdftohtml.dir/WebFont.cc.o: fofi/FoFiTrueType.h +xpdf/CMakeFiles/pdftohtml.dir/WebFont.cc.o: fofi/FoFiType1C.h +xpdf/CMakeFiles/pdftohtml.dir/WebFont.cc.o: goo/GHash.h +xpdf/CMakeFiles/pdftohtml.dir/WebFont.cc.o: goo/GMutex.h +xpdf/CMakeFiles/pdftohtml.dir/WebFont.cc.o: goo/GString.h +xpdf/CMakeFiles/pdftohtml.dir/WebFont.cc.o: goo/gfile.h +xpdf/CMakeFiles/pdftohtml.dir/WebFont.cc.o: goo/gmem.h +xpdf/CMakeFiles/pdftohtml.dir/WebFont.cc.o: goo/gmempp.h +xpdf/CMakeFiles/pdftohtml.dir/WebFont.cc.o: goo/gtypes.h + +xpdf/CMakeFiles/pdftohtml.dir/pdftohtml.cc.o: xpdf/Array.h +xpdf/CMakeFiles/pdftohtml.dir/pdftohtml.cc.o: xpdf/Catalog.h +xpdf/CMakeFiles/pdftohtml.dir/pdftohtml.cc.o: xpdf/CharTypes.h +xpdf/CMakeFiles/pdftohtml.dir/pdftohtml.cc.o: xpdf/Dict.h +xpdf/CMakeFiles/pdftohtml.dir/pdftohtml.cc.o: xpdf/Error.h +xpdf/CMakeFiles/pdftohtml.dir/pdftohtml.cc.o: xpdf/ErrorCodes.h +xpdf/CMakeFiles/pdftohtml.dir/pdftohtml.cc.o: xpdf/GlobalParams.h +xpdf/CMakeFiles/pdftohtml.dir/pdftohtml.cc.o: xpdf/HTMLGen.h +xpdf/CMakeFiles/pdftohtml.dir/pdftohtml.cc.o: xpdf/Object.h +xpdf/CMakeFiles/pdftohtml.dir/pdftohtml.cc.o: xpdf/PDFDoc.h +xpdf/CMakeFiles/pdftohtml.dir/pdftohtml.cc.o: xpdf/Page.h +xpdf/CMakeFiles/pdftohtml.dir/pdftohtml.cc.o: xpdf/Stream.h +xpdf/CMakeFiles/pdftohtml.dir/pdftohtml.cc.o: xpdf/XRef.h +xpdf/CMakeFiles/pdftohtml.dir/pdftohtml.cc.o: xpdf/config.h +xpdf/CMakeFiles/pdftohtml.dir/pdftohtml.cc.o: xpdf/pdftohtml.cc +xpdf/CMakeFiles/pdftohtml.dir/pdftohtml.cc.o: aconf.h +xpdf/CMakeFiles/pdftohtml.dir/pdftohtml.cc.o: aconf2.h +xpdf/CMakeFiles/pdftohtml.dir/pdftohtml.cc.o: goo/GMutex.h +xpdf/CMakeFiles/pdftohtml.dir/pdftohtml.cc.o: goo/GString.h +xpdf/CMakeFiles/pdftohtml.dir/pdftohtml.cc.o: goo/gfile.h +xpdf/CMakeFiles/pdftohtml.dir/pdftohtml.cc.o: goo/gmem.h +xpdf/CMakeFiles/pdftohtml.dir/pdftohtml.cc.o: goo/gmempp.h +xpdf/CMakeFiles/pdftohtml.dir/pdftohtml.cc.o: goo/gtypes.h +xpdf/CMakeFiles/pdftohtml.dir/pdftohtml.cc.o: goo/parseargs.h + diff --git a/xpdf/CMakeFiles/pdftohtml.dir/flags.make b/xpdf/CMakeFiles/pdftohtml.dir/flags.make new file mode 100644 index 0000000..300fa3e --- /dev/null +++ b/xpdf/CMakeFiles/pdftohtml.dir/flags.make @@ -0,0 +1,10 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +# compile CXX with /usr/bin/c++ +CXX_DEFINES = + +CXX_INCLUDES = -I/home/calvin/src/xpdf-4.04 -I/home/calvin/src/xpdf-4.04/goo -I/home/calvin/src/xpdf-4.04/fofi -I/home/calvin/src/xpdf-4.04/splash + +CXX_FLAGS = + diff --git a/xpdf/CMakeFiles/pdftohtml.dir/link.txt b/xpdf/CMakeFiles/pdftohtml.dir/link.txt new file mode 100644 index 0000000..f2d088c --- /dev/null +++ b/xpdf/CMakeFiles/pdftohtml.dir/link.txt @@ -0,0 +1 @@ +/usr/bin/c++ -rdynamic CMakeFiles/pdftohtml.dir/HTMLGen.cc.o CMakeFiles/pdftohtml.dir/ShadingImage.cc.o CMakeFiles/pdftohtml.dir/SplashOutputDev.cc.o CMakeFiles/pdftohtml.dir/TextOutputDev.cc.o CMakeFiles/pdftohtml.dir/WebFont.cc.o CMakeFiles/pdftohtml.dir/pdftohtml.cc.o CMakeFiles/xpdf_objs.dir/AcroForm.cc.o CMakeFiles/xpdf_objs.dir/Annot.cc.o CMakeFiles/xpdf_objs.dir/Array.cc.o CMakeFiles/xpdf_objs.dir/BuiltinFont.cc.o CMakeFiles/xpdf_objs.dir/BuiltinFontTables.cc.o CMakeFiles/xpdf_objs.dir/Catalog.cc.o CMakeFiles/xpdf_objs.dir/CharCodeToUnicode.cc.o CMakeFiles/xpdf_objs.dir/CMap.cc.o CMakeFiles/xpdf_objs.dir/Decrypt.cc.o CMakeFiles/xpdf_objs.dir/Dict.cc.o CMakeFiles/xpdf_objs.dir/Error.cc.o CMakeFiles/xpdf_objs.dir/FontEncodingTables.cc.o CMakeFiles/xpdf_objs.dir/Function.cc.o CMakeFiles/xpdf_objs.dir/Gfx.cc.o CMakeFiles/xpdf_objs.dir/GfxFont.cc.o CMakeFiles/xpdf_objs.dir/GfxState.cc.o CMakeFiles/xpdf_objs.dir/GlobalParams.cc.o CMakeFiles/xpdf_objs.dir/JArithmeticDecoder.cc.o CMakeFiles/xpdf_objs.dir/JBIG2Stream.cc.o CMakeFiles/xpdf_objs.dir/JPXStream.cc.o CMakeFiles/xpdf_objs.dir/Lexer.cc.o CMakeFiles/xpdf_objs.dir/Link.cc.o CMakeFiles/xpdf_objs.dir/NameToCharCode.cc.o CMakeFiles/xpdf_objs.dir/Object.cc.o CMakeFiles/xpdf_objs.dir/OptionalContent.cc.o CMakeFiles/xpdf_objs.dir/Outline.cc.o CMakeFiles/xpdf_objs.dir/OutputDev.cc.o CMakeFiles/xpdf_objs.dir/Page.cc.o CMakeFiles/xpdf_objs.dir/Parser.cc.o CMakeFiles/xpdf_objs.dir/PDF417Barcode.cc.o CMakeFiles/xpdf_objs.dir/PDFDoc.cc.o CMakeFiles/xpdf_objs.dir/PDFDocEncoding.cc.o CMakeFiles/xpdf_objs.dir/PSTokenizer.cc.o CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.o CMakeFiles/xpdf_objs.dir/Stream.cc.o CMakeFiles/xpdf_objs.dir/TextString.cc.o CMakeFiles/xpdf_objs.dir/UnicodeMap.cc.o CMakeFiles/xpdf_objs.dir/UnicodeRemapping.cc.o CMakeFiles/xpdf_objs.dir/UnicodeTypeTable.cc.o CMakeFiles/xpdf_objs.dir/UTF8.cc.o CMakeFiles/xpdf_objs.dir/XFAScanner.cc.o CMakeFiles/xpdf_objs.dir/XRef.cc.o CMakeFiles/xpdf_objs.dir/Zoox.cc.o -o pdftohtml ../goo/libgoo.a ../fofi/libfofi.a ../splash/libsplash.a -lfreetype -lpng -lz -lfontconfig -lpthread diff --git a/xpdf/CMakeFiles/pdftohtml.dir/pdftohtml.cc.o b/xpdf/CMakeFiles/pdftohtml.dir/pdftohtml.cc.o new file mode 100644 index 0000000..93e8a74 Binary files /dev/null and b/xpdf/CMakeFiles/pdftohtml.dir/pdftohtml.cc.o differ diff --git a/xpdf/CMakeFiles/pdftohtml.dir/progress.make b/xpdf/CMakeFiles/pdftohtml.dir/progress.make new file mode 100644 index 0000000..58b10d2 --- /dev/null +++ b/xpdf/CMakeFiles/pdftohtml.dir/progress.make @@ -0,0 +1,8 @@ +CMAKE_PROGRESS_1 = 20 +CMAKE_PROGRESS_2 = +CMAKE_PROGRESS_3 = 21 +CMAKE_PROGRESS_4 = 22 +CMAKE_PROGRESS_5 = +CMAKE_PROGRESS_6 = 23 +CMAKE_PROGRESS_7 = 24 + diff --git a/xpdf/CMakeFiles/pdftopng.dir/CXX.includecache b/xpdf/CMakeFiles/pdftopng.dir/CXX.includecache new file mode 100644 index 0000000..687b577 --- /dev/null +++ b/xpdf/CMakeFiles/pdftopng.dir/CXX.includecache @@ -0,0 +1,580 @@ +#IncludeRegexLine: ^[ ]*[#%][ ]*(include|import)[ ]*[<"]([^">]+)([">]) + +#IncludeRegexScan: ^.*$ + +#IncludeRegexComplain: ^$ + +#IncludeRegexTransform: + +/home/calvin/src/xpdf-4.04/xpdf/Array.h +aconf.h +- +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h + +/home/calvin/src/xpdf-4.04/xpdf/BuiltinFont.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h + +/home/calvin/src/xpdf-4.04/xpdf/BuiltinFontTables.h +BuiltinFont.h +/home/calvin/src/xpdf-4.04/xpdf/BuiltinFont.h + +/home/calvin/src/xpdf-4.04/xpdf/Catalog.h +aconf.h +- +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h +CharTypes.h +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + +/home/calvin/src/xpdf-4.04/xpdf/CharCodeToUnicode.h +aconf.h +- +CharTypes.h +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h + +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + +/home/calvin/src/xpdf-4.04/xpdf/Dict.h +aconf.h +- +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h + +/home/calvin/src/xpdf-4.04/xpdf/Error.h +aconf.h +- +stdio.h +- +config.h +/home/calvin/src/xpdf-4.04/xpdf/config.h +gfile.h +/home/calvin/src/xpdf-4.04/xpdf/gfile.h + +/home/calvin/src/xpdf-4.04/xpdf/FontEncodingTables.h + +/home/calvin/src/xpdf-4.04/xpdf/Function.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h + +/home/calvin/src/xpdf-4.04/xpdf/Gfx.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +gfile.h +/home/calvin/src/xpdf-4.04/xpdf/gfile.h +GfxState.h +/home/calvin/src/xpdf-4.04/xpdf/GfxState.h + +/home/calvin/src/xpdf-4.04/xpdf/GfxFont.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +GString.h +/home/calvin/src/xpdf-4.04/xpdf/GString.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h +CharTypes.h +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + +/home/calvin/src/xpdf-4.04/xpdf/GfxState.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h +Function.h +/home/calvin/src/xpdf-4.04/xpdf/Function.h + +/home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h +aconf.h +- +stdio.h +- +windows.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +CharTypes.h +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h + +/home/calvin/src/xpdf-4.04/xpdf/JPXStream.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h +Stream.h +/home/calvin/src/xpdf-4.04/xpdf/Stream.h + +/home/calvin/src/xpdf-4.04/xpdf/Link.h +aconf.h +- +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h + +/home/calvin/src/xpdf-4.04/xpdf/Object.h +aconf.h +- +stdio.h +- +string.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +gmem.h +/home/calvin/src/xpdf-4.04/xpdf/gmem.h +gfile.h +/home/calvin/src/xpdf-4.04/xpdf/gfile.h +GString.h +/home/calvin/src/xpdf-4.04/xpdf/GString.h +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h +Array.h +/home/calvin/src/xpdf-4.04/xpdf/Array.h +Dict.h +/home/calvin/src/xpdf-4.04/xpdf/Dict.h +Stream.h +/home/calvin/src/xpdf-4.04/xpdf/Stream.h + +/home/calvin/src/xpdf-4.04/xpdf/OutputDev.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +CharTypes.h +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + +/home/calvin/src/xpdf-4.04/xpdf/PDFDoc.h +aconf.h +- +stdio.h +- +XRef.h +/home/calvin/src/xpdf-4.04/xpdf/XRef.h +Catalog.h +/home/calvin/src/xpdf-4.04/xpdf/Catalog.h +Page.h +/home/calvin/src/xpdf-4.04/xpdf/Page.h + +/home/calvin/src/xpdf-4.04/xpdf/Page.h +aconf.h +- +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h + +/home/calvin/src/xpdf-4.04/xpdf/ShadingImage.cc +aconf.h +- +math.h +- +Trace.h +/home/calvin/src/xpdf-4.04/xpdf/Trace.h +GfxState.h +/home/calvin/src/xpdf-4.04/xpdf/GfxState.h +SplashBitmap.h +/home/calvin/src/xpdf-4.04/xpdf/SplashBitmap.h +SplashPattern.h +/home/calvin/src/xpdf-4.04/xpdf/SplashPattern.h +SplashPath.h +/home/calvin/src/xpdf-4.04/xpdf/SplashPath.h +Splash.h +/home/calvin/src/xpdf-4.04/xpdf/Splash.h +ShadingImage.h +/home/calvin/src/xpdf-4.04/xpdf/ShadingImage.h + +/home/calvin/src/xpdf-4.04/xpdf/ShadingImage.h +aconf.h +- +SplashTypes.h +/home/calvin/src/xpdf-4.04/xpdf/SplashTypes.h + +/home/calvin/src/xpdf-4.04/xpdf/SplashOutputDev.cc +aconf.h +- +string.h +- +math.h +- +limits.h +- +gmempp.h +/home/calvin/src/xpdf-4.04/xpdf/gmempp.h +gfile.h +/home/calvin/src/xpdf-4.04/xpdf/gfile.h +Trace.h +/home/calvin/src/xpdf-4.04/xpdf/Trace.h +GlobalParams.h +/home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h +Error.h +/home/calvin/src/xpdf-4.04/xpdf/Error.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h +Gfx.h +/home/calvin/src/xpdf-4.04/xpdf/Gfx.h +GfxFont.h +/home/calvin/src/xpdf-4.04/xpdf/GfxFont.h +ShadingImage.h +/home/calvin/src/xpdf-4.04/xpdf/ShadingImage.h +Link.h +/home/calvin/src/xpdf-4.04/xpdf/Link.h +CharCodeToUnicode.h +/home/calvin/src/xpdf-4.04/xpdf/CharCodeToUnicode.h +FontEncodingTables.h +/home/calvin/src/xpdf-4.04/xpdf/FontEncodingTables.h +BuiltinFont.h +/home/calvin/src/xpdf-4.04/xpdf/BuiltinFont.h +BuiltinFontTables.h +/home/calvin/src/xpdf-4.04/xpdf/BuiltinFontTables.h +FoFiTrueType.h +/home/calvin/src/xpdf-4.04/xpdf/FoFiTrueType.h +FoFiType1C.h +/home/calvin/src/xpdf-4.04/xpdf/FoFiType1C.h +JPXStream.h +/home/calvin/src/xpdf-4.04/xpdf/JPXStream.h +SplashBitmap.h +/home/calvin/src/xpdf-4.04/xpdf/SplashBitmap.h +SplashGlyphBitmap.h +/home/calvin/src/xpdf-4.04/xpdf/SplashGlyphBitmap.h +SplashPattern.h +/home/calvin/src/xpdf-4.04/xpdf/SplashPattern.h +SplashScreen.h +/home/calvin/src/xpdf-4.04/xpdf/SplashScreen.h +SplashPath.h +/home/calvin/src/xpdf-4.04/xpdf/SplashPath.h +SplashState.h +/home/calvin/src/xpdf-4.04/xpdf/SplashState.h +SplashErrorCodes.h +/home/calvin/src/xpdf-4.04/xpdf/SplashErrorCodes.h +SplashFontEngine.h +/home/calvin/src/xpdf-4.04/xpdf/SplashFontEngine.h +SplashFont.h +/home/calvin/src/xpdf-4.04/xpdf/SplashFont.h +SplashFontFile.h +/home/calvin/src/xpdf-4.04/xpdf/SplashFontFile.h +SplashFontFileID.h +/home/calvin/src/xpdf-4.04/xpdf/SplashFontFileID.h +Splash.h +/home/calvin/src/xpdf-4.04/xpdf/Splash.h +SplashOutputDev.h +/home/calvin/src/xpdf-4.04/xpdf/SplashOutputDev.h + +/home/calvin/src/xpdf-4.04/xpdf/SplashOutputDev.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +SplashTypes.h +/home/calvin/src/xpdf-4.04/xpdf/SplashTypes.h +config.h +/home/calvin/src/xpdf-4.04/xpdf/config.h +OutputDev.h +/home/calvin/src/xpdf-4.04/xpdf/OutputDev.h +GfxState.h +/home/calvin/src/xpdf-4.04/xpdf/GfxState.h + +/home/calvin/src/xpdf-4.04/xpdf/Stream.h +aconf.h +- +stdio.h +- +jpeglib.h +- +setjmp.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +gfile.h +/home/calvin/src/xpdf-4.04/xpdf/gfile.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h + +/home/calvin/src/xpdf-4.04/xpdf/XRef.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +gfile.h +/home/calvin/src/xpdf-4.04/xpdf/gfile.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h + +/home/calvin/src/xpdf-4.04/xpdf/config.h + +/home/calvin/src/xpdf-4.04/xpdf/pdftopng.cc +aconf.h +- +stdlib.h +- +stdio.h +- +png.h +- +io.h +- +fcntl.h +- +gmem.h +/home/calvin/src/xpdf-4.04/xpdf/gmem.h +gmempp.h +/home/calvin/src/xpdf-4.04/xpdf/gmempp.h +parseargs.h +/home/calvin/src/xpdf-4.04/xpdf/parseargs.h +GString.h +/home/calvin/src/xpdf-4.04/xpdf/GString.h +gfile.h +/home/calvin/src/xpdf-4.04/xpdf/gfile.h +GlobalParams.h +/home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h +PDFDoc.h +/home/calvin/src/xpdf-4.04/xpdf/PDFDoc.h +SplashBitmap.h +/home/calvin/src/xpdf-4.04/xpdf/SplashBitmap.h +Splash.h +/home/calvin/src/xpdf-4.04/xpdf/Splash.h +SplashOutputDev.h +/home/calvin/src/xpdf-4.04/xpdf/SplashOutputDev.h +Error.h +/home/calvin/src/xpdf-4.04/xpdf/Error.h +config.h +/home/calvin/src/xpdf-4.04/xpdf/config.h + +aconf.h +aconf2.h +- + +aconf2.h +AvailabilityMacros.h +- + +fofi/FoFiBase.h +aconf.h +- +gtypes.h +fofi/gtypes.h + +fofi/FoFiTrueType.h +aconf.h +- +gtypes.h +fofi/gtypes.h +FoFiBase.h +fofi/FoFiBase.h + +fofi/FoFiType1C.h +aconf.h +- +gtypes.h +fofi/gtypes.h +FoFiBase.h +fofi/FoFiBase.h + +goo/FixedPoint.h +aconf.h +- +stdio.h +- +stdlib.h +- +gtypes.h +goo/gtypes.h + +goo/GMutex.h +aconf.h +- +windows.h +- +intrin.h +- +pthread.h +- + +goo/GString.h +aconf.h +- +limits.h +- +stdarg.h +- +gtypes.h +goo/gtypes.h + +goo/Trace.h +aconf.h +- + +goo/gfile.h +aconf.h +- +stdio.h +- +stdlib.h +- +stddef.h +- +sys/stat.h +- +win32lib.h +- +windows.h +- +unistd.h +- +sys/types.h +- +gtypes.h +goo/gtypes.h + +goo/gmem.h +stdio.h +- +aconf.h +- + +goo/gmempp.h +stdlib.h +- + +goo/gtypes.h + +goo/parseargs.h +gtypes.h +goo/gtypes.h + +splash/Splash.h +aconf.h +- +SplashTypes.h +splash/SplashTypes.h +SplashClip.h +splash/SplashClip.h + +splash/SplashBitmap.h +aconf.h +- +stdio.h +- +limits.h +- +stdint.h +- +SplashTypes.h +splash/SplashTypes.h + +splash/SplashClip.h +aconf.h +- +SplashTypes.h +splash/SplashTypes.h +SplashMath.h +splash/SplashMath.h + +splash/SplashErrorCodes.h +aconf.h +- + +splash/SplashFont.h +aconf.h +- +gtypes.h +splash/gtypes.h +SplashTypes.h +splash/SplashTypes.h +SplashMath.h +splash/SplashMath.h + +splash/SplashFontEngine.h +aconf.h +- +gtypes.h +splash/gtypes.h + +splash/SplashFontFile.h +aconf.h +- +gtypes.h +splash/gtypes.h +SplashTypes.h +splash/SplashTypes.h +GMutex.h +splash/GMutex.h + +splash/SplashFontFileID.h +aconf.h +- +gtypes.h +splash/gtypes.h + +splash/SplashGlyphBitmap.h +aconf.h +- +gtypes.h +splash/gtypes.h + +splash/SplashMath.h +aconf.h +- +FixedPoint.h +splash/FixedPoint.h +math.h +- +emmintrin.h +- +SplashTypes.h +splash/SplashTypes.h + +splash/SplashPath.h +aconf.h +- +SplashTypes.h +splash/SplashTypes.h + +splash/SplashPattern.h +aconf.h +- +SplashTypes.h +splash/SplashTypes.h + +splash/SplashScreen.h +aconf.h +- +SplashTypes.h +splash/SplashTypes.h + +splash/SplashState.h +aconf.h +- +SplashTypes.h +splash/SplashTypes.h + +splash/SplashTypes.h +aconf.h +- +gtypes.h +splash/gtypes.h +FixedPoint.h +splash/FixedPoint.h + diff --git a/xpdf/CMakeFiles/pdftopng.dir/DependInfo.cmake b/xpdf/CMakeFiles/pdftopng.dir/DependInfo.cmake new file mode 100644 index 0000000..a453451 --- /dev/null +++ b/xpdf/CMakeFiles/pdftopng.dir/DependInfo.cmake @@ -0,0 +1,29 @@ +# The set of languages for which implicit dependencies are needed: +set(CMAKE_DEPENDS_LANGUAGES + "CXX" + ) +# The set of files for implicit dependencies of each language: +set(CMAKE_DEPENDS_CHECK_CXX + "/home/calvin/src/xpdf-4.04/xpdf/ShadingImage.cc" "/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/pdftopng.dir/ShadingImage.cc.o" + "/home/calvin/src/xpdf-4.04/xpdf/SplashOutputDev.cc" "/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/pdftopng.dir/SplashOutputDev.cc.o" + "/home/calvin/src/xpdf-4.04/xpdf/pdftopng.cc" "/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/pdftopng.dir/pdftopng.cc.o" + ) +set(CMAKE_CXX_COMPILER_ID "GNU") + +# The include file search paths: +set(CMAKE_CXX_TARGET_INCLUDE_PATH + "." + "goo" + "fofi" + "splash" + ) + +# Targets to which this target links. +set(CMAKE_TARGET_LINKED_INFO_FILES + "/home/calvin/src/xpdf-4.04/goo/CMakeFiles/goo.dir/DependInfo.cmake" + "/home/calvin/src/xpdf-4.04/fofi/CMakeFiles/fofi.dir/DependInfo.cmake" + "/home/calvin/src/xpdf-4.04/splash/CMakeFiles/splash.dir/DependInfo.cmake" + ) + +# Fortran module output directory. +set(CMAKE_Fortran_TARGET_MODULE_DIR "") diff --git a/xpdf/CMakeFiles/pdftopng.dir/ShadingImage.cc.o b/xpdf/CMakeFiles/pdftopng.dir/ShadingImage.cc.o new file mode 100644 index 0000000..d53401f Binary files /dev/null and b/xpdf/CMakeFiles/pdftopng.dir/ShadingImage.cc.o differ diff --git a/xpdf/CMakeFiles/pdftopng.dir/SplashOutputDev.cc.o b/xpdf/CMakeFiles/pdftopng.dir/SplashOutputDev.cc.o new file mode 100644 index 0000000..7fdcd23 Binary files /dev/null and b/xpdf/CMakeFiles/pdftopng.dir/SplashOutputDev.cc.o differ diff --git a/xpdf/CMakeFiles/pdftopng.dir/build.make b/xpdf/CMakeFiles/pdftopng.dir/build.make new file mode 100644 index 0000000..f1b4caa --- /dev/null +++ b/xpdf/CMakeFiles/pdftopng.dir/build.make @@ -0,0 +1,240 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +# Delete rule output on recipe failure. +.DELETE_ON_ERROR: + + +#============================================================================= +# Special targets provided by cmake. + +# Disable implicit rules so canonical targets will work. +.SUFFIXES: + + +# Disable VCS-based implicit rules. +% : %,v + + +# Disable VCS-based implicit rules. +% : RCS/% + + +# Disable VCS-based implicit rules. +% : RCS/%,v + + +# Disable VCS-based implicit rules. +% : SCCS/s.% + + +# Disable VCS-based implicit rules. +% : s.% + + +.SUFFIXES: .hpux_make_needs_suffix_list + + +# Command-line flag to silence nested $(MAKE). +$(VERBOSE)MAKESILENT = -s + +#Suppress display of executed commands. +$(VERBOSE).SILENT: + +# A target that is always out of date. +cmake_force: + +.PHONY : cmake_force + +#============================================================================= +# Set environment variables for the build. + +# The shell in which to execute make rules. +SHELL = /bin/sh + +# The CMake executable. +CMAKE_COMMAND = /usr/bin/cmake + +# The command to remove a file. +RM = /usr/bin/cmake -E rm -f + +# Escaping for special characters. +EQUALS = = + +# The top-level source directory on which CMake was run. +CMAKE_SOURCE_DIR = /home/calvin/src/xpdf-4.04 + +# The top-level build directory on which CMake was run. +CMAKE_BINARY_DIR = /home/calvin/src/xpdf-4.04 + +# Include any dependencies generated for this target. +include xpdf/CMakeFiles/pdftopng.dir/depend.make + +# Include the progress variables for this target. +include xpdf/CMakeFiles/pdftopng.dir/progress.make + +# Include the compile flags for this target's objects. +include xpdf/CMakeFiles/pdftopng.dir/flags.make + +xpdf/CMakeFiles/pdftopng.dir/ShadingImage.cc.o: xpdf/CMakeFiles/pdftopng.dir/flags.make +xpdf/CMakeFiles/pdftopng.dir/ShadingImage.cc.o: xpdf/ShadingImage.cc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_1) "Building CXX object xpdf/CMakeFiles/pdftopng.dir/ShadingImage.cc.o" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/pdftopng.dir/ShadingImage.cc.o -c /home/calvin/src/xpdf-4.04/xpdf/ShadingImage.cc + +xpdf/CMakeFiles/pdftopng.dir/ShadingImage.cc.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/pdftopng.dir/ShadingImage.cc.i" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf/ShadingImage.cc > CMakeFiles/pdftopng.dir/ShadingImage.cc.i + +xpdf/CMakeFiles/pdftopng.dir/ShadingImage.cc.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/pdftopng.dir/ShadingImage.cc.s" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf/ShadingImage.cc -o CMakeFiles/pdftopng.dir/ShadingImage.cc.s + +xpdf/CMakeFiles/pdftopng.dir/SplashOutputDev.cc.o: xpdf/CMakeFiles/pdftopng.dir/flags.make +xpdf/CMakeFiles/pdftopng.dir/SplashOutputDev.cc.o: xpdf/SplashOutputDev.cc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_2) "Building CXX object xpdf/CMakeFiles/pdftopng.dir/SplashOutputDev.cc.o" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/pdftopng.dir/SplashOutputDev.cc.o -c /home/calvin/src/xpdf-4.04/xpdf/SplashOutputDev.cc + +xpdf/CMakeFiles/pdftopng.dir/SplashOutputDev.cc.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/pdftopng.dir/SplashOutputDev.cc.i" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf/SplashOutputDev.cc > CMakeFiles/pdftopng.dir/SplashOutputDev.cc.i + +xpdf/CMakeFiles/pdftopng.dir/SplashOutputDev.cc.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/pdftopng.dir/SplashOutputDev.cc.s" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf/SplashOutputDev.cc -o CMakeFiles/pdftopng.dir/SplashOutputDev.cc.s + +xpdf/CMakeFiles/pdftopng.dir/pdftopng.cc.o: xpdf/CMakeFiles/pdftopng.dir/flags.make +xpdf/CMakeFiles/pdftopng.dir/pdftopng.cc.o: xpdf/pdftopng.cc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_3) "Building CXX object xpdf/CMakeFiles/pdftopng.dir/pdftopng.cc.o" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/pdftopng.dir/pdftopng.cc.o -c /home/calvin/src/xpdf-4.04/xpdf/pdftopng.cc + +xpdf/CMakeFiles/pdftopng.dir/pdftopng.cc.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/pdftopng.dir/pdftopng.cc.i" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf/pdftopng.cc > CMakeFiles/pdftopng.dir/pdftopng.cc.i + +xpdf/CMakeFiles/pdftopng.dir/pdftopng.cc.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/pdftopng.dir/pdftopng.cc.s" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf/pdftopng.cc -o CMakeFiles/pdftopng.dir/pdftopng.cc.s + +# Object files for target pdftopng +pdftopng_OBJECTS = \ +"CMakeFiles/pdftopng.dir/ShadingImage.cc.o" \ +"CMakeFiles/pdftopng.dir/SplashOutputDev.cc.o" \ +"CMakeFiles/pdftopng.dir/pdftopng.cc.o" + +# External object files for target pdftopng +pdftopng_EXTERNAL_OBJECTS = \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/AcroForm.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Annot.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Array.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFont.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFontTables.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Catalog.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/CharCodeToUnicode.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/CMap.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Decrypt.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Dict.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Error.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/FontEncodingTables.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Function.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Gfx.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/GfxFont.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/GfxState.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/GlobalParams.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/JArithmeticDecoder.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/JBIG2Stream.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/JPXStream.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Lexer.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Link.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/NameToCharCode.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Object.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/OptionalContent.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Outline.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/OutputDev.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Page.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Parser.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/PDF417Barcode.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/PDFDoc.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/PDFDocEncoding.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/PSTokenizer.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Stream.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/TextString.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/UnicodeMap.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/UnicodeRemapping.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/UnicodeTypeTable.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/UTF8.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/XFAScanner.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/XRef.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Zoox.cc.o" + +xpdf/pdftopng: xpdf/CMakeFiles/pdftopng.dir/ShadingImage.cc.o +xpdf/pdftopng: xpdf/CMakeFiles/pdftopng.dir/SplashOutputDev.cc.o +xpdf/pdftopng: xpdf/CMakeFiles/pdftopng.dir/pdftopng.cc.o +xpdf/pdftopng: xpdf/CMakeFiles/xpdf_objs.dir/AcroForm.cc.o +xpdf/pdftopng: xpdf/CMakeFiles/xpdf_objs.dir/Annot.cc.o +xpdf/pdftopng: xpdf/CMakeFiles/xpdf_objs.dir/Array.cc.o +xpdf/pdftopng: xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFont.cc.o +xpdf/pdftopng: xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFontTables.cc.o +xpdf/pdftopng: xpdf/CMakeFiles/xpdf_objs.dir/Catalog.cc.o +xpdf/pdftopng: xpdf/CMakeFiles/xpdf_objs.dir/CharCodeToUnicode.cc.o +xpdf/pdftopng: xpdf/CMakeFiles/xpdf_objs.dir/CMap.cc.o +xpdf/pdftopng: xpdf/CMakeFiles/xpdf_objs.dir/Decrypt.cc.o +xpdf/pdftopng: xpdf/CMakeFiles/xpdf_objs.dir/Dict.cc.o +xpdf/pdftopng: xpdf/CMakeFiles/xpdf_objs.dir/Error.cc.o +xpdf/pdftopng: xpdf/CMakeFiles/xpdf_objs.dir/FontEncodingTables.cc.o +xpdf/pdftopng: xpdf/CMakeFiles/xpdf_objs.dir/Function.cc.o +xpdf/pdftopng: xpdf/CMakeFiles/xpdf_objs.dir/Gfx.cc.o +xpdf/pdftopng: xpdf/CMakeFiles/xpdf_objs.dir/GfxFont.cc.o +xpdf/pdftopng: xpdf/CMakeFiles/xpdf_objs.dir/GfxState.cc.o +xpdf/pdftopng: xpdf/CMakeFiles/xpdf_objs.dir/GlobalParams.cc.o +xpdf/pdftopng: xpdf/CMakeFiles/xpdf_objs.dir/JArithmeticDecoder.cc.o +xpdf/pdftopng: xpdf/CMakeFiles/xpdf_objs.dir/JBIG2Stream.cc.o +xpdf/pdftopng: xpdf/CMakeFiles/xpdf_objs.dir/JPXStream.cc.o +xpdf/pdftopng: xpdf/CMakeFiles/xpdf_objs.dir/Lexer.cc.o +xpdf/pdftopng: xpdf/CMakeFiles/xpdf_objs.dir/Link.cc.o +xpdf/pdftopng: xpdf/CMakeFiles/xpdf_objs.dir/NameToCharCode.cc.o +xpdf/pdftopng: xpdf/CMakeFiles/xpdf_objs.dir/Object.cc.o +xpdf/pdftopng: xpdf/CMakeFiles/xpdf_objs.dir/OptionalContent.cc.o +xpdf/pdftopng: xpdf/CMakeFiles/xpdf_objs.dir/Outline.cc.o +xpdf/pdftopng: xpdf/CMakeFiles/xpdf_objs.dir/OutputDev.cc.o +xpdf/pdftopng: xpdf/CMakeFiles/xpdf_objs.dir/Page.cc.o +xpdf/pdftopng: xpdf/CMakeFiles/xpdf_objs.dir/Parser.cc.o +xpdf/pdftopng: xpdf/CMakeFiles/xpdf_objs.dir/PDF417Barcode.cc.o +xpdf/pdftopng: xpdf/CMakeFiles/xpdf_objs.dir/PDFDoc.cc.o +xpdf/pdftopng: xpdf/CMakeFiles/xpdf_objs.dir/PDFDocEncoding.cc.o +xpdf/pdftopng: xpdf/CMakeFiles/xpdf_objs.dir/PSTokenizer.cc.o +xpdf/pdftopng: xpdf/CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.o +xpdf/pdftopng: xpdf/CMakeFiles/xpdf_objs.dir/Stream.cc.o +xpdf/pdftopng: xpdf/CMakeFiles/xpdf_objs.dir/TextString.cc.o +xpdf/pdftopng: xpdf/CMakeFiles/xpdf_objs.dir/UnicodeMap.cc.o +xpdf/pdftopng: xpdf/CMakeFiles/xpdf_objs.dir/UnicodeRemapping.cc.o +xpdf/pdftopng: xpdf/CMakeFiles/xpdf_objs.dir/UnicodeTypeTable.cc.o +xpdf/pdftopng: xpdf/CMakeFiles/xpdf_objs.dir/UTF8.cc.o +xpdf/pdftopng: xpdf/CMakeFiles/xpdf_objs.dir/XFAScanner.cc.o +xpdf/pdftopng: xpdf/CMakeFiles/xpdf_objs.dir/XRef.cc.o +xpdf/pdftopng: xpdf/CMakeFiles/xpdf_objs.dir/Zoox.cc.o +xpdf/pdftopng: xpdf/CMakeFiles/pdftopng.dir/build.make +xpdf/pdftopng: goo/libgoo.a +xpdf/pdftopng: fofi/libfofi.a +xpdf/pdftopng: splash/libsplash.a +xpdf/pdftopng: /usr/lib/x86_64-linux-gnu/libfreetype.so +xpdf/pdftopng: /usr/lib/x86_64-linux-gnu/libpng.so +xpdf/pdftopng: /usr/lib/x86_64-linux-gnu/libz.so +xpdf/pdftopng: /usr/lib/x86_64-linux-gnu/libfontconfig.so +xpdf/pdftopng: xpdf/CMakeFiles/pdftopng.dir/link.txt + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --bold --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_4) "Linking CXX executable pdftopng" + cd /home/calvin/src/xpdf-4.04/xpdf && $(CMAKE_COMMAND) -E cmake_link_script CMakeFiles/pdftopng.dir/link.txt --verbose=$(VERBOSE) + +# Rule to build all files generated by this target. +xpdf/CMakeFiles/pdftopng.dir/build: xpdf/pdftopng + +.PHONY : xpdf/CMakeFiles/pdftopng.dir/build + +xpdf/CMakeFiles/pdftopng.dir/clean: + cd /home/calvin/src/xpdf-4.04/xpdf && $(CMAKE_COMMAND) -P CMakeFiles/pdftopng.dir/cmake_clean.cmake +.PHONY : xpdf/CMakeFiles/pdftopng.dir/clean + +xpdf/CMakeFiles/pdftopng.dir/depend: + cd /home/calvin/src/xpdf-4.04 && $(CMAKE_COMMAND) -E cmake_depends "Unix Makefiles" /home/calvin/src/xpdf-4.04 /home/calvin/src/xpdf-4.04/xpdf /home/calvin/src/xpdf-4.04 /home/calvin/src/xpdf-4.04/xpdf /home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/pdftopng.dir/DependInfo.cmake --color=$(COLOR) +.PHONY : xpdf/CMakeFiles/pdftopng.dir/depend + diff --git a/xpdf/CMakeFiles/pdftopng.dir/cmake_clean.cmake b/xpdf/CMakeFiles/pdftopng.dir/cmake_clean.cmake new file mode 100644 index 0000000..13af5a4 --- /dev/null +++ b/xpdf/CMakeFiles/pdftopng.dir/cmake_clean.cmake @@ -0,0 +1,12 @@ +file(REMOVE_RECURSE + "CMakeFiles/pdftopng.dir/ShadingImage.cc.o" + "CMakeFiles/pdftopng.dir/SplashOutputDev.cc.o" + "CMakeFiles/pdftopng.dir/pdftopng.cc.o" + "pdftopng" + "pdftopng.pdb" +) + +# Per-language clean rules from dependency scanning. +foreach(lang CXX) + include(CMakeFiles/pdftopng.dir/cmake_clean_${lang}.cmake OPTIONAL) +endforeach() diff --git a/xpdf/CMakeFiles/pdftopng.dir/depend.internal b/xpdf/CMakeFiles/pdftopng.dir/depend.internal new file mode 100644 index 0000000..2a6b180 --- /dev/null +++ b/xpdf/CMakeFiles/pdftopng.dir/depend.internal @@ -0,0 +1,112 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +xpdf/CMakeFiles/pdftopng.dir/ShadingImage.cc.o + /home/calvin/src/xpdf-4.04/xpdf/Array.h + /home/calvin/src/xpdf-4.04/xpdf/Dict.h + /home/calvin/src/xpdf-4.04/xpdf/Function.h + /home/calvin/src/xpdf-4.04/xpdf/GfxState.h + /home/calvin/src/xpdf-4.04/xpdf/Object.h + /home/calvin/src/xpdf-4.04/xpdf/ShadingImage.cc + /home/calvin/src/xpdf-4.04/xpdf/ShadingImage.h + /home/calvin/src/xpdf-4.04/xpdf/Stream.h + aconf.h + aconf2.h + goo/FixedPoint.h + goo/GMutex.h + goo/GString.h + goo/Trace.h + goo/gfile.h + goo/gmem.h + goo/gtypes.h + splash/Splash.h + splash/SplashBitmap.h + splash/SplashClip.h + splash/SplashMath.h + splash/SplashPath.h + splash/SplashPattern.h + splash/SplashTypes.h +xpdf/CMakeFiles/pdftopng.dir/SplashOutputDev.cc.o + /home/calvin/src/xpdf-4.04/xpdf/Array.h + /home/calvin/src/xpdf-4.04/xpdf/BuiltinFont.h + /home/calvin/src/xpdf-4.04/xpdf/BuiltinFontTables.h + /home/calvin/src/xpdf-4.04/xpdf/CharCodeToUnicode.h + /home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + /home/calvin/src/xpdf-4.04/xpdf/Dict.h + /home/calvin/src/xpdf-4.04/xpdf/Error.h + /home/calvin/src/xpdf-4.04/xpdf/FontEncodingTables.h + /home/calvin/src/xpdf-4.04/xpdf/Function.h + /home/calvin/src/xpdf-4.04/xpdf/Gfx.h + /home/calvin/src/xpdf-4.04/xpdf/GfxFont.h + /home/calvin/src/xpdf-4.04/xpdf/GfxState.h + /home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h + /home/calvin/src/xpdf-4.04/xpdf/JPXStream.h + /home/calvin/src/xpdf-4.04/xpdf/Link.h + /home/calvin/src/xpdf-4.04/xpdf/Object.h + /home/calvin/src/xpdf-4.04/xpdf/OutputDev.h + /home/calvin/src/xpdf-4.04/xpdf/ShadingImage.h + /home/calvin/src/xpdf-4.04/xpdf/SplashOutputDev.cc + /home/calvin/src/xpdf-4.04/xpdf/SplashOutputDev.h + /home/calvin/src/xpdf-4.04/xpdf/Stream.h + /home/calvin/src/xpdf-4.04/xpdf/config.h + aconf.h + aconf2.h + fofi/FoFiBase.h + fofi/FoFiTrueType.h + fofi/FoFiType1C.h + goo/FixedPoint.h + goo/GMutex.h + goo/GString.h + goo/Trace.h + goo/gfile.h + goo/gmem.h + goo/gmempp.h + goo/gtypes.h + splash/Splash.h + splash/SplashBitmap.h + splash/SplashClip.h + splash/SplashErrorCodes.h + splash/SplashFont.h + splash/SplashFontEngine.h + splash/SplashFontFile.h + splash/SplashFontFileID.h + splash/SplashGlyphBitmap.h + splash/SplashMath.h + splash/SplashPath.h + splash/SplashPattern.h + splash/SplashScreen.h + splash/SplashState.h + splash/SplashTypes.h +xpdf/CMakeFiles/pdftopng.dir/pdftopng.cc.o + /home/calvin/src/xpdf-4.04/xpdf/Array.h + /home/calvin/src/xpdf-4.04/xpdf/Catalog.h + /home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + /home/calvin/src/xpdf-4.04/xpdf/Dict.h + /home/calvin/src/xpdf-4.04/xpdf/Error.h + /home/calvin/src/xpdf-4.04/xpdf/Function.h + /home/calvin/src/xpdf-4.04/xpdf/GfxState.h + /home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h + /home/calvin/src/xpdf-4.04/xpdf/Object.h + /home/calvin/src/xpdf-4.04/xpdf/OutputDev.h + /home/calvin/src/xpdf-4.04/xpdf/PDFDoc.h + /home/calvin/src/xpdf-4.04/xpdf/Page.h + /home/calvin/src/xpdf-4.04/xpdf/SplashOutputDev.h + /home/calvin/src/xpdf-4.04/xpdf/Stream.h + /home/calvin/src/xpdf-4.04/xpdf/XRef.h + /home/calvin/src/xpdf-4.04/xpdf/config.h + /home/calvin/src/xpdf-4.04/xpdf/pdftopng.cc + aconf.h + aconf2.h + goo/FixedPoint.h + goo/GMutex.h + goo/GString.h + goo/gfile.h + goo/gmem.h + goo/gmempp.h + goo/gtypes.h + goo/parseargs.h + splash/Splash.h + splash/SplashBitmap.h + splash/SplashClip.h + splash/SplashMath.h + splash/SplashTypes.h diff --git a/xpdf/CMakeFiles/pdftopng.dir/depend.make b/xpdf/CMakeFiles/pdftopng.dir/depend.make new file mode 100644 index 0000000..688e588 --- /dev/null +++ b/xpdf/CMakeFiles/pdftopng.dir/depend.make @@ -0,0 +1,112 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +xpdf/CMakeFiles/pdftopng.dir/ShadingImage.cc.o: xpdf/Array.h +xpdf/CMakeFiles/pdftopng.dir/ShadingImage.cc.o: xpdf/Dict.h +xpdf/CMakeFiles/pdftopng.dir/ShadingImage.cc.o: xpdf/Function.h +xpdf/CMakeFiles/pdftopng.dir/ShadingImage.cc.o: xpdf/GfxState.h +xpdf/CMakeFiles/pdftopng.dir/ShadingImage.cc.o: xpdf/Object.h +xpdf/CMakeFiles/pdftopng.dir/ShadingImage.cc.o: xpdf/ShadingImage.cc +xpdf/CMakeFiles/pdftopng.dir/ShadingImage.cc.o: xpdf/ShadingImage.h +xpdf/CMakeFiles/pdftopng.dir/ShadingImage.cc.o: xpdf/Stream.h +xpdf/CMakeFiles/pdftopng.dir/ShadingImage.cc.o: aconf.h +xpdf/CMakeFiles/pdftopng.dir/ShadingImage.cc.o: aconf2.h +xpdf/CMakeFiles/pdftopng.dir/ShadingImage.cc.o: goo/FixedPoint.h +xpdf/CMakeFiles/pdftopng.dir/ShadingImage.cc.o: goo/GMutex.h +xpdf/CMakeFiles/pdftopng.dir/ShadingImage.cc.o: goo/GString.h +xpdf/CMakeFiles/pdftopng.dir/ShadingImage.cc.o: goo/Trace.h +xpdf/CMakeFiles/pdftopng.dir/ShadingImage.cc.o: goo/gfile.h +xpdf/CMakeFiles/pdftopng.dir/ShadingImage.cc.o: goo/gmem.h +xpdf/CMakeFiles/pdftopng.dir/ShadingImage.cc.o: goo/gtypes.h +xpdf/CMakeFiles/pdftopng.dir/ShadingImage.cc.o: splash/Splash.h +xpdf/CMakeFiles/pdftopng.dir/ShadingImage.cc.o: splash/SplashBitmap.h +xpdf/CMakeFiles/pdftopng.dir/ShadingImage.cc.o: splash/SplashClip.h +xpdf/CMakeFiles/pdftopng.dir/ShadingImage.cc.o: splash/SplashMath.h +xpdf/CMakeFiles/pdftopng.dir/ShadingImage.cc.o: splash/SplashPath.h +xpdf/CMakeFiles/pdftopng.dir/ShadingImage.cc.o: splash/SplashPattern.h +xpdf/CMakeFiles/pdftopng.dir/ShadingImage.cc.o: splash/SplashTypes.h + +xpdf/CMakeFiles/pdftopng.dir/SplashOutputDev.cc.o: xpdf/Array.h +xpdf/CMakeFiles/pdftopng.dir/SplashOutputDev.cc.o: xpdf/BuiltinFont.h +xpdf/CMakeFiles/pdftopng.dir/SplashOutputDev.cc.o: xpdf/BuiltinFontTables.h +xpdf/CMakeFiles/pdftopng.dir/SplashOutputDev.cc.o: xpdf/CharCodeToUnicode.h +xpdf/CMakeFiles/pdftopng.dir/SplashOutputDev.cc.o: xpdf/CharTypes.h +xpdf/CMakeFiles/pdftopng.dir/SplashOutputDev.cc.o: xpdf/Dict.h +xpdf/CMakeFiles/pdftopng.dir/SplashOutputDev.cc.o: xpdf/Error.h +xpdf/CMakeFiles/pdftopng.dir/SplashOutputDev.cc.o: xpdf/FontEncodingTables.h +xpdf/CMakeFiles/pdftopng.dir/SplashOutputDev.cc.o: xpdf/Function.h +xpdf/CMakeFiles/pdftopng.dir/SplashOutputDev.cc.o: xpdf/Gfx.h +xpdf/CMakeFiles/pdftopng.dir/SplashOutputDev.cc.o: xpdf/GfxFont.h +xpdf/CMakeFiles/pdftopng.dir/SplashOutputDev.cc.o: xpdf/GfxState.h +xpdf/CMakeFiles/pdftopng.dir/SplashOutputDev.cc.o: xpdf/GlobalParams.h +xpdf/CMakeFiles/pdftopng.dir/SplashOutputDev.cc.o: xpdf/JPXStream.h +xpdf/CMakeFiles/pdftopng.dir/SplashOutputDev.cc.o: xpdf/Link.h +xpdf/CMakeFiles/pdftopng.dir/SplashOutputDev.cc.o: xpdf/Object.h +xpdf/CMakeFiles/pdftopng.dir/SplashOutputDev.cc.o: xpdf/OutputDev.h +xpdf/CMakeFiles/pdftopng.dir/SplashOutputDev.cc.o: xpdf/ShadingImage.h +xpdf/CMakeFiles/pdftopng.dir/SplashOutputDev.cc.o: xpdf/SplashOutputDev.cc +xpdf/CMakeFiles/pdftopng.dir/SplashOutputDev.cc.o: xpdf/SplashOutputDev.h +xpdf/CMakeFiles/pdftopng.dir/SplashOutputDev.cc.o: xpdf/Stream.h +xpdf/CMakeFiles/pdftopng.dir/SplashOutputDev.cc.o: xpdf/config.h +xpdf/CMakeFiles/pdftopng.dir/SplashOutputDev.cc.o: aconf.h +xpdf/CMakeFiles/pdftopng.dir/SplashOutputDev.cc.o: aconf2.h +xpdf/CMakeFiles/pdftopng.dir/SplashOutputDev.cc.o: fofi/FoFiBase.h +xpdf/CMakeFiles/pdftopng.dir/SplashOutputDev.cc.o: fofi/FoFiTrueType.h +xpdf/CMakeFiles/pdftopng.dir/SplashOutputDev.cc.o: fofi/FoFiType1C.h +xpdf/CMakeFiles/pdftopng.dir/SplashOutputDev.cc.o: goo/FixedPoint.h +xpdf/CMakeFiles/pdftopng.dir/SplashOutputDev.cc.o: goo/GMutex.h +xpdf/CMakeFiles/pdftopng.dir/SplashOutputDev.cc.o: goo/GString.h +xpdf/CMakeFiles/pdftopng.dir/SplashOutputDev.cc.o: goo/Trace.h +xpdf/CMakeFiles/pdftopng.dir/SplashOutputDev.cc.o: goo/gfile.h +xpdf/CMakeFiles/pdftopng.dir/SplashOutputDev.cc.o: goo/gmem.h +xpdf/CMakeFiles/pdftopng.dir/SplashOutputDev.cc.o: goo/gmempp.h +xpdf/CMakeFiles/pdftopng.dir/SplashOutputDev.cc.o: goo/gtypes.h +xpdf/CMakeFiles/pdftopng.dir/SplashOutputDev.cc.o: splash/Splash.h +xpdf/CMakeFiles/pdftopng.dir/SplashOutputDev.cc.o: splash/SplashBitmap.h +xpdf/CMakeFiles/pdftopng.dir/SplashOutputDev.cc.o: splash/SplashClip.h +xpdf/CMakeFiles/pdftopng.dir/SplashOutputDev.cc.o: splash/SplashErrorCodes.h +xpdf/CMakeFiles/pdftopng.dir/SplashOutputDev.cc.o: splash/SplashFont.h +xpdf/CMakeFiles/pdftopng.dir/SplashOutputDev.cc.o: splash/SplashFontEngine.h +xpdf/CMakeFiles/pdftopng.dir/SplashOutputDev.cc.o: splash/SplashFontFile.h +xpdf/CMakeFiles/pdftopng.dir/SplashOutputDev.cc.o: splash/SplashFontFileID.h +xpdf/CMakeFiles/pdftopng.dir/SplashOutputDev.cc.o: splash/SplashGlyphBitmap.h +xpdf/CMakeFiles/pdftopng.dir/SplashOutputDev.cc.o: splash/SplashMath.h +xpdf/CMakeFiles/pdftopng.dir/SplashOutputDev.cc.o: splash/SplashPath.h +xpdf/CMakeFiles/pdftopng.dir/SplashOutputDev.cc.o: splash/SplashPattern.h +xpdf/CMakeFiles/pdftopng.dir/SplashOutputDev.cc.o: splash/SplashScreen.h +xpdf/CMakeFiles/pdftopng.dir/SplashOutputDev.cc.o: splash/SplashState.h +xpdf/CMakeFiles/pdftopng.dir/SplashOutputDev.cc.o: splash/SplashTypes.h + +xpdf/CMakeFiles/pdftopng.dir/pdftopng.cc.o: xpdf/Array.h +xpdf/CMakeFiles/pdftopng.dir/pdftopng.cc.o: xpdf/Catalog.h +xpdf/CMakeFiles/pdftopng.dir/pdftopng.cc.o: xpdf/CharTypes.h +xpdf/CMakeFiles/pdftopng.dir/pdftopng.cc.o: xpdf/Dict.h +xpdf/CMakeFiles/pdftopng.dir/pdftopng.cc.o: xpdf/Error.h +xpdf/CMakeFiles/pdftopng.dir/pdftopng.cc.o: xpdf/Function.h +xpdf/CMakeFiles/pdftopng.dir/pdftopng.cc.o: xpdf/GfxState.h +xpdf/CMakeFiles/pdftopng.dir/pdftopng.cc.o: xpdf/GlobalParams.h +xpdf/CMakeFiles/pdftopng.dir/pdftopng.cc.o: xpdf/Object.h +xpdf/CMakeFiles/pdftopng.dir/pdftopng.cc.o: xpdf/OutputDev.h +xpdf/CMakeFiles/pdftopng.dir/pdftopng.cc.o: xpdf/PDFDoc.h +xpdf/CMakeFiles/pdftopng.dir/pdftopng.cc.o: xpdf/Page.h +xpdf/CMakeFiles/pdftopng.dir/pdftopng.cc.o: xpdf/SplashOutputDev.h +xpdf/CMakeFiles/pdftopng.dir/pdftopng.cc.o: xpdf/Stream.h +xpdf/CMakeFiles/pdftopng.dir/pdftopng.cc.o: xpdf/XRef.h +xpdf/CMakeFiles/pdftopng.dir/pdftopng.cc.o: xpdf/config.h +xpdf/CMakeFiles/pdftopng.dir/pdftopng.cc.o: xpdf/pdftopng.cc +xpdf/CMakeFiles/pdftopng.dir/pdftopng.cc.o: aconf.h +xpdf/CMakeFiles/pdftopng.dir/pdftopng.cc.o: aconf2.h +xpdf/CMakeFiles/pdftopng.dir/pdftopng.cc.o: goo/FixedPoint.h +xpdf/CMakeFiles/pdftopng.dir/pdftopng.cc.o: goo/GMutex.h +xpdf/CMakeFiles/pdftopng.dir/pdftopng.cc.o: goo/GString.h +xpdf/CMakeFiles/pdftopng.dir/pdftopng.cc.o: goo/gfile.h +xpdf/CMakeFiles/pdftopng.dir/pdftopng.cc.o: goo/gmem.h +xpdf/CMakeFiles/pdftopng.dir/pdftopng.cc.o: goo/gmempp.h +xpdf/CMakeFiles/pdftopng.dir/pdftopng.cc.o: goo/gtypes.h +xpdf/CMakeFiles/pdftopng.dir/pdftopng.cc.o: goo/parseargs.h +xpdf/CMakeFiles/pdftopng.dir/pdftopng.cc.o: splash/Splash.h +xpdf/CMakeFiles/pdftopng.dir/pdftopng.cc.o: splash/SplashBitmap.h +xpdf/CMakeFiles/pdftopng.dir/pdftopng.cc.o: splash/SplashClip.h +xpdf/CMakeFiles/pdftopng.dir/pdftopng.cc.o: splash/SplashMath.h +xpdf/CMakeFiles/pdftopng.dir/pdftopng.cc.o: splash/SplashTypes.h + diff --git a/xpdf/CMakeFiles/pdftopng.dir/flags.make b/xpdf/CMakeFiles/pdftopng.dir/flags.make new file mode 100644 index 0000000..300fa3e --- /dev/null +++ b/xpdf/CMakeFiles/pdftopng.dir/flags.make @@ -0,0 +1,10 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +# compile CXX with /usr/bin/c++ +CXX_DEFINES = + +CXX_INCLUDES = -I/home/calvin/src/xpdf-4.04 -I/home/calvin/src/xpdf-4.04/goo -I/home/calvin/src/xpdf-4.04/fofi -I/home/calvin/src/xpdf-4.04/splash + +CXX_FLAGS = + diff --git a/xpdf/CMakeFiles/pdftopng.dir/link.txt b/xpdf/CMakeFiles/pdftopng.dir/link.txt new file mode 100644 index 0000000..1efa06b --- /dev/null +++ b/xpdf/CMakeFiles/pdftopng.dir/link.txt @@ -0,0 +1 @@ +/usr/bin/c++ -rdynamic CMakeFiles/pdftopng.dir/ShadingImage.cc.o CMakeFiles/pdftopng.dir/SplashOutputDev.cc.o CMakeFiles/pdftopng.dir/pdftopng.cc.o CMakeFiles/xpdf_objs.dir/AcroForm.cc.o CMakeFiles/xpdf_objs.dir/Annot.cc.o CMakeFiles/xpdf_objs.dir/Array.cc.o CMakeFiles/xpdf_objs.dir/BuiltinFont.cc.o CMakeFiles/xpdf_objs.dir/BuiltinFontTables.cc.o CMakeFiles/xpdf_objs.dir/Catalog.cc.o CMakeFiles/xpdf_objs.dir/CharCodeToUnicode.cc.o CMakeFiles/xpdf_objs.dir/CMap.cc.o CMakeFiles/xpdf_objs.dir/Decrypt.cc.o CMakeFiles/xpdf_objs.dir/Dict.cc.o CMakeFiles/xpdf_objs.dir/Error.cc.o CMakeFiles/xpdf_objs.dir/FontEncodingTables.cc.o CMakeFiles/xpdf_objs.dir/Function.cc.o CMakeFiles/xpdf_objs.dir/Gfx.cc.o CMakeFiles/xpdf_objs.dir/GfxFont.cc.o CMakeFiles/xpdf_objs.dir/GfxState.cc.o CMakeFiles/xpdf_objs.dir/GlobalParams.cc.o CMakeFiles/xpdf_objs.dir/JArithmeticDecoder.cc.o CMakeFiles/xpdf_objs.dir/JBIG2Stream.cc.o CMakeFiles/xpdf_objs.dir/JPXStream.cc.o CMakeFiles/xpdf_objs.dir/Lexer.cc.o CMakeFiles/xpdf_objs.dir/Link.cc.o CMakeFiles/xpdf_objs.dir/NameToCharCode.cc.o CMakeFiles/xpdf_objs.dir/Object.cc.o CMakeFiles/xpdf_objs.dir/OptionalContent.cc.o CMakeFiles/xpdf_objs.dir/Outline.cc.o CMakeFiles/xpdf_objs.dir/OutputDev.cc.o CMakeFiles/xpdf_objs.dir/Page.cc.o CMakeFiles/xpdf_objs.dir/Parser.cc.o CMakeFiles/xpdf_objs.dir/PDF417Barcode.cc.o CMakeFiles/xpdf_objs.dir/PDFDoc.cc.o CMakeFiles/xpdf_objs.dir/PDFDocEncoding.cc.o CMakeFiles/xpdf_objs.dir/PSTokenizer.cc.o CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.o CMakeFiles/xpdf_objs.dir/Stream.cc.o CMakeFiles/xpdf_objs.dir/TextString.cc.o CMakeFiles/xpdf_objs.dir/UnicodeMap.cc.o CMakeFiles/xpdf_objs.dir/UnicodeRemapping.cc.o CMakeFiles/xpdf_objs.dir/UnicodeTypeTable.cc.o CMakeFiles/xpdf_objs.dir/UTF8.cc.o CMakeFiles/xpdf_objs.dir/XFAScanner.cc.o CMakeFiles/xpdf_objs.dir/XRef.cc.o CMakeFiles/xpdf_objs.dir/Zoox.cc.o -o pdftopng ../goo/libgoo.a ../fofi/libfofi.a ../splash/libsplash.a -lfreetype -lpng -lz -lfontconfig -lpthread diff --git a/xpdf/CMakeFiles/pdftopng.dir/pdftopng.cc.o b/xpdf/CMakeFiles/pdftopng.dir/pdftopng.cc.o new file mode 100644 index 0000000..7b360c9 Binary files /dev/null and b/xpdf/CMakeFiles/pdftopng.dir/pdftopng.cc.o differ diff --git a/xpdf/CMakeFiles/pdftopng.dir/progress.make b/xpdf/CMakeFiles/pdftopng.dir/progress.make new file mode 100644 index 0000000..8360789 --- /dev/null +++ b/xpdf/CMakeFiles/pdftopng.dir/progress.make @@ -0,0 +1,5 @@ +CMAKE_PROGRESS_1 = 25 +CMAKE_PROGRESS_2 = +CMAKE_PROGRESS_3 = 26 +CMAKE_PROGRESS_4 = 27 + diff --git a/xpdf/CMakeFiles/pdftoppm.dir/CXX.includecache b/xpdf/CMakeFiles/pdftoppm.dir/CXX.includecache new file mode 100644 index 0000000..bef6767 --- /dev/null +++ b/xpdf/CMakeFiles/pdftoppm.dir/CXX.includecache @@ -0,0 +1,578 @@ +#IncludeRegexLine: ^[ ]*[#%][ ]*(include|import)[ ]*[<"]([^">]+)([">]) + +#IncludeRegexScan: ^.*$ + +#IncludeRegexComplain: ^$ + +#IncludeRegexTransform: + +/home/calvin/src/xpdf-4.04/xpdf/Array.h +aconf.h +- +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h + +/home/calvin/src/xpdf-4.04/xpdf/BuiltinFont.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h + +/home/calvin/src/xpdf-4.04/xpdf/BuiltinFontTables.h +BuiltinFont.h +/home/calvin/src/xpdf-4.04/xpdf/BuiltinFont.h + +/home/calvin/src/xpdf-4.04/xpdf/Catalog.h +aconf.h +- +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h +CharTypes.h +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + +/home/calvin/src/xpdf-4.04/xpdf/CharCodeToUnicode.h +aconf.h +- +CharTypes.h +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h + +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + +/home/calvin/src/xpdf-4.04/xpdf/Dict.h +aconf.h +- +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h + +/home/calvin/src/xpdf-4.04/xpdf/Error.h +aconf.h +- +stdio.h +- +config.h +/home/calvin/src/xpdf-4.04/xpdf/config.h +gfile.h +/home/calvin/src/xpdf-4.04/xpdf/gfile.h + +/home/calvin/src/xpdf-4.04/xpdf/FontEncodingTables.h + +/home/calvin/src/xpdf-4.04/xpdf/Function.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h + +/home/calvin/src/xpdf-4.04/xpdf/Gfx.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +gfile.h +/home/calvin/src/xpdf-4.04/xpdf/gfile.h +GfxState.h +/home/calvin/src/xpdf-4.04/xpdf/GfxState.h + +/home/calvin/src/xpdf-4.04/xpdf/GfxFont.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +GString.h +/home/calvin/src/xpdf-4.04/xpdf/GString.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h +CharTypes.h +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + +/home/calvin/src/xpdf-4.04/xpdf/GfxState.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h +Function.h +/home/calvin/src/xpdf-4.04/xpdf/Function.h + +/home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h +aconf.h +- +stdio.h +- +windows.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +CharTypes.h +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h + +/home/calvin/src/xpdf-4.04/xpdf/JPXStream.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h +Stream.h +/home/calvin/src/xpdf-4.04/xpdf/Stream.h + +/home/calvin/src/xpdf-4.04/xpdf/Link.h +aconf.h +- +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h + +/home/calvin/src/xpdf-4.04/xpdf/Object.h +aconf.h +- +stdio.h +- +string.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +gmem.h +/home/calvin/src/xpdf-4.04/xpdf/gmem.h +gfile.h +/home/calvin/src/xpdf-4.04/xpdf/gfile.h +GString.h +/home/calvin/src/xpdf-4.04/xpdf/GString.h +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h +Array.h +/home/calvin/src/xpdf-4.04/xpdf/Array.h +Dict.h +/home/calvin/src/xpdf-4.04/xpdf/Dict.h +Stream.h +/home/calvin/src/xpdf-4.04/xpdf/Stream.h + +/home/calvin/src/xpdf-4.04/xpdf/OutputDev.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +CharTypes.h +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + +/home/calvin/src/xpdf-4.04/xpdf/PDFDoc.h +aconf.h +- +stdio.h +- +XRef.h +/home/calvin/src/xpdf-4.04/xpdf/XRef.h +Catalog.h +/home/calvin/src/xpdf-4.04/xpdf/Catalog.h +Page.h +/home/calvin/src/xpdf-4.04/xpdf/Page.h + +/home/calvin/src/xpdf-4.04/xpdf/Page.h +aconf.h +- +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h + +/home/calvin/src/xpdf-4.04/xpdf/ShadingImage.cc +aconf.h +- +math.h +- +Trace.h +/home/calvin/src/xpdf-4.04/xpdf/Trace.h +GfxState.h +/home/calvin/src/xpdf-4.04/xpdf/GfxState.h +SplashBitmap.h +/home/calvin/src/xpdf-4.04/xpdf/SplashBitmap.h +SplashPattern.h +/home/calvin/src/xpdf-4.04/xpdf/SplashPattern.h +SplashPath.h +/home/calvin/src/xpdf-4.04/xpdf/SplashPath.h +Splash.h +/home/calvin/src/xpdf-4.04/xpdf/Splash.h +ShadingImage.h +/home/calvin/src/xpdf-4.04/xpdf/ShadingImage.h + +/home/calvin/src/xpdf-4.04/xpdf/ShadingImage.h +aconf.h +- +SplashTypes.h +/home/calvin/src/xpdf-4.04/xpdf/SplashTypes.h + +/home/calvin/src/xpdf-4.04/xpdf/SplashOutputDev.cc +aconf.h +- +string.h +- +math.h +- +limits.h +- +gmempp.h +/home/calvin/src/xpdf-4.04/xpdf/gmempp.h +gfile.h +/home/calvin/src/xpdf-4.04/xpdf/gfile.h +Trace.h +/home/calvin/src/xpdf-4.04/xpdf/Trace.h +GlobalParams.h +/home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h +Error.h +/home/calvin/src/xpdf-4.04/xpdf/Error.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h +Gfx.h +/home/calvin/src/xpdf-4.04/xpdf/Gfx.h +GfxFont.h +/home/calvin/src/xpdf-4.04/xpdf/GfxFont.h +ShadingImage.h +/home/calvin/src/xpdf-4.04/xpdf/ShadingImage.h +Link.h +/home/calvin/src/xpdf-4.04/xpdf/Link.h +CharCodeToUnicode.h +/home/calvin/src/xpdf-4.04/xpdf/CharCodeToUnicode.h +FontEncodingTables.h +/home/calvin/src/xpdf-4.04/xpdf/FontEncodingTables.h +BuiltinFont.h +/home/calvin/src/xpdf-4.04/xpdf/BuiltinFont.h +BuiltinFontTables.h +/home/calvin/src/xpdf-4.04/xpdf/BuiltinFontTables.h +FoFiTrueType.h +/home/calvin/src/xpdf-4.04/xpdf/FoFiTrueType.h +FoFiType1C.h +/home/calvin/src/xpdf-4.04/xpdf/FoFiType1C.h +JPXStream.h +/home/calvin/src/xpdf-4.04/xpdf/JPXStream.h +SplashBitmap.h +/home/calvin/src/xpdf-4.04/xpdf/SplashBitmap.h +SplashGlyphBitmap.h +/home/calvin/src/xpdf-4.04/xpdf/SplashGlyphBitmap.h +SplashPattern.h +/home/calvin/src/xpdf-4.04/xpdf/SplashPattern.h +SplashScreen.h +/home/calvin/src/xpdf-4.04/xpdf/SplashScreen.h +SplashPath.h +/home/calvin/src/xpdf-4.04/xpdf/SplashPath.h +SplashState.h +/home/calvin/src/xpdf-4.04/xpdf/SplashState.h +SplashErrorCodes.h +/home/calvin/src/xpdf-4.04/xpdf/SplashErrorCodes.h +SplashFontEngine.h +/home/calvin/src/xpdf-4.04/xpdf/SplashFontEngine.h +SplashFont.h +/home/calvin/src/xpdf-4.04/xpdf/SplashFont.h +SplashFontFile.h +/home/calvin/src/xpdf-4.04/xpdf/SplashFontFile.h +SplashFontFileID.h +/home/calvin/src/xpdf-4.04/xpdf/SplashFontFileID.h +Splash.h +/home/calvin/src/xpdf-4.04/xpdf/Splash.h +SplashOutputDev.h +/home/calvin/src/xpdf-4.04/xpdf/SplashOutputDev.h + +/home/calvin/src/xpdf-4.04/xpdf/SplashOutputDev.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +SplashTypes.h +/home/calvin/src/xpdf-4.04/xpdf/SplashTypes.h +config.h +/home/calvin/src/xpdf-4.04/xpdf/config.h +OutputDev.h +/home/calvin/src/xpdf-4.04/xpdf/OutputDev.h +GfxState.h +/home/calvin/src/xpdf-4.04/xpdf/GfxState.h + +/home/calvin/src/xpdf-4.04/xpdf/Stream.h +aconf.h +- +stdio.h +- +jpeglib.h +- +setjmp.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +gfile.h +/home/calvin/src/xpdf-4.04/xpdf/gfile.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h + +/home/calvin/src/xpdf-4.04/xpdf/XRef.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +gfile.h +/home/calvin/src/xpdf-4.04/xpdf/gfile.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h + +/home/calvin/src/xpdf-4.04/xpdf/config.h + +/home/calvin/src/xpdf-4.04/xpdf/pdftoppm.cc +aconf.h +- +stdio.h +- +io.h +- +fcntl.h +- +fenv.h +- +fpu_control.h +- +gmem.h +/home/calvin/src/xpdf-4.04/xpdf/gmem.h +gmempp.h +/home/calvin/src/xpdf-4.04/xpdf/gmempp.h +parseargs.h +/home/calvin/src/xpdf-4.04/xpdf/parseargs.h +GString.h +/home/calvin/src/xpdf-4.04/xpdf/GString.h +GlobalParams.h +/home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h +PDFDoc.h +/home/calvin/src/xpdf-4.04/xpdf/PDFDoc.h +SplashBitmap.h +/home/calvin/src/xpdf-4.04/xpdf/SplashBitmap.h +Splash.h +/home/calvin/src/xpdf-4.04/xpdf/Splash.h +SplashOutputDev.h +/home/calvin/src/xpdf-4.04/xpdf/SplashOutputDev.h +Error.h +/home/calvin/src/xpdf-4.04/xpdf/Error.h +config.h +/home/calvin/src/xpdf-4.04/xpdf/config.h + +aconf.h +aconf2.h +- + +aconf2.h +AvailabilityMacros.h +- + +fofi/FoFiBase.h +aconf.h +- +gtypes.h +fofi/gtypes.h + +fofi/FoFiTrueType.h +aconf.h +- +gtypes.h +fofi/gtypes.h +FoFiBase.h +fofi/FoFiBase.h + +fofi/FoFiType1C.h +aconf.h +- +gtypes.h +fofi/gtypes.h +FoFiBase.h +fofi/FoFiBase.h + +goo/FixedPoint.h +aconf.h +- +stdio.h +- +stdlib.h +- +gtypes.h +goo/gtypes.h + +goo/GMutex.h +aconf.h +- +windows.h +- +intrin.h +- +pthread.h +- + +goo/GString.h +aconf.h +- +limits.h +- +stdarg.h +- +gtypes.h +goo/gtypes.h + +goo/Trace.h +aconf.h +- + +goo/gfile.h +aconf.h +- +stdio.h +- +stdlib.h +- +stddef.h +- +sys/stat.h +- +win32lib.h +- +windows.h +- +unistd.h +- +sys/types.h +- +gtypes.h +goo/gtypes.h + +goo/gmem.h +stdio.h +- +aconf.h +- + +goo/gmempp.h +stdlib.h +- + +goo/gtypes.h + +goo/parseargs.h +gtypes.h +goo/gtypes.h + +splash/Splash.h +aconf.h +- +SplashTypes.h +splash/SplashTypes.h +SplashClip.h +splash/SplashClip.h + +splash/SplashBitmap.h +aconf.h +- +stdio.h +- +limits.h +- +stdint.h +- +SplashTypes.h +splash/SplashTypes.h + +splash/SplashClip.h +aconf.h +- +SplashTypes.h +splash/SplashTypes.h +SplashMath.h +splash/SplashMath.h + +splash/SplashErrorCodes.h +aconf.h +- + +splash/SplashFont.h +aconf.h +- +gtypes.h +splash/gtypes.h +SplashTypes.h +splash/SplashTypes.h +SplashMath.h +splash/SplashMath.h + +splash/SplashFontEngine.h +aconf.h +- +gtypes.h +splash/gtypes.h + +splash/SplashFontFile.h +aconf.h +- +gtypes.h +splash/gtypes.h +SplashTypes.h +splash/SplashTypes.h +GMutex.h +splash/GMutex.h + +splash/SplashFontFileID.h +aconf.h +- +gtypes.h +splash/gtypes.h + +splash/SplashGlyphBitmap.h +aconf.h +- +gtypes.h +splash/gtypes.h + +splash/SplashMath.h +aconf.h +- +FixedPoint.h +splash/FixedPoint.h +math.h +- +emmintrin.h +- +SplashTypes.h +splash/SplashTypes.h + +splash/SplashPath.h +aconf.h +- +SplashTypes.h +splash/SplashTypes.h + +splash/SplashPattern.h +aconf.h +- +SplashTypes.h +splash/SplashTypes.h + +splash/SplashScreen.h +aconf.h +- +SplashTypes.h +splash/SplashTypes.h + +splash/SplashState.h +aconf.h +- +SplashTypes.h +splash/SplashTypes.h + +splash/SplashTypes.h +aconf.h +- +gtypes.h +splash/gtypes.h +FixedPoint.h +splash/FixedPoint.h + diff --git a/xpdf/CMakeFiles/pdftoppm.dir/DependInfo.cmake b/xpdf/CMakeFiles/pdftoppm.dir/DependInfo.cmake new file mode 100644 index 0000000..b616d8b --- /dev/null +++ b/xpdf/CMakeFiles/pdftoppm.dir/DependInfo.cmake @@ -0,0 +1,29 @@ +# The set of languages for which implicit dependencies are needed: +set(CMAKE_DEPENDS_LANGUAGES + "CXX" + ) +# The set of files for implicit dependencies of each language: +set(CMAKE_DEPENDS_CHECK_CXX + "/home/calvin/src/xpdf-4.04/xpdf/ShadingImage.cc" "/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/pdftoppm.dir/ShadingImage.cc.o" + "/home/calvin/src/xpdf-4.04/xpdf/SplashOutputDev.cc" "/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/pdftoppm.dir/SplashOutputDev.cc.o" + "/home/calvin/src/xpdf-4.04/xpdf/pdftoppm.cc" "/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/pdftoppm.dir/pdftoppm.cc.o" + ) +set(CMAKE_CXX_COMPILER_ID "GNU") + +# The include file search paths: +set(CMAKE_CXX_TARGET_INCLUDE_PATH + "." + "goo" + "fofi" + "splash" + ) + +# Targets to which this target links. +set(CMAKE_TARGET_LINKED_INFO_FILES + "/home/calvin/src/xpdf-4.04/goo/CMakeFiles/goo.dir/DependInfo.cmake" + "/home/calvin/src/xpdf-4.04/fofi/CMakeFiles/fofi.dir/DependInfo.cmake" + "/home/calvin/src/xpdf-4.04/splash/CMakeFiles/splash.dir/DependInfo.cmake" + ) + +# Fortran module output directory. +set(CMAKE_Fortran_TARGET_MODULE_DIR "") diff --git a/xpdf/CMakeFiles/pdftoppm.dir/ShadingImage.cc.o b/xpdf/CMakeFiles/pdftoppm.dir/ShadingImage.cc.o new file mode 100644 index 0000000..d53401f Binary files /dev/null and b/xpdf/CMakeFiles/pdftoppm.dir/ShadingImage.cc.o differ diff --git a/xpdf/CMakeFiles/pdftoppm.dir/SplashOutputDev.cc.o b/xpdf/CMakeFiles/pdftoppm.dir/SplashOutputDev.cc.o new file mode 100644 index 0000000..7fdcd23 Binary files /dev/null and b/xpdf/CMakeFiles/pdftoppm.dir/SplashOutputDev.cc.o differ diff --git a/xpdf/CMakeFiles/pdftoppm.dir/build.make b/xpdf/CMakeFiles/pdftoppm.dir/build.make new file mode 100644 index 0000000..e41071e --- /dev/null +++ b/xpdf/CMakeFiles/pdftoppm.dir/build.make @@ -0,0 +1,238 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +# Delete rule output on recipe failure. +.DELETE_ON_ERROR: + + +#============================================================================= +# Special targets provided by cmake. + +# Disable implicit rules so canonical targets will work. +.SUFFIXES: + + +# Disable VCS-based implicit rules. +% : %,v + + +# Disable VCS-based implicit rules. +% : RCS/% + + +# Disable VCS-based implicit rules. +% : RCS/%,v + + +# Disable VCS-based implicit rules. +% : SCCS/s.% + + +# Disable VCS-based implicit rules. +% : s.% + + +.SUFFIXES: .hpux_make_needs_suffix_list + + +# Command-line flag to silence nested $(MAKE). +$(VERBOSE)MAKESILENT = -s + +#Suppress display of executed commands. +$(VERBOSE).SILENT: + +# A target that is always out of date. +cmake_force: + +.PHONY : cmake_force + +#============================================================================= +# Set environment variables for the build. + +# The shell in which to execute make rules. +SHELL = /bin/sh + +# The CMake executable. +CMAKE_COMMAND = /usr/bin/cmake + +# The command to remove a file. +RM = /usr/bin/cmake -E rm -f + +# Escaping for special characters. +EQUALS = = + +# The top-level source directory on which CMake was run. +CMAKE_SOURCE_DIR = /home/calvin/src/xpdf-4.04 + +# The top-level build directory on which CMake was run. +CMAKE_BINARY_DIR = /home/calvin/src/xpdf-4.04 + +# Include any dependencies generated for this target. +include xpdf/CMakeFiles/pdftoppm.dir/depend.make + +# Include the progress variables for this target. +include xpdf/CMakeFiles/pdftoppm.dir/progress.make + +# Include the compile flags for this target's objects. +include xpdf/CMakeFiles/pdftoppm.dir/flags.make + +xpdf/CMakeFiles/pdftoppm.dir/ShadingImage.cc.o: xpdf/CMakeFiles/pdftoppm.dir/flags.make +xpdf/CMakeFiles/pdftoppm.dir/ShadingImage.cc.o: xpdf/ShadingImage.cc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_1) "Building CXX object xpdf/CMakeFiles/pdftoppm.dir/ShadingImage.cc.o" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/pdftoppm.dir/ShadingImage.cc.o -c /home/calvin/src/xpdf-4.04/xpdf/ShadingImage.cc + +xpdf/CMakeFiles/pdftoppm.dir/ShadingImage.cc.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/pdftoppm.dir/ShadingImage.cc.i" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf/ShadingImage.cc > CMakeFiles/pdftoppm.dir/ShadingImage.cc.i + +xpdf/CMakeFiles/pdftoppm.dir/ShadingImage.cc.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/pdftoppm.dir/ShadingImage.cc.s" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf/ShadingImage.cc -o CMakeFiles/pdftoppm.dir/ShadingImage.cc.s + +xpdf/CMakeFiles/pdftoppm.dir/SplashOutputDev.cc.o: xpdf/CMakeFiles/pdftoppm.dir/flags.make +xpdf/CMakeFiles/pdftoppm.dir/SplashOutputDev.cc.o: xpdf/SplashOutputDev.cc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_2) "Building CXX object xpdf/CMakeFiles/pdftoppm.dir/SplashOutputDev.cc.o" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/pdftoppm.dir/SplashOutputDev.cc.o -c /home/calvin/src/xpdf-4.04/xpdf/SplashOutputDev.cc + +xpdf/CMakeFiles/pdftoppm.dir/SplashOutputDev.cc.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/pdftoppm.dir/SplashOutputDev.cc.i" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf/SplashOutputDev.cc > CMakeFiles/pdftoppm.dir/SplashOutputDev.cc.i + +xpdf/CMakeFiles/pdftoppm.dir/SplashOutputDev.cc.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/pdftoppm.dir/SplashOutputDev.cc.s" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf/SplashOutputDev.cc -o CMakeFiles/pdftoppm.dir/SplashOutputDev.cc.s + +xpdf/CMakeFiles/pdftoppm.dir/pdftoppm.cc.o: xpdf/CMakeFiles/pdftoppm.dir/flags.make +xpdf/CMakeFiles/pdftoppm.dir/pdftoppm.cc.o: xpdf/pdftoppm.cc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_3) "Building CXX object xpdf/CMakeFiles/pdftoppm.dir/pdftoppm.cc.o" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/pdftoppm.dir/pdftoppm.cc.o -c /home/calvin/src/xpdf-4.04/xpdf/pdftoppm.cc + +xpdf/CMakeFiles/pdftoppm.dir/pdftoppm.cc.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/pdftoppm.dir/pdftoppm.cc.i" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf/pdftoppm.cc > CMakeFiles/pdftoppm.dir/pdftoppm.cc.i + +xpdf/CMakeFiles/pdftoppm.dir/pdftoppm.cc.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/pdftoppm.dir/pdftoppm.cc.s" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf/pdftoppm.cc -o CMakeFiles/pdftoppm.dir/pdftoppm.cc.s + +# Object files for target pdftoppm +pdftoppm_OBJECTS = \ +"CMakeFiles/pdftoppm.dir/ShadingImage.cc.o" \ +"CMakeFiles/pdftoppm.dir/SplashOutputDev.cc.o" \ +"CMakeFiles/pdftoppm.dir/pdftoppm.cc.o" + +# External object files for target pdftoppm +pdftoppm_EXTERNAL_OBJECTS = \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/AcroForm.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Annot.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Array.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFont.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFontTables.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Catalog.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/CharCodeToUnicode.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/CMap.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Decrypt.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Dict.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Error.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/FontEncodingTables.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Function.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Gfx.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/GfxFont.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/GfxState.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/GlobalParams.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/JArithmeticDecoder.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/JBIG2Stream.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/JPXStream.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Lexer.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Link.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/NameToCharCode.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Object.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/OptionalContent.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Outline.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/OutputDev.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Page.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Parser.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/PDF417Barcode.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/PDFDoc.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/PDFDocEncoding.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/PSTokenizer.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Stream.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/TextString.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/UnicodeMap.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/UnicodeRemapping.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/UnicodeTypeTable.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/UTF8.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/XFAScanner.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/XRef.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Zoox.cc.o" + +xpdf/pdftoppm: xpdf/CMakeFiles/pdftoppm.dir/ShadingImage.cc.o +xpdf/pdftoppm: xpdf/CMakeFiles/pdftoppm.dir/SplashOutputDev.cc.o +xpdf/pdftoppm: xpdf/CMakeFiles/pdftoppm.dir/pdftoppm.cc.o +xpdf/pdftoppm: xpdf/CMakeFiles/xpdf_objs.dir/AcroForm.cc.o +xpdf/pdftoppm: xpdf/CMakeFiles/xpdf_objs.dir/Annot.cc.o +xpdf/pdftoppm: xpdf/CMakeFiles/xpdf_objs.dir/Array.cc.o +xpdf/pdftoppm: xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFont.cc.o +xpdf/pdftoppm: xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFontTables.cc.o +xpdf/pdftoppm: xpdf/CMakeFiles/xpdf_objs.dir/Catalog.cc.o +xpdf/pdftoppm: xpdf/CMakeFiles/xpdf_objs.dir/CharCodeToUnicode.cc.o +xpdf/pdftoppm: xpdf/CMakeFiles/xpdf_objs.dir/CMap.cc.o +xpdf/pdftoppm: xpdf/CMakeFiles/xpdf_objs.dir/Decrypt.cc.o +xpdf/pdftoppm: xpdf/CMakeFiles/xpdf_objs.dir/Dict.cc.o +xpdf/pdftoppm: xpdf/CMakeFiles/xpdf_objs.dir/Error.cc.o +xpdf/pdftoppm: xpdf/CMakeFiles/xpdf_objs.dir/FontEncodingTables.cc.o +xpdf/pdftoppm: xpdf/CMakeFiles/xpdf_objs.dir/Function.cc.o +xpdf/pdftoppm: xpdf/CMakeFiles/xpdf_objs.dir/Gfx.cc.o +xpdf/pdftoppm: xpdf/CMakeFiles/xpdf_objs.dir/GfxFont.cc.o +xpdf/pdftoppm: xpdf/CMakeFiles/xpdf_objs.dir/GfxState.cc.o +xpdf/pdftoppm: xpdf/CMakeFiles/xpdf_objs.dir/GlobalParams.cc.o +xpdf/pdftoppm: xpdf/CMakeFiles/xpdf_objs.dir/JArithmeticDecoder.cc.o +xpdf/pdftoppm: xpdf/CMakeFiles/xpdf_objs.dir/JBIG2Stream.cc.o +xpdf/pdftoppm: xpdf/CMakeFiles/xpdf_objs.dir/JPXStream.cc.o +xpdf/pdftoppm: xpdf/CMakeFiles/xpdf_objs.dir/Lexer.cc.o +xpdf/pdftoppm: xpdf/CMakeFiles/xpdf_objs.dir/Link.cc.o +xpdf/pdftoppm: xpdf/CMakeFiles/xpdf_objs.dir/NameToCharCode.cc.o +xpdf/pdftoppm: xpdf/CMakeFiles/xpdf_objs.dir/Object.cc.o +xpdf/pdftoppm: xpdf/CMakeFiles/xpdf_objs.dir/OptionalContent.cc.o +xpdf/pdftoppm: xpdf/CMakeFiles/xpdf_objs.dir/Outline.cc.o +xpdf/pdftoppm: xpdf/CMakeFiles/xpdf_objs.dir/OutputDev.cc.o +xpdf/pdftoppm: xpdf/CMakeFiles/xpdf_objs.dir/Page.cc.o +xpdf/pdftoppm: xpdf/CMakeFiles/xpdf_objs.dir/Parser.cc.o +xpdf/pdftoppm: xpdf/CMakeFiles/xpdf_objs.dir/PDF417Barcode.cc.o +xpdf/pdftoppm: xpdf/CMakeFiles/xpdf_objs.dir/PDFDoc.cc.o +xpdf/pdftoppm: xpdf/CMakeFiles/xpdf_objs.dir/PDFDocEncoding.cc.o +xpdf/pdftoppm: xpdf/CMakeFiles/xpdf_objs.dir/PSTokenizer.cc.o +xpdf/pdftoppm: xpdf/CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.o +xpdf/pdftoppm: xpdf/CMakeFiles/xpdf_objs.dir/Stream.cc.o +xpdf/pdftoppm: xpdf/CMakeFiles/xpdf_objs.dir/TextString.cc.o +xpdf/pdftoppm: xpdf/CMakeFiles/xpdf_objs.dir/UnicodeMap.cc.o +xpdf/pdftoppm: xpdf/CMakeFiles/xpdf_objs.dir/UnicodeRemapping.cc.o +xpdf/pdftoppm: xpdf/CMakeFiles/xpdf_objs.dir/UnicodeTypeTable.cc.o +xpdf/pdftoppm: xpdf/CMakeFiles/xpdf_objs.dir/UTF8.cc.o +xpdf/pdftoppm: xpdf/CMakeFiles/xpdf_objs.dir/XFAScanner.cc.o +xpdf/pdftoppm: xpdf/CMakeFiles/xpdf_objs.dir/XRef.cc.o +xpdf/pdftoppm: xpdf/CMakeFiles/xpdf_objs.dir/Zoox.cc.o +xpdf/pdftoppm: xpdf/CMakeFiles/pdftoppm.dir/build.make +xpdf/pdftoppm: goo/libgoo.a +xpdf/pdftoppm: fofi/libfofi.a +xpdf/pdftoppm: splash/libsplash.a +xpdf/pdftoppm: /usr/lib/x86_64-linux-gnu/libfreetype.so +xpdf/pdftoppm: /usr/lib/x86_64-linux-gnu/libfontconfig.so +xpdf/pdftoppm: xpdf/CMakeFiles/pdftoppm.dir/link.txt + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --bold --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_4) "Linking CXX executable pdftoppm" + cd /home/calvin/src/xpdf-4.04/xpdf && $(CMAKE_COMMAND) -E cmake_link_script CMakeFiles/pdftoppm.dir/link.txt --verbose=$(VERBOSE) + +# Rule to build all files generated by this target. +xpdf/CMakeFiles/pdftoppm.dir/build: xpdf/pdftoppm + +.PHONY : xpdf/CMakeFiles/pdftoppm.dir/build + +xpdf/CMakeFiles/pdftoppm.dir/clean: + cd /home/calvin/src/xpdf-4.04/xpdf && $(CMAKE_COMMAND) -P CMakeFiles/pdftoppm.dir/cmake_clean.cmake +.PHONY : xpdf/CMakeFiles/pdftoppm.dir/clean + +xpdf/CMakeFiles/pdftoppm.dir/depend: + cd /home/calvin/src/xpdf-4.04 && $(CMAKE_COMMAND) -E cmake_depends "Unix Makefiles" /home/calvin/src/xpdf-4.04 /home/calvin/src/xpdf-4.04/xpdf /home/calvin/src/xpdf-4.04 /home/calvin/src/xpdf-4.04/xpdf /home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/pdftoppm.dir/DependInfo.cmake --color=$(COLOR) +.PHONY : xpdf/CMakeFiles/pdftoppm.dir/depend + diff --git a/xpdf/CMakeFiles/pdftoppm.dir/cmake_clean.cmake b/xpdf/CMakeFiles/pdftoppm.dir/cmake_clean.cmake new file mode 100644 index 0000000..ce282b3 --- /dev/null +++ b/xpdf/CMakeFiles/pdftoppm.dir/cmake_clean.cmake @@ -0,0 +1,12 @@ +file(REMOVE_RECURSE + "CMakeFiles/pdftoppm.dir/ShadingImage.cc.o" + "CMakeFiles/pdftoppm.dir/SplashOutputDev.cc.o" + "CMakeFiles/pdftoppm.dir/pdftoppm.cc.o" + "pdftoppm" + "pdftoppm.pdb" +) + +# Per-language clean rules from dependency scanning. +foreach(lang CXX) + include(CMakeFiles/pdftoppm.dir/cmake_clean_${lang}.cmake OPTIONAL) +endforeach() diff --git a/xpdf/CMakeFiles/pdftoppm.dir/depend.internal b/xpdf/CMakeFiles/pdftoppm.dir/depend.internal new file mode 100644 index 0000000..b16d7d4 --- /dev/null +++ b/xpdf/CMakeFiles/pdftoppm.dir/depend.internal @@ -0,0 +1,112 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +xpdf/CMakeFiles/pdftoppm.dir/ShadingImage.cc.o + /home/calvin/src/xpdf-4.04/xpdf/Array.h + /home/calvin/src/xpdf-4.04/xpdf/Dict.h + /home/calvin/src/xpdf-4.04/xpdf/Function.h + /home/calvin/src/xpdf-4.04/xpdf/GfxState.h + /home/calvin/src/xpdf-4.04/xpdf/Object.h + /home/calvin/src/xpdf-4.04/xpdf/ShadingImage.cc + /home/calvin/src/xpdf-4.04/xpdf/ShadingImage.h + /home/calvin/src/xpdf-4.04/xpdf/Stream.h + aconf.h + aconf2.h + goo/FixedPoint.h + goo/GMutex.h + goo/GString.h + goo/Trace.h + goo/gfile.h + goo/gmem.h + goo/gtypes.h + splash/Splash.h + splash/SplashBitmap.h + splash/SplashClip.h + splash/SplashMath.h + splash/SplashPath.h + splash/SplashPattern.h + splash/SplashTypes.h +xpdf/CMakeFiles/pdftoppm.dir/SplashOutputDev.cc.o + /home/calvin/src/xpdf-4.04/xpdf/Array.h + /home/calvin/src/xpdf-4.04/xpdf/BuiltinFont.h + /home/calvin/src/xpdf-4.04/xpdf/BuiltinFontTables.h + /home/calvin/src/xpdf-4.04/xpdf/CharCodeToUnicode.h + /home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + /home/calvin/src/xpdf-4.04/xpdf/Dict.h + /home/calvin/src/xpdf-4.04/xpdf/Error.h + /home/calvin/src/xpdf-4.04/xpdf/FontEncodingTables.h + /home/calvin/src/xpdf-4.04/xpdf/Function.h + /home/calvin/src/xpdf-4.04/xpdf/Gfx.h + /home/calvin/src/xpdf-4.04/xpdf/GfxFont.h + /home/calvin/src/xpdf-4.04/xpdf/GfxState.h + /home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h + /home/calvin/src/xpdf-4.04/xpdf/JPXStream.h + /home/calvin/src/xpdf-4.04/xpdf/Link.h + /home/calvin/src/xpdf-4.04/xpdf/Object.h + /home/calvin/src/xpdf-4.04/xpdf/OutputDev.h + /home/calvin/src/xpdf-4.04/xpdf/ShadingImage.h + /home/calvin/src/xpdf-4.04/xpdf/SplashOutputDev.cc + /home/calvin/src/xpdf-4.04/xpdf/SplashOutputDev.h + /home/calvin/src/xpdf-4.04/xpdf/Stream.h + /home/calvin/src/xpdf-4.04/xpdf/config.h + aconf.h + aconf2.h + fofi/FoFiBase.h + fofi/FoFiTrueType.h + fofi/FoFiType1C.h + goo/FixedPoint.h + goo/GMutex.h + goo/GString.h + goo/Trace.h + goo/gfile.h + goo/gmem.h + goo/gmempp.h + goo/gtypes.h + splash/Splash.h + splash/SplashBitmap.h + splash/SplashClip.h + splash/SplashErrorCodes.h + splash/SplashFont.h + splash/SplashFontEngine.h + splash/SplashFontFile.h + splash/SplashFontFileID.h + splash/SplashGlyphBitmap.h + splash/SplashMath.h + splash/SplashPath.h + splash/SplashPattern.h + splash/SplashScreen.h + splash/SplashState.h + splash/SplashTypes.h +xpdf/CMakeFiles/pdftoppm.dir/pdftoppm.cc.o + /home/calvin/src/xpdf-4.04/xpdf/Array.h + /home/calvin/src/xpdf-4.04/xpdf/Catalog.h + /home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + /home/calvin/src/xpdf-4.04/xpdf/Dict.h + /home/calvin/src/xpdf-4.04/xpdf/Error.h + /home/calvin/src/xpdf-4.04/xpdf/Function.h + /home/calvin/src/xpdf-4.04/xpdf/GfxState.h + /home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h + /home/calvin/src/xpdf-4.04/xpdf/Object.h + /home/calvin/src/xpdf-4.04/xpdf/OutputDev.h + /home/calvin/src/xpdf-4.04/xpdf/PDFDoc.h + /home/calvin/src/xpdf-4.04/xpdf/Page.h + /home/calvin/src/xpdf-4.04/xpdf/SplashOutputDev.h + /home/calvin/src/xpdf-4.04/xpdf/Stream.h + /home/calvin/src/xpdf-4.04/xpdf/XRef.h + /home/calvin/src/xpdf-4.04/xpdf/config.h + /home/calvin/src/xpdf-4.04/xpdf/pdftoppm.cc + aconf.h + aconf2.h + goo/FixedPoint.h + goo/GMutex.h + goo/GString.h + goo/gfile.h + goo/gmem.h + goo/gmempp.h + goo/gtypes.h + goo/parseargs.h + splash/Splash.h + splash/SplashBitmap.h + splash/SplashClip.h + splash/SplashMath.h + splash/SplashTypes.h diff --git a/xpdf/CMakeFiles/pdftoppm.dir/depend.make b/xpdf/CMakeFiles/pdftoppm.dir/depend.make new file mode 100644 index 0000000..5ec2642 --- /dev/null +++ b/xpdf/CMakeFiles/pdftoppm.dir/depend.make @@ -0,0 +1,112 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +xpdf/CMakeFiles/pdftoppm.dir/ShadingImage.cc.o: xpdf/Array.h +xpdf/CMakeFiles/pdftoppm.dir/ShadingImage.cc.o: xpdf/Dict.h +xpdf/CMakeFiles/pdftoppm.dir/ShadingImage.cc.o: xpdf/Function.h +xpdf/CMakeFiles/pdftoppm.dir/ShadingImage.cc.o: xpdf/GfxState.h +xpdf/CMakeFiles/pdftoppm.dir/ShadingImage.cc.o: xpdf/Object.h +xpdf/CMakeFiles/pdftoppm.dir/ShadingImage.cc.o: xpdf/ShadingImage.cc +xpdf/CMakeFiles/pdftoppm.dir/ShadingImage.cc.o: xpdf/ShadingImage.h +xpdf/CMakeFiles/pdftoppm.dir/ShadingImage.cc.o: xpdf/Stream.h +xpdf/CMakeFiles/pdftoppm.dir/ShadingImage.cc.o: aconf.h +xpdf/CMakeFiles/pdftoppm.dir/ShadingImage.cc.o: aconf2.h +xpdf/CMakeFiles/pdftoppm.dir/ShadingImage.cc.o: goo/FixedPoint.h +xpdf/CMakeFiles/pdftoppm.dir/ShadingImage.cc.o: goo/GMutex.h +xpdf/CMakeFiles/pdftoppm.dir/ShadingImage.cc.o: goo/GString.h +xpdf/CMakeFiles/pdftoppm.dir/ShadingImage.cc.o: goo/Trace.h +xpdf/CMakeFiles/pdftoppm.dir/ShadingImage.cc.o: goo/gfile.h +xpdf/CMakeFiles/pdftoppm.dir/ShadingImage.cc.o: goo/gmem.h +xpdf/CMakeFiles/pdftoppm.dir/ShadingImage.cc.o: goo/gtypes.h +xpdf/CMakeFiles/pdftoppm.dir/ShadingImage.cc.o: splash/Splash.h +xpdf/CMakeFiles/pdftoppm.dir/ShadingImage.cc.o: splash/SplashBitmap.h +xpdf/CMakeFiles/pdftoppm.dir/ShadingImage.cc.o: splash/SplashClip.h +xpdf/CMakeFiles/pdftoppm.dir/ShadingImage.cc.o: splash/SplashMath.h +xpdf/CMakeFiles/pdftoppm.dir/ShadingImage.cc.o: splash/SplashPath.h +xpdf/CMakeFiles/pdftoppm.dir/ShadingImage.cc.o: splash/SplashPattern.h +xpdf/CMakeFiles/pdftoppm.dir/ShadingImage.cc.o: splash/SplashTypes.h + +xpdf/CMakeFiles/pdftoppm.dir/SplashOutputDev.cc.o: xpdf/Array.h +xpdf/CMakeFiles/pdftoppm.dir/SplashOutputDev.cc.o: xpdf/BuiltinFont.h +xpdf/CMakeFiles/pdftoppm.dir/SplashOutputDev.cc.o: xpdf/BuiltinFontTables.h +xpdf/CMakeFiles/pdftoppm.dir/SplashOutputDev.cc.o: xpdf/CharCodeToUnicode.h +xpdf/CMakeFiles/pdftoppm.dir/SplashOutputDev.cc.o: xpdf/CharTypes.h +xpdf/CMakeFiles/pdftoppm.dir/SplashOutputDev.cc.o: xpdf/Dict.h +xpdf/CMakeFiles/pdftoppm.dir/SplashOutputDev.cc.o: xpdf/Error.h +xpdf/CMakeFiles/pdftoppm.dir/SplashOutputDev.cc.o: xpdf/FontEncodingTables.h +xpdf/CMakeFiles/pdftoppm.dir/SplashOutputDev.cc.o: xpdf/Function.h +xpdf/CMakeFiles/pdftoppm.dir/SplashOutputDev.cc.o: xpdf/Gfx.h +xpdf/CMakeFiles/pdftoppm.dir/SplashOutputDev.cc.o: xpdf/GfxFont.h +xpdf/CMakeFiles/pdftoppm.dir/SplashOutputDev.cc.o: xpdf/GfxState.h +xpdf/CMakeFiles/pdftoppm.dir/SplashOutputDev.cc.o: xpdf/GlobalParams.h +xpdf/CMakeFiles/pdftoppm.dir/SplashOutputDev.cc.o: xpdf/JPXStream.h +xpdf/CMakeFiles/pdftoppm.dir/SplashOutputDev.cc.o: xpdf/Link.h +xpdf/CMakeFiles/pdftoppm.dir/SplashOutputDev.cc.o: xpdf/Object.h +xpdf/CMakeFiles/pdftoppm.dir/SplashOutputDev.cc.o: xpdf/OutputDev.h +xpdf/CMakeFiles/pdftoppm.dir/SplashOutputDev.cc.o: xpdf/ShadingImage.h +xpdf/CMakeFiles/pdftoppm.dir/SplashOutputDev.cc.o: xpdf/SplashOutputDev.cc +xpdf/CMakeFiles/pdftoppm.dir/SplashOutputDev.cc.o: xpdf/SplashOutputDev.h +xpdf/CMakeFiles/pdftoppm.dir/SplashOutputDev.cc.o: xpdf/Stream.h +xpdf/CMakeFiles/pdftoppm.dir/SplashOutputDev.cc.o: xpdf/config.h +xpdf/CMakeFiles/pdftoppm.dir/SplashOutputDev.cc.o: aconf.h +xpdf/CMakeFiles/pdftoppm.dir/SplashOutputDev.cc.o: aconf2.h +xpdf/CMakeFiles/pdftoppm.dir/SplashOutputDev.cc.o: fofi/FoFiBase.h +xpdf/CMakeFiles/pdftoppm.dir/SplashOutputDev.cc.o: fofi/FoFiTrueType.h +xpdf/CMakeFiles/pdftoppm.dir/SplashOutputDev.cc.o: fofi/FoFiType1C.h +xpdf/CMakeFiles/pdftoppm.dir/SplashOutputDev.cc.o: goo/FixedPoint.h +xpdf/CMakeFiles/pdftoppm.dir/SplashOutputDev.cc.o: goo/GMutex.h +xpdf/CMakeFiles/pdftoppm.dir/SplashOutputDev.cc.o: goo/GString.h +xpdf/CMakeFiles/pdftoppm.dir/SplashOutputDev.cc.o: goo/Trace.h +xpdf/CMakeFiles/pdftoppm.dir/SplashOutputDev.cc.o: goo/gfile.h +xpdf/CMakeFiles/pdftoppm.dir/SplashOutputDev.cc.o: goo/gmem.h +xpdf/CMakeFiles/pdftoppm.dir/SplashOutputDev.cc.o: goo/gmempp.h +xpdf/CMakeFiles/pdftoppm.dir/SplashOutputDev.cc.o: goo/gtypes.h +xpdf/CMakeFiles/pdftoppm.dir/SplashOutputDev.cc.o: splash/Splash.h +xpdf/CMakeFiles/pdftoppm.dir/SplashOutputDev.cc.o: splash/SplashBitmap.h +xpdf/CMakeFiles/pdftoppm.dir/SplashOutputDev.cc.o: splash/SplashClip.h +xpdf/CMakeFiles/pdftoppm.dir/SplashOutputDev.cc.o: splash/SplashErrorCodes.h +xpdf/CMakeFiles/pdftoppm.dir/SplashOutputDev.cc.o: splash/SplashFont.h +xpdf/CMakeFiles/pdftoppm.dir/SplashOutputDev.cc.o: splash/SplashFontEngine.h +xpdf/CMakeFiles/pdftoppm.dir/SplashOutputDev.cc.o: splash/SplashFontFile.h +xpdf/CMakeFiles/pdftoppm.dir/SplashOutputDev.cc.o: splash/SplashFontFileID.h +xpdf/CMakeFiles/pdftoppm.dir/SplashOutputDev.cc.o: splash/SplashGlyphBitmap.h +xpdf/CMakeFiles/pdftoppm.dir/SplashOutputDev.cc.o: splash/SplashMath.h +xpdf/CMakeFiles/pdftoppm.dir/SplashOutputDev.cc.o: splash/SplashPath.h +xpdf/CMakeFiles/pdftoppm.dir/SplashOutputDev.cc.o: splash/SplashPattern.h +xpdf/CMakeFiles/pdftoppm.dir/SplashOutputDev.cc.o: splash/SplashScreen.h +xpdf/CMakeFiles/pdftoppm.dir/SplashOutputDev.cc.o: splash/SplashState.h +xpdf/CMakeFiles/pdftoppm.dir/SplashOutputDev.cc.o: splash/SplashTypes.h + +xpdf/CMakeFiles/pdftoppm.dir/pdftoppm.cc.o: xpdf/Array.h +xpdf/CMakeFiles/pdftoppm.dir/pdftoppm.cc.o: xpdf/Catalog.h +xpdf/CMakeFiles/pdftoppm.dir/pdftoppm.cc.o: xpdf/CharTypes.h +xpdf/CMakeFiles/pdftoppm.dir/pdftoppm.cc.o: xpdf/Dict.h +xpdf/CMakeFiles/pdftoppm.dir/pdftoppm.cc.o: xpdf/Error.h +xpdf/CMakeFiles/pdftoppm.dir/pdftoppm.cc.o: xpdf/Function.h +xpdf/CMakeFiles/pdftoppm.dir/pdftoppm.cc.o: xpdf/GfxState.h +xpdf/CMakeFiles/pdftoppm.dir/pdftoppm.cc.o: xpdf/GlobalParams.h +xpdf/CMakeFiles/pdftoppm.dir/pdftoppm.cc.o: xpdf/Object.h +xpdf/CMakeFiles/pdftoppm.dir/pdftoppm.cc.o: xpdf/OutputDev.h +xpdf/CMakeFiles/pdftoppm.dir/pdftoppm.cc.o: xpdf/PDFDoc.h +xpdf/CMakeFiles/pdftoppm.dir/pdftoppm.cc.o: xpdf/Page.h +xpdf/CMakeFiles/pdftoppm.dir/pdftoppm.cc.o: xpdf/SplashOutputDev.h +xpdf/CMakeFiles/pdftoppm.dir/pdftoppm.cc.o: xpdf/Stream.h +xpdf/CMakeFiles/pdftoppm.dir/pdftoppm.cc.o: xpdf/XRef.h +xpdf/CMakeFiles/pdftoppm.dir/pdftoppm.cc.o: xpdf/config.h +xpdf/CMakeFiles/pdftoppm.dir/pdftoppm.cc.o: xpdf/pdftoppm.cc +xpdf/CMakeFiles/pdftoppm.dir/pdftoppm.cc.o: aconf.h +xpdf/CMakeFiles/pdftoppm.dir/pdftoppm.cc.o: aconf2.h +xpdf/CMakeFiles/pdftoppm.dir/pdftoppm.cc.o: goo/FixedPoint.h +xpdf/CMakeFiles/pdftoppm.dir/pdftoppm.cc.o: goo/GMutex.h +xpdf/CMakeFiles/pdftoppm.dir/pdftoppm.cc.o: goo/GString.h +xpdf/CMakeFiles/pdftoppm.dir/pdftoppm.cc.o: goo/gfile.h +xpdf/CMakeFiles/pdftoppm.dir/pdftoppm.cc.o: goo/gmem.h +xpdf/CMakeFiles/pdftoppm.dir/pdftoppm.cc.o: goo/gmempp.h +xpdf/CMakeFiles/pdftoppm.dir/pdftoppm.cc.o: goo/gtypes.h +xpdf/CMakeFiles/pdftoppm.dir/pdftoppm.cc.o: goo/parseargs.h +xpdf/CMakeFiles/pdftoppm.dir/pdftoppm.cc.o: splash/Splash.h +xpdf/CMakeFiles/pdftoppm.dir/pdftoppm.cc.o: splash/SplashBitmap.h +xpdf/CMakeFiles/pdftoppm.dir/pdftoppm.cc.o: splash/SplashClip.h +xpdf/CMakeFiles/pdftoppm.dir/pdftoppm.cc.o: splash/SplashMath.h +xpdf/CMakeFiles/pdftoppm.dir/pdftoppm.cc.o: splash/SplashTypes.h + diff --git a/xpdf/CMakeFiles/pdftoppm.dir/flags.make b/xpdf/CMakeFiles/pdftoppm.dir/flags.make new file mode 100644 index 0000000..300fa3e --- /dev/null +++ b/xpdf/CMakeFiles/pdftoppm.dir/flags.make @@ -0,0 +1,10 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +# compile CXX with /usr/bin/c++ +CXX_DEFINES = + +CXX_INCLUDES = -I/home/calvin/src/xpdf-4.04 -I/home/calvin/src/xpdf-4.04/goo -I/home/calvin/src/xpdf-4.04/fofi -I/home/calvin/src/xpdf-4.04/splash + +CXX_FLAGS = + diff --git a/xpdf/CMakeFiles/pdftoppm.dir/link.txt b/xpdf/CMakeFiles/pdftoppm.dir/link.txt new file mode 100644 index 0000000..5ae1f1d --- /dev/null +++ b/xpdf/CMakeFiles/pdftoppm.dir/link.txt @@ -0,0 +1 @@ +/usr/bin/c++ -rdynamic CMakeFiles/pdftoppm.dir/ShadingImage.cc.o CMakeFiles/pdftoppm.dir/SplashOutputDev.cc.o CMakeFiles/pdftoppm.dir/pdftoppm.cc.o CMakeFiles/xpdf_objs.dir/AcroForm.cc.o CMakeFiles/xpdf_objs.dir/Annot.cc.o CMakeFiles/xpdf_objs.dir/Array.cc.o CMakeFiles/xpdf_objs.dir/BuiltinFont.cc.o CMakeFiles/xpdf_objs.dir/BuiltinFontTables.cc.o CMakeFiles/xpdf_objs.dir/Catalog.cc.o CMakeFiles/xpdf_objs.dir/CharCodeToUnicode.cc.o CMakeFiles/xpdf_objs.dir/CMap.cc.o CMakeFiles/xpdf_objs.dir/Decrypt.cc.o CMakeFiles/xpdf_objs.dir/Dict.cc.o CMakeFiles/xpdf_objs.dir/Error.cc.o CMakeFiles/xpdf_objs.dir/FontEncodingTables.cc.o CMakeFiles/xpdf_objs.dir/Function.cc.o CMakeFiles/xpdf_objs.dir/Gfx.cc.o CMakeFiles/xpdf_objs.dir/GfxFont.cc.o CMakeFiles/xpdf_objs.dir/GfxState.cc.o CMakeFiles/xpdf_objs.dir/GlobalParams.cc.o CMakeFiles/xpdf_objs.dir/JArithmeticDecoder.cc.o CMakeFiles/xpdf_objs.dir/JBIG2Stream.cc.o CMakeFiles/xpdf_objs.dir/JPXStream.cc.o CMakeFiles/xpdf_objs.dir/Lexer.cc.o CMakeFiles/xpdf_objs.dir/Link.cc.o CMakeFiles/xpdf_objs.dir/NameToCharCode.cc.o CMakeFiles/xpdf_objs.dir/Object.cc.o CMakeFiles/xpdf_objs.dir/OptionalContent.cc.o CMakeFiles/xpdf_objs.dir/Outline.cc.o CMakeFiles/xpdf_objs.dir/OutputDev.cc.o CMakeFiles/xpdf_objs.dir/Page.cc.o CMakeFiles/xpdf_objs.dir/Parser.cc.o CMakeFiles/xpdf_objs.dir/PDF417Barcode.cc.o CMakeFiles/xpdf_objs.dir/PDFDoc.cc.o CMakeFiles/xpdf_objs.dir/PDFDocEncoding.cc.o CMakeFiles/xpdf_objs.dir/PSTokenizer.cc.o CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.o CMakeFiles/xpdf_objs.dir/Stream.cc.o CMakeFiles/xpdf_objs.dir/TextString.cc.o CMakeFiles/xpdf_objs.dir/UnicodeMap.cc.o CMakeFiles/xpdf_objs.dir/UnicodeRemapping.cc.o CMakeFiles/xpdf_objs.dir/UnicodeTypeTable.cc.o CMakeFiles/xpdf_objs.dir/UTF8.cc.o CMakeFiles/xpdf_objs.dir/XFAScanner.cc.o CMakeFiles/xpdf_objs.dir/XRef.cc.o CMakeFiles/xpdf_objs.dir/Zoox.cc.o -o pdftoppm ../goo/libgoo.a ../fofi/libfofi.a ../splash/libsplash.a -lfreetype -lfontconfig -lpthread diff --git a/xpdf/CMakeFiles/pdftoppm.dir/pdftoppm.cc.o b/xpdf/CMakeFiles/pdftoppm.dir/pdftoppm.cc.o new file mode 100644 index 0000000..dac6dcd Binary files /dev/null and b/xpdf/CMakeFiles/pdftoppm.dir/pdftoppm.cc.o differ diff --git a/xpdf/CMakeFiles/pdftoppm.dir/progress.make b/xpdf/CMakeFiles/pdftoppm.dir/progress.make new file mode 100644 index 0000000..5bc3364 --- /dev/null +++ b/xpdf/CMakeFiles/pdftoppm.dir/progress.make @@ -0,0 +1,5 @@ +CMAKE_PROGRESS_1 = 28 +CMAKE_PROGRESS_2 = +CMAKE_PROGRESS_3 = 29 +CMAKE_PROGRESS_4 = 30 + diff --git a/xpdf/CMakeFiles/pdftops.dir/CXX.includecache b/xpdf/CMakeFiles/pdftops.dir/CXX.includecache new file mode 100644 index 0000000..0059595 --- /dev/null +++ b/xpdf/CMakeFiles/pdftops.dir/CXX.includecache @@ -0,0 +1,740 @@ +#IncludeRegexLine: ^[ ]*[#%][ ]*(include|import)[ ]*[<"]([^">]+)([">]) + +#IncludeRegexScan: ^.*$ + +#IncludeRegexComplain: ^$ + +#IncludeRegexTransform: + +/home/calvin/src/xpdf-4.04/xpdf/AcroForm.h +aconf.h +- + +/home/calvin/src/xpdf-4.04/xpdf/Annot.h +aconf.h +- + +/home/calvin/src/xpdf-4.04/xpdf/Array.h +aconf.h +- +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h + +/home/calvin/src/xpdf-4.04/xpdf/BuiltinFont.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h + +/home/calvin/src/xpdf-4.04/xpdf/BuiltinFontTables.h +BuiltinFont.h +/home/calvin/src/xpdf-4.04/xpdf/BuiltinFont.h + +/home/calvin/src/xpdf-4.04/xpdf/Catalog.h +aconf.h +- +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h +CharTypes.h +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + +/home/calvin/src/xpdf-4.04/xpdf/CharCodeToUnicode.h +aconf.h +- +CharTypes.h +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h + +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + +/home/calvin/src/xpdf-4.04/xpdf/Dict.h +aconf.h +- +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h + +/home/calvin/src/xpdf-4.04/xpdf/Error.h +aconf.h +- +stdio.h +- +config.h +/home/calvin/src/xpdf-4.04/xpdf/config.h +gfile.h +/home/calvin/src/xpdf-4.04/xpdf/gfile.h + +/home/calvin/src/xpdf-4.04/xpdf/FontEncodingTables.h + +/home/calvin/src/xpdf-4.04/xpdf/Function.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h + +/home/calvin/src/xpdf-4.04/xpdf/Gfx.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +gfile.h +/home/calvin/src/xpdf-4.04/xpdf/gfile.h +GfxState.h +/home/calvin/src/xpdf-4.04/xpdf/GfxState.h + +/home/calvin/src/xpdf-4.04/xpdf/GfxFont.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +GString.h +/home/calvin/src/xpdf-4.04/xpdf/GString.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h +CharTypes.h +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + +/home/calvin/src/xpdf-4.04/xpdf/GfxState.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h +Function.h +/home/calvin/src/xpdf-4.04/xpdf/Function.h + +/home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h +aconf.h +- +stdio.h +- +windows.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +CharTypes.h +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h + +/home/calvin/src/xpdf-4.04/xpdf/JPXStream.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h +Stream.h +/home/calvin/src/xpdf-4.04/xpdf/Stream.h + +/home/calvin/src/xpdf-4.04/xpdf/Link.h +aconf.h +- +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h + +/home/calvin/src/xpdf-4.04/xpdf/Object.h +aconf.h +- +stdio.h +- +string.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +gmem.h +/home/calvin/src/xpdf-4.04/xpdf/gmem.h +gfile.h +/home/calvin/src/xpdf-4.04/xpdf/gfile.h +GString.h +/home/calvin/src/xpdf-4.04/xpdf/GString.h +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h +Array.h +/home/calvin/src/xpdf-4.04/xpdf/Array.h +Dict.h +/home/calvin/src/xpdf-4.04/xpdf/Dict.h +Stream.h +/home/calvin/src/xpdf-4.04/xpdf/Stream.h + +/home/calvin/src/xpdf-4.04/xpdf/OutputDev.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +CharTypes.h +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + +/home/calvin/src/xpdf-4.04/xpdf/PDFDoc.h +aconf.h +- +stdio.h +- +XRef.h +/home/calvin/src/xpdf-4.04/xpdf/XRef.h +Catalog.h +/home/calvin/src/xpdf-4.04/xpdf/Catalog.h +Page.h +/home/calvin/src/xpdf-4.04/xpdf/Page.h + +/home/calvin/src/xpdf-4.04/xpdf/PSOutputDev.cc +aconf.h +- +stdio.h +- +stddef.h +- +stdarg.h +- +signal.h +- +math.h +- +gmempp.h +/home/calvin/src/xpdf-4.04/xpdf/gmempp.h +GString.h +/home/calvin/src/xpdf-4.04/xpdf/GString.h +GList.h +/home/calvin/src/xpdf-4.04/xpdf/GList.h +GHash.h +/home/calvin/src/xpdf-4.04/xpdf/GHash.h +config.h +/home/calvin/src/xpdf-4.04/xpdf/config.h +GlobalParams.h +/home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h +Error.h +/home/calvin/src/xpdf-4.04/xpdf/Error.h +Function.h +/home/calvin/src/xpdf-4.04/xpdf/Function.h +Gfx.h +/home/calvin/src/xpdf-4.04/xpdf/Gfx.h +GfxState.h +/home/calvin/src/xpdf-4.04/xpdf/GfxState.h +GfxFont.h +/home/calvin/src/xpdf-4.04/xpdf/GfxFont.h +UnicodeMap.h +/home/calvin/src/xpdf-4.04/xpdf/UnicodeMap.h +FoFiType1C.h +/home/calvin/src/xpdf-4.04/xpdf/FoFiType1C.h +FoFiTrueType.h +/home/calvin/src/xpdf-4.04/xpdf/FoFiTrueType.h +Catalog.h +/home/calvin/src/xpdf-4.04/xpdf/Catalog.h +Page.h +/home/calvin/src/xpdf-4.04/xpdf/Page.h +Stream.h +/home/calvin/src/xpdf-4.04/xpdf/Stream.h +Annot.h +/home/calvin/src/xpdf-4.04/xpdf/Annot.h +PDFDoc.h +/home/calvin/src/xpdf-4.04/xpdf/PDFDoc.h +XRef.h +/home/calvin/src/xpdf-4.04/xpdf/XRef.h +PreScanOutputDev.h +/home/calvin/src/xpdf-4.04/xpdf/PreScanOutputDev.h +CharCodeToUnicode.h +/home/calvin/src/xpdf-4.04/xpdf/CharCodeToUnicode.h +AcroForm.h +/home/calvin/src/xpdf-4.04/xpdf/AcroForm.h +TextString.h +/home/calvin/src/xpdf-4.04/xpdf/TextString.h +Splash.h +/home/calvin/src/xpdf-4.04/xpdf/Splash.h +SplashBitmap.h +/home/calvin/src/xpdf-4.04/xpdf/SplashBitmap.h +SplashOutputDev.h +/home/calvin/src/xpdf-4.04/xpdf/SplashOutputDev.h +PSOutputDev.h +/home/calvin/src/xpdf-4.04/xpdf/PSOutputDev.h + +/home/calvin/src/xpdf-4.04/xpdf/PSOutputDev.h +aconf.h +- +stddef.h +- +config.h +/home/calvin/src/xpdf-4.04/xpdf/config.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h +GlobalParams.h +/home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h +OutputDev.h +/home/calvin/src/xpdf-4.04/xpdf/OutputDev.h + +/home/calvin/src/xpdf-4.04/xpdf/Page.h +aconf.h +- +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h + +/home/calvin/src/xpdf-4.04/xpdf/PreScanOutputDev.cc +aconf.h +- +math.h +- +gmempp.h +/home/calvin/src/xpdf-4.04/xpdf/gmempp.h +GlobalParams.h +/home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h +Page.h +/home/calvin/src/xpdf-4.04/xpdf/Page.h +Gfx.h +/home/calvin/src/xpdf-4.04/xpdf/Gfx.h +GfxFont.h +/home/calvin/src/xpdf-4.04/xpdf/GfxFont.h +Link.h +/home/calvin/src/xpdf-4.04/xpdf/Link.h +PreScanOutputDev.h +/home/calvin/src/xpdf-4.04/xpdf/PreScanOutputDev.h + +/home/calvin/src/xpdf-4.04/xpdf/PreScanOutputDev.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +GfxState.h +/home/calvin/src/xpdf-4.04/xpdf/GfxState.h +OutputDev.h +/home/calvin/src/xpdf-4.04/xpdf/OutputDev.h + +/home/calvin/src/xpdf-4.04/xpdf/ShadingImage.cc +aconf.h +- +math.h +- +Trace.h +/home/calvin/src/xpdf-4.04/xpdf/Trace.h +GfxState.h +/home/calvin/src/xpdf-4.04/xpdf/GfxState.h +SplashBitmap.h +/home/calvin/src/xpdf-4.04/xpdf/SplashBitmap.h +SplashPattern.h +/home/calvin/src/xpdf-4.04/xpdf/SplashPattern.h +SplashPath.h +/home/calvin/src/xpdf-4.04/xpdf/SplashPath.h +Splash.h +/home/calvin/src/xpdf-4.04/xpdf/Splash.h +ShadingImage.h +/home/calvin/src/xpdf-4.04/xpdf/ShadingImage.h + +/home/calvin/src/xpdf-4.04/xpdf/ShadingImage.h +aconf.h +- +SplashTypes.h +/home/calvin/src/xpdf-4.04/xpdf/SplashTypes.h + +/home/calvin/src/xpdf-4.04/xpdf/SplashOutputDev.cc +aconf.h +- +string.h +- +math.h +- +limits.h +- +gmempp.h +/home/calvin/src/xpdf-4.04/xpdf/gmempp.h +gfile.h +/home/calvin/src/xpdf-4.04/xpdf/gfile.h +Trace.h +/home/calvin/src/xpdf-4.04/xpdf/Trace.h +GlobalParams.h +/home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h +Error.h +/home/calvin/src/xpdf-4.04/xpdf/Error.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h +Gfx.h +/home/calvin/src/xpdf-4.04/xpdf/Gfx.h +GfxFont.h +/home/calvin/src/xpdf-4.04/xpdf/GfxFont.h +ShadingImage.h +/home/calvin/src/xpdf-4.04/xpdf/ShadingImage.h +Link.h +/home/calvin/src/xpdf-4.04/xpdf/Link.h +CharCodeToUnicode.h +/home/calvin/src/xpdf-4.04/xpdf/CharCodeToUnicode.h +FontEncodingTables.h +/home/calvin/src/xpdf-4.04/xpdf/FontEncodingTables.h +BuiltinFont.h +/home/calvin/src/xpdf-4.04/xpdf/BuiltinFont.h +BuiltinFontTables.h +/home/calvin/src/xpdf-4.04/xpdf/BuiltinFontTables.h +FoFiTrueType.h +/home/calvin/src/xpdf-4.04/xpdf/FoFiTrueType.h +FoFiType1C.h +/home/calvin/src/xpdf-4.04/xpdf/FoFiType1C.h +JPXStream.h +/home/calvin/src/xpdf-4.04/xpdf/JPXStream.h +SplashBitmap.h +/home/calvin/src/xpdf-4.04/xpdf/SplashBitmap.h +SplashGlyphBitmap.h +/home/calvin/src/xpdf-4.04/xpdf/SplashGlyphBitmap.h +SplashPattern.h +/home/calvin/src/xpdf-4.04/xpdf/SplashPattern.h +SplashScreen.h +/home/calvin/src/xpdf-4.04/xpdf/SplashScreen.h +SplashPath.h +/home/calvin/src/xpdf-4.04/xpdf/SplashPath.h +SplashState.h +/home/calvin/src/xpdf-4.04/xpdf/SplashState.h +SplashErrorCodes.h +/home/calvin/src/xpdf-4.04/xpdf/SplashErrorCodes.h +SplashFontEngine.h +/home/calvin/src/xpdf-4.04/xpdf/SplashFontEngine.h +SplashFont.h +/home/calvin/src/xpdf-4.04/xpdf/SplashFont.h +SplashFontFile.h +/home/calvin/src/xpdf-4.04/xpdf/SplashFontFile.h +SplashFontFileID.h +/home/calvin/src/xpdf-4.04/xpdf/SplashFontFileID.h +Splash.h +/home/calvin/src/xpdf-4.04/xpdf/Splash.h +SplashOutputDev.h +/home/calvin/src/xpdf-4.04/xpdf/SplashOutputDev.h + +/home/calvin/src/xpdf-4.04/xpdf/SplashOutputDev.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +SplashTypes.h +/home/calvin/src/xpdf-4.04/xpdf/SplashTypes.h +config.h +/home/calvin/src/xpdf-4.04/xpdf/config.h +OutputDev.h +/home/calvin/src/xpdf-4.04/xpdf/OutputDev.h +GfxState.h +/home/calvin/src/xpdf-4.04/xpdf/GfxState.h + +/home/calvin/src/xpdf-4.04/xpdf/Stream.h +aconf.h +- +stdio.h +- +jpeglib.h +- +setjmp.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +gfile.h +/home/calvin/src/xpdf-4.04/xpdf/gfile.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h + +/home/calvin/src/xpdf-4.04/xpdf/TextString.h +aconf.h +- +CharTypes.h +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + +/home/calvin/src/xpdf-4.04/xpdf/UnicodeMap.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +CharTypes.h +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h + +/home/calvin/src/xpdf-4.04/xpdf/XRef.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +gfile.h +/home/calvin/src/xpdf-4.04/xpdf/gfile.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h + +/home/calvin/src/xpdf-4.04/xpdf/config.h + +/home/calvin/src/xpdf-4.04/xpdf/pdftops.cc +aconf.h +- +stdio.h +- +stdlib.h +- +stddef.h +- +string.h +- +fenv.h +- +fpu_control.h +- +gmem.h +/home/calvin/src/xpdf-4.04/xpdf/gmem.h +gmempp.h +/home/calvin/src/xpdf-4.04/xpdf/gmempp.h +parseargs.h +/home/calvin/src/xpdf-4.04/xpdf/parseargs.h +GString.h +/home/calvin/src/xpdf-4.04/xpdf/GString.h +GlobalParams.h +/home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h +Stream.h +/home/calvin/src/xpdf-4.04/xpdf/Stream.h +Array.h +/home/calvin/src/xpdf-4.04/xpdf/Array.h +Dict.h +/home/calvin/src/xpdf-4.04/xpdf/Dict.h +XRef.h +/home/calvin/src/xpdf-4.04/xpdf/XRef.h +Catalog.h +/home/calvin/src/xpdf-4.04/xpdf/Catalog.h +Page.h +/home/calvin/src/xpdf-4.04/xpdf/Page.h +PDFDoc.h +/home/calvin/src/xpdf-4.04/xpdf/PDFDoc.h +PSOutputDev.h +/home/calvin/src/xpdf-4.04/xpdf/PSOutputDev.h +Error.h +/home/calvin/src/xpdf-4.04/xpdf/Error.h +config.h +/home/calvin/src/xpdf-4.04/xpdf/config.h + +aconf.h +aconf2.h +- + +aconf2.h +AvailabilityMacros.h +- + +fofi/FoFiBase.h +aconf.h +- +gtypes.h +fofi/gtypes.h + +fofi/FoFiTrueType.h +aconf.h +- +gtypes.h +fofi/gtypes.h +FoFiBase.h +fofi/FoFiBase.h + +fofi/FoFiType1C.h +aconf.h +- +gtypes.h +fofi/gtypes.h +FoFiBase.h +fofi/FoFiBase.h + +goo/FixedPoint.h +aconf.h +- +stdio.h +- +stdlib.h +- +gtypes.h +goo/gtypes.h + +goo/GHash.h +aconf.h +- +gtypes.h +goo/gtypes.h + +goo/GList.h +aconf.h +- +gtypes.h +goo/gtypes.h + +goo/GMutex.h +aconf.h +- +windows.h +- +intrin.h +- +pthread.h +- + +goo/GString.h +aconf.h +- +limits.h +- +stdarg.h +- +gtypes.h +goo/gtypes.h + +goo/Trace.h +aconf.h +- + +goo/gfile.h +aconf.h +- +stdio.h +- +stdlib.h +- +stddef.h +- +sys/stat.h +- +win32lib.h +- +windows.h +- +unistd.h +- +sys/types.h +- +gtypes.h +goo/gtypes.h + +goo/gmem.h +stdio.h +- +aconf.h +- + +goo/gmempp.h +stdlib.h +- + +goo/gtypes.h + +goo/parseargs.h +gtypes.h +goo/gtypes.h + +splash/Splash.h +aconf.h +- +SplashTypes.h +splash/SplashTypes.h +SplashClip.h +splash/SplashClip.h + +splash/SplashBitmap.h +aconf.h +- +stdio.h +- +limits.h +- +stdint.h +- +SplashTypes.h +splash/SplashTypes.h + +splash/SplashClip.h +aconf.h +- +SplashTypes.h +splash/SplashTypes.h +SplashMath.h +splash/SplashMath.h + +splash/SplashErrorCodes.h +aconf.h +- + +splash/SplashFont.h +aconf.h +- +gtypes.h +splash/gtypes.h +SplashTypes.h +splash/SplashTypes.h +SplashMath.h +splash/SplashMath.h + +splash/SplashFontEngine.h +aconf.h +- +gtypes.h +splash/gtypes.h + +splash/SplashFontFile.h +aconf.h +- +gtypes.h +splash/gtypes.h +SplashTypes.h +splash/SplashTypes.h +GMutex.h +splash/GMutex.h + +splash/SplashFontFileID.h +aconf.h +- +gtypes.h +splash/gtypes.h + +splash/SplashGlyphBitmap.h +aconf.h +- +gtypes.h +splash/gtypes.h + +splash/SplashMath.h +aconf.h +- +FixedPoint.h +splash/FixedPoint.h +math.h +- +emmintrin.h +- +SplashTypes.h +splash/SplashTypes.h + +splash/SplashPath.h +aconf.h +- +SplashTypes.h +splash/SplashTypes.h + +splash/SplashPattern.h +aconf.h +- +SplashTypes.h +splash/SplashTypes.h + +splash/SplashScreen.h +aconf.h +- +SplashTypes.h +splash/SplashTypes.h + +splash/SplashState.h +aconf.h +- +SplashTypes.h +splash/SplashTypes.h + +splash/SplashTypes.h +aconf.h +- +gtypes.h +splash/gtypes.h +FixedPoint.h +splash/FixedPoint.h + diff --git a/xpdf/CMakeFiles/pdftops.dir/DependInfo.cmake b/xpdf/CMakeFiles/pdftops.dir/DependInfo.cmake new file mode 100644 index 0000000..b67d102 --- /dev/null +++ b/xpdf/CMakeFiles/pdftops.dir/DependInfo.cmake @@ -0,0 +1,31 @@ +# The set of languages for which implicit dependencies are needed: +set(CMAKE_DEPENDS_LANGUAGES + "CXX" + ) +# The set of files for implicit dependencies of each language: +set(CMAKE_DEPENDS_CHECK_CXX + "/home/calvin/src/xpdf-4.04/xpdf/PSOutputDev.cc" "/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/pdftops.dir/PSOutputDev.cc.o" + "/home/calvin/src/xpdf-4.04/xpdf/PreScanOutputDev.cc" "/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/pdftops.dir/PreScanOutputDev.cc.o" + "/home/calvin/src/xpdf-4.04/xpdf/ShadingImage.cc" "/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/pdftops.dir/ShadingImage.cc.o" + "/home/calvin/src/xpdf-4.04/xpdf/SplashOutputDev.cc" "/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/pdftops.dir/SplashOutputDev.cc.o" + "/home/calvin/src/xpdf-4.04/xpdf/pdftops.cc" "/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/pdftops.dir/pdftops.cc.o" + ) +set(CMAKE_CXX_COMPILER_ID "GNU") + +# The include file search paths: +set(CMAKE_CXX_TARGET_INCLUDE_PATH + "." + "goo" + "fofi" + "splash" + ) + +# Targets to which this target links. +set(CMAKE_TARGET_LINKED_INFO_FILES + "/home/calvin/src/xpdf-4.04/goo/CMakeFiles/goo.dir/DependInfo.cmake" + "/home/calvin/src/xpdf-4.04/fofi/CMakeFiles/fofi.dir/DependInfo.cmake" + "/home/calvin/src/xpdf-4.04/splash/CMakeFiles/splash.dir/DependInfo.cmake" + ) + +# Fortran module output directory. +set(CMAKE_Fortran_TARGET_MODULE_DIR "") diff --git a/xpdf/CMakeFiles/pdftops.dir/PSOutputDev.cc.o b/xpdf/CMakeFiles/pdftops.dir/PSOutputDev.cc.o new file mode 100644 index 0000000..188db5b Binary files /dev/null and b/xpdf/CMakeFiles/pdftops.dir/PSOutputDev.cc.o differ diff --git a/xpdf/CMakeFiles/pdftops.dir/PreScanOutputDev.cc.o b/xpdf/CMakeFiles/pdftops.dir/PreScanOutputDev.cc.o new file mode 100644 index 0000000..cdfd031 Binary files /dev/null and b/xpdf/CMakeFiles/pdftops.dir/PreScanOutputDev.cc.o differ diff --git a/xpdf/CMakeFiles/pdftops.dir/ShadingImage.cc.o b/xpdf/CMakeFiles/pdftops.dir/ShadingImage.cc.o new file mode 100644 index 0000000..d53401f Binary files /dev/null and b/xpdf/CMakeFiles/pdftops.dir/ShadingImage.cc.o differ diff --git a/xpdf/CMakeFiles/pdftops.dir/SplashOutputDev.cc.o b/xpdf/CMakeFiles/pdftops.dir/SplashOutputDev.cc.o new file mode 100644 index 0000000..7fdcd23 Binary files /dev/null and b/xpdf/CMakeFiles/pdftops.dir/SplashOutputDev.cc.o differ diff --git a/xpdf/CMakeFiles/pdftops.dir/build.make b/xpdf/CMakeFiles/pdftops.dir/build.make new file mode 100644 index 0000000..993be55 --- /dev/null +++ b/xpdf/CMakeFiles/pdftops.dir/build.make @@ -0,0 +1,268 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +# Delete rule output on recipe failure. +.DELETE_ON_ERROR: + + +#============================================================================= +# Special targets provided by cmake. + +# Disable implicit rules so canonical targets will work. +.SUFFIXES: + + +# Disable VCS-based implicit rules. +% : %,v + + +# Disable VCS-based implicit rules. +% : RCS/% + + +# Disable VCS-based implicit rules. +% : RCS/%,v + + +# Disable VCS-based implicit rules. +% : SCCS/s.% + + +# Disable VCS-based implicit rules. +% : s.% + + +.SUFFIXES: .hpux_make_needs_suffix_list + + +# Command-line flag to silence nested $(MAKE). +$(VERBOSE)MAKESILENT = -s + +#Suppress display of executed commands. +$(VERBOSE).SILENT: + +# A target that is always out of date. +cmake_force: + +.PHONY : cmake_force + +#============================================================================= +# Set environment variables for the build. + +# The shell in which to execute make rules. +SHELL = /bin/sh + +# The CMake executable. +CMAKE_COMMAND = /usr/bin/cmake + +# The command to remove a file. +RM = /usr/bin/cmake -E rm -f + +# Escaping for special characters. +EQUALS = = + +# The top-level source directory on which CMake was run. +CMAKE_SOURCE_DIR = /home/calvin/src/xpdf-4.04 + +# The top-level build directory on which CMake was run. +CMAKE_BINARY_DIR = /home/calvin/src/xpdf-4.04 + +# Include any dependencies generated for this target. +include xpdf/CMakeFiles/pdftops.dir/depend.make + +# Include the progress variables for this target. +include xpdf/CMakeFiles/pdftops.dir/progress.make + +# Include the compile flags for this target's objects. +include xpdf/CMakeFiles/pdftops.dir/flags.make + +xpdf/CMakeFiles/pdftops.dir/PreScanOutputDev.cc.o: xpdf/CMakeFiles/pdftops.dir/flags.make +xpdf/CMakeFiles/pdftops.dir/PreScanOutputDev.cc.o: xpdf/PreScanOutputDev.cc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_1) "Building CXX object xpdf/CMakeFiles/pdftops.dir/PreScanOutputDev.cc.o" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/pdftops.dir/PreScanOutputDev.cc.o -c /home/calvin/src/xpdf-4.04/xpdf/PreScanOutputDev.cc + +xpdf/CMakeFiles/pdftops.dir/PreScanOutputDev.cc.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/pdftops.dir/PreScanOutputDev.cc.i" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf/PreScanOutputDev.cc > CMakeFiles/pdftops.dir/PreScanOutputDev.cc.i + +xpdf/CMakeFiles/pdftops.dir/PreScanOutputDev.cc.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/pdftops.dir/PreScanOutputDev.cc.s" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf/PreScanOutputDev.cc -o CMakeFiles/pdftops.dir/PreScanOutputDev.cc.s + +xpdf/CMakeFiles/pdftops.dir/PSOutputDev.cc.o: xpdf/CMakeFiles/pdftops.dir/flags.make +xpdf/CMakeFiles/pdftops.dir/PSOutputDev.cc.o: xpdf/PSOutputDev.cc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_2) "Building CXX object xpdf/CMakeFiles/pdftops.dir/PSOutputDev.cc.o" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/pdftops.dir/PSOutputDev.cc.o -c /home/calvin/src/xpdf-4.04/xpdf/PSOutputDev.cc + +xpdf/CMakeFiles/pdftops.dir/PSOutputDev.cc.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/pdftops.dir/PSOutputDev.cc.i" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf/PSOutputDev.cc > CMakeFiles/pdftops.dir/PSOutputDev.cc.i + +xpdf/CMakeFiles/pdftops.dir/PSOutputDev.cc.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/pdftops.dir/PSOutputDev.cc.s" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf/PSOutputDev.cc -o CMakeFiles/pdftops.dir/PSOutputDev.cc.s + +xpdf/CMakeFiles/pdftops.dir/ShadingImage.cc.o: xpdf/CMakeFiles/pdftops.dir/flags.make +xpdf/CMakeFiles/pdftops.dir/ShadingImage.cc.o: xpdf/ShadingImage.cc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_3) "Building CXX object xpdf/CMakeFiles/pdftops.dir/ShadingImage.cc.o" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/pdftops.dir/ShadingImage.cc.o -c /home/calvin/src/xpdf-4.04/xpdf/ShadingImage.cc + +xpdf/CMakeFiles/pdftops.dir/ShadingImage.cc.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/pdftops.dir/ShadingImage.cc.i" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf/ShadingImage.cc > CMakeFiles/pdftops.dir/ShadingImage.cc.i + +xpdf/CMakeFiles/pdftops.dir/ShadingImage.cc.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/pdftops.dir/ShadingImage.cc.s" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf/ShadingImage.cc -o CMakeFiles/pdftops.dir/ShadingImage.cc.s + +xpdf/CMakeFiles/pdftops.dir/SplashOutputDev.cc.o: xpdf/CMakeFiles/pdftops.dir/flags.make +xpdf/CMakeFiles/pdftops.dir/SplashOutputDev.cc.o: xpdf/SplashOutputDev.cc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_4) "Building CXX object xpdf/CMakeFiles/pdftops.dir/SplashOutputDev.cc.o" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/pdftops.dir/SplashOutputDev.cc.o -c /home/calvin/src/xpdf-4.04/xpdf/SplashOutputDev.cc + +xpdf/CMakeFiles/pdftops.dir/SplashOutputDev.cc.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/pdftops.dir/SplashOutputDev.cc.i" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf/SplashOutputDev.cc > CMakeFiles/pdftops.dir/SplashOutputDev.cc.i + +xpdf/CMakeFiles/pdftops.dir/SplashOutputDev.cc.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/pdftops.dir/SplashOutputDev.cc.s" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf/SplashOutputDev.cc -o CMakeFiles/pdftops.dir/SplashOutputDev.cc.s + +xpdf/CMakeFiles/pdftops.dir/pdftops.cc.o: xpdf/CMakeFiles/pdftops.dir/flags.make +xpdf/CMakeFiles/pdftops.dir/pdftops.cc.o: xpdf/pdftops.cc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_5) "Building CXX object xpdf/CMakeFiles/pdftops.dir/pdftops.cc.o" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/pdftops.dir/pdftops.cc.o -c /home/calvin/src/xpdf-4.04/xpdf/pdftops.cc + +xpdf/CMakeFiles/pdftops.dir/pdftops.cc.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/pdftops.dir/pdftops.cc.i" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf/pdftops.cc > CMakeFiles/pdftops.dir/pdftops.cc.i + +xpdf/CMakeFiles/pdftops.dir/pdftops.cc.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/pdftops.dir/pdftops.cc.s" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf/pdftops.cc -o CMakeFiles/pdftops.dir/pdftops.cc.s + +# Object files for target pdftops +pdftops_OBJECTS = \ +"CMakeFiles/pdftops.dir/PreScanOutputDev.cc.o" \ +"CMakeFiles/pdftops.dir/PSOutputDev.cc.o" \ +"CMakeFiles/pdftops.dir/ShadingImage.cc.o" \ +"CMakeFiles/pdftops.dir/SplashOutputDev.cc.o" \ +"CMakeFiles/pdftops.dir/pdftops.cc.o" + +# External object files for target pdftops +pdftops_EXTERNAL_OBJECTS = \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/AcroForm.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Annot.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Array.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFont.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFontTables.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Catalog.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/CharCodeToUnicode.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/CMap.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Decrypt.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Dict.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Error.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/FontEncodingTables.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Function.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Gfx.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/GfxFont.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/GfxState.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/GlobalParams.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/JArithmeticDecoder.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/JBIG2Stream.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/JPXStream.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Lexer.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Link.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/NameToCharCode.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Object.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/OptionalContent.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Outline.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/OutputDev.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Page.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Parser.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/PDF417Barcode.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/PDFDoc.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/PDFDocEncoding.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/PSTokenizer.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Stream.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/TextString.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/UnicodeMap.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/UnicodeRemapping.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/UnicodeTypeTable.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/UTF8.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/XFAScanner.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/XRef.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Zoox.cc.o" + +xpdf/pdftops: xpdf/CMakeFiles/pdftops.dir/PreScanOutputDev.cc.o +xpdf/pdftops: xpdf/CMakeFiles/pdftops.dir/PSOutputDev.cc.o +xpdf/pdftops: xpdf/CMakeFiles/pdftops.dir/ShadingImage.cc.o +xpdf/pdftops: xpdf/CMakeFiles/pdftops.dir/SplashOutputDev.cc.o +xpdf/pdftops: xpdf/CMakeFiles/pdftops.dir/pdftops.cc.o +xpdf/pdftops: xpdf/CMakeFiles/xpdf_objs.dir/AcroForm.cc.o +xpdf/pdftops: xpdf/CMakeFiles/xpdf_objs.dir/Annot.cc.o +xpdf/pdftops: xpdf/CMakeFiles/xpdf_objs.dir/Array.cc.o +xpdf/pdftops: xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFont.cc.o +xpdf/pdftops: xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFontTables.cc.o +xpdf/pdftops: xpdf/CMakeFiles/xpdf_objs.dir/Catalog.cc.o +xpdf/pdftops: xpdf/CMakeFiles/xpdf_objs.dir/CharCodeToUnicode.cc.o +xpdf/pdftops: xpdf/CMakeFiles/xpdf_objs.dir/CMap.cc.o +xpdf/pdftops: xpdf/CMakeFiles/xpdf_objs.dir/Decrypt.cc.o +xpdf/pdftops: xpdf/CMakeFiles/xpdf_objs.dir/Dict.cc.o +xpdf/pdftops: xpdf/CMakeFiles/xpdf_objs.dir/Error.cc.o +xpdf/pdftops: xpdf/CMakeFiles/xpdf_objs.dir/FontEncodingTables.cc.o +xpdf/pdftops: xpdf/CMakeFiles/xpdf_objs.dir/Function.cc.o +xpdf/pdftops: xpdf/CMakeFiles/xpdf_objs.dir/Gfx.cc.o +xpdf/pdftops: xpdf/CMakeFiles/xpdf_objs.dir/GfxFont.cc.o +xpdf/pdftops: xpdf/CMakeFiles/xpdf_objs.dir/GfxState.cc.o +xpdf/pdftops: xpdf/CMakeFiles/xpdf_objs.dir/GlobalParams.cc.o +xpdf/pdftops: xpdf/CMakeFiles/xpdf_objs.dir/JArithmeticDecoder.cc.o +xpdf/pdftops: xpdf/CMakeFiles/xpdf_objs.dir/JBIG2Stream.cc.o +xpdf/pdftops: xpdf/CMakeFiles/xpdf_objs.dir/JPXStream.cc.o +xpdf/pdftops: xpdf/CMakeFiles/xpdf_objs.dir/Lexer.cc.o +xpdf/pdftops: xpdf/CMakeFiles/xpdf_objs.dir/Link.cc.o +xpdf/pdftops: xpdf/CMakeFiles/xpdf_objs.dir/NameToCharCode.cc.o +xpdf/pdftops: xpdf/CMakeFiles/xpdf_objs.dir/Object.cc.o +xpdf/pdftops: xpdf/CMakeFiles/xpdf_objs.dir/OptionalContent.cc.o +xpdf/pdftops: xpdf/CMakeFiles/xpdf_objs.dir/Outline.cc.o +xpdf/pdftops: xpdf/CMakeFiles/xpdf_objs.dir/OutputDev.cc.o +xpdf/pdftops: xpdf/CMakeFiles/xpdf_objs.dir/Page.cc.o +xpdf/pdftops: xpdf/CMakeFiles/xpdf_objs.dir/Parser.cc.o +xpdf/pdftops: xpdf/CMakeFiles/xpdf_objs.dir/PDF417Barcode.cc.o +xpdf/pdftops: xpdf/CMakeFiles/xpdf_objs.dir/PDFDoc.cc.o +xpdf/pdftops: xpdf/CMakeFiles/xpdf_objs.dir/PDFDocEncoding.cc.o +xpdf/pdftops: xpdf/CMakeFiles/xpdf_objs.dir/PSTokenizer.cc.o +xpdf/pdftops: xpdf/CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.o +xpdf/pdftops: xpdf/CMakeFiles/xpdf_objs.dir/Stream.cc.o +xpdf/pdftops: xpdf/CMakeFiles/xpdf_objs.dir/TextString.cc.o +xpdf/pdftops: xpdf/CMakeFiles/xpdf_objs.dir/UnicodeMap.cc.o +xpdf/pdftops: xpdf/CMakeFiles/xpdf_objs.dir/UnicodeRemapping.cc.o +xpdf/pdftops: xpdf/CMakeFiles/xpdf_objs.dir/UnicodeTypeTable.cc.o +xpdf/pdftops: xpdf/CMakeFiles/xpdf_objs.dir/UTF8.cc.o +xpdf/pdftops: xpdf/CMakeFiles/xpdf_objs.dir/XFAScanner.cc.o +xpdf/pdftops: xpdf/CMakeFiles/xpdf_objs.dir/XRef.cc.o +xpdf/pdftops: xpdf/CMakeFiles/xpdf_objs.dir/Zoox.cc.o +xpdf/pdftops: xpdf/CMakeFiles/pdftops.dir/build.make +xpdf/pdftops: goo/libgoo.a +xpdf/pdftops: fofi/libfofi.a +xpdf/pdftops: splash/libsplash.a +xpdf/pdftops: /usr/lib/x86_64-linux-gnu/libfreetype.so +xpdf/pdftops: /usr/lib/x86_64-linux-gnu/libfontconfig.so +xpdf/pdftops: xpdf/CMakeFiles/pdftops.dir/link.txt + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --bold --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_6) "Linking CXX executable pdftops" + cd /home/calvin/src/xpdf-4.04/xpdf && $(CMAKE_COMMAND) -E cmake_link_script CMakeFiles/pdftops.dir/link.txt --verbose=$(VERBOSE) + +# Rule to build all files generated by this target. +xpdf/CMakeFiles/pdftops.dir/build: xpdf/pdftops + +.PHONY : xpdf/CMakeFiles/pdftops.dir/build + +xpdf/CMakeFiles/pdftops.dir/clean: + cd /home/calvin/src/xpdf-4.04/xpdf && $(CMAKE_COMMAND) -P CMakeFiles/pdftops.dir/cmake_clean.cmake +.PHONY : xpdf/CMakeFiles/pdftops.dir/clean + +xpdf/CMakeFiles/pdftops.dir/depend: + cd /home/calvin/src/xpdf-4.04 && $(CMAKE_COMMAND) -E cmake_depends "Unix Makefiles" /home/calvin/src/xpdf-4.04 /home/calvin/src/xpdf-4.04/xpdf /home/calvin/src/xpdf-4.04 /home/calvin/src/xpdf-4.04/xpdf /home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/pdftops.dir/DependInfo.cmake --color=$(COLOR) +.PHONY : xpdf/CMakeFiles/pdftops.dir/depend + diff --git a/xpdf/CMakeFiles/pdftops.dir/cmake_clean.cmake b/xpdf/CMakeFiles/pdftops.dir/cmake_clean.cmake new file mode 100644 index 0000000..cfc8a66 --- /dev/null +++ b/xpdf/CMakeFiles/pdftops.dir/cmake_clean.cmake @@ -0,0 +1,14 @@ +file(REMOVE_RECURSE + "CMakeFiles/pdftops.dir/PSOutputDev.cc.o" + "CMakeFiles/pdftops.dir/PreScanOutputDev.cc.o" + "CMakeFiles/pdftops.dir/ShadingImage.cc.o" + "CMakeFiles/pdftops.dir/SplashOutputDev.cc.o" + "CMakeFiles/pdftops.dir/pdftops.cc.o" + "pdftops" + "pdftops.pdb" +) + +# Per-language clean rules from dependency scanning. +foreach(lang CXX) + include(CMakeFiles/pdftops.dir/cmake_clean_${lang}.cmake OPTIONAL) +endforeach() diff --git a/xpdf/CMakeFiles/pdftops.dir/depend.internal b/xpdf/CMakeFiles/pdftops.dir/depend.internal new file mode 100644 index 0000000..ef982bf --- /dev/null +++ b/xpdf/CMakeFiles/pdftops.dir/depend.internal @@ -0,0 +1,174 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +xpdf/CMakeFiles/pdftops.dir/PSOutputDev.cc.o + /home/calvin/src/xpdf-4.04/xpdf/AcroForm.h + /home/calvin/src/xpdf-4.04/xpdf/Annot.h + /home/calvin/src/xpdf-4.04/xpdf/Array.h + /home/calvin/src/xpdf-4.04/xpdf/Catalog.h + /home/calvin/src/xpdf-4.04/xpdf/CharCodeToUnicode.h + /home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + /home/calvin/src/xpdf-4.04/xpdf/Dict.h + /home/calvin/src/xpdf-4.04/xpdf/Error.h + /home/calvin/src/xpdf-4.04/xpdf/Function.h + /home/calvin/src/xpdf-4.04/xpdf/Gfx.h + /home/calvin/src/xpdf-4.04/xpdf/GfxFont.h + /home/calvin/src/xpdf-4.04/xpdf/GfxState.h + /home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h + /home/calvin/src/xpdf-4.04/xpdf/Object.h + /home/calvin/src/xpdf-4.04/xpdf/OutputDev.h + /home/calvin/src/xpdf-4.04/xpdf/PDFDoc.h + /home/calvin/src/xpdf-4.04/xpdf/PSOutputDev.cc + /home/calvin/src/xpdf-4.04/xpdf/PSOutputDev.h + /home/calvin/src/xpdf-4.04/xpdf/Page.h + /home/calvin/src/xpdf-4.04/xpdf/PreScanOutputDev.h + /home/calvin/src/xpdf-4.04/xpdf/SplashOutputDev.h + /home/calvin/src/xpdf-4.04/xpdf/Stream.h + /home/calvin/src/xpdf-4.04/xpdf/TextString.h + /home/calvin/src/xpdf-4.04/xpdf/UnicodeMap.h + /home/calvin/src/xpdf-4.04/xpdf/XRef.h + /home/calvin/src/xpdf-4.04/xpdf/config.h + aconf.h + aconf2.h + fofi/FoFiBase.h + fofi/FoFiTrueType.h + fofi/FoFiType1C.h + goo/FixedPoint.h + goo/GHash.h + goo/GList.h + goo/GMutex.h + goo/GString.h + goo/gfile.h + goo/gmem.h + goo/gmempp.h + goo/gtypes.h + splash/Splash.h + splash/SplashBitmap.h + splash/SplashClip.h + splash/SplashMath.h + splash/SplashTypes.h +xpdf/CMakeFiles/pdftops.dir/PreScanOutputDev.cc.o + /home/calvin/src/xpdf-4.04/xpdf/Array.h + /home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + /home/calvin/src/xpdf-4.04/xpdf/Dict.h + /home/calvin/src/xpdf-4.04/xpdf/Function.h + /home/calvin/src/xpdf-4.04/xpdf/Gfx.h + /home/calvin/src/xpdf-4.04/xpdf/GfxFont.h + /home/calvin/src/xpdf-4.04/xpdf/GfxState.h + /home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h + /home/calvin/src/xpdf-4.04/xpdf/Link.h + /home/calvin/src/xpdf-4.04/xpdf/Object.h + /home/calvin/src/xpdf-4.04/xpdf/OutputDev.h + /home/calvin/src/xpdf-4.04/xpdf/Page.h + /home/calvin/src/xpdf-4.04/xpdf/PreScanOutputDev.cc + /home/calvin/src/xpdf-4.04/xpdf/PreScanOutputDev.h + /home/calvin/src/xpdf-4.04/xpdf/Stream.h + aconf.h + aconf2.h + goo/GMutex.h + goo/GString.h + goo/gfile.h + goo/gmem.h + goo/gmempp.h + goo/gtypes.h +xpdf/CMakeFiles/pdftops.dir/ShadingImage.cc.o + /home/calvin/src/xpdf-4.04/xpdf/Array.h + /home/calvin/src/xpdf-4.04/xpdf/Dict.h + /home/calvin/src/xpdf-4.04/xpdf/Function.h + /home/calvin/src/xpdf-4.04/xpdf/GfxState.h + /home/calvin/src/xpdf-4.04/xpdf/Object.h + /home/calvin/src/xpdf-4.04/xpdf/ShadingImage.cc + /home/calvin/src/xpdf-4.04/xpdf/ShadingImage.h + /home/calvin/src/xpdf-4.04/xpdf/Stream.h + aconf.h + aconf2.h + goo/FixedPoint.h + goo/GMutex.h + goo/GString.h + goo/Trace.h + goo/gfile.h + goo/gmem.h + goo/gtypes.h + splash/Splash.h + splash/SplashBitmap.h + splash/SplashClip.h + splash/SplashMath.h + splash/SplashPath.h + splash/SplashPattern.h + splash/SplashTypes.h +xpdf/CMakeFiles/pdftops.dir/SplashOutputDev.cc.o + /home/calvin/src/xpdf-4.04/xpdf/Array.h + /home/calvin/src/xpdf-4.04/xpdf/BuiltinFont.h + /home/calvin/src/xpdf-4.04/xpdf/BuiltinFontTables.h + /home/calvin/src/xpdf-4.04/xpdf/CharCodeToUnicode.h + /home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + /home/calvin/src/xpdf-4.04/xpdf/Dict.h + /home/calvin/src/xpdf-4.04/xpdf/Error.h + /home/calvin/src/xpdf-4.04/xpdf/FontEncodingTables.h + /home/calvin/src/xpdf-4.04/xpdf/Function.h + /home/calvin/src/xpdf-4.04/xpdf/Gfx.h + /home/calvin/src/xpdf-4.04/xpdf/GfxFont.h + /home/calvin/src/xpdf-4.04/xpdf/GfxState.h + /home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h + /home/calvin/src/xpdf-4.04/xpdf/JPXStream.h + /home/calvin/src/xpdf-4.04/xpdf/Link.h + /home/calvin/src/xpdf-4.04/xpdf/Object.h + /home/calvin/src/xpdf-4.04/xpdf/OutputDev.h + /home/calvin/src/xpdf-4.04/xpdf/ShadingImage.h + /home/calvin/src/xpdf-4.04/xpdf/SplashOutputDev.cc + /home/calvin/src/xpdf-4.04/xpdf/SplashOutputDev.h + /home/calvin/src/xpdf-4.04/xpdf/Stream.h + /home/calvin/src/xpdf-4.04/xpdf/config.h + aconf.h + aconf2.h + fofi/FoFiBase.h + fofi/FoFiTrueType.h + fofi/FoFiType1C.h + goo/FixedPoint.h + goo/GMutex.h + goo/GString.h + goo/Trace.h + goo/gfile.h + goo/gmem.h + goo/gmempp.h + goo/gtypes.h + splash/Splash.h + splash/SplashBitmap.h + splash/SplashClip.h + splash/SplashErrorCodes.h + splash/SplashFont.h + splash/SplashFontEngine.h + splash/SplashFontFile.h + splash/SplashFontFileID.h + splash/SplashGlyphBitmap.h + splash/SplashMath.h + splash/SplashPath.h + splash/SplashPattern.h + splash/SplashScreen.h + splash/SplashState.h + splash/SplashTypes.h +xpdf/CMakeFiles/pdftops.dir/pdftops.cc.o + /home/calvin/src/xpdf-4.04/xpdf/Array.h + /home/calvin/src/xpdf-4.04/xpdf/Catalog.h + /home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + /home/calvin/src/xpdf-4.04/xpdf/Dict.h + /home/calvin/src/xpdf-4.04/xpdf/Error.h + /home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h + /home/calvin/src/xpdf-4.04/xpdf/Object.h + /home/calvin/src/xpdf-4.04/xpdf/OutputDev.h + /home/calvin/src/xpdf-4.04/xpdf/PDFDoc.h + /home/calvin/src/xpdf-4.04/xpdf/PSOutputDev.h + /home/calvin/src/xpdf-4.04/xpdf/Page.h + /home/calvin/src/xpdf-4.04/xpdf/Stream.h + /home/calvin/src/xpdf-4.04/xpdf/XRef.h + /home/calvin/src/xpdf-4.04/xpdf/config.h + /home/calvin/src/xpdf-4.04/xpdf/pdftops.cc + aconf.h + aconf2.h + goo/GMutex.h + goo/GString.h + goo/gfile.h + goo/gmem.h + goo/gmempp.h + goo/gtypes.h + goo/parseargs.h diff --git a/xpdf/CMakeFiles/pdftops.dir/depend.make b/xpdf/CMakeFiles/pdftops.dir/depend.make new file mode 100644 index 0000000..d3429a4 --- /dev/null +++ b/xpdf/CMakeFiles/pdftops.dir/depend.make @@ -0,0 +1,174 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +xpdf/CMakeFiles/pdftops.dir/PSOutputDev.cc.o: xpdf/AcroForm.h +xpdf/CMakeFiles/pdftops.dir/PSOutputDev.cc.o: xpdf/Annot.h +xpdf/CMakeFiles/pdftops.dir/PSOutputDev.cc.o: xpdf/Array.h +xpdf/CMakeFiles/pdftops.dir/PSOutputDev.cc.o: xpdf/Catalog.h +xpdf/CMakeFiles/pdftops.dir/PSOutputDev.cc.o: xpdf/CharCodeToUnicode.h +xpdf/CMakeFiles/pdftops.dir/PSOutputDev.cc.o: xpdf/CharTypes.h +xpdf/CMakeFiles/pdftops.dir/PSOutputDev.cc.o: xpdf/Dict.h +xpdf/CMakeFiles/pdftops.dir/PSOutputDev.cc.o: xpdf/Error.h +xpdf/CMakeFiles/pdftops.dir/PSOutputDev.cc.o: xpdf/Function.h +xpdf/CMakeFiles/pdftops.dir/PSOutputDev.cc.o: xpdf/Gfx.h +xpdf/CMakeFiles/pdftops.dir/PSOutputDev.cc.o: xpdf/GfxFont.h +xpdf/CMakeFiles/pdftops.dir/PSOutputDev.cc.o: xpdf/GfxState.h +xpdf/CMakeFiles/pdftops.dir/PSOutputDev.cc.o: xpdf/GlobalParams.h +xpdf/CMakeFiles/pdftops.dir/PSOutputDev.cc.o: xpdf/Object.h +xpdf/CMakeFiles/pdftops.dir/PSOutputDev.cc.o: xpdf/OutputDev.h +xpdf/CMakeFiles/pdftops.dir/PSOutputDev.cc.o: xpdf/PDFDoc.h +xpdf/CMakeFiles/pdftops.dir/PSOutputDev.cc.o: xpdf/PSOutputDev.cc +xpdf/CMakeFiles/pdftops.dir/PSOutputDev.cc.o: xpdf/PSOutputDev.h +xpdf/CMakeFiles/pdftops.dir/PSOutputDev.cc.o: xpdf/Page.h +xpdf/CMakeFiles/pdftops.dir/PSOutputDev.cc.o: xpdf/PreScanOutputDev.h +xpdf/CMakeFiles/pdftops.dir/PSOutputDev.cc.o: xpdf/SplashOutputDev.h +xpdf/CMakeFiles/pdftops.dir/PSOutputDev.cc.o: xpdf/Stream.h +xpdf/CMakeFiles/pdftops.dir/PSOutputDev.cc.o: xpdf/TextString.h +xpdf/CMakeFiles/pdftops.dir/PSOutputDev.cc.o: xpdf/UnicodeMap.h +xpdf/CMakeFiles/pdftops.dir/PSOutputDev.cc.o: xpdf/XRef.h +xpdf/CMakeFiles/pdftops.dir/PSOutputDev.cc.o: xpdf/config.h +xpdf/CMakeFiles/pdftops.dir/PSOutputDev.cc.o: aconf.h +xpdf/CMakeFiles/pdftops.dir/PSOutputDev.cc.o: aconf2.h +xpdf/CMakeFiles/pdftops.dir/PSOutputDev.cc.o: fofi/FoFiBase.h +xpdf/CMakeFiles/pdftops.dir/PSOutputDev.cc.o: fofi/FoFiTrueType.h +xpdf/CMakeFiles/pdftops.dir/PSOutputDev.cc.o: fofi/FoFiType1C.h +xpdf/CMakeFiles/pdftops.dir/PSOutputDev.cc.o: goo/FixedPoint.h +xpdf/CMakeFiles/pdftops.dir/PSOutputDev.cc.o: goo/GHash.h +xpdf/CMakeFiles/pdftops.dir/PSOutputDev.cc.o: goo/GList.h +xpdf/CMakeFiles/pdftops.dir/PSOutputDev.cc.o: goo/GMutex.h +xpdf/CMakeFiles/pdftops.dir/PSOutputDev.cc.o: goo/GString.h +xpdf/CMakeFiles/pdftops.dir/PSOutputDev.cc.o: goo/gfile.h +xpdf/CMakeFiles/pdftops.dir/PSOutputDev.cc.o: goo/gmem.h +xpdf/CMakeFiles/pdftops.dir/PSOutputDev.cc.o: goo/gmempp.h +xpdf/CMakeFiles/pdftops.dir/PSOutputDev.cc.o: goo/gtypes.h +xpdf/CMakeFiles/pdftops.dir/PSOutputDev.cc.o: splash/Splash.h +xpdf/CMakeFiles/pdftops.dir/PSOutputDev.cc.o: splash/SplashBitmap.h +xpdf/CMakeFiles/pdftops.dir/PSOutputDev.cc.o: splash/SplashClip.h +xpdf/CMakeFiles/pdftops.dir/PSOutputDev.cc.o: splash/SplashMath.h +xpdf/CMakeFiles/pdftops.dir/PSOutputDev.cc.o: splash/SplashTypes.h + +xpdf/CMakeFiles/pdftops.dir/PreScanOutputDev.cc.o: xpdf/Array.h +xpdf/CMakeFiles/pdftops.dir/PreScanOutputDev.cc.o: xpdf/CharTypes.h +xpdf/CMakeFiles/pdftops.dir/PreScanOutputDev.cc.o: xpdf/Dict.h +xpdf/CMakeFiles/pdftops.dir/PreScanOutputDev.cc.o: xpdf/Function.h +xpdf/CMakeFiles/pdftops.dir/PreScanOutputDev.cc.o: xpdf/Gfx.h +xpdf/CMakeFiles/pdftops.dir/PreScanOutputDev.cc.o: xpdf/GfxFont.h +xpdf/CMakeFiles/pdftops.dir/PreScanOutputDev.cc.o: xpdf/GfxState.h +xpdf/CMakeFiles/pdftops.dir/PreScanOutputDev.cc.o: xpdf/GlobalParams.h +xpdf/CMakeFiles/pdftops.dir/PreScanOutputDev.cc.o: xpdf/Link.h +xpdf/CMakeFiles/pdftops.dir/PreScanOutputDev.cc.o: xpdf/Object.h +xpdf/CMakeFiles/pdftops.dir/PreScanOutputDev.cc.o: xpdf/OutputDev.h +xpdf/CMakeFiles/pdftops.dir/PreScanOutputDev.cc.o: xpdf/Page.h +xpdf/CMakeFiles/pdftops.dir/PreScanOutputDev.cc.o: xpdf/PreScanOutputDev.cc +xpdf/CMakeFiles/pdftops.dir/PreScanOutputDev.cc.o: xpdf/PreScanOutputDev.h +xpdf/CMakeFiles/pdftops.dir/PreScanOutputDev.cc.o: xpdf/Stream.h +xpdf/CMakeFiles/pdftops.dir/PreScanOutputDev.cc.o: aconf.h +xpdf/CMakeFiles/pdftops.dir/PreScanOutputDev.cc.o: aconf2.h +xpdf/CMakeFiles/pdftops.dir/PreScanOutputDev.cc.o: goo/GMutex.h +xpdf/CMakeFiles/pdftops.dir/PreScanOutputDev.cc.o: goo/GString.h +xpdf/CMakeFiles/pdftops.dir/PreScanOutputDev.cc.o: goo/gfile.h +xpdf/CMakeFiles/pdftops.dir/PreScanOutputDev.cc.o: goo/gmem.h +xpdf/CMakeFiles/pdftops.dir/PreScanOutputDev.cc.o: goo/gmempp.h +xpdf/CMakeFiles/pdftops.dir/PreScanOutputDev.cc.o: goo/gtypes.h + +xpdf/CMakeFiles/pdftops.dir/ShadingImage.cc.o: xpdf/Array.h +xpdf/CMakeFiles/pdftops.dir/ShadingImage.cc.o: xpdf/Dict.h +xpdf/CMakeFiles/pdftops.dir/ShadingImage.cc.o: xpdf/Function.h +xpdf/CMakeFiles/pdftops.dir/ShadingImage.cc.o: xpdf/GfxState.h +xpdf/CMakeFiles/pdftops.dir/ShadingImage.cc.o: xpdf/Object.h +xpdf/CMakeFiles/pdftops.dir/ShadingImage.cc.o: xpdf/ShadingImage.cc +xpdf/CMakeFiles/pdftops.dir/ShadingImage.cc.o: xpdf/ShadingImage.h +xpdf/CMakeFiles/pdftops.dir/ShadingImage.cc.o: xpdf/Stream.h +xpdf/CMakeFiles/pdftops.dir/ShadingImage.cc.o: aconf.h +xpdf/CMakeFiles/pdftops.dir/ShadingImage.cc.o: aconf2.h +xpdf/CMakeFiles/pdftops.dir/ShadingImage.cc.o: goo/FixedPoint.h +xpdf/CMakeFiles/pdftops.dir/ShadingImage.cc.o: goo/GMutex.h +xpdf/CMakeFiles/pdftops.dir/ShadingImage.cc.o: goo/GString.h +xpdf/CMakeFiles/pdftops.dir/ShadingImage.cc.o: goo/Trace.h +xpdf/CMakeFiles/pdftops.dir/ShadingImage.cc.o: goo/gfile.h +xpdf/CMakeFiles/pdftops.dir/ShadingImage.cc.o: goo/gmem.h +xpdf/CMakeFiles/pdftops.dir/ShadingImage.cc.o: goo/gtypes.h +xpdf/CMakeFiles/pdftops.dir/ShadingImage.cc.o: splash/Splash.h +xpdf/CMakeFiles/pdftops.dir/ShadingImage.cc.o: splash/SplashBitmap.h +xpdf/CMakeFiles/pdftops.dir/ShadingImage.cc.o: splash/SplashClip.h +xpdf/CMakeFiles/pdftops.dir/ShadingImage.cc.o: splash/SplashMath.h +xpdf/CMakeFiles/pdftops.dir/ShadingImage.cc.o: splash/SplashPath.h +xpdf/CMakeFiles/pdftops.dir/ShadingImage.cc.o: splash/SplashPattern.h +xpdf/CMakeFiles/pdftops.dir/ShadingImage.cc.o: splash/SplashTypes.h + +xpdf/CMakeFiles/pdftops.dir/SplashOutputDev.cc.o: xpdf/Array.h +xpdf/CMakeFiles/pdftops.dir/SplashOutputDev.cc.o: xpdf/BuiltinFont.h +xpdf/CMakeFiles/pdftops.dir/SplashOutputDev.cc.o: xpdf/BuiltinFontTables.h +xpdf/CMakeFiles/pdftops.dir/SplashOutputDev.cc.o: xpdf/CharCodeToUnicode.h +xpdf/CMakeFiles/pdftops.dir/SplashOutputDev.cc.o: xpdf/CharTypes.h +xpdf/CMakeFiles/pdftops.dir/SplashOutputDev.cc.o: xpdf/Dict.h +xpdf/CMakeFiles/pdftops.dir/SplashOutputDev.cc.o: xpdf/Error.h +xpdf/CMakeFiles/pdftops.dir/SplashOutputDev.cc.o: xpdf/FontEncodingTables.h +xpdf/CMakeFiles/pdftops.dir/SplashOutputDev.cc.o: xpdf/Function.h +xpdf/CMakeFiles/pdftops.dir/SplashOutputDev.cc.o: xpdf/Gfx.h +xpdf/CMakeFiles/pdftops.dir/SplashOutputDev.cc.o: xpdf/GfxFont.h +xpdf/CMakeFiles/pdftops.dir/SplashOutputDev.cc.o: xpdf/GfxState.h +xpdf/CMakeFiles/pdftops.dir/SplashOutputDev.cc.o: xpdf/GlobalParams.h +xpdf/CMakeFiles/pdftops.dir/SplashOutputDev.cc.o: xpdf/JPXStream.h +xpdf/CMakeFiles/pdftops.dir/SplashOutputDev.cc.o: xpdf/Link.h +xpdf/CMakeFiles/pdftops.dir/SplashOutputDev.cc.o: xpdf/Object.h +xpdf/CMakeFiles/pdftops.dir/SplashOutputDev.cc.o: xpdf/OutputDev.h +xpdf/CMakeFiles/pdftops.dir/SplashOutputDev.cc.o: xpdf/ShadingImage.h +xpdf/CMakeFiles/pdftops.dir/SplashOutputDev.cc.o: xpdf/SplashOutputDev.cc +xpdf/CMakeFiles/pdftops.dir/SplashOutputDev.cc.o: xpdf/SplashOutputDev.h +xpdf/CMakeFiles/pdftops.dir/SplashOutputDev.cc.o: xpdf/Stream.h +xpdf/CMakeFiles/pdftops.dir/SplashOutputDev.cc.o: xpdf/config.h +xpdf/CMakeFiles/pdftops.dir/SplashOutputDev.cc.o: aconf.h +xpdf/CMakeFiles/pdftops.dir/SplashOutputDev.cc.o: aconf2.h +xpdf/CMakeFiles/pdftops.dir/SplashOutputDev.cc.o: fofi/FoFiBase.h +xpdf/CMakeFiles/pdftops.dir/SplashOutputDev.cc.o: fofi/FoFiTrueType.h +xpdf/CMakeFiles/pdftops.dir/SplashOutputDev.cc.o: fofi/FoFiType1C.h +xpdf/CMakeFiles/pdftops.dir/SplashOutputDev.cc.o: goo/FixedPoint.h +xpdf/CMakeFiles/pdftops.dir/SplashOutputDev.cc.o: goo/GMutex.h +xpdf/CMakeFiles/pdftops.dir/SplashOutputDev.cc.o: goo/GString.h +xpdf/CMakeFiles/pdftops.dir/SplashOutputDev.cc.o: goo/Trace.h +xpdf/CMakeFiles/pdftops.dir/SplashOutputDev.cc.o: goo/gfile.h +xpdf/CMakeFiles/pdftops.dir/SplashOutputDev.cc.o: goo/gmem.h +xpdf/CMakeFiles/pdftops.dir/SplashOutputDev.cc.o: goo/gmempp.h +xpdf/CMakeFiles/pdftops.dir/SplashOutputDev.cc.o: goo/gtypes.h +xpdf/CMakeFiles/pdftops.dir/SplashOutputDev.cc.o: splash/Splash.h +xpdf/CMakeFiles/pdftops.dir/SplashOutputDev.cc.o: splash/SplashBitmap.h +xpdf/CMakeFiles/pdftops.dir/SplashOutputDev.cc.o: splash/SplashClip.h +xpdf/CMakeFiles/pdftops.dir/SplashOutputDev.cc.o: splash/SplashErrorCodes.h +xpdf/CMakeFiles/pdftops.dir/SplashOutputDev.cc.o: splash/SplashFont.h +xpdf/CMakeFiles/pdftops.dir/SplashOutputDev.cc.o: splash/SplashFontEngine.h +xpdf/CMakeFiles/pdftops.dir/SplashOutputDev.cc.o: splash/SplashFontFile.h +xpdf/CMakeFiles/pdftops.dir/SplashOutputDev.cc.o: splash/SplashFontFileID.h +xpdf/CMakeFiles/pdftops.dir/SplashOutputDev.cc.o: splash/SplashGlyphBitmap.h +xpdf/CMakeFiles/pdftops.dir/SplashOutputDev.cc.o: splash/SplashMath.h +xpdf/CMakeFiles/pdftops.dir/SplashOutputDev.cc.o: splash/SplashPath.h +xpdf/CMakeFiles/pdftops.dir/SplashOutputDev.cc.o: splash/SplashPattern.h +xpdf/CMakeFiles/pdftops.dir/SplashOutputDev.cc.o: splash/SplashScreen.h +xpdf/CMakeFiles/pdftops.dir/SplashOutputDev.cc.o: splash/SplashState.h +xpdf/CMakeFiles/pdftops.dir/SplashOutputDev.cc.o: splash/SplashTypes.h + +xpdf/CMakeFiles/pdftops.dir/pdftops.cc.o: xpdf/Array.h +xpdf/CMakeFiles/pdftops.dir/pdftops.cc.o: xpdf/Catalog.h +xpdf/CMakeFiles/pdftops.dir/pdftops.cc.o: xpdf/CharTypes.h +xpdf/CMakeFiles/pdftops.dir/pdftops.cc.o: xpdf/Dict.h +xpdf/CMakeFiles/pdftops.dir/pdftops.cc.o: xpdf/Error.h +xpdf/CMakeFiles/pdftops.dir/pdftops.cc.o: xpdf/GlobalParams.h +xpdf/CMakeFiles/pdftops.dir/pdftops.cc.o: xpdf/Object.h +xpdf/CMakeFiles/pdftops.dir/pdftops.cc.o: xpdf/OutputDev.h +xpdf/CMakeFiles/pdftops.dir/pdftops.cc.o: xpdf/PDFDoc.h +xpdf/CMakeFiles/pdftops.dir/pdftops.cc.o: xpdf/PSOutputDev.h +xpdf/CMakeFiles/pdftops.dir/pdftops.cc.o: xpdf/Page.h +xpdf/CMakeFiles/pdftops.dir/pdftops.cc.o: xpdf/Stream.h +xpdf/CMakeFiles/pdftops.dir/pdftops.cc.o: xpdf/XRef.h +xpdf/CMakeFiles/pdftops.dir/pdftops.cc.o: xpdf/config.h +xpdf/CMakeFiles/pdftops.dir/pdftops.cc.o: xpdf/pdftops.cc +xpdf/CMakeFiles/pdftops.dir/pdftops.cc.o: aconf.h +xpdf/CMakeFiles/pdftops.dir/pdftops.cc.o: aconf2.h +xpdf/CMakeFiles/pdftops.dir/pdftops.cc.o: goo/GMutex.h +xpdf/CMakeFiles/pdftops.dir/pdftops.cc.o: goo/GString.h +xpdf/CMakeFiles/pdftops.dir/pdftops.cc.o: goo/gfile.h +xpdf/CMakeFiles/pdftops.dir/pdftops.cc.o: goo/gmem.h +xpdf/CMakeFiles/pdftops.dir/pdftops.cc.o: goo/gmempp.h +xpdf/CMakeFiles/pdftops.dir/pdftops.cc.o: goo/gtypes.h +xpdf/CMakeFiles/pdftops.dir/pdftops.cc.o: goo/parseargs.h + diff --git a/xpdf/CMakeFiles/pdftops.dir/flags.make b/xpdf/CMakeFiles/pdftops.dir/flags.make new file mode 100644 index 0000000..300fa3e --- /dev/null +++ b/xpdf/CMakeFiles/pdftops.dir/flags.make @@ -0,0 +1,10 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +# compile CXX with /usr/bin/c++ +CXX_DEFINES = + +CXX_INCLUDES = -I/home/calvin/src/xpdf-4.04 -I/home/calvin/src/xpdf-4.04/goo -I/home/calvin/src/xpdf-4.04/fofi -I/home/calvin/src/xpdf-4.04/splash + +CXX_FLAGS = + diff --git a/xpdf/CMakeFiles/pdftops.dir/link.txt b/xpdf/CMakeFiles/pdftops.dir/link.txt new file mode 100644 index 0000000..741b396 --- /dev/null +++ b/xpdf/CMakeFiles/pdftops.dir/link.txt @@ -0,0 +1 @@ +/usr/bin/c++ -rdynamic CMakeFiles/pdftops.dir/PreScanOutputDev.cc.o CMakeFiles/pdftops.dir/PSOutputDev.cc.o CMakeFiles/pdftops.dir/ShadingImage.cc.o CMakeFiles/pdftops.dir/SplashOutputDev.cc.o CMakeFiles/pdftops.dir/pdftops.cc.o CMakeFiles/xpdf_objs.dir/AcroForm.cc.o CMakeFiles/xpdf_objs.dir/Annot.cc.o CMakeFiles/xpdf_objs.dir/Array.cc.o CMakeFiles/xpdf_objs.dir/BuiltinFont.cc.o CMakeFiles/xpdf_objs.dir/BuiltinFontTables.cc.o CMakeFiles/xpdf_objs.dir/Catalog.cc.o CMakeFiles/xpdf_objs.dir/CharCodeToUnicode.cc.o CMakeFiles/xpdf_objs.dir/CMap.cc.o CMakeFiles/xpdf_objs.dir/Decrypt.cc.o CMakeFiles/xpdf_objs.dir/Dict.cc.o CMakeFiles/xpdf_objs.dir/Error.cc.o CMakeFiles/xpdf_objs.dir/FontEncodingTables.cc.o CMakeFiles/xpdf_objs.dir/Function.cc.o CMakeFiles/xpdf_objs.dir/Gfx.cc.o CMakeFiles/xpdf_objs.dir/GfxFont.cc.o CMakeFiles/xpdf_objs.dir/GfxState.cc.o CMakeFiles/xpdf_objs.dir/GlobalParams.cc.o CMakeFiles/xpdf_objs.dir/JArithmeticDecoder.cc.o CMakeFiles/xpdf_objs.dir/JBIG2Stream.cc.o CMakeFiles/xpdf_objs.dir/JPXStream.cc.o CMakeFiles/xpdf_objs.dir/Lexer.cc.o CMakeFiles/xpdf_objs.dir/Link.cc.o CMakeFiles/xpdf_objs.dir/NameToCharCode.cc.o CMakeFiles/xpdf_objs.dir/Object.cc.o CMakeFiles/xpdf_objs.dir/OptionalContent.cc.o CMakeFiles/xpdf_objs.dir/Outline.cc.o CMakeFiles/xpdf_objs.dir/OutputDev.cc.o CMakeFiles/xpdf_objs.dir/Page.cc.o CMakeFiles/xpdf_objs.dir/Parser.cc.o CMakeFiles/xpdf_objs.dir/PDF417Barcode.cc.o CMakeFiles/xpdf_objs.dir/PDFDoc.cc.o CMakeFiles/xpdf_objs.dir/PDFDocEncoding.cc.o CMakeFiles/xpdf_objs.dir/PSTokenizer.cc.o CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.o CMakeFiles/xpdf_objs.dir/Stream.cc.o CMakeFiles/xpdf_objs.dir/TextString.cc.o CMakeFiles/xpdf_objs.dir/UnicodeMap.cc.o CMakeFiles/xpdf_objs.dir/UnicodeRemapping.cc.o CMakeFiles/xpdf_objs.dir/UnicodeTypeTable.cc.o CMakeFiles/xpdf_objs.dir/UTF8.cc.o CMakeFiles/xpdf_objs.dir/XFAScanner.cc.o CMakeFiles/xpdf_objs.dir/XRef.cc.o CMakeFiles/xpdf_objs.dir/Zoox.cc.o -o pdftops ../goo/libgoo.a ../fofi/libfofi.a ../splash/libsplash.a -lfreetype -lfontconfig -lpthread diff --git a/xpdf/CMakeFiles/pdftops.dir/pdftops.cc.o b/xpdf/CMakeFiles/pdftops.dir/pdftops.cc.o new file mode 100644 index 0000000..e8ea530 Binary files /dev/null and b/xpdf/CMakeFiles/pdftops.dir/pdftops.cc.o differ diff --git a/xpdf/CMakeFiles/pdftops.dir/progress.make b/xpdf/CMakeFiles/pdftops.dir/progress.make new file mode 100644 index 0000000..552915a --- /dev/null +++ b/xpdf/CMakeFiles/pdftops.dir/progress.make @@ -0,0 +1,7 @@ +CMAKE_PROGRESS_1 = 31 +CMAKE_PROGRESS_2 = +CMAKE_PROGRESS_3 = 32 +CMAKE_PROGRESS_4 = 33 +CMAKE_PROGRESS_5 = 34 +CMAKE_PROGRESS_6 = + diff --git a/xpdf/CMakeFiles/pdftotext.dir/CXX.includecache b/xpdf/CMakeFiles/pdftotext.dir/CXX.includecache new file mode 100644 index 0000000..1a61806 --- /dev/null +++ b/xpdf/CMakeFiles/pdftotext.dir/CXX.includecache @@ -0,0 +1,388 @@ +#IncludeRegexLine: ^[ ]*[#%][ ]*(include|import)[ ]*[<"]([^">]+)([">]) + +#IncludeRegexScan: ^.*$ + +#IncludeRegexComplain: ^$ + +#IncludeRegexTransform: + +/home/calvin/src/xpdf-4.04/xpdf/Array.h +aconf.h +- +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h + +/home/calvin/src/xpdf-4.04/xpdf/Catalog.h +aconf.h +- +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h +CharTypes.h +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + +/home/calvin/src/xpdf-4.04/xpdf/Dict.h +aconf.h +- +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h + +/home/calvin/src/xpdf-4.04/xpdf/Error.h +aconf.h +- +stdio.h +- +config.h +/home/calvin/src/xpdf-4.04/xpdf/config.h +gfile.h +/home/calvin/src/xpdf-4.04/xpdf/gfile.h + +/home/calvin/src/xpdf-4.04/xpdf/Function.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h + +/home/calvin/src/xpdf-4.04/xpdf/GfxFont.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +GString.h +/home/calvin/src/xpdf-4.04/xpdf/GString.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h +CharTypes.h +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + +/home/calvin/src/xpdf-4.04/xpdf/GfxState.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h +Function.h +/home/calvin/src/xpdf-4.04/xpdf/Function.h + +/home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h +aconf.h +- +stdio.h +- +windows.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +CharTypes.h +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h + +/home/calvin/src/xpdf-4.04/xpdf/Link.h +aconf.h +- +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h + +/home/calvin/src/xpdf-4.04/xpdf/Object.h +aconf.h +- +stdio.h +- +string.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +gmem.h +/home/calvin/src/xpdf-4.04/xpdf/gmem.h +gfile.h +/home/calvin/src/xpdf-4.04/xpdf/gfile.h +GString.h +/home/calvin/src/xpdf-4.04/xpdf/GString.h +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h +Array.h +/home/calvin/src/xpdf-4.04/xpdf/Array.h +Dict.h +/home/calvin/src/xpdf-4.04/xpdf/Dict.h +Stream.h +/home/calvin/src/xpdf-4.04/xpdf/Stream.h + +/home/calvin/src/xpdf-4.04/xpdf/OutputDev.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +CharTypes.h +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + +/home/calvin/src/xpdf-4.04/xpdf/PDFDoc.h +aconf.h +- +stdio.h +- +XRef.h +/home/calvin/src/xpdf-4.04/xpdf/XRef.h +Catalog.h +/home/calvin/src/xpdf-4.04/xpdf/Catalog.h +Page.h +/home/calvin/src/xpdf-4.04/xpdf/Page.h + +/home/calvin/src/xpdf-4.04/xpdf/Page.h +aconf.h +- +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h + +/home/calvin/src/xpdf-4.04/xpdf/Stream.h +aconf.h +- +stdio.h +- +jpeglib.h +- +setjmp.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +gfile.h +/home/calvin/src/xpdf-4.04/xpdf/gfile.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h + +/home/calvin/src/xpdf-4.04/xpdf/TextOutputDev.cc +aconf.h +- +stdio.h +- +stdlib.h +- +stddef.h +- +math.h +- +limits.h +- +ctype.h +- +fcntl.h +- +io.h +- +gmem.h +/home/calvin/src/xpdf-4.04/xpdf/gmem.h +gmempp.h +/home/calvin/src/xpdf-4.04/xpdf/gmempp.h +GString.h +/home/calvin/src/xpdf-4.04/xpdf/GString.h +GList.h +/home/calvin/src/xpdf-4.04/xpdf/GList.h +gfile.h +/home/calvin/src/xpdf-4.04/xpdf/gfile.h +config.h +/home/calvin/src/xpdf-4.04/xpdf/config.h +Error.h +/home/calvin/src/xpdf-4.04/xpdf/Error.h +GlobalParams.h +/home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h +UnicodeMap.h +/home/calvin/src/xpdf-4.04/xpdf/UnicodeMap.h +UnicodeRemapping.h +/home/calvin/src/xpdf-4.04/xpdf/UnicodeRemapping.h +UnicodeTypeTable.h +/home/calvin/src/xpdf-4.04/xpdf/UnicodeTypeTable.h +GfxState.h +/home/calvin/src/xpdf-4.04/xpdf/GfxState.h +Link.h +/home/calvin/src/xpdf-4.04/xpdf/Link.h +TextOutputDev.h +/home/calvin/src/xpdf-4.04/xpdf/TextOutputDev.h + +/home/calvin/src/xpdf-4.04/xpdf/TextOutputDev.h +aconf.h +- +stdio.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +GfxFont.h +/home/calvin/src/xpdf-4.04/xpdf/GfxFont.h +OutputDev.h +/home/calvin/src/xpdf-4.04/xpdf/OutputDev.h + +/home/calvin/src/xpdf-4.04/xpdf/TextString.h +aconf.h +- +CharTypes.h +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + +/home/calvin/src/xpdf-4.04/xpdf/UnicodeMap.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +CharTypes.h +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h + +/home/calvin/src/xpdf-4.04/xpdf/UnicodeRemapping.h +aconf.h +- +CharTypes.h +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + +/home/calvin/src/xpdf-4.04/xpdf/UnicodeTypeTable.h +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h + +/home/calvin/src/xpdf-4.04/xpdf/XRef.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +gfile.h +/home/calvin/src/xpdf-4.04/xpdf/gfile.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h + +/home/calvin/src/xpdf-4.04/xpdf/config.h + +/home/calvin/src/xpdf-4.04/xpdf/pdftotext.cc +aconf.h +- +stdio.h +- +stdlib.h +- +stddef.h +- +string.h +- +fenv.h +- +fpu_control.h +- +gmem.h +/home/calvin/src/xpdf-4.04/xpdf/gmem.h +gmempp.h +/home/calvin/src/xpdf-4.04/xpdf/gmempp.h +parseargs.h +/home/calvin/src/xpdf-4.04/xpdf/parseargs.h +GString.h +/home/calvin/src/xpdf-4.04/xpdf/GString.h +GList.h +/home/calvin/src/xpdf-4.04/xpdf/GList.h +GlobalParams.h +/home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h +Stream.h +/home/calvin/src/xpdf-4.04/xpdf/Stream.h +Array.h +/home/calvin/src/xpdf-4.04/xpdf/Array.h +Dict.h +/home/calvin/src/xpdf-4.04/xpdf/Dict.h +XRef.h +/home/calvin/src/xpdf-4.04/xpdf/XRef.h +Catalog.h +/home/calvin/src/xpdf-4.04/xpdf/Catalog.h +Page.h +/home/calvin/src/xpdf-4.04/xpdf/Page.h +PDFDoc.h +/home/calvin/src/xpdf-4.04/xpdf/PDFDoc.h +TextOutputDev.h +/home/calvin/src/xpdf-4.04/xpdf/TextOutputDev.h +CharTypes.h +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h +UnicodeMap.h +/home/calvin/src/xpdf-4.04/xpdf/UnicodeMap.h +TextString.h +/home/calvin/src/xpdf-4.04/xpdf/TextString.h +Error.h +/home/calvin/src/xpdf-4.04/xpdf/Error.h +config.h +/home/calvin/src/xpdf-4.04/xpdf/config.h + +aconf.h +aconf2.h +- + +aconf2.h +AvailabilityMacros.h +- + +goo/GList.h +aconf.h +- +gtypes.h +goo/gtypes.h + +goo/GMutex.h +aconf.h +- +windows.h +- +intrin.h +- +pthread.h +- + +goo/GString.h +aconf.h +- +limits.h +- +stdarg.h +- +gtypes.h +goo/gtypes.h + +goo/gfile.h +aconf.h +- +stdio.h +- +stdlib.h +- +stddef.h +- +sys/stat.h +- +win32lib.h +- +windows.h +- +unistd.h +- +sys/types.h +- +gtypes.h +goo/gtypes.h + +goo/gmem.h +stdio.h +- +aconf.h +- + +goo/gmempp.h +stdlib.h +- + +goo/gtypes.h + +goo/parseargs.h +gtypes.h +goo/gtypes.h + diff --git a/xpdf/CMakeFiles/pdftotext.dir/DependInfo.cmake b/xpdf/CMakeFiles/pdftotext.dir/DependInfo.cmake new file mode 100644 index 0000000..85290d5 --- /dev/null +++ b/xpdf/CMakeFiles/pdftotext.dir/DependInfo.cmake @@ -0,0 +1,27 @@ +# The set of languages for which implicit dependencies are needed: +set(CMAKE_DEPENDS_LANGUAGES + "CXX" + ) +# The set of files for implicit dependencies of each language: +set(CMAKE_DEPENDS_CHECK_CXX + "/home/calvin/src/xpdf-4.04/xpdf/TextOutputDev.cc" "/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/pdftotext.dir/TextOutputDev.cc.o" + "/home/calvin/src/xpdf-4.04/xpdf/pdftotext.cc" "/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/pdftotext.dir/pdftotext.cc.o" + ) +set(CMAKE_CXX_COMPILER_ID "GNU") + +# The include file search paths: +set(CMAKE_CXX_TARGET_INCLUDE_PATH + "." + "goo" + "fofi" + "splash" + ) + +# Targets to which this target links. +set(CMAKE_TARGET_LINKED_INFO_FILES + "/home/calvin/src/xpdf-4.04/goo/CMakeFiles/goo.dir/DependInfo.cmake" + "/home/calvin/src/xpdf-4.04/fofi/CMakeFiles/fofi.dir/DependInfo.cmake" + ) + +# Fortran module output directory. +set(CMAKE_Fortran_TARGET_MODULE_DIR "") diff --git a/xpdf/CMakeFiles/pdftotext.dir/TextOutputDev.cc.o b/xpdf/CMakeFiles/pdftotext.dir/TextOutputDev.cc.o new file mode 100644 index 0000000..ac16080 Binary files /dev/null and b/xpdf/CMakeFiles/pdftotext.dir/TextOutputDev.cc.o differ diff --git a/xpdf/CMakeFiles/pdftotext.dir/build.make b/xpdf/CMakeFiles/pdftotext.dir/build.make new file mode 100644 index 0000000..3d849f1 --- /dev/null +++ b/xpdf/CMakeFiles/pdftotext.dir/build.make @@ -0,0 +1,221 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +# Delete rule output on recipe failure. +.DELETE_ON_ERROR: + + +#============================================================================= +# Special targets provided by cmake. + +# Disable implicit rules so canonical targets will work. +.SUFFIXES: + + +# Disable VCS-based implicit rules. +% : %,v + + +# Disable VCS-based implicit rules. +% : RCS/% + + +# Disable VCS-based implicit rules. +% : RCS/%,v + + +# Disable VCS-based implicit rules. +% : SCCS/s.% + + +# Disable VCS-based implicit rules. +% : s.% + + +.SUFFIXES: .hpux_make_needs_suffix_list + + +# Command-line flag to silence nested $(MAKE). +$(VERBOSE)MAKESILENT = -s + +#Suppress display of executed commands. +$(VERBOSE).SILENT: + +# A target that is always out of date. +cmake_force: + +.PHONY : cmake_force + +#============================================================================= +# Set environment variables for the build. + +# The shell in which to execute make rules. +SHELL = /bin/sh + +# The CMake executable. +CMAKE_COMMAND = /usr/bin/cmake + +# The command to remove a file. +RM = /usr/bin/cmake -E rm -f + +# Escaping for special characters. +EQUALS = = + +# The top-level source directory on which CMake was run. +CMAKE_SOURCE_DIR = /home/calvin/src/xpdf-4.04 + +# The top-level build directory on which CMake was run. +CMAKE_BINARY_DIR = /home/calvin/src/xpdf-4.04 + +# Include any dependencies generated for this target. +include xpdf/CMakeFiles/pdftotext.dir/depend.make + +# Include the progress variables for this target. +include xpdf/CMakeFiles/pdftotext.dir/progress.make + +# Include the compile flags for this target's objects. +include xpdf/CMakeFiles/pdftotext.dir/flags.make + +xpdf/CMakeFiles/pdftotext.dir/TextOutputDev.cc.o: xpdf/CMakeFiles/pdftotext.dir/flags.make +xpdf/CMakeFiles/pdftotext.dir/TextOutputDev.cc.o: xpdf/TextOutputDev.cc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_1) "Building CXX object xpdf/CMakeFiles/pdftotext.dir/TextOutputDev.cc.o" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/pdftotext.dir/TextOutputDev.cc.o -c /home/calvin/src/xpdf-4.04/xpdf/TextOutputDev.cc + +xpdf/CMakeFiles/pdftotext.dir/TextOutputDev.cc.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/pdftotext.dir/TextOutputDev.cc.i" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf/TextOutputDev.cc > CMakeFiles/pdftotext.dir/TextOutputDev.cc.i + +xpdf/CMakeFiles/pdftotext.dir/TextOutputDev.cc.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/pdftotext.dir/TextOutputDev.cc.s" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf/TextOutputDev.cc -o CMakeFiles/pdftotext.dir/TextOutputDev.cc.s + +xpdf/CMakeFiles/pdftotext.dir/pdftotext.cc.o: xpdf/CMakeFiles/pdftotext.dir/flags.make +xpdf/CMakeFiles/pdftotext.dir/pdftotext.cc.o: xpdf/pdftotext.cc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_2) "Building CXX object xpdf/CMakeFiles/pdftotext.dir/pdftotext.cc.o" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/pdftotext.dir/pdftotext.cc.o -c /home/calvin/src/xpdf-4.04/xpdf/pdftotext.cc + +xpdf/CMakeFiles/pdftotext.dir/pdftotext.cc.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/pdftotext.dir/pdftotext.cc.i" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf/pdftotext.cc > CMakeFiles/pdftotext.dir/pdftotext.cc.i + +xpdf/CMakeFiles/pdftotext.dir/pdftotext.cc.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/pdftotext.dir/pdftotext.cc.s" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf/pdftotext.cc -o CMakeFiles/pdftotext.dir/pdftotext.cc.s + +# Object files for target pdftotext +pdftotext_OBJECTS = \ +"CMakeFiles/pdftotext.dir/TextOutputDev.cc.o" \ +"CMakeFiles/pdftotext.dir/pdftotext.cc.o" + +# External object files for target pdftotext +pdftotext_EXTERNAL_OBJECTS = \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/AcroForm.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Annot.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Array.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFont.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFontTables.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Catalog.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/CharCodeToUnicode.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/CMap.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Decrypt.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Dict.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Error.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/FontEncodingTables.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Function.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Gfx.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/GfxFont.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/GfxState.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/GlobalParams.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/JArithmeticDecoder.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/JBIG2Stream.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/JPXStream.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Lexer.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Link.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/NameToCharCode.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Object.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/OptionalContent.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Outline.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/OutputDev.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Page.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Parser.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/PDF417Barcode.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/PDFDoc.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/PDFDocEncoding.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/PSTokenizer.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Stream.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/TextString.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/UnicodeMap.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/UnicodeRemapping.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/UnicodeTypeTable.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/UTF8.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/XFAScanner.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/XRef.cc.o" \ +"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Zoox.cc.o" + +xpdf/pdftotext: xpdf/CMakeFiles/pdftotext.dir/TextOutputDev.cc.o +xpdf/pdftotext: xpdf/CMakeFiles/pdftotext.dir/pdftotext.cc.o +xpdf/pdftotext: xpdf/CMakeFiles/xpdf_objs.dir/AcroForm.cc.o +xpdf/pdftotext: xpdf/CMakeFiles/xpdf_objs.dir/Annot.cc.o +xpdf/pdftotext: xpdf/CMakeFiles/xpdf_objs.dir/Array.cc.o +xpdf/pdftotext: xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFont.cc.o +xpdf/pdftotext: xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFontTables.cc.o +xpdf/pdftotext: xpdf/CMakeFiles/xpdf_objs.dir/Catalog.cc.o +xpdf/pdftotext: xpdf/CMakeFiles/xpdf_objs.dir/CharCodeToUnicode.cc.o +xpdf/pdftotext: xpdf/CMakeFiles/xpdf_objs.dir/CMap.cc.o +xpdf/pdftotext: xpdf/CMakeFiles/xpdf_objs.dir/Decrypt.cc.o +xpdf/pdftotext: xpdf/CMakeFiles/xpdf_objs.dir/Dict.cc.o +xpdf/pdftotext: xpdf/CMakeFiles/xpdf_objs.dir/Error.cc.o +xpdf/pdftotext: xpdf/CMakeFiles/xpdf_objs.dir/FontEncodingTables.cc.o +xpdf/pdftotext: xpdf/CMakeFiles/xpdf_objs.dir/Function.cc.o +xpdf/pdftotext: xpdf/CMakeFiles/xpdf_objs.dir/Gfx.cc.o +xpdf/pdftotext: xpdf/CMakeFiles/xpdf_objs.dir/GfxFont.cc.o +xpdf/pdftotext: xpdf/CMakeFiles/xpdf_objs.dir/GfxState.cc.o +xpdf/pdftotext: xpdf/CMakeFiles/xpdf_objs.dir/GlobalParams.cc.o +xpdf/pdftotext: xpdf/CMakeFiles/xpdf_objs.dir/JArithmeticDecoder.cc.o +xpdf/pdftotext: xpdf/CMakeFiles/xpdf_objs.dir/JBIG2Stream.cc.o +xpdf/pdftotext: xpdf/CMakeFiles/xpdf_objs.dir/JPXStream.cc.o +xpdf/pdftotext: xpdf/CMakeFiles/xpdf_objs.dir/Lexer.cc.o +xpdf/pdftotext: xpdf/CMakeFiles/xpdf_objs.dir/Link.cc.o +xpdf/pdftotext: xpdf/CMakeFiles/xpdf_objs.dir/NameToCharCode.cc.o +xpdf/pdftotext: xpdf/CMakeFiles/xpdf_objs.dir/Object.cc.o +xpdf/pdftotext: xpdf/CMakeFiles/xpdf_objs.dir/OptionalContent.cc.o +xpdf/pdftotext: xpdf/CMakeFiles/xpdf_objs.dir/Outline.cc.o +xpdf/pdftotext: xpdf/CMakeFiles/xpdf_objs.dir/OutputDev.cc.o +xpdf/pdftotext: xpdf/CMakeFiles/xpdf_objs.dir/Page.cc.o +xpdf/pdftotext: xpdf/CMakeFiles/xpdf_objs.dir/Parser.cc.o +xpdf/pdftotext: xpdf/CMakeFiles/xpdf_objs.dir/PDF417Barcode.cc.o +xpdf/pdftotext: xpdf/CMakeFiles/xpdf_objs.dir/PDFDoc.cc.o +xpdf/pdftotext: xpdf/CMakeFiles/xpdf_objs.dir/PDFDocEncoding.cc.o +xpdf/pdftotext: xpdf/CMakeFiles/xpdf_objs.dir/PSTokenizer.cc.o +xpdf/pdftotext: xpdf/CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.o +xpdf/pdftotext: xpdf/CMakeFiles/xpdf_objs.dir/Stream.cc.o +xpdf/pdftotext: xpdf/CMakeFiles/xpdf_objs.dir/TextString.cc.o +xpdf/pdftotext: xpdf/CMakeFiles/xpdf_objs.dir/UnicodeMap.cc.o +xpdf/pdftotext: xpdf/CMakeFiles/xpdf_objs.dir/UnicodeRemapping.cc.o +xpdf/pdftotext: xpdf/CMakeFiles/xpdf_objs.dir/UnicodeTypeTable.cc.o +xpdf/pdftotext: xpdf/CMakeFiles/xpdf_objs.dir/UTF8.cc.o +xpdf/pdftotext: xpdf/CMakeFiles/xpdf_objs.dir/XFAScanner.cc.o +xpdf/pdftotext: xpdf/CMakeFiles/xpdf_objs.dir/XRef.cc.o +xpdf/pdftotext: xpdf/CMakeFiles/xpdf_objs.dir/Zoox.cc.o +xpdf/pdftotext: xpdf/CMakeFiles/pdftotext.dir/build.make +xpdf/pdftotext: goo/libgoo.a +xpdf/pdftotext: fofi/libfofi.a +xpdf/pdftotext: /usr/lib/x86_64-linux-gnu/libfontconfig.so +xpdf/pdftotext: xpdf/CMakeFiles/pdftotext.dir/link.txt + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --bold --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_3) "Linking CXX executable pdftotext" + cd /home/calvin/src/xpdf-4.04/xpdf && $(CMAKE_COMMAND) -E cmake_link_script CMakeFiles/pdftotext.dir/link.txt --verbose=$(VERBOSE) + +# Rule to build all files generated by this target. +xpdf/CMakeFiles/pdftotext.dir/build: xpdf/pdftotext + +.PHONY : xpdf/CMakeFiles/pdftotext.dir/build + +xpdf/CMakeFiles/pdftotext.dir/clean: + cd /home/calvin/src/xpdf-4.04/xpdf && $(CMAKE_COMMAND) -P CMakeFiles/pdftotext.dir/cmake_clean.cmake +.PHONY : xpdf/CMakeFiles/pdftotext.dir/clean + +xpdf/CMakeFiles/pdftotext.dir/depend: + cd /home/calvin/src/xpdf-4.04 && $(CMAKE_COMMAND) -E cmake_depends "Unix Makefiles" /home/calvin/src/xpdf-4.04 /home/calvin/src/xpdf-4.04/xpdf /home/calvin/src/xpdf-4.04 /home/calvin/src/xpdf-4.04/xpdf /home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/pdftotext.dir/DependInfo.cmake --color=$(COLOR) +.PHONY : xpdf/CMakeFiles/pdftotext.dir/depend + diff --git a/xpdf/CMakeFiles/pdftotext.dir/cmake_clean.cmake b/xpdf/CMakeFiles/pdftotext.dir/cmake_clean.cmake new file mode 100644 index 0000000..edcbe41 --- /dev/null +++ b/xpdf/CMakeFiles/pdftotext.dir/cmake_clean.cmake @@ -0,0 +1,11 @@ +file(REMOVE_RECURSE + "CMakeFiles/pdftotext.dir/TextOutputDev.cc.o" + "CMakeFiles/pdftotext.dir/pdftotext.cc.o" + "pdftotext" + "pdftotext.pdb" +) + +# Per-language clean rules from dependency scanning. +foreach(lang CXX) + include(CMakeFiles/pdftotext.dir/cmake_clean_${lang}.cmake OPTIONAL) +endforeach() diff --git a/xpdf/CMakeFiles/pdftotext.dir/depend.internal b/xpdf/CMakeFiles/pdftotext.dir/depend.internal new file mode 100644 index 0000000..6c86d4f --- /dev/null +++ b/xpdf/CMakeFiles/pdftotext.dir/depend.internal @@ -0,0 +1,60 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +xpdf/CMakeFiles/pdftotext.dir/TextOutputDev.cc.o + /home/calvin/src/xpdf-4.04/xpdf/Array.h + /home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + /home/calvin/src/xpdf-4.04/xpdf/Dict.h + /home/calvin/src/xpdf-4.04/xpdf/Error.h + /home/calvin/src/xpdf-4.04/xpdf/Function.h + /home/calvin/src/xpdf-4.04/xpdf/GfxFont.h + /home/calvin/src/xpdf-4.04/xpdf/GfxState.h + /home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h + /home/calvin/src/xpdf-4.04/xpdf/Link.h + /home/calvin/src/xpdf-4.04/xpdf/Object.h + /home/calvin/src/xpdf-4.04/xpdf/OutputDev.h + /home/calvin/src/xpdf-4.04/xpdf/Stream.h + /home/calvin/src/xpdf-4.04/xpdf/TextOutputDev.cc + /home/calvin/src/xpdf-4.04/xpdf/TextOutputDev.h + /home/calvin/src/xpdf-4.04/xpdf/UnicodeMap.h + /home/calvin/src/xpdf-4.04/xpdf/UnicodeRemapping.h + /home/calvin/src/xpdf-4.04/xpdf/UnicodeTypeTable.h + /home/calvin/src/xpdf-4.04/xpdf/config.h + aconf.h + aconf2.h + goo/GList.h + goo/GMutex.h + goo/GString.h + goo/gfile.h + goo/gmem.h + goo/gmempp.h + goo/gtypes.h +xpdf/CMakeFiles/pdftotext.dir/pdftotext.cc.o + /home/calvin/src/xpdf-4.04/xpdf/Array.h + /home/calvin/src/xpdf-4.04/xpdf/Catalog.h + /home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + /home/calvin/src/xpdf-4.04/xpdf/Dict.h + /home/calvin/src/xpdf-4.04/xpdf/Error.h + /home/calvin/src/xpdf-4.04/xpdf/GfxFont.h + /home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h + /home/calvin/src/xpdf-4.04/xpdf/Object.h + /home/calvin/src/xpdf-4.04/xpdf/OutputDev.h + /home/calvin/src/xpdf-4.04/xpdf/PDFDoc.h + /home/calvin/src/xpdf-4.04/xpdf/Page.h + /home/calvin/src/xpdf-4.04/xpdf/Stream.h + /home/calvin/src/xpdf-4.04/xpdf/TextOutputDev.h + /home/calvin/src/xpdf-4.04/xpdf/TextString.h + /home/calvin/src/xpdf-4.04/xpdf/UnicodeMap.h + /home/calvin/src/xpdf-4.04/xpdf/XRef.h + /home/calvin/src/xpdf-4.04/xpdf/config.h + /home/calvin/src/xpdf-4.04/xpdf/pdftotext.cc + aconf.h + aconf2.h + goo/GList.h + goo/GMutex.h + goo/GString.h + goo/gfile.h + goo/gmem.h + goo/gmempp.h + goo/gtypes.h + goo/parseargs.h diff --git a/xpdf/CMakeFiles/pdftotext.dir/depend.make b/xpdf/CMakeFiles/pdftotext.dir/depend.make new file mode 100644 index 0000000..f3f739c --- /dev/null +++ b/xpdf/CMakeFiles/pdftotext.dir/depend.make @@ -0,0 +1,60 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +xpdf/CMakeFiles/pdftotext.dir/TextOutputDev.cc.o: xpdf/Array.h +xpdf/CMakeFiles/pdftotext.dir/TextOutputDev.cc.o: xpdf/CharTypes.h +xpdf/CMakeFiles/pdftotext.dir/TextOutputDev.cc.o: xpdf/Dict.h +xpdf/CMakeFiles/pdftotext.dir/TextOutputDev.cc.o: xpdf/Error.h +xpdf/CMakeFiles/pdftotext.dir/TextOutputDev.cc.o: xpdf/Function.h +xpdf/CMakeFiles/pdftotext.dir/TextOutputDev.cc.o: xpdf/GfxFont.h +xpdf/CMakeFiles/pdftotext.dir/TextOutputDev.cc.o: xpdf/GfxState.h +xpdf/CMakeFiles/pdftotext.dir/TextOutputDev.cc.o: xpdf/GlobalParams.h +xpdf/CMakeFiles/pdftotext.dir/TextOutputDev.cc.o: xpdf/Link.h +xpdf/CMakeFiles/pdftotext.dir/TextOutputDev.cc.o: xpdf/Object.h +xpdf/CMakeFiles/pdftotext.dir/TextOutputDev.cc.o: xpdf/OutputDev.h +xpdf/CMakeFiles/pdftotext.dir/TextOutputDev.cc.o: xpdf/Stream.h +xpdf/CMakeFiles/pdftotext.dir/TextOutputDev.cc.o: xpdf/TextOutputDev.cc +xpdf/CMakeFiles/pdftotext.dir/TextOutputDev.cc.o: xpdf/TextOutputDev.h +xpdf/CMakeFiles/pdftotext.dir/TextOutputDev.cc.o: xpdf/UnicodeMap.h +xpdf/CMakeFiles/pdftotext.dir/TextOutputDev.cc.o: xpdf/UnicodeRemapping.h +xpdf/CMakeFiles/pdftotext.dir/TextOutputDev.cc.o: xpdf/UnicodeTypeTable.h +xpdf/CMakeFiles/pdftotext.dir/TextOutputDev.cc.o: xpdf/config.h +xpdf/CMakeFiles/pdftotext.dir/TextOutputDev.cc.o: aconf.h +xpdf/CMakeFiles/pdftotext.dir/TextOutputDev.cc.o: aconf2.h +xpdf/CMakeFiles/pdftotext.dir/TextOutputDev.cc.o: goo/GList.h +xpdf/CMakeFiles/pdftotext.dir/TextOutputDev.cc.o: goo/GMutex.h +xpdf/CMakeFiles/pdftotext.dir/TextOutputDev.cc.o: goo/GString.h +xpdf/CMakeFiles/pdftotext.dir/TextOutputDev.cc.o: goo/gfile.h +xpdf/CMakeFiles/pdftotext.dir/TextOutputDev.cc.o: goo/gmem.h +xpdf/CMakeFiles/pdftotext.dir/TextOutputDev.cc.o: goo/gmempp.h +xpdf/CMakeFiles/pdftotext.dir/TextOutputDev.cc.o: goo/gtypes.h + +xpdf/CMakeFiles/pdftotext.dir/pdftotext.cc.o: xpdf/Array.h +xpdf/CMakeFiles/pdftotext.dir/pdftotext.cc.o: xpdf/Catalog.h +xpdf/CMakeFiles/pdftotext.dir/pdftotext.cc.o: xpdf/CharTypes.h +xpdf/CMakeFiles/pdftotext.dir/pdftotext.cc.o: xpdf/Dict.h +xpdf/CMakeFiles/pdftotext.dir/pdftotext.cc.o: xpdf/Error.h +xpdf/CMakeFiles/pdftotext.dir/pdftotext.cc.o: xpdf/GfxFont.h +xpdf/CMakeFiles/pdftotext.dir/pdftotext.cc.o: xpdf/GlobalParams.h +xpdf/CMakeFiles/pdftotext.dir/pdftotext.cc.o: xpdf/Object.h +xpdf/CMakeFiles/pdftotext.dir/pdftotext.cc.o: xpdf/OutputDev.h +xpdf/CMakeFiles/pdftotext.dir/pdftotext.cc.o: xpdf/PDFDoc.h +xpdf/CMakeFiles/pdftotext.dir/pdftotext.cc.o: xpdf/Page.h +xpdf/CMakeFiles/pdftotext.dir/pdftotext.cc.o: xpdf/Stream.h +xpdf/CMakeFiles/pdftotext.dir/pdftotext.cc.o: xpdf/TextOutputDev.h +xpdf/CMakeFiles/pdftotext.dir/pdftotext.cc.o: xpdf/TextString.h +xpdf/CMakeFiles/pdftotext.dir/pdftotext.cc.o: xpdf/UnicodeMap.h +xpdf/CMakeFiles/pdftotext.dir/pdftotext.cc.o: xpdf/XRef.h +xpdf/CMakeFiles/pdftotext.dir/pdftotext.cc.o: xpdf/config.h +xpdf/CMakeFiles/pdftotext.dir/pdftotext.cc.o: xpdf/pdftotext.cc +xpdf/CMakeFiles/pdftotext.dir/pdftotext.cc.o: aconf.h +xpdf/CMakeFiles/pdftotext.dir/pdftotext.cc.o: aconf2.h +xpdf/CMakeFiles/pdftotext.dir/pdftotext.cc.o: goo/GList.h +xpdf/CMakeFiles/pdftotext.dir/pdftotext.cc.o: goo/GMutex.h +xpdf/CMakeFiles/pdftotext.dir/pdftotext.cc.o: goo/GString.h +xpdf/CMakeFiles/pdftotext.dir/pdftotext.cc.o: goo/gfile.h +xpdf/CMakeFiles/pdftotext.dir/pdftotext.cc.o: goo/gmem.h +xpdf/CMakeFiles/pdftotext.dir/pdftotext.cc.o: goo/gmempp.h +xpdf/CMakeFiles/pdftotext.dir/pdftotext.cc.o: goo/gtypes.h +xpdf/CMakeFiles/pdftotext.dir/pdftotext.cc.o: goo/parseargs.h + diff --git a/xpdf/CMakeFiles/pdftotext.dir/flags.make b/xpdf/CMakeFiles/pdftotext.dir/flags.make new file mode 100644 index 0000000..300fa3e --- /dev/null +++ b/xpdf/CMakeFiles/pdftotext.dir/flags.make @@ -0,0 +1,10 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +# compile CXX with /usr/bin/c++ +CXX_DEFINES = + +CXX_INCLUDES = -I/home/calvin/src/xpdf-4.04 -I/home/calvin/src/xpdf-4.04/goo -I/home/calvin/src/xpdf-4.04/fofi -I/home/calvin/src/xpdf-4.04/splash + +CXX_FLAGS = + diff --git a/xpdf/CMakeFiles/pdftotext.dir/link.txt b/xpdf/CMakeFiles/pdftotext.dir/link.txt new file mode 100644 index 0000000..40ee1ee --- /dev/null +++ b/xpdf/CMakeFiles/pdftotext.dir/link.txt @@ -0,0 +1 @@ +/usr/bin/c++ -rdynamic CMakeFiles/pdftotext.dir/TextOutputDev.cc.o CMakeFiles/pdftotext.dir/pdftotext.cc.o CMakeFiles/xpdf_objs.dir/AcroForm.cc.o CMakeFiles/xpdf_objs.dir/Annot.cc.o CMakeFiles/xpdf_objs.dir/Array.cc.o CMakeFiles/xpdf_objs.dir/BuiltinFont.cc.o CMakeFiles/xpdf_objs.dir/BuiltinFontTables.cc.o CMakeFiles/xpdf_objs.dir/Catalog.cc.o CMakeFiles/xpdf_objs.dir/CharCodeToUnicode.cc.o CMakeFiles/xpdf_objs.dir/CMap.cc.o CMakeFiles/xpdf_objs.dir/Decrypt.cc.o CMakeFiles/xpdf_objs.dir/Dict.cc.o CMakeFiles/xpdf_objs.dir/Error.cc.o CMakeFiles/xpdf_objs.dir/FontEncodingTables.cc.o CMakeFiles/xpdf_objs.dir/Function.cc.o CMakeFiles/xpdf_objs.dir/Gfx.cc.o CMakeFiles/xpdf_objs.dir/GfxFont.cc.o CMakeFiles/xpdf_objs.dir/GfxState.cc.o CMakeFiles/xpdf_objs.dir/GlobalParams.cc.o CMakeFiles/xpdf_objs.dir/JArithmeticDecoder.cc.o CMakeFiles/xpdf_objs.dir/JBIG2Stream.cc.o CMakeFiles/xpdf_objs.dir/JPXStream.cc.o CMakeFiles/xpdf_objs.dir/Lexer.cc.o CMakeFiles/xpdf_objs.dir/Link.cc.o CMakeFiles/xpdf_objs.dir/NameToCharCode.cc.o CMakeFiles/xpdf_objs.dir/Object.cc.o CMakeFiles/xpdf_objs.dir/OptionalContent.cc.o CMakeFiles/xpdf_objs.dir/Outline.cc.o CMakeFiles/xpdf_objs.dir/OutputDev.cc.o CMakeFiles/xpdf_objs.dir/Page.cc.o CMakeFiles/xpdf_objs.dir/Parser.cc.o CMakeFiles/xpdf_objs.dir/PDF417Barcode.cc.o CMakeFiles/xpdf_objs.dir/PDFDoc.cc.o CMakeFiles/xpdf_objs.dir/PDFDocEncoding.cc.o CMakeFiles/xpdf_objs.dir/PSTokenizer.cc.o CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.o CMakeFiles/xpdf_objs.dir/Stream.cc.o CMakeFiles/xpdf_objs.dir/TextString.cc.o CMakeFiles/xpdf_objs.dir/UnicodeMap.cc.o CMakeFiles/xpdf_objs.dir/UnicodeRemapping.cc.o CMakeFiles/xpdf_objs.dir/UnicodeTypeTable.cc.o CMakeFiles/xpdf_objs.dir/UTF8.cc.o CMakeFiles/xpdf_objs.dir/XFAScanner.cc.o CMakeFiles/xpdf_objs.dir/XRef.cc.o CMakeFiles/xpdf_objs.dir/Zoox.cc.o -o pdftotext ../goo/libgoo.a ../fofi/libfofi.a -lfontconfig -lpthread diff --git a/xpdf/CMakeFiles/pdftotext.dir/pdftotext.cc.o b/xpdf/CMakeFiles/pdftotext.dir/pdftotext.cc.o new file mode 100644 index 0000000..6ff5f23 Binary files /dev/null and b/xpdf/CMakeFiles/pdftotext.dir/pdftotext.cc.o differ diff --git a/xpdf/CMakeFiles/pdftotext.dir/progress.make b/xpdf/CMakeFiles/pdftotext.dir/progress.make new file mode 100644 index 0000000..fa7e3ea --- /dev/null +++ b/xpdf/CMakeFiles/pdftotext.dir/progress.make @@ -0,0 +1,4 @@ +CMAKE_PROGRESS_1 = 35 +CMAKE_PROGRESS_2 = 36 +CMAKE_PROGRESS_3 = 37 + diff --git a/xpdf/CMakeFiles/progress.marks b/xpdf/CMakeFiles/progress.marks new file mode 100644 index 0000000..8643cf6 --- /dev/null +++ b/xpdf/CMakeFiles/progress.marks @@ -0,0 +1 @@ +89 diff --git a/xpdf/CMakeFiles/xpdf_objs.dir/AcroForm.cc.o b/xpdf/CMakeFiles/xpdf_objs.dir/AcroForm.cc.o new file mode 100644 index 0000000..cd7c8a9 Binary files /dev/null and b/xpdf/CMakeFiles/xpdf_objs.dir/AcroForm.cc.o differ diff --git a/xpdf/CMakeFiles/xpdf_objs.dir/Annot.cc.o b/xpdf/CMakeFiles/xpdf_objs.dir/Annot.cc.o new file mode 100644 index 0000000..7868573 Binary files /dev/null and b/xpdf/CMakeFiles/xpdf_objs.dir/Annot.cc.o differ diff --git a/xpdf/CMakeFiles/xpdf_objs.dir/Array.cc.o b/xpdf/CMakeFiles/xpdf_objs.dir/Array.cc.o new file mode 100644 index 0000000..d1b880c Binary files /dev/null and b/xpdf/CMakeFiles/xpdf_objs.dir/Array.cc.o differ diff --git a/xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFont.cc.o b/xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFont.cc.o new file mode 100644 index 0000000..6b43c65 Binary files /dev/null and b/xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFont.cc.o differ diff --git a/xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFontTables.cc.o b/xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFontTables.cc.o new file mode 100644 index 0000000..f4ecf30 Binary files /dev/null and b/xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFontTables.cc.o differ diff --git a/xpdf/CMakeFiles/xpdf_objs.dir/CMap.cc.o b/xpdf/CMakeFiles/xpdf_objs.dir/CMap.cc.o new file mode 100644 index 0000000..6a517e5 Binary files /dev/null and b/xpdf/CMakeFiles/xpdf_objs.dir/CMap.cc.o differ diff --git a/xpdf/CMakeFiles/xpdf_objs.dir/CXX.includecache b/xpdf/CMakeFiles/xpdf_objs.dir/CXX.includecache new file mode 100644 index 0000000..8dcd92b --- /dev/null +++ b/xpdf/CMakeFiles/xpdf_objs.dir/CXX.includecache @@ -0,0 +1,1596 @@ +#IncludeRegexLine: ^[ ]*[#%][ ]*(include|import)[ ]*[<"]([^">]+)([">]) + +#IncludeRegexScan: ^.*$ + +#IncludeRegexComplain: ^$ + +#IncludeRegexTransform: + +/home/calvin/src/xpdf-4.04/xpdf/AcroForm.cc +aconf.h +- +stdlib.h +- +math.h +- +gmem.h +/home/calvin/src/xpdf-4.04/xpdf/gmem.h +gmempp.h +/home/calvin/src/xpdf-4.04/xpdf/gmempp.h +GString.h +/home/calvin/src/xpdf-4.04/xpdf/GString.h +GList.h +/home/calvin/src/xpdf-4.04/xpdf/GList.h +GlobalParams.h +/home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h +Error.h +/home/calvin/src/xpdf-4.04/xpdf/Error.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h +PDFDoc.h +/home/calvin/src/xpdf-4.04/xpdf/PDFDoc.h +TextString.h +/home/calvin/src/xpdf-4.04/xpdf/TextString.h +Gfx.h +/home/calvin/src/xpdf-4.04/xpdf/Gfx.h +GfxFont.h +/home/calvin/src/xpdf-4.04/xpdf/GfxFont.h +OptionalContent.h +/home/calvin/src/xpdf-4.04/xpdf/OptionalContent.h +Annot.h +/home/calvin/src/xpdf-4.04/xpdf/Annot.h +Lexer.h +/home/calvin/src/xpdf-4.04/xpdf/Lexer.h +XFAScanner.h +/home/calvin/src/xpdf-4.04/xpdf/XFAScanner.h +UTF8.h +/home/calvin/src/xpdf-4.04/xpdf/UTF8.h +PDF417Barcode.h +/home/calvin/src/xpdf-4.04/xpdf/PDF417Barcode.h +AcroForm.h +/home/calvin/src/xpdf-4.04/xpdf/AcroForm.h + +/home/calvin/src/xpdf-4.04/xpdf/AcroForm.h +aconf.h +- + +/home/calvin/src/xpdf-4.04/xpdf/Annot.cc +aconf.h +- +stdlib.h +- +math.h +- +gmem.h +/home/calvin/src/xpdf-4.04/xpdf/gmem.h +gmempp.h +/home/calvin/src/xpdf-4.04/xpdf/gmempp.h +GList.h +/home/calvin/src/xpdf-4.04/xpdf/GList.h +Error.h +/home/calvin/src/xpdf-4.04/xpdf/Error.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h +Catalog.h +/home/calvin/src/xpdf-4.04/xpdf/Catalog.h +Gfx.h +/home/calvin/src/xpdf-4.04/xpdf/Gfx.h +GfxFont.h +/home/calvin/src/xpdf-4.04/xpdf/GfxFont.h +Lexer.h +/home/calvin/src/xpdf-4.04/xpdf/Lexer.h +PDFDoc.h +/home/calvin/src/xpdf-4.04/xpdf/PDFDoc.h +OptionalContent.h +/home/calvin/src/xpdf-4.04/xpdf/OptionalContent.h +AcroForm.h +/home/calvin/src/xpdf-4.04/xpdf/AcroForm.h +BuiltinFontTables.h +/home/calvin/src/xpdf-4.04/xpdf/BuiltinFontTables.h +FontEncodingTables.h +/home/calvin/src/xpdf-4.04/xpdf/FontEncodingTables.h +Annot.h +/home/calvin/src/xpdf-4.04/xpdf/Annot.h + +/home/calvin/src/xpdf-4.04/xpdf/Annot.h +aconf.h +- + +/home/calvin/src/xpdf-4.04/xpdf/Array.cc +aconf.h +- +stdlib.h +- +stddef.h +- +gmem.h +/home/calvin/src/xpdf-4.04/xpdf/gmem.h +gmempp.h +/home/calvin/src/xpdf-4.04/xpdf/gmempp.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h +Array.h +/home/calvin/src/xpdf-4.04/xpdf/Array.h + +/home/calvin/src/xpdf-4.04/xpdf/Array.h +aconf.h +- +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h + +/home/calvin/src/xpdf-4.04/xpdf/BuiltinFont.cc +aconf.h +- +stdlib.h +- +string.h +- +gmem.h +/home/calvin/src/xpdf-4.04/xpdf/gmem.h +gmempp.h +/home/calvin/src/xpdf-4.04/xpdf/gmempp.h +FontEncodingTables.h +/home/calvin/src/xpdf-4.04/xpdf/FontEncodingTables.h +BuiltinFont.h +/home/calvin/src/xpdf-4.04/xpdf/BuiltinFont.h + +/home/calvin/src/xpdf-4.04/xpdf/BuiltinFont.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h + +/home/calvin/src/xpdf-4.04/xpdf/BuiltinFontTables.cc +aconf.h +- +stdlib.h +- +gmempp.h +/home/calvin/src/xpdf-4.04/xpdf/gmempp.h +FontEncodingTables.h +/home/calvin/src/xpdf-4.04/xpdf/FontEncodingTables.h +BuiltinFontTables.h +/home/calvin/src/xpdf-4.04/xpdf/BuiltinFontTables.h + +/home/calvin/src/xpdf-4.04/xpdf/BuiltinFontTables.h +BuiltinFont.h +/home/calvin/src/xpdf-4.04/xpdf/BuiltinFont.h + +/home/calvin/src/xpdf-4.04/xpdf/CMap.cc +aconf.h +- +stdio.h +- +stdlib.h +- +string.h +- +ctype.h +- +gmem.h +/home/calvin/src/xpdf-4.04/xpdf/gmem.h +gmempp.h +/home/calvin/src/xpdf-4.04/xpdf/gmempp.h +gfile.h +/home/calvin/src/xpdf-4.04/xpdf/gfile.h +GString.h +/home/calvin/src/xpdf-4.04/xpdf/GString.h +Error.h +/home/calvin/src/xpdf-4.04/xpdf/Error.h +GlobalParams.h +/home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h +PSTokenizer.h +/home/calvin/src/xpdf-4.04/xpdf/PSTokenizer.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h +Stream.h +/home/calvin/src/xpdf-4.04/xpdf/Stream.h +CMap.h +/home/calvin/src/xpdf-4.04/xpdf/CMap.h + +/home/calvin/src/xpdf-4.04/xpdf/CMap.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +CharTypes.h +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h + +/home/calvin/src/xpdf-4.04/xpdf/Catalog.cc +aconf.h +- +string.h +- +stddef.h +- +limits.h +- +gmem.h +/home/calvin/src/xpdf-4.04/xpdf/gmem.h +gmempp.h +/home/calvin/src/xpdf-4.04/xpdf/gmempp.h +gfile.h +/home/calvin/src/xpdf-4.04/xpdf/gfile.h +GList.h +/home/calvin/src/xpdf-4.04/xpdf/GList.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h +CharTypes.h +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h +PDFDoc.h +/home/calvin/src/xpdf-4.04/xpdf/PDFDoc.h +XRef.h +/home/calvin/src/xpdf-4.04/xpdf/XRef.h +Array.h +/home/calvin/src/xpdf-4.04/xpdf/Array.h +Dict.h +/home/calvin/src/xpdf-4.04/xpdf/Dict.h +Page.h +/home/calvin/src/xpdf-4.04/xpdf/Page.h +Error.h +/home/calvin/src/xpdf-4.04/xpdf/Error.h +Link.h +/home/calvin/src/xpdf-4.04/xpdf/Link.h +AcroForm.h +/home/calvin/src/xpdf-4.04/xpdf/AcroForm.h +TextString.h +/home/calvin/src/xpdf-4.04/xpdf/TextString.h +Catalog.h +/home/calvin/src/xpdf-4.04/xpdf/Catalog.h + +/home/calvin/src/xpdf-4.04/xpdf/Catalog.h +aconf.h +- +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h +CharTypes.h +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + +/home/calvin/src/xpdf-4.04/xpdf/CharCodeToUnicode.cc +aconf.h +- +stdio.h +- +string.h +- +gmem.h +/home/calvin/src/xpdf-4.04/xpdf/gmem.h +gmempp.h +/home/calvin/src/xpdf-4.04/xpdf/gmempp.h +gfile.h +/home/calvin/src/xpdf-4.04/xpdf/gfile.h +GString.h +/home/calvin/src/xpdf-4.04/xpdf/GString.h +Error.h +/home/calvin/src/xpdf-4.04/xpdf/Error.h +GlobalParams.h +/home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h +PSTokenizer.h +/home/calvin/src/xpdf-4.04/xpdf/PSTokenizer.h +CharCodeToUnicode.h +/home/calvin/src/xpdf-4.04/xpdf/CharCodeToUnicode.h + +/home/calvin/src/xpdf-4.04/xpdf/CharCodeToUnicode.h +aconf.h +- +CharTypes.h +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h + +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + +/home/calvin/src/xpdf-4.04/xpdf/Decrypt.cc +aconf.h +- +string.h +- +gmem.h +/home/calvin/src/xpdf-4.04/xpdf/gmem.h +gmempp.h +/home/calvin/src/xpdf-4.04/xpdf/gmempp.h +Decrypt.h +/home/calvin/src/xpdf-4.04/xpdf/Decrypt.h + +/home/calvin/src/xpdf-4.04/xpdf/Decrypt.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +GString.h +/home/calvin/src/xpdf-4.04/xpdf/GString.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h +Stream.h +/home/calvin/src/xpdf-4.04/xpdf/Stream.h + +/home/calvin/src/xpdf-4.04/xpdf/Dict.cc +aconf.h +- +stddef.h +- +string.h +- +gmem.h +/home/calvin/src/xpdf-4.04/xpdf/gmem.h +gmempp.h +/home/calvin/src/xpdf-4.04/xpdf/gmempp.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h +XRef.h +/home/calvin/src/xpdf-4.04/xpdf/XRef.h +Dict.h +/home/calvin/src/xpdf-4.04/xpdf/Dict.h + +/home/calvin/src/xpdf-4.04/xpdf/Dict.h +aconf.h +- +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h + +/home/calvin/src/xpdf-4.04/xpdf/DisplayState.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +SplashTypes.h +/home/calvin/src/xpdf-4.04/xpdf/SplashTypes.h + +/home/calvin/src/xpdf-4.04/xpdf/Error.cc +aconf.h +- +stdio.h +- +stddef.h +- +stdarg.h +- +gmempp.h +/home/calvin/src/xpdf-4.04/xpdf/gmempp.h +GString.h +/home/calvin/src/xpdf-4.04/xpdf/GString.h +GlobalParams.h +/home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h +Error.h +/home/calvin/src/xpdf-4.04/xpdf/Error.h + +/home/calvin/src/xpdf-4.04/xpdf/Error.h +aconf.h +- +stdio.h +- +config.h +/home/calvin/src/xpdf-4.04/xpdf/config.h +gfile.h +/home/calvin/src/xpdf-4.04/xpdf/gfile.h + +/home/calvin/src/xpdf-4.04/xpdf/ErrorCodes.h + +/home/calvin/src/xpdf-4.04/xpdf/FontEncodingTables.cc +aconf.h +- +stdlib.h +- +gmempp.h +/home/calvin/src/xpdf-4.04/xpdf/gmempp.h +FontEncodingTables.h +/home/calvin/src/xpdf-4.04/xpdf/FontEncodingTables.h + +/home/calvin/src/xpdf-4.04/xpdf/FontEncodingTables.h + +/home/calvin/src/xpdf-4.04/xpdf/Function.cc +aconf.h +- +stdlib.h +- +string.h +- +ctype.h +- +math.h +- +gmem.h +/home/calvin/src/xpdf-4.04/xpdf/gmem.h +gmempp.h +/home/calvin/src/xpdf-4.04/xpdf/gmempp.h +GList.h +/home/calvin/src/xpdf-4.04/xpdf/GList.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h +Dict.h +/home/calvin/src/xpdf-4.04/xpdf/Dict.h +Stream.h +/home/calvin/src/xpdf-4.04/xpdf/Stream.h +Error.h +/home/calvin/src/xpdf-4.04/xpdf/Error.h +Function.h +/home/calvin/src/xpdf-4.04/xpdf/Function.h + +/home/calvin/src/xpdf-4.04/xpdf/Function.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h + +/home/calvin/src/xpdf-4.04/xpdf/Gfx.cc +aconf.h +- +stdlib.h +- +stdio.h +- +stddef.h +- +string.h +- +math.h +- +gmem.h +/home/calvin/src/xpdf-4.04/xpdf/gmem.h +gmempp.h +/home/calvin/src/xpdf-4.04/xpdf/gmempp.h +GString.h +/home/calvin/src/xpdf-4.04/xpdf/GString.h +GList.h +/home/calvin/src/xpdf-4.04/xpdf/GList.h +Trace.h +/home/calvin/src/xpdf-4.04/xpdf/Trace.h +GlobalParams.h +/home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h +CharTypes.h +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h +PDFDoc.h +/home/calvin/src/xpdf-4.04/xpdf/PDFDoc.h +Array.h +/home/calvin/src/xpdf-4.04/xpdf/Array.h +Dict.h +/home/calvin/src/xpdf-4.04/xpdf/Dict.h +Stream.h +/home/calvin/src/xpdf-4.04/xpdf/Stream.h +Lexer.h +/home/calvin/src/xpdf-4.04/xpdf/Lexer.h +Parser.h +/home/calvin/src/xpdf-4.04/xpdf/Parser.h +GfxFont.h +/home/calvin/src/xpdf-4.04/xpdf/GfxFont.h +GfxState.h +/home/calvin/src/xpdf-4.04/xpdf/GfxState.h +OutputDev.h +/home/calvin/src/xpdf-4.04/xpdf/OutputDev.h +Page.h +/home/calvin/src/xpdf-4.04/xpdf/Page.h +Annot.h +/home/calvin/src/xpdf-4.04/xpdf/Annot.h +OptionalContent.h +/home/calvin/src/xpdf-4.04/xpdf/OptionalContent.h +Error.h +/home/calvin/src/xpdf-4.04/xpdf/Error.h +TextString.h +/home/calvin/src/xpdf-4.04/xpdf/TextString.h +Gfx.h +/home/calvin/src/xpdf-4.04/xpdf/Gfx.h + +/home/calvin/src/xpdf-4.04/xpdf/Gfx.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +gfile.h +/home/calvin/src/xpdf-4.04/xpdf/gfile.h +GfxState.h +/home/calvin/src/xpdf-4.04/xpdf/GfxState.h + +/home/calvin/src/xpdf-4.04/xpdf/GfxFont.cc +aconf.h +- +stdio.h +- +stdlib.h +- +string.h +- +ctype.h +- +math.h +- +limits.h +- +gmem.h +/home/calvin/src/xpdf-4.04/xpdf/gmem.h +gmempp.h +/home/calvin/src/xpdf-4.04/xpdf/gmempp.h +GList.h +/home/calvin/src/xpdf-4.04/xpdf/GList.h +GHash.h +/home/calvin/src/xpdf-4.04/xpdf/GHash.h +Error.h +/home/calvin/src/xpdf-4.04/xpdf/Error.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h +Dict.h +/home/calvin/src/xpdf-4.04/xpdf/Dict.h +GlobalParams.h +/home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h +CMap.h +/home/calvin/src/xpdf-4.04/xpdf/CMap.h +CharCodeToUnicode.h +/home/calvin/src/xpdf-4.04/xpdf/CharCodeToUnicode.h +FontEncodingTables.h +/home/calvin/src/xpdf-4.04/xpdf/FontEncodingTables.h +BuiltinFontTables.h +/home/calvin/src/xpdf-4.04/xpdf/BuiltinFontTables.h +FoFiIdentifier.h +/home/calvin/src/xpdf-4.04/xpdf/FoFiIdentifier.h +FoFiType1.h +/home/calvin/src/xpdf-4.04/xpdf/FoFiType1.h +FoFiType1C.h +/home/calvin/src/xpdf-4.04/xpdf/FoFiType1C.h +FoFiTrueType.h +/home/calvin/src/xpdf-4.04/xpdf/FoFiTrueType.h +GfxFont.h +/home/calvin/src/xpdf-4.04/xpdf/GfxFont.h + +/home/calvin/src/xpdf-4.04/xpdf/GfxFont.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +GString.h +/home/calvin/src/xpdf-4.04/xpdf/GString.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h +CharTypes.h +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + +/home/calvin/src/xpdf-4.04/xpdf/GfxState.cc +aconf.h +- +stddef.h +- +math.h +- +string.h +- +gmem.h +/home/calvin/src/xpdf-4.04/xpdf/gmem.h +gmempp.h +/home/calvin/src/xpdf-4.04/xpdf/gmempp.h +Error.h +/home/calvin/src/xpdf-4.04/xpdf/Error.h +GlobalParams.h +/home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h +Array.h +/home/calvin/src/xpdf-4.04/xpdf/Array.h +Page.h +/home/calvin/src/xpdf-4.04/xpdf/Page.h +XRef.h +/home/calvin/src/xpdf-4.04/xpdf/XRef.h +GfxState.h +/home/calvin/src/xpdf-4.04/xpdf/GfxState.h + +/home/calvin/src/xpdf-4.04/xpdf/GfxState.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h +Function.h +/home/calvin/src/xpdf-4.04/xpdf/Function.h + +/home/calvin/src/xpdf-4.04/xpdf/GlobalParams.cc +aconf.h +- +string.h +- +stdio.h +- +stdarg.h +- +ctype.h +- +time.h +- +shlobj.h +- +paper.h +- +fontconfig/fontconfig.h +- +gmem.h +/home/calvin/src/xpdf-4.04/xpdf/gmem.h +gmempp.h +/home/calvin/src/xpdf-4.04/xpdf/gmempp.h +GString.h +/home/calvin/src/xpdf-4.04/xpdf/GString.h +GList.h +/home/calvin/src/xpdf-4.04/xpdf/GList.h +GHash.h +/home/calvin/src/xpdf-4.04/xpdf/GHash.h +gfile.h +/home/calvin/src/xpdf-4.04/xpdf/gfile.h +FoFiIdentifier.h +/home/calvin/src/xpdf-4.04/xpdf/FoFiIdentifier.h +Error.h +/home/calvin/src/xpdf-4.04/xpdf/Error.h +NameToCharCode.h +/home/calvin/src/xpdf-4.04/xpdf/NameToCharCode.h +CharCodeToUnicode.h +/home/calvin/src/xpdf-4.04/xpdf/CharCodeToUnicode.h +UnicodeRemapping.h +/home/calvin/src/xpdf-4.04/xpdf/UnicodeRemapping.h +UnicodeMap.h +/home/calvin/src/xpdf-4.04/xpdf/UnicodeMap.h +CMap.h +/home/calvin/src/xpdf-4.04/xpdf/CMap.h +BuiltinFontTables.h +/home/calvin/src/xpdf-4.04/xpdf/BuiltinFontTables.h +FontEncodingTables.h +/home/calvin/src/xpdf-4.04/xpdf/FontEncodingTables.h +GlobalParams.h +/home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h +NameToUnicodeTable.h +/home/calvin/src/xpdf-4.04/xpdf/NameToUnicodeTable.h +UnicodeMapTables.h +/home/calvin/src/xpdf-4.04/xpdf/UnicodeMapTables.h +UTF8.h +/home/calvin/src/xpdf-4.04/xpdf/UTF8.h + +/home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h +aconf.h +- +stdio.h +- +windows.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +CharTypes.h +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h + +/home/calvin/src/xpdf-4.04/xpdf/JArithmeticDecoder.cc +aconf.h +- +gmempp.h +/home/calvin/src/xpdf-4.04/xpdf/gmempp.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h +Stream.h +/home/calvin/src/xpdf-4.04/xpdf/Stream.h +JArithmeticDecoder.h +/home/calvin/src/xpdf-4.04/xpdf/JArithmeticDecoder.h + +/home/calvin/src/xpdf-4.04/xpdf/JArithmeticDecoder.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h + +/home/calvin/src/xpdf-4.04/xpdf/JBIG2Stream.cc +aconf.h +- +stdlib.h +- +limits.h +- +gmempp.h +/home/calvin/src/xpdf-4.04/xpdf/gmempp.h +GList.h +/home/calvin/src/xpdf-4.04/xpdf/GList.h +Error.h +/home/calvin/src/xpdf-4.04/xpdf/Error.h +JArithmeticDecoder.h +/home/calvin/src/xpdf-4.04/xpdf/JArithmeticDecoder.h +JBIG2Stream.h +/home/calvin/src/xpdf-4.04/xpdf/JBIG2Stream.h +Stream-CCITT.h +/home/calvin/src/xpdf-4.04/xpdf/Stream-CCITT.h + +/home/calvin/src/xpdf-4.04/xpdf/JBIG2Stream.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h +Stream.h +/home/calvin/src/xpdf-4.04/xpdf/Stream.h + +/home/calvin/src/xpdf-4.04/xpdf/JPXStream.cc +aconf.h +- +limits.h +- +gmem.h +/home/calvin/src/xpdf-4.04/xpdf/gmem.h +gmempp.h +/home/calvin/src/xpdf-4.04/xpdf/gmempp.h +Error.h +/home/calvin/src/xpdf-4.04/xpdf/Error.h +JArithmeticDecoder.h +/home/calvin/src/xpdf-4.04/xpdf/JArithmeticDecoder.h +JPXStream.h +/home/calvin/src/xpdf-4.04/xpdf/JPXStream.h + +/home/calvin/src/xpdf-4.04/xpdf/JPXStream.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h +Stream.h +/home/calvin/src/xpdf-4.04/xpdf/Stream.h + +/home/calvin/src/xpdf-4.04/xpdf/Lexer.cc +aconf.h +- +stdlib.h +- +stddef.h +- +string.h +- +ctype.h +- +gmempp.h +/home/calvin/src/xpdf-4.04/xpdf/gmempp.h +Lexer.h +/home/calvin/src/xpdf-4.04/xpdf/Lexer.h +Error.h +/home/calvin/src/xpdf-4.04/xpdf/Error.h + +/home/calvin/src/xpdf-4.04/xpdf/Lexer.h +aconf.h +- +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h +Stream.h +/home/calvin/src/xpdf-4.04/xpdf/Stream.h + +/home/calvin/src/xpdf-4.04/xpdf/Link.cc +aconf.h +- +stddef.h +- +string.h +- +gmem.h +/home/calvin/src/xpdf-4.04/xpdf/gmem.h +gmempp.h +/home/calvin/src/xpdf-4.04/xpdf/gmempp.h +GString.h +/home/calvin/src/xpdf-4.04/xpdf/GString.h +Error.h +/home/calvin/src/xpdf-4.04/xpdf/Error.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h +Array.h +/home/calvin/src/xpdf-4.04/xpdf/Array.h +Dict.h +/home/calvin/src/xpdf-4.04/xpdf/Dict.h +Link.h +/home/calvin/src/xpdf-4.04/xpdf/Link.h + +/home/calvin/src/xpdf-4.04/xpdf/Link.h +aconf.h +- +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h + +/home/calvin/src/xpdf-4.04/xpdf/NameToCharCode.cc +aconf.h +- +string.h +- +gmem.h +/home/calvin/src/xpdf-4.04/xpdf/gmem.h +gmempp.h +/home/calvin/src/xpdf-4.04/xpdf/gmempp.h +NameToCharCode.h +/home/calvin/src/xpdf-4.04/xpdf/NameToCharCode.h + +/home/calvin/src/xpdf-4.04/xpdf/NameToCharCode.h +aconf.h +- +CharTypes.h +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + +/home/calvin/src/xpdf-4.04/xpdf/NameToUnicodeTable.h + +/home/calvin/src/xpdf-4.04/xpdf/Object.cc +aconf.h +- +stddef.h +- +gmempp.h +/home/calvin/src/xpdf-4.04/xpdf/gmempp.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h +Array.h +/home/calvin/src/xpdf-4.04/xpdf/Array.h +Dict.h +/home/calvin/src/xpdf-4.04/xpdf/Dict.h +Error.h +/home/calvin/src/xpdf-4.04/xpdf/Error.h +Stream.h +/home/calvin/src/xpdf-4.04/xpdf/Stream.h +XRef.h +/home/calvin/src/xpdf-4.04/xpdf/XRef.h + +/home/calvin/src/xpdf-4.04/xpdf/Object.h +aconf.h +- +stdio.h +- +string.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +gmem.h +/home/calvin/src/xpdf-4.04/xpdf/gmem.h +gfile.h +/home/calvin/src/xpdf-4.04/xpdf/gfile.h +GString.h +/home/calvin/src/xpdf-4.04/xpdf/GString.h +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h +Array.h +/home/calvin/src/xpdf-4.04/xpdf/Array.h +Dict.h +/home/calvin/src/xpdf-4.04/xpdf/Dict.h +Stream.h +/home/calvin/src/xpdf-4.04/xpdf/Stream.h + +/home/calvin/src/xpdf-4.04/xpdf/OptionalContent.cc +aconf.h +- +gmempp.h +/home/calvin/src/xpdf-4.04/xpdf/gmempp.h +GString.h +/home/calvin/src/xpdf-4.04/xpdf/GString.h +GList.h +/home/calvin/src/xpdf-4.04/xpdf/GList.h +Error.h +/home/calvin/src/xpdf-4.04/xpdf/Error.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h +PDFDoc.h +/home/calvin/src/xpdf-4.04/xpdf/PDFDoc.h +TextString.h +/home/calvin/src/xpdf-4.04/xpdf/TextString.h +OptionalContent.h +/home/calvin/src/xpdf-4.04/xpdf/OptionalContent.h + +/home/calvin/src/xpdf-4.04/xpdf/OptionalContent.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h +CharTypes.h +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + +/home/calvin/src/xpdf-4.04/xpdf/Outline.cc +aconf.h +- +gmem.h +/home/calvin/src/xpdf-4.04/xpdf/gmem.h +gmempp.h +/home/calvin/src/xpdf-4.04/xpdf/gmempp.h +GString.h +/home/calvin/src/xpdf-4.04/xpdf/GString.h +GList.h +/home/calvin/src/xpdf-4.04/xpdf/GList.h +Error.h +/home/calvin/src/xpdf-4.04/xpdf/Error.h +Link.h +/home/calvin/src/xpdf-4.04/xpdf/Link.h +TextString.h +/home/calvin/src/xpdf-4.04/xpdf/TextString.h +Outline.h +/home/calvin/src/xpdf-4.04/xpdf/Outline.h + +/home/calvin/src/xpdf-4.04/xpdf/Outline.h +aconf.h +- +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h +CharTypes.h +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + +/home/calvin/src/xpdf-4.04/xpdf/OutputDev.cc +aconf.h +- +stddef.h +- +gmempp.h +/home/calvin/src/xpdf-4.04/xpdf/gmempp.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h +Stream.h +/home/calvin/src/xpdf-4.04/xpdf/Stream.h +GfxState.h +/home/calvin/src/xpdf-4.04/xpdf/GfxState.h +OutputDev.h +/home/calvin/src/xpdf-4.04/xpdf/OutputDev.h + +/home/calvin/src/xpdf-4.04/xpdf/OutputDev.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +CharTypes.h +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + +/home/calvin/src/xpdf-4.04/xpdf/PDF417Barcode.cc +aconf.h +- +math.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +GString.h +/home/calvin/src/xpdf-4.04/xpdf/GString.h +GList.h +/home/calvin/src/xpdf-4.04/xpdf/GList.h +Error.h +/home/calvin/src/xpdf-4.04/xpdf/Error.h +PDF417Barcode.h +/home/calvin/src/xpdf-4.04/xpdf/PDF417Barcode.h + +/home/calvin/src/xpdf-4.04/xpdf/PDF417Barcode.h +aconf.h +- + +/home/calvin/src/xpdf-4.04/xpdf/PDFCore.h +aconf.h +- +stdlib.h +- +SplashTypes.h +/home/calvin/src/xpdf-4.04/xpdf/SplashTypes.h +CharTypes.h +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h +DisplayState.h +/home/calvin/src/xpdf-4.04/xpdf/DisplayState.h +TextOutputDev.h +/home/calvin/src/xpdf-4.04/xpdf/TextOutputDev.h + +/home/calvin/src/xpdf-4.04/xpdf/PDFDoc.cc +aconf.h +- +stdio.h +- +stdlib.h +- +stddef.h +- +string.h +- +windows.h +- +gmempp.h +/home/calvin/src/xpdf-4.04/xpdf/gmempp.h +GString.h +/home/calvin/src/xpdf-4.04/xpdf/GString.h +gfile.h +/home/calvin/src/xpdf-4.04/xpdf/gfile.h +config.h +/home/calvin/src/xpdf-4.04/xpdf/config.h +GlobalParams.h +/home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h +Page.h +/home/calvin/src/xpdf-4.04/xpdf/Page.h +Catalog.h +/home/calvin/src/xpdf-4.04/xpdf/Catalog.h +Stream.h +/home/calvin/src/xpdf-4.04/xpdf/Stream.h +XRef.h +/home/calvin/src/xpdf-4.04/xpdf/XRef.h +Link.h +/home/calvin/src/xpdf-4.04/xpdf/Link.h +OutputDev.h +/home/calvin/src/xpdf-4.04/xpdf/OutputDev.h +Error.h +/home/calvin/src/xpdf-4.04/xpdf/Error.h +ErrorCodes.h +/home/calvin/src/xpdf-4.04/xpdf/ErrorCodes.h +Lexer.h +/home/calvin/src/xpdf-4.04/xpdf/Lexer.h +Parser.h +/home/calvin/src/xpdf-4.04/xpdf/Parser.h +SecurityHandler.h +/home/calvin/src/xpdf-4.04/xpdf/SecurityHandler.h +UTF8.h +/home/calvin/src/xpdf-4.04/xpdf/UTF8.h +Outline.h +/home/calvin/src/xpdf-4.04/xpdf/Outline.h +OptionalContent.h +/home/calvin/src/xpdf-4.04/xpdf/OptionalContent.h +PDFDoc.h +/home/calvin/src/xpdf-4.04/xpdf/PDFDoc.h + +/home/calvin/src/xpdf-4.04/xpdf/PDFDoc.h +aconf.h +- +stdio.h +- +XRef.h +/home/calvin/src/xpdf-4.04/xpdf/XRef.h +Catalog.h +/home/calvin/src/xpdf-4.04/xpdf/Catalog.h +Page.h +/home/calvin/src/xpdf-4.04/xpdf/Page.h + +/home/calvin/src/xpdf-4.04/xpdf/PDFDocEncoding.cc +aconf.h +- +gmempp.h +/home/calvin/src/xpdf-4.04/xpdf/gmempp.h +PDFDocEncoding.h +/home/calvin/src/xpdf-4.04/xpdf/PDFDocEncoding.h + +/home/calvin/src/xpdf-4.04/xpdf/PDFDocEncoding.h +CharTypes.h +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + +/home/calvin/src/xpdf-4.04/xpdf/PSTokenizer.cc +aconf.h +- +stdio.h +- +stdlib.h +- +gmempp.h +/home/calvin/src/xpdf-4.04/xpdf/gmempp.h +PSTokenizer.h +/home/calvin/src/xpdf-4.04/xpdf/PSTokenizer.h + +/home/calvin/src/xpdf-4.04/xpdf/PSTokenizer.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h + +/home/calvin/src/xpdf-4.04/xpdf/Page.cc +aconf.h +- +stddef.h +- +gmempp.h +/home/calvin/src/xpdf-4.04/xpdf/gmempp.h +Trace.h +/home/calvin/src/xpdf-4.04/xpdf/Trace.h +GlobalParams.h +/home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h +Array.h +/home/calvin/src/xpdf-4.04/xpdf/Array.h +Dict.h +/home/calvin/src/xpdf-4.04/xpdf/Dict.h +PDFDoc.h +/home/calvin/src/xpdf-4.04/xpdf/PDFDoc.h +XRef.h +/home/calvin/src/xpdf-4.04/xpdf/XRef.h +Link.h +/home/calvin/src/xpdf-4.04/xpdf/Link.h +OutputDev.h +/home/calvin/src/xpdf-4.04/xpdf/OutputDev.h +Gfx.h +/home/calvin/src/xpdf-4.04/xpdf/Gfx.h +GfxState.h +/home/calvin/src/xpdf-4.04/xpdf/GfxState.h +Annot.h +/home/calvin/src/xpdf-4.04/xpdf/Annot.h +AcroForm.h +/home/calvin/src/xpdf-4.04/xpdf/AcroForm.h +Error.h +/home/calvin/src/xpdf-4.04/xpdf/Error.h +Catalog.h +/home/calvin/src/xpdf-4.04/xpdf/Catalog.h +Page.h +/home/calvin/src/xpdf-4.04/xpdf/Page.h + +/home/calvin/src/xpdf-4.04/xpdf/Page.h +aconf.h +- +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h + +/home/calvin/src/xpdf-4.04/xpdf/Parser.cc +aconf.h +- +stddef.h +- +string.h +- +gmempp.h +/home/calvin/src/xpdf-4.04/xpdf/gmempp.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h +Array.h +/home/calvin/src/xpdf-4.04/xpdf/Array.h +Dict.h +/home/calvin/src/xpdf-4.04/xpdf/Dict.h +Decrypt.h +/home/calvin/src/xpdf-4.04/xpdf/Decrypt.h +Parser.h +/home/calvin/src/xpdf-4.04/xpdf/Parser.h +XRef.h +/home/calvin/src/xpdf-4.04/xpdf/XRef.h +Error.h +/home/calvin/src/xpdf-4.04/xpdf/Error.h + +/home/calvin/src/xpdf-4.04/xpdf/Parser.h +aconf.h +- +Lexer.h +/home/calvin/src/xpdf-4.04/xpdf/Lexer.h + +/home/calvin/src/xpdf-4.04/xpdf/SecurityHandler.cc +aconf.h +- +gmempp.h +/home/calvin/src/xpdf-4.04/xpdf/gmempp.h +GString.h +/home/calvin/src/xpdf-4.04/xpdf/GString.h +PDFDoc.h +/home/calvin/src/xpdf-4.04/xpdf/PDFDoc.h +Decrypt.h +/home/calvin/src/xpdf-4.04/xpdf/Decrypt.h +Error.h +/home/calvin/src/xpdf-4.04/xpdf/Error.h +GlobalParams.h +/home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h +PDFCore.h +/home/calvin/src/xpdf-4.04/xpdf/PDFCore.h +SecurityHandler.h +/home/calvin/src/xpdf-4.04/xpdf/SecurityHandler.h + +/home/calvin/src/xpdf-4.04/xpdf/SecurityHandler.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h + +/home/calvin/src/xpdf-4.04/xpdf/Stream-CCITT.h + +/home/calvin/src/xpdf-4.04/xpdf/Stream.cc +aconf.h +- +stdio.h +- +stdlib.h +- +stddef.h +- +limits.h +- +io.h +- +unistd.h +- +string.h +- +ctype.h +- +gmem.h +/home/calvin/src/xpdf-4.04/xpdf/gmem.h +gmempp.h +/home/calvin/src/xpdf-4.04/xpdf/gmempp.h +gfile.h +/home/calvin/src/xpdf-4.04/xpdf/gfile.h +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h +config.h +/home/calvin/src/xpdf-4.04/xpdf/config.h +Error.h +/home/calvin/src/xpdf-4.04/xpdf/Error.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h +Lexer.h +/home/calvin/src/xpdf-4.04/xpdf/Lexer.h +GfxState.h +/home/calvin/src/xpdf-4.04/xpdf/GfxState.h +Stream.h +/home/calvin/src/xpdf-4.04/xpdf/Stream.h +JBIG2Stream.h +/home/calvin/src/xpdf-4.04/xpdf/JBIG2Stream.h +JPXStream.h +/home/calvin/src/xpdf-4.04/xpdf/JPXStream.h +Stream-CCITT.h +/home/calvin/src/xpdf-4.04/xpdf/Stream-CCITT.h + +/home/calvin/src/xpdf-4.04/xpdf/Stream.h +aconf.h +- +stdio.h +- +jpeglib.h +- +setjmp.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +gfile.h +/home/calvin/src/xpdf-4.04/xpdf/gfile.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h + +/home/calvin/src/xpdf-4.04/xpdf/TextOutputDev.h +aconf.h +- +stdio.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +GfxFont.h +/home/calvin/src/xpdf-4.04/xpdf/GfxFont.h +OutputDev.h +/home/calvin/src/xpdf-4.04/xpdf/OutputDev.h + +/home/calvin/src/xpdf-4.04/xpdf/TextString.cc +aconf.h +- +string.h +- +gmem.h +/home/calvin/src/xpdf-4.04/xpdf/gmem.h +gmempp.h +/home/calvin/src/xpdf-4.04/xpdf/gmempp.h +GString.h +/home/calvin/src/xpdf-4.04/xpdf/GString.h +PDFDocEncoding.h +/home/calvin/src/xpdf-4.04/xpdf/PDFDocEncoding.h +UTF8.h +/home/calvin/src/xpdf-4.04/xpdf/UTF8.h +TextString.h +/home/calvin/src/xpdf-4.04/xpdf/TextString.h + +/home/calvin/src/xpdf-4.04/xpdf/TextString.h +aconf.h +- +CharTypes.h +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + +/home/calvin/src/xpdf-4.04/xpdf/UTF8.cc +aconf.h +- +UTF8.h +/home/calvin/src/xpdf-4.04/xpdf/UTF8.h + +/home/calvin/src/xpdf-4.04/xpdf/UTF8.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +GString.h +/home/calvin/src/xpdf-4.04/xpdf/GString.h +CharTypes.h +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + +/home/calvin/src/xpdf-4.04/xpdf/UnicodeMap.cc +aconf.h +- +stdio.h +- +string.h +- +gmem.h +/home/calvin/src/xpdf-4.04/xpdf/gmem.h +gmempp.h +/home/calvin/src/xpdf-4.04/xpdf/gmempp.h +gfile.h +/home/calvin/src/xpdf-4.04/xpdf/gfile.h +GString.h +/home/calvin/src/xpdf-4.04/xpdf/GString.h +GList.h +/home/calvin/src/xpdf-4.04/xpdf/GList.h +Error.h +/home/calvin/src/xpdf-4.04/xpdf/Error.h +GlobalParams.h +/home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h +UnicodeMap.h +/home/calvin/src/xpdf-4.04/xpdf/UnicodeMap.h + +/home/calvin/src/xpdf-4.04/xpdf/UnicodeMap.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +CharTypes.h +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h + +/home/calvin/src/xpdf-4.04/xpdf/UnicodeMapTables.h + +/home/calvin/src/xpdf-4.04/xpdf/UnicodeRemapping.cc +aconf.h +- +stdio.h +- +string.h +- +gmem.h +/home/calvin/src/xpdf-4.04/xpdf/gmem.h +gmempp.h +/home/calvin/src/xpdf-4.04/xpdf/gmempp.h +gfile.h +/home/calvin/src/xpdf-4.04/xpdf/gfile.h +GString.h +/home/calvin/src/xpdf-4.04/xpdf/GString.h +Error.h +/home/calvin/src/xpdf-4.04/xpdf/Error.h +UnicodeRemapping.h +/home/calvin/src/xpdf-4.04/xpdf/UnicodeRemapping.h + +/home/calvin/src/xpdf-4.04/xpdf/UnicodeRemapping.h +aconf.h +- +CharTypes.h +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + +/home/calvin/src/xpdf-4.04/xpdf/UnicodeTypeTable.cc +aconf.h +- +stdlib.h +- +gmempp.h +/home/calvin/src/xpdf-4.04/xpdf/gmempp.h +CharTypes.h +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h +UnicodeTypeTable.h +/home/calvin/src/xpdf-4.04/xpdf/UnicodeTypeTable.h + +/home/calvin/src/xpdf-4.04/xpdf/UnicodeTypeTable.h +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h + +/home/calvin/src/xpdf-4.04/xpdf/XFAScanner.cc +aconf.h +- +GString.h +/home/calvin/src/xpdf-4.04/xpdf/GString.h +GHash.h +/home/calvin/src/xpdf-4.04/xpdf/GHash.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h +Error.h +/home/calvin/src/xpdf-4.04/xpdf/Error.h +Zoox.h +/home/calvin/src/xpdf-4.04/xpdf/Zoox.h +XFAScanner.h +/home/calvin/src/xpdf-4.04/xpdf/XFAScanner.h + +/home/calvin/src/xpdf-4.04/xpdf/XFAScanner.h +aconf.h +- + +/home/calvin/src/xpdf-4.04/xpdf/XRef.cc +aconf.h +- +stdlib.h +- +stddef.h +- +string.h +- +ctype.h +- +limits.h +- +gmem.h +/home/calvin/src/xpdf-4.04/xpdf/gmem.h +gmempp.h +/home/calvin/src/xpdf-4.04/xpdf/gmempp.h +gfile.h +/home/calvin/src/xpdf-4.04/xpdf/gfile.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h +Stream.h +/home/calvin/src/xpdf-4.04/xpdf/Stream.h +Lexer.h +/home/calvin/src/xpdf-4.04/xpdf/Lexer.h +Parser.h +/home/calvin/src/xpdf-4.04/xpdf/Parser.h +Dict.h +/home/calvin/src/xpdf-4.04/xpdf/Dict.h +Error.h +/home/calvin/src/xpdf-4.04/xpdf/Error.h +ErrorCodes.h +/home/calvin/src/xpdf-4.04/xpdf/ErrorCodes.h +XRef.h +/home/calvin/src/xpdf-4.04/xpdf/XRef.h + +/home/calvin/src/xpdf-4.04/xpdf/XRef.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +gfile.h +/home/calvin/src/xpdf-4.04/xpdf/gfile.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h + +/home/calvin/src/xpdf-4.04/xpdf/Zoox.cc +aconf.h +- +stdlib.h +- +stdio.h +- +string.h +- +gmem.h +/home/calvin/src/xpdf-4.04/xpdf/gmem.h +gmempp.h +/home/calvin/src/xpdf-4.04/xpdf/gmempp.h +GString.h +/home/calvin/src/xpdf-4.04/xpdf/GString.h +GList.h +/home/calvin/src/xpdf-4.04/xpdf/GList.h +GHash.h +/home/calvin/src/xpdf-4.04/xpdf/GHash.h +Zoox.h +/home/calvin/src/xpdf-4.04/xpdf/Zoox.h + +/home/calvin/src/xpdf-4.04/xpdf/Zoox.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h + +/home/calvin/src/xpdf-4.04/xpdf/config.h + +aconf.h +aconf2.h +- + +aconf2.h +AvailabilityMacros.h +- + +fofi/FoFiBase.h +aconf.h +- +gtypes.h +fofi/gtypes.h + +fofi/FoFiIdentifier.h +aconf.h +- + +fofi/FoFiTrueType.h +aconf.h +- +gtypes.h +fofi/gtypes.h +FoFiBase.h +fofi/FoFiBase.h + +fofi/FoFiType1.h +aconf.h +- +gtypes.h +fofi/gtypes.h +FoFiBase.h +fofi/FoFiBase.h + +fofi/FoFiType1C.h +aconf.h +- +gtypes.h +fofi/gtypes.h +FoFiBase.h +fofi/FoFiBase.h + +goo/FixedPoint.h +aconf.h +- +stdio.h +- +stdlib.h +- +gtypes.h +goo/gtypes.h + +goo/GHash.h +aconf.h +- +gtypes.h +goo/gtypes.h + +goo/GList.h +aconf.h +- +gtypes.h +goo/gtypes.h + +goo/GMutex.h +aconf.h +- +windows.h +- +intrin.h +- +pthread.h +- + +goo/GString.h +aconf.h +- +limits.h +- +stdarg.h +- +gtypes.h +goo/gtypes.h + +goo/Trace.h +aconf.h +- + +goo/gfile.h +aconf.h +- +stdio.h +- +stdlib.h +- +stddef.h +- +sys/stat.h +- +win32lib.h +- +windows.h +- +unistd.h +- +sys/types.h +- +gtypes.h +goo/gtypes.h + +goo/gmem.h +stdio.h +- +aconf.h +- + +goo/gmempp.h +stdlib.h +- + +goo/gtypes.h + +splash/SplashTypes.h +aconf.h +- +gtypes.h +splash/gtypes.h +FixedPoint.h +splash/FixedPoint.h + diff --git a/xpdf/CMakeFiles/xpdf_objs.dir/Catalog.cc.o b/xpdf/CMakeFiles/xpdf_objs.dir/Catalog.cc.o new file mode 100644 index 0000000..b18f432 Binary files /dev/null and b/xpdf/CMakeFiles/xpdf_objs.dir/Catalog.cc.o differ diff --git a/xpdf/CMakeFiles/xpdf_objs.dir/CharCodeToUnicode.cc.o b/xpdf/CMakeFiles/xpdf_objs.dir/CharCodeToUnicode.cc.o new file mode 100644 index 0000000..340a4c1 Binary files /dev/null and b/xpdf/CMakeFiles/xpdf_objs.dir/CharCodeToUnicode.cc.o differ diff --git a/xpdf/CMakeFiles/xpdf_objs.dir/Decrypt.cc.o b/xpdf/CMakeFiles/xpdf_objs.dir/Decrypt.cc.o new file mode 100644 index 0000000..ea723f2 Binary files /dev/null and b/xpdf/CMakeFiles/xpdf_objs.dir/Decrypt.cc.o differ diff --git a/xpdf/CMakeFiles/xpdf_objs.dir/DependInfo.cmake b/xpdf/CMakeFiles/xpdf_objs.dir/DependInfo.cmake new file mode 100644 index 0000000..ae4a812 --- /dev/null +++ b/xpdf/CMakeFiles/xpdf_objs.dir/DependInfo.cmake @@ -0,0 +1,66 @@ +# The set of languages for which implicit dependencies are needed: +set(CMAKE_DEPENDS_LANGUAGES + "CXX" + ) +# The set of files for implicit dependencies of each language: +set(CMAKE_DEPENDS_CHECK_CXX + "/home/calvin/src/xpdf-4.04/xpdf/AcroForm.cc" "/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/AcroForm.cc.o" + "/home/calvin/src/xpdf-4.04/xpdf/Annot.cc" "/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Annot.cc.o" + "/home/calvin/src/xpdf-4.04/xpdf/Array.cc" "/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Array.cc.o" + "/home/calvin/src/xpdf-4.04/xpdf/BuiltinFont.cc" "/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFont.cc.o" + "/home/calvin/src/xpdf-4.04/xpdf/BuiltinFontTables.cc" "/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFontTables.cc.o" + "/home/calvin/src/xpdf-4.04/xpdf/CMap.cc" "/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/CMap.cc.o" + "/home/calvin/src/xpdf-4.04/xpdf/Catalog.cc" "/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Catalog.cc.o" + "/home/calvin/src/xpdf-4.04/xpdf/CharCodeToUnicode.cc" "/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/CharCodeToUnicode.cc.o" + "/home/calvin/src/xpdf-4.04/xpdf/Decrypt.cc" "/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Decrypt.cc.o" + "/home/calvin/src/xpdf-4.04/xpdf/Dict.cc" "/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Dict.cc.o" + "/home/calvin/src/xpdf-4.04/xpdf/Error.cc" "/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Error.cc.o" + "/home/calvin/src/xpdf-4.04/xpdf/FontEncodingTables.cc" "/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/FontEncodingTables.cc.o" + "/home/calvin/src/xpdf-4.04/xpdf/Function.cc" "/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Function.cc.o" + "/home/calvin/src/xpdf-4.04/xpdf/Gfx.cc" "/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Gfx.cc.o" + "/home/calvin/src/xpdf-4.04/xpdf/GfxFont.cc" "/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/GfxFont.cc.o" + "/home/calvin/src/xpdf-4.04/xpdf/GfxState.cc" "/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/GfxState.cc.o" + "/home/calvin/src/xpdf-4.04/xpdf/GlobalParams.cc" "/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/GlobalParams.cc.o" + "/home/calvin/src/xpdf-4.04/xpdf/JArithmeticDecoder.cc" "/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/JArithmeticDecoder.cc.o" + "/home/calvin/src/xpdf-4.04/xpdf/JBIG2Stream.cc" "/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/JBIG2Stream.cc.o" + "/home/calvin/src/xpdf-4.04/xpdf/JPXStream.cc" "/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/JPXStream.cc.o" + "/home/calvin/src/xpdf-4.04/xpdf/Lexer.cc" "/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Lexer.cc.o" + "/home/calvin/src/xpdf-4.04/xpdf/Link.cc" "/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Link.cc.o" + "/home/calvin/src/xpdf-4.04/xpdf/NameToCharCode.cc" "/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/NameToCharCode.cc.o" + "/home/calvin/src/xpdf-4.04/xpdf/Object.cc" "/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Object.cc.o" + "/home/calvin/src/xpdf-4.04/xpdf/OptionalContent.cc" "/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/OptionalContent.cc.o" + "/home/calvin/src/xpdf-4.04/xpdf/Outline.cc" "/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Outline.cc.o" + "/home/calvin/src/xpdf-4.04/xpdf/OutputDev.cc" "/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/OutputDev.cc.o" + "/home/calvin/src/xpdf-4.04/xpdf/PDF417Barcode.cc" "/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/PDF417Barcode.cc.o" + "/home/calvin/src/xpdf-4.04/xpdf/PDFDoc.cc" "/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/PDFDoc.cc.o" + "/home/calvin/src/xpdf-4.04/xpdf/PDFDocEncoding.cc" "/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/PDFDocEncoding.cc.o" + "/home/calvin/src/xpdf-4.04/xpdf/PSTokenizer.cc" "/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/PSTokenizer.cc.o" + "/home/calvin/src/xpdf-4.04/xpdf/Page.cc" "/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Page.cc.o" + "/home/calvin/src/xpdf-4.04/xpdf/Parser.cc" "/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Parser.cc.o" + "/home/calvin/src/xpdf-4.04/xpdf/SecurityHandler.cc" "/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.o" + "/home/calvin/src/xpdf-4.04/xpdf/Stream.cc" "/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Stream.cc.o" + "/home/calvin/src/xpdf-4.04/xpdf/TextString.cc" "/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/TextString.cc.o" + "/home/calvin/src/xpdf-4.04/xpdf/UTF8.cc" "/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/UTF8.cc.o" + "/home/calvin/src/xpdf-4.04/xpdf/UnicodeMap.cc" "/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/UnicodeMap.cc.o" + "/home/calvin/src/xpdf-4.04/xpdf/UnicodeRemapping.cc" "/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/UnicodeRemapping.cc.o" + "/home/calvin/src/xpdf-4.04/xpdf/UnicodeTypeTable.cc" "/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/UnicodeTypeTable.cc.o" + "/home/calvin/src/xpdf-4.04/xpdf/XFAScanner.cc" "/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/XFAScanner.cc.o" + "/home/calvin/src/xpdf-4.04/xpdf/XRef.cc" "/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/XRef.cc.o" + "/home/calvin/src/xpdf-4.04/xpdf/Zoox.cc" "/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/Zoox.cc.o" + ) +set(CMAKE_CXX_COMPILER_ID "GNU") + +# The include file search paths: +set(CMAKE_CXX_TARGET_INCLUDE_PATH + "." + "goo" + "fofi" + "splash" + ) + +# Targets to which this target links. +set(CMAKE_TARGET_LINKED_INFO_FILES + ) + +# Fortran module output directory. +set(CMAKE_Fortran_TARGET_MODULE_DIR "") diff --git a/xpdf/CMakeFiles/xpdf_objs.dir/Dict.cc.o b/xpdf/CMakeFiles/xpdf_objs.dir/Dict.cc.o new file mode 100644 index 0000000..4eb2016 Binary files /dev/null and b/xpdf/CMakeFiles/xpdf_objs.dir/Dict.cc.o differ diff --git a/xpdf/CMakeFiles/xpdf_objs.dir/Error.cc.o b/xpdf/CMakeFiles/xpdf_objs.dir/Error.cc.o new file mode 100644 index 0000000..5f203c0 Binary files /dev/null and b/xpdf/CMakeFiles/xpdf_objs.dir/Error.cc.o differ diff --git a/xpdf/CMakeFiles/xpdf_objs.dir/FontEncodingTables.cc.o b/xpdf/CMakeFiles/xpdf_objs.dir/FontEncodingTables.cc.o new file mode 100644 index 0000000..5390007 Binary files /dev/null and b/xpdf/CMakeFiles/xpdf_objs.dir/FontEncodingTables.cc.o differ diff --git a/xpdf/CMakeFiles/xpdf_objs.dir/Function.cc.o b/xpdf/CMakeFiles/xpdf_objs.dir/Function.cc.o new file mode 100644 index 0000000..1acd682 Binary files /dev/null and b/xpdf/CMakeFiles/xpdf_objs.dir/Function.cc.o differ diff --git a/xpdf/CMakeFiles/xpdf_objs.dir/Gfx.cc.o b/xpdf/CMakeFiles/xpdf_objs.dir/Gfx.cc.o new file mode 100644 index 0000000..e95b418 Binary files /dev/null and b/xpdf/CMakeFiles/xpdf_objs.dir/Gfx.cc.o differ diff --git a/xpdf/CMakeFiles/xpdf_objs.dir/GfxFont.cc.o b/xpdf/CMakeFiles/xpdf_objs.dir/GfxFont.cc.o new file mode 100644 index 0000000..a64a17d Binary files /dev/null and b/xpdf/CMakeFiles/xpdf_objs.dir/GfxFont.cc.o differ diff --git a/xpdf/CMakeFiles/xpdf_objs.dir/GfxState.cc.o b/xpdf/CMakeFiles/xpdf_objs.dir/GfxState.cc.o new file mode 100644 index 0000000..8348496 Binary files /dev/null and b/xpdf/CMakeFiles/xpdf_objs.dir/GfxState.cc.o differ diff --git a/xpdf/CMakeFiles/xpdf_objs.dir/GlobalParams.cc.o b/xpdf/CMakeFiles/xpdf_objs.dir/GlobalParams.cc.o new file mode 100644 index 0000000..184b8a1 Binary files /dev/null and b/xpdf/CMakeFiles/xpdf_objs.dir/GlobalParams.cc.o differ diff --git a/xpdf/CMakeFiles/xpdf_objs.dir/JArithmeticDecoder.cc.o b/xpdf/CMakeFiles/xpdf_objs.dir/JArithmeticDecoder.cc.o new file mode 100644 index 0000000..875b29f Binary files /dev/null and b/xpdf/CMakeFiles/xpdf_objs.dir/JArithmeticDecoder.cc.o differ diff --git a/xpdf/CMakeFiles/xpdf_objs.dir/JBIG2Stream.cc.o b/xpdf/CMakeFiles/xpdf_objs.dir/JBIG2Stream.cc.o new file mode 100644 index 0000000..eca6f32 Binary files /dev/null and b/xpdf/CMakeFiles/xpdf_objs.dir/JBIG2Stream.cc.o differ diff --git a/xpdf/CMakeFiles/xpdf_objs.dir/JPXStream.cc.o b/xpdf/CMakeFiles/xpdf_objs.dir/JPXStream.cc.o new file mode 100644 index 0000000..080bf23 Binary files /dev/null and b/xpdf/CMakeFiles/xpdf_objs.dir/JPXStream.cc.o differ diff --git a/xpdf/CMakeFiles/xpdf_objs.dir/Lexer.cc.o b/xpdf/CMakeFiles/xpdf_objs.dir/Lexer.cc.o new file mode 100644 index 0000000..9ca4a04 Binary files /dev/null and b/xpdf/CMakeFiles/xpdf_objs.dir/Lexer.cc.o differ diff --git a/xpdf/CMakeFiles/xpdf_objs.dir/Link.cc.o b/xpdf/CMakeFiles/xpdf_objs.dir/Link.cc.o new file mode 100644 index 0000000..f4d3509 Binary files /dev/null and b/xpdf/CMakeFiles/xpdf_objs.dir/Link.cc.o differ diff --git a/xpdf/CMakeFiles/xpdf_objs.dir/NameToCharCode.cc.o b/xpdf/CMakeFiles/xpdf_objs.dir/NameToCharCode.cc.o new file mode 100644 index 0000000..52a8134 Binary files /dev/null and b/xpdf/CMakeFiles/xpdf_objs.dir/NameToCharCode.cc.o differ diff --git a/xpdf/CMakeFiles/xpdf_objs.dir/Object.cc.o b/xpdf/CMakeFiles/xpdf_objs.dir/Object.cc.o new file mode 100644 index 0000000..e45eb08 Binary files /dev/null and b/xpdf/CMakeFiles/xpdf_objs.dir/Object.cc.o differ diff --git a/xpdf/CMakeFiles/xpdf_objs.dir/OptionalContent.cc.o b/xpdf/CMakeFiles/xpdf_objs.dir/OptionalContent.cc.o new file mode 100644 index 0000000..ad36ac2 Binary files /dev/null and b/xpdf/CMakeFiles/xpdf_objs.dir/OptionalContent.cc.o differ diff --git a/xpdf/CMakeFiles/xpdf_objs.dir/Outline.cc.o b/xpdf/CMakeFiles/xpdf_objs.dir/Outline.cc.o new file mode 100644 index 0000000..6635313 Binary files /dev/null and b/xpdf/CMakeFiles/xpdf_objs.dir/Outline.cc.o differ diff --git a/xpdf/CMakeFiles/xpdf_objs.dir/OutputDev.cc.o b/xpdf/CMakeFiles/xpdf_objs.dir/OutputDev.cc.o new file mode 100644 index 0000000..3ce43ef Binary files /dev/null and b/xpdf/CMakeFiles/xpdf_objs.dir/OutputDev.cc.o differ diff --git a/xpdf/CMakeFiles/xpdf_objs.dir/PDF417Barcode.cc.o b/xpdf/CMakeFiles/xpdf_objs.dir/PDF417Barcode.cc.o new file mode 100644 index 0000000..85183bb Binary files /dev/null and b/xpdf/CMakeFiles/xpdf_objs.dir/PDF417Barcode.cc.o differ diff --git a/xpdf/CMakeFiles/xpdf_objs.dir/PDFDoc.cc.o b/xpdf/CMakeFiles/xpdf_objs.dir/PDFDoc.cc.o new file mode 100644 index 0000000..8c49cfd Binary files /dev/null and b/xpdf/CMakeFiles/xpdf_objs.dir/PDFDoc.cc.o differ diff --git a/xpdf/CMakeFiles/xpdf_objs.dir/PDFDocEncoding.cc.o b/xpdf/CMakeFiles/xpdf_objs.dir/PDFDocEncoding.cc.o new file mode 100644 index 0000000..582a397 Binary files /dev/null and b/xpdf/CMakeFiles/xpdf_objs.dir/PDFDocEncoding.cc.o differ diff --git a/xpdf/CMakeFiles/xpdf_objs.dir/PSTokenizer.cc.o b/xpdf/CMakeFiles/xpdf_objs.dir/PSTokenizer.cc.o new file mode 100644 index 0000000..ba43ffc Binary files /dev/null and b/xpdf/CMakeFiles/xpdf_objs.dir/PSTokenizer.cc.o differ diff --git a/xpdf/CMakeFiles/xpdf_objs.dir/Page.cc.o b/xpdf/CMakeFiles/xpdf_objs.dir/Page.cc.o new file mode 100644 index 0000000..41661e9 Binary files /dev/null and b/xpdf/CMakeFiles/xpdf_objs.dir/Page.cc.o differ diff --git a/xpdf/CMakeFiles/xpdf_objs.dir/Parser.cc.o b/xpdf/CMakeFiles/xpdf_objs.dir/Parser.cc.o new file mode 100644 index 0000000..ada812e Binary files /dev/null and b/xpdf/CMakeFiles/xpdf_objs.dir/Parser.cc.o differ diff --git a/xpdf/CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.o b/xpdf/CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.o new file mode 100644 index 0000000..49705c4 Binary files /dev/null and b/xpdf/CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.o differ diff --git a/xpdf/CMakeFiles/xpdf_objs.dir/Stream.cc.o b/xpdf/CMakeFiles/xpdf_objs.dir/Stream.cc.o new file mode 100644 index 0000000..1d1c58c Binary files /dev/null and b/xpdf/CMakeFiles/xpdf_objs.dir/Stream.cc.o differ diff --git a/xpdf/CMakeFiles/xpdf_objs.dir/TextString.cc.o b/xpdf/CMakeFiles/xpdf_objs.dir/TextString.cc.o new file mode 100644 index 0000000..a1307b7 Binary files /dev/null and b/xpdf/CMakeFiles/xpdf_objs.dir/TextString.cc.o differ diff --git a/xpdf/CMakeFiles/xpdf_objs.dir/UTF8.cc.o b/xpdf/CMakeFiles/xpdf_objs.dir/UTF8.cc.o new file mode 100644 index 0000000..9c43897 Binary files /dev/null and b/xpdf/CMakeFiles/xpdf_objs.dir/UTF8.cc.o differ diff --git a/xpdf/CMakeFiles/xpdf_objs.dir/UnicodeMap.cc.o b/xpdf/CMakeFiles/xpdf_objs.dir/UnicodeMap.cc.o new file mode 100644 index 0000000..48e9301 Binary files /dev/null and b/xpdf/CMakeFiles/xpdf_objs.dir/UnicodeMap.cc.o differ diff --git a/xpdf/CMakeFiles/xpdf_objs.dir/UnicodeRemapping.cc.o b/xpdf/CMakeFiles/xpdf_objs.dir/UnicodeRemapping.cc.o new file mode 100644 index 0000000..2eb4211 Binary files /dev/null and b/xpdf/CMakeFiles/xpdf_objs.dir/UnicodeRemapping.cc.o differ diff --git a/xpdf/CMakeFiles/xpdf_objs.dir/UnicodeTypeTable.cc.o b/xpdf/CMakeFiles/xpdf_objs.dir/UnicodeTypeTable.cc.o new file mode 100644 index 0000000..2f9b569 Binary files /dev/null and b/xpdf/CMakeFiles/xpdf_objs.dir/UnicodeTypeTable.cc.o differ diff --git a/xpdf/CMakeFiles/xpdf_objs.dir/XFAScanner.cc.o b/xpdf/CMakeFiles/xpdf_objs.dir/XFAScanner.cc.o new file mode 100644 index 0000000..40c29c4 Binary files /dev/null and b/xpdf/CMakeFiles/xpdf_objs.dir/XFAScanner.cc.o differ diff --git a/xpdf/CMakeFiles/xpdf_objs.dir/XRef.cc.o b/xpdf/CMakeFiles/xpdf_objs.dir/XRef.cc.o new file mode 100644 index 0000000..1b010d9 Binary files /dev/null and b/xpdf/CMakeFiles/xpdf_objs.dir/XRef.cc.o differ diff --git a/xpdf/CMakeFiles/xpdf_objs.dir/Zoox.cc.o b/xpdf/CMakeFiles/xpdf_objs.dir/Zoox.cc.o new file mode 100644 index 0000000..aed8893 Binary files /dev/null and b/xpdf/CMakeFiles/xpdf_objs.dir/Zoox.cc.o differ diff --git a/xpdf/CMakeFiles/xpdf_objs.dir/build.make b/xpdf/CMakeFiles/xpdf_objs.dir/build.make new file mode 100644 index 0000000..5a12735 --- /dev/null +++ b/xpdf/CMakeFiles/xpdf_objs.dir/build.make @@ -0,0 +1,697 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +# Delete rule output on recipe failure. +.DELETE_ON_ERROR: + + +#============================================================================= +# Special targets provided by cmake. + +# Disable implicit rules so canonical targets will work. +.SUFFIXES: + + +# Disable VCS-based implicit rules. +% : %,v + + +# Disable VCS-based implicit rules. +% : RCS/% + + +# Disable VCS-based implicit rules. +% : RCS/%,v + + +# Disable VCS-based implicit rules. +% : SCCS/s.% + + +# Disable VCS-based implicit rules. +% : s.% + + +.SUFFIXES: .hpux_make_needs_suffix_list + + +# Command-line flag to silence nested $(MAKE). +$(VERBOSE)MAKESILENT = -s + +#Suppress display of executed commands. +$(VERBOSE).SILENT: + +# A target that is always out of date. +cmake_force: + +.PHONY : cmake_force + +#============================================================================= +# Set environment variables for the build. + +# The shell in which to execute make rules. +SHELL = /bin/sh + +# The CMake executable. +CMAKE_COMMAND = /usr/bin/cmake + +# The command to remove a file. +RM = /usr/bin/cmake -E rm -f + +# Escaping for special characters. +EQUALS = = + +# The top-level source directory on which CMake was run. +CMAKE_SOURCE_DIR = /home/calvin/src/xpdf-4.04 + +# The top-level build directory on which CMake was run. +CMAKE_BINARY_DIR = /home/calvin/src/xpdf-4.04 + +# Include any dependencies generated for this target. +include xpdf/CMakeFiles/xpdf_objs.dir/depend.make + +# Include the progress variables for this target. +include xpdf/CMakeFiles/xpdf_objs.dir/progress.make + +# Include the compile flags for this target's objects. +include xpdf/CMakeFiles/xpdf_objs.dir/flags.make + +xpdf/CMakeFiles/xpdf_objs.dir/AcroForm.cc.o: xpdf/CMakeFiles/xpdf_objs.dir/flags.make +xpdf/CMakeFiles/xpdf_objs.dir/AcroForm.cc.o: xpdf/AcroForm.cc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_1) "Building CXX object xpdf/CMakeFiles/xpdf_objs.dir/AcroForm.cc.o" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/xpdf_objs.dir/AcroForm.cc.o -c /home/calvin/src/xpdf-4.04/xpdf/AcroForm.cc + +xpdf/CMakeFiles/xpdf_objs.dir/AcroForm.cc.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/xpdf_objs.dir/AcroForm.cc.i" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf/AcroForm.cc > CMakeFiles/xpdf_objs.dir/AcroForm.cc.i + +xpdf/CMakeFiles/xpdf_objs.dir/AcroForm.cc.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/xpdf_objs.dir/AcroForm.cc.s" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf/AcroForm.cc -o CMakeFiles/xpdf_objs.dir/AcroForm.cc.s + +xpdf/CMakeFiles/xpdf_objs.dir/Annot.cc.o: xpdf/CMakeFiles/xpdf_objs.dir/flags.make +xpdf/CMakeFiles/xpdf_objs.dir/Annot.cc.o: xpdf/Annot.cc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_2) "Building CXX object xpdf/CMakeFiles/xpdf_objs.dir/Annot.cc.o" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/xpdf_objs.dir/Annot.cc.o -c /home/calvin/src/xpdf-4.04/xpdf/Annot.cc + +xpdf/CMakeFiles/xpdf_objs.dir/Annot.cc.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/xpdf_objs.dir/Annot.cc.i" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf/Annot.cc > CMakeFiles/xpdf_objs.dir/Annot.cc.i + +xpdf/CMakeFiles/xpdf_objs.dir/Annot.cc.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/xpdf_objs.dir/Annot.cc.s" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf/Annot.cc -o CMakeFiles/xpdf_objs.dir/Annot.cc.s + +xpdf/CMakeFiles/xpdf_objs.dir/Array.cc.o: xpdf/CMakeFiles/xpdf_objs.dir/flags.make +xpdf/CMakeFiles/xpdf_objs.dir/Array.cc.o: xpdf/Array.cc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_3) "Building CXX object xpdf/CMakeFiles/xpdf_objs.dir/Array.cc.o" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/xpdf_objs.dir/Array.cc.o -c /home/calvin/src/xpdf-4.04/xpdf/Array.cc + +xpdf/CMakeFiles/xpdf_objs.dir/Array.cc.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/xpdf_objs.dir/Array.cc.i" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf/Array.cc > CMakeFiles/xpdf_objs.dir/Array.cc.i + +xpdf/CMakeFiles/xpdf_objs.dir/Array.cc.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/xpdf_objs.dir/Array.cc.s" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf/Array.cc -o CMakeFiles/xpdf_objs.dir/Array.cc.s + +xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFont.cc.o: xpdf/CMakeFiles/xpdf_objs.dir/flags.make +xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFont.cc.o: xpdf/BuiltinFont.cc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_4) "Building CXX object xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFont.cc.o" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/xpdf_objs.dir/BuiltinFont.cc.o -c /home/calvin/src/xpdf-4.04/xpdf/BuiltinFont.cc + +xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFont.cc.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/xpdf_objs.dir/BuiltinFont.cc.i" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf/BuiltinFont.cc > CMakeFiles/xpdf_objs.dir/BuiltinFont.cc.i + +xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFont.cc.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/xpdf_objs.dir/BuiltinFont.cc.s" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf/BuiltinFont.cc -o CMakeFiles/xpdf_objs.dir/BuiltinFont.cc.s + +xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFontTables.cc.o: xpdf/CMakeFiles/xpdf_objs.dir/flags.make +xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFontTables.cc.o: xpdf/BuiltinFontTables.cc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_5) "Building CXX object xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFontTables.cc.o" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/xpdf_objs.dir/BuiltinFontTables.cc.o -c /home/calvin/src/xpdf-4.04/xpdf/BuiltinFontTables.cc + +xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFontTables.cc.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/xpdf_objs.dir/BuiltinFontTables.cc.i" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf/BuiltinFontTables.cc > CMakeFiles/xpdf_objs.dir/BuiltinFontTables.cc.i + +xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFontTables.cc.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/xpdf_objs.dir/BuiltinFontTables.cc.s" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf/BuiltinFontTables.cc -o CMakeFiles/xpdf_objs.dir/BuiltinFontTables.cc.s + +xpdf/CMakeFiles/xpdf_objs.dir/Catalog.cc.o: xpdf/CMakeFiles/xpdf_objs.dir/flags.make +xpdf/CMakeFiles/xpdf_objs.dir/Catalog.cc.o: xpdf/Catalog.cc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_6) "Building CXX object xpdf/CMakeFiles/xpdf_objs.dir/Catalog.cc.o" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/xpdf_objs.dir/Catalog.cc.o -c /home/calvin/src/xpdf-4.04/xpdf/Catalog.cc + +xpdf/CMakeFiles/xpdf_objs.dir/Catalog.cc.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/xpdf_objs.dir/Catalog.cc.i" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf/Catalog.cc > CMakeFiles/xpdf_objs.dir/Catalog.cc.i + +xpdf/CMakeFiles/xpdf_objs.dir/Catalog.cc.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/xpdf_objs.dir/Catalog.cc.s" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf/Catalog.cc -o CMakeFiles/xpdf_objs.dir/Catalog.cc.s + +xpdf/CMakeFiles/xpdf_objs.dir/CharCodeToUnicode.cc.o: xpdf/CMakeFiles/xpdf_objs.dir/flags.make +xpdf/CMakeFiles/xpdf_objs.dir/CharCodeToUnicode.cc.o: xpdf/CharCodeToUnicode.cc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_7) "Building CXX object xpdf/CMakeFiles/xpdf_objs.dir/CharCodeToUnicode.cc.o" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/xpdf_objs.dir/CharCodeToUnicode.cc.o -c /home/calvin/src/xpdf-4.04/xpdf/CharCodeToUnicode.cc + +xpdf/CMakeFiles/xpdf_objs.dir/CharCodeToUnicode.cc.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/xpdf_objs.dir/CharCodeToUnicode.cc.i" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf/CharCodeToUnicode.cc > CMakeFiles/xpdf_objs.dir/CharCodeToUnicode.cc.i + +xpdf/CMakeFiles/xpdf_objs.dir/CharCodeToUnicode.cc.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/xpdf_objs.dir/CharCodeToUnicode.cc.s" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf/CharCodeToUnicode.cc -o CMakeFiles/xpdf_objs.dir/CharCodeToUnicode.cc.s + +xpdf/CMakeFiles/xpdf_objs.dir/CMap.cc.o: xpdf/CMakeFiles/xpdf_objs.dir/flags.make +xpdf/CMakeFiles/xpdf_objs.dir/CMap.cc.o: xpdf/CMap.cc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_8) "Building CXX object xpdf/CMakeFiles/xpdf_objs.dir/CMap.cc.o" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/xpdf_objs.dir/CMap.cc.o -c /home/calvin/src/xpdf-4.04/xpdf/CMap.cc + +xpdf/CMakeFiles/xpdf_objs.dir/CMap.cc.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/xpdf_objs.dir/CMap.cc.i" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf/CMap.cc > CMakeFiles/xpdf_objs.dir/CMap.cc.i + +xpdf/CMakeFiles/xpdf_objs.dir/CMap.cc.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/xpdf_objs.dir/CMap.cc.s" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf/CMap.cc -o CMakeFiles/xpdf_objs.dir/CMap.cc.s + +xpdf/CMakeFiles/xpdf_objs.dir/Decrypt.cc.o: xpdf/CMakeFiles/xpdf_objs.dir/flags.make +xpdf/CMakeFiles/xpdf_objs.dir/Decrypt.cc.o: xpdf/Decrypt.cc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_9) "Building CXX object xpdf/CMakeFiles/xpdf_objs.dir/Decrypt.cc.o" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/xpdf_objs.dir/Decrypt.cc.o -c /home/calvin/src/xpdf-4.04/xpdf/Decrypt.cc + +xpdf/CMakeFiles/xpdf_objs.dir/Decrypt.cc.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/xpdf_objs.dir/Decrypt.cc.i" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf/Decrypt.cc > CMakeFiles/xpdf_objs.dir/Decrypt.cc.i + +xpdf/CMakeFiles/xpdf_objs.dir/Decrypt.cc.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/xpdf_objs.dir/Decrypt.cc.s" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf/Decrypt.cc -o CMakeFiles/xpdf_objs.dir/Decrypt.cc.s + +xpdf/CMakeFiles/xpdf_objs.dir/Dict.cc.o: xpdf/CMakeFiles/xpdf_objs.dir/flags.make +xpdf/CMakeFiles/xpdf_objs.dir/Dict.cc.o: xpdf/Dict.cc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_10) "Building CXX object xpdf/CMakeFiles/xpdf_objs.dir/Dict.cc.o" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/xpdf_objs.dir/Dict.cc.o -c /home/calvin/src/xpdf-4.04/xpdf/Dict.cc + +xpdf/CMakeFiles/xpdf_objs.dir/Dict.cc.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/xpdf_objs.dir/Dict.cc.i" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf/Dict.cc > CMakeFiles/xpdf_objs.dir/Dict.cc.i + +xpdf/CMakeFiles/xpdf_objs.dir/Dict.cc.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/xpdf_objs.dir/Dict.cc.s" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf/Dict.cc -o CMakeFiles/xpdf_objs.dir/Dict.cc.s + +xpdf/CMakeFiles/xpdf_objs.dir/Error.cc.o: xpdf/CMakeFiles/xpdf_objs.dir/flags.make +xpdf/CMakeFiles/xpdf_objs.dir/Error.cc.o: xpdf/Error.cc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_11) "Building CXX object xpdf/CMakeFiles/xpdf_objs.dir/Error.cc.o" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/xpdf_objs.dir/Error.cc.o -c /home/calvin/src/xpdf-4.04/xpdf/Error.cc + +xpdf/CMakeFiles/xpdf_objs.dir/Error.cc.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/xpdf_objs.dir/Error.cc.i" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf/Error.cc > CMakeFiles/xpdf_objs.dir/Error.cc.i + +xpdf/CMakeFiles/xpdf_objs.dir/Error.cc.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/xpdf_objs.dir/Error.cc.s" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf/Error.cc -o CMakeFiles/xpdf_objs.dir/Error.cc.s + +xpdf/CMakeFiles/xpdf_objs.dir/FontEncodingTables.cc.o: xpdf/CMakeFiles/xpdf_objs.dir/flags.make +xpdf/CMakeFiles/xpdf_objs.dir/FontEncodingTables.cc.o: xpdf/FontEncodingTables.cc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_12) "Building CXX object xpdf/CMakeFiles/xpdf_objs.dir/FontEncodingTables.cc.o" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/xpdf_objs.dir/FontEncodingTables.cc.o -c /home/calvin/src/xpdf-4.04/xpdf/FontEncodingTables.cc + +xpdf/CMakeFiles/xpdf_objs.dir/FontEncodingTables.cc.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/xpdf_objs.dir/FontEncodingTables.cc.i" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf/FontEncodingTables.cc > CMakeFiles/xpdf_objs.dir/FontEncodingTables.cc.i + +xpdf/CMakeFiles/xpdf_objs.dir/FontEncodingTables.cc.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/xpdf_objs.dir/FontEncodingTables.cc.s" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf/FontEncodingTables.cc -o CMakeFiles/xpdf_objs.dir/FontEncodingTables.cc.s + +xpdf/CMakeFiles/xpdf_objs.dir/Function.cc.o: xpdf/CMakeFiles/xpdf_objs.dir/flags.make +xpdf/CMakeFiles/xpdf_objs.dir/Function.cc.o: xpdf/Function.cc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_13) "Building CXX object xpdf/CMakeFiles/xpdf_objs.dir/Function.cc.o" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/xpdf_objs.dir/Function.cc.o -c /home/calvin/src/xpdf-4.04/xpdf/Function.cc + +xpdf/CMakeFiles/xpdf_objs.dir/Function.cc.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/xpdf_objs.dir/Function.cc.i" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf/Function.cc > CMakeFiles/xpdf_objs.dir/Function.cc.i + +xpdf/CMakeFiles/xpdf_objs.dir/Function.cc.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/xpdf_objs.dir/Function.cc.s" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf/Function.cc -o CMakeFiles/xpdf_objs.dir/Function.cc.s + +xpdf/CMakeFiles/xpdf_objs.dir/Gfx.cc.o: xpdf/CMakeFiles/xpdf_objs.dir/flags.make +xpdf/CMakeFiles/xpdf_objs.dir/Gfx.cc.o: xpdf/Gfx.cc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_14) "Building CXX object xpdf/CMakeFiles/xpdf_objs.dir/Gfx.cc.o" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/xpdf_objs.dir/Gfx.cc.o -c /home/calvin/src/xpdf-4.04/xpdf/Gfx.cc + +xpdf/CMakeFiles/xpdf_objs.dir/Gfx.cc.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/xpdf_objs.dir/Gfx.cc.i" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf/Gfx.cc > CMakeFiles/xpdf_objs.dir/Gfx.cc.i + +xpdf/CMakeFiles/xpdf_objs.dir/Gfx.cc.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/xpdf_objs.dir/Gfx.cc.s" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf/Gfx.cc -o CMakeFiles/xpdf_objs.dir/Gfx.cc.s + +xpdf/CMakeFiles/xpdf_objs.dir/GfxFont.cc.o: xpdf/CMakeFiles/xpdf_objs.dir/flags.make +xpdf/CMakeFiles/xpdf_objs.dir/GfxFont.cc.o: xpdf/GfxFont.cc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_15) "Building CXX object xpdf/CMakeFiles/xpdf_objs.dir/GfxFont.cc.o" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/xpdf_objs.dir/GfxFont.cc.o -c /home/calvin/src/xpdf-4.04/xpdf/GfxFont.cc + +xpdf/CMakeFiles/xpdf_objs.dir/GfxFont.cc.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/xpdf_objs.dir/GfxFont.cc.i" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf/GfxFont.cc > CMakeFiles/xpdf_objs.dir/GfxFont.cc.i + +xpdf/CMakeFiles/xpdf_objs.dir/GfxFont.cc.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/xpdf_objs.dir/GfxFont.cc.s" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf/GfxFont.cc -o CMakeFiles/xpdf_objs.dir/GfxFont.cc.s + +xpdf/CMakeFiles/xpdf_objs.dir/GfxState.cc.o: xpdf/CMakeFiles/xpdf_objs.dir/flags.make +xpdf/CMakeFiles/xpdf_objs.dir/GfxState.cc.o: xpdf/GfxState.cc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_16) "Building CXX object xpdf/CMakeFiles/xpdf_objs.dir/GfxState.cc.o" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/xpdf_objs.dir/GfxState.cc.o -c /home/calvin/src/xpdf-4.04/xpdf/GfxState.cc + +xpdf/CMakeFiles/xpdf_objs.dir/GfxState.cc.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/xpdf_objs.dir/GfxState.cc.i" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf/GfxState.cc > CMakeFiles/xpdf_objs.dir/GfxState.cc.i + +xpdf/CMakeFiles/xpdf_objs.dir/GfxState.cc.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/xpdf_objs.dir/GfxState.cc.s" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf/GfxState.cc -o CMakeFiles/xpdf_objs.dir/GfxState.cc.s + +xpdf/CMakeFiles/xpdf_objs.dir/GlobalParams.cc.o: xpdf/CMakeFiles/xpdf_objs.dir/flags.make +xpdf/CMakeFiles/xpdf_objs.dir/GlobalParams.cc.o: xpdf/GlobalParams.cc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_17) "Building CXX object xpdf/CMakeFiles/xpdf_objs.dir/GlobalParams.cc.o" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/xpdf_objs.dir/GlobalParams.cc.o -c /home/calvin/src/xpdf-4.04/xpdf/GlobalParams.cc + +xpdf/CMakeFiles/xpdf_objs.dir/GlobalParams.cc.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/xpdf_objs.dir/GlobalParams.cc.i" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf/GlobalParams.cc > CMakeFiles/xpdf_objs.dir/GlobalParams.cc.i + +xpdf/CMakeFiles/xpdf_objs.dir/GlobalParams.cc.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/xpdf_objs.dir/GlobalParams.cc.s" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf/GlobalParams.cc -o CMakeFiles/xpdf_objs.dir/GlobalParams.cc.s + +xpdf/CMakeFiles/xpdf_objs.dir/JArithmeticDecoder.cc.o: xpdf/CMakeFiles/xpdf_objs.dir/flags.make +xpdf/CMakeFiles/xpdf_objs.dir/JArithmeticDecoder.cc.o: xpdf/JArithmeticDecoder.cc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_18) "Building CXX object xpdf/CMakeFiles/xpdf_objs.dir/JArithmeticDecoder.cc.o" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/xpdf_objs.dir/JArithmeticDecoder.cc.o -c /home/calvin/src/xpdf-4.04/xpdf/JArithmeticDecoder.cc + +xpdf/CMakeFiles/xpdf_objs.dir/JArithmeticDecoder.cc.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/xpdf_objs.dir/JArithmeticDecoder.cc.i" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf/JArithmeticDecoder.cc > CMakeFiles/xpdf_objs.dir/JArithmeticDecoder.cc.i + +xpdf/CMakeFiles/xpdf_objs.dir/JArithmeticDecoder.cc.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/xpdf_objs.dir/JArithmeticDecoder.cc.s" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf/JArithmeticDecoder.cc -o CMakeFiles/xpdf_objs.dir/JArithmeticDecoder.cc.s + +xpdf/CMakeFiles/xpdf_objs.dir/JBIG2Stream.cc.o: xpdf/CMakeFiles/xpdf_objs.dir/flags.make +xpdf/CMakeFiles/xpdf_objs.dir/JBIG2Stream.cc.o: xpdf/JBIG2Stream.cc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_19) "Building CXX object xpdf/CMakeFiles/xpdf_objs.dir/JBIG2Stream.cc.o" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/xpdf_objs.dir/JBIG2Stream.cc.o -c /home/calvin/src/xpdf-4.04/xpdf/JBIG2Stream.cc + +xpdf/CMakeFiles/xpdf_objs.dir/JBIG2Stream.cc.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/xpdf_objs.dir/JBIG2Stream.cc.i" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf/JBIG2Stream.cc > CMakeFiles/xpdf_objs.dir/JBIG2Stream.cc.i + +xpdf/CMakeFiles/xpdf_objs.dir/JBIG2Stream.cc.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/xpdf_objs.dir/JBIG2Stream.cc.s" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf/JBIG2Stream.cc -o CMakeFiles/xpdf_objs.dir/JBIG2Stream.cc.s + +xpdf/CMakeFiles/xpdf_objs.dir/JPXStream.cc.o: xpdf/CMakeFiles/xpdf_objs.dir/flags.make +xpdf/CMakeFiles/xpdf_objs.dir/JPXStream.cc.o: xpdf/JPXStream.cc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_20) "Building CXX object xpdf/CMakeFiles/xpdf_objs.dir/JPXStream.cc.o" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/xpdf_objs.dir/JPXStream.cc.o -c /home/calvin/src/xpdf-4.04/xpdf/JPXStream.cc + +xpdf/CMakeFiles/xpdf_objs.dir/JPXStream.cc.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/xpdf_objs.dir/JPXStream.cc.i" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf/JPXStream.cc > CMakeFiles/xpdf_objs.dir/JPXStream.cc.i + +xpdf/CMakeFiles/xpdf_objs.dir/JPXStream.cc.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/xpdf_objs.dir/JPXStream.cc.s" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf/JPXStream.cc -o CMakeFiles/xpdf_objs.dir/JPXStream.cc.s + +xpdf/CMakeFiles/xpdf_objs.dir/Lexer.cc.o: xpdf/CMakeFiles/xpdf_objs.dir/flags.make +xpdf/CMakeFiles/xpdf_objs.dir/Lexer.cc.o: xpdf/Lexer.cc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_21) "Building CXX object xpdf/CMakeFiles/xpdf_objs.dir/Lexer.cc.o" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/xpdf_objs.dir/Lexer.cc.o -c /home/calvin/src/xpdf-4.04/xpdf/Lexer.cc + +xpdf/CMakeFiles/xpdf_objs.dir/Lexer.cc.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/xpdf_objs.dir/Lexer.cc.i" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf/Lexer.cc > CMakeFiles/xpdf_objs.dir/Lexer.cc.i + +xpdf/CMakeFiles/xpdf_objs.dir/Lexer.cc.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/xpdf_objs.dir/Lexer.cc.s" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf/Lexer.cc -o CMakeFiles/xpdf_objs.dir/Lexer.cc.s + +xpdf/CMakeFiles/xpdf_objs.dir/Link.cc.o: xpdf/CMakeFiles/xpdf_objs.dir/flags.make +xpdf/CMakeFiles/xpdf_objs.dir/Link.cc.o: xpdf/Link.cc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_22) "Building CXX object xpdf/CMakeFiles/xpdf_objs.dir/Link.cc.o" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/xpdf_objs.dir/Link.cc.o -c /home/calvin/src/xpdf-4.04/xpdf/Link.cc + +xpdf/CMakeFiles/xpdf_objs.dir/Link.cc.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/xpdf_objs.dir/Link.cc.i" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf/Link.cc > CMakeFiles/xpdf_objs.dir/Link.cc.i + +xpdf/CMakeFiles/xpdf_objs.dir/Link.cc.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/xpdf_objs.dir/Link.cc.s" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf/Link.cc -o CMakeFiles/xpdf_objs.dir/Link.cc.s + +xpdf/CMakeFiles/xpdf_objs.dir/NameToCharCode.cc.o: xpdf/CMakeFiles/xpdf_objs.dir/flags.make +xpdf/CMakeFiles/xpdf_objs.dir/NameToCharCode.cc.o: xpdf/NameToCharCode.cc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_23) "Building CXX object xpdf/CMakeFiles/xpdf_objs.dir/NameToCharCode.cc.o" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/xpdf_objs.dir/NameToCharCode.cc.o -c /home/calvin/src/xpdf-4.04/xpdf/NameToCharCode.cc + +xpdf/CMakeFiles/xpdf_objs.dir/NameToCharCode.cc.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/xpdf_objs.dir/NameToCharCode.cc.i" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf/NameToCharCode.cc > CMakeFiles/xpdf_objs.dir/NameToCharCode.cc.i + +xpdf/CMakeFiles/xpdf_objs.dir/NameToCharCode.cc.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/xpdf_objs.dir/NameToCharCode.cc.s" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf/NameToCharCode.cc -o CMakeFiles/xpdf_objs.dir/NameToCharCode.cc.s + +xpdf/CMakeFiles/xpdf_objs.dir/Object.cc.o: xpdf/CMakeFiles/xpdf_objs.dir/flags.make +xpdf/CMakeFiles/xpdf_objs.dir/Object.cc.o: xpdf/Object.cc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_24) "Building CXX object xpdf/CMakeFiles/xpdf_objs.dir/Object.cc.o" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/xpdf_objs.dir/Object.cc.o -c /home/calvin/src/xpdf-4.04/xpdf/Object.cc + +xpdf/CMakeFiles/xpdf_objs.dir/Object.cc.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/xpdf_objs.dir/Object.cc.i" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf/Object.cc > CMakeFiles/xpdf_objs.dir/Object.cc.i + +xpdf/CMakeFiles/xpdf_objs.dir/Object.cc.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/xpdf_objs.dir/Object.cc.s" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf/Object.cc -o CMakeFiles/xpdf_objs.dir/Object.cc.s + +xpdf/CMakeFiles/xpdf_objs.dir/OptionalContent.cc.o: xpdf/CMakeFiles/xpdf_objs.dir/flags.make +xpdf/CMakeFiles/xpdf_objs.dir/OptionalContent.cc.o: xpdf/OptionalContent.cc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_25) "Building CXX object xpdf/CMakeFiles/xpdf_objs.dir/OptionalContent.cc.o" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/xpdf_objs.dir/OptionalContent.cc.o -c /home/calvin/src/xpdf-4.04/xpdf/OptionalContent.cc + +xpdf/CMakeFiles/xpdf_objs.dir/OptionalContent.cc.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/xpdf_objs.dir/OptionalContent.cc.i" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf/OptionalContent.cc > CMakeFiles/xpdf_objs.dir/OptionalContent.cc.i + +xpdf/CMakeFiles/xpdf_objs.dir/OptionalContent.cc.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/xpdf_objs.dir/OptionalContent.cc.s" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf/OptionalContent.cc -o CMakeFiles/xpdf_objs.dir/OptionalContent.cc.s + +xpdf/CMakeFiles/xpdf_objs.dir/Outline.cc.o: xpdf/CMakeFiles/xpdf_objs.dir/flags.make +xpdf/CMakeFiles/xpdf_objs.dir/Outline.cc.o: xpdf/Outline.cc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_26) "Building CXX object xpdf/CMakeFiles/xpdf_objs.dir/Outline.cc.o" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/xpdf_objs.dir/Outline.cc.o -c /home/calvin/src/xpdf-4.04/xpdf/Outline.cc + +xpdf/CMakeFiles/xpdf_objs.dir/Outline.cc.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/xpdf_objs.dir/Outline.cc.i" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf/Outline.cc > CMakeFiles/xpdf_objs.dir/Outline.cc.i + +xpdf/CMakeFiles/xpdf_objs.dir/Outline.cc.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/xpdf_objs.dir/Outline.cc.s" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf/Outline.cc -o CMakeFiles/xpdf_objs.dir/Outline.cc.s + +xpdf/CMakeFiles/xpdf_objs.dir/OutputDev.cc.o: xpdf/CMakeFiles/xpdf_objs.dir/flags.make +xpdf/CMakeFiles/xpdf_objs.dir/OutputDev.cc.o: xpdf/OutputDev.cc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_27) "Building CXX object xpdf/CMakeFiles/xpdf_objs.dir/OutputDev.cc.o" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/xpdf_objs.dir/OutputDev.cc.o -c /home/calvin/src/xpdf-4.04/xpdf/OutputDev.cc + +xpdf/CMakeFiles/xpdf_objs.dir/OutputDev.cc.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/xpdf_objs.dir/OutputDev.cc.i" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf/OutputDev.cc > CMakeFiles/xpdf_objs.dir/OutputDev.cc.i + +xpdf/CMakeFiles/xpdf_objs.dir/OutputDev.cc.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/xpdf_objs.dir/OutputDev.cc.s" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf/OutputDev.cc -o CMakeFiles/xpdf_objs.dir/OutputDev.cc.s + +xpdf/CMakeFiles/xpdf_objs.dir/Page.cc.o: xpdf/CMakeFiles/xpdf_objs.dir/flags.make +xpdf/CMakeFiles/xpdf_objs.dir/Page.cc.o: xpdf/Page.cc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_28) "Building CXX object xpdf/CMakeFiles/xpdf_objs.dir/Page.cc.o" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/xpdf_objs.dir/Page.cc.o -c /home/calvin/src/xpdf-4.04/xpdf/Page.cc + +xpdf/CMakeFiles/xpdf_objs.dir/Page.cc.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/xpdf_objs.dir/Page.cc.i" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf/Page.cc > CMakeFiles/xpdf_objs.dir/Page.cc.i + +xpdf/CMakeFiles/xpdf_objs.dir/Page.cc.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/xpdf_objs.dir/Page.cc.s" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf/Page.cc -o CMakeFiles/xpdf_objs.dir/Page.cc.s + +xpdf/CMakeFiles/xpdf_objs.dir/Parser.cc.o: xpdf/CMakeFiles/xpdf_objs.dir/flags.make +xpdf/CMakeFiles/xpdf_objs.dir/Parser.cc.o: xpdf/Parser.cc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_29) "Building CXX object xpdf/CMakeFiles/xpdf_objs.dir/Parser.cc.o" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/xpdf_objs.dir/Parser.cc.o -c /home/calvin/src/xpdf-4.04/xpdf/Parser.cc + +xpdf/CMakeFiles/xpdf_objs.dir/Parser.cc.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/xpdf_objs.dir/Parser.cc.i" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf/Parser.cc > CMakeFiles/xpdf_objs.dir/Parser.cc.i + +xpdf/CMakeFiles/xpdf_objs.dir/Parser.cc.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/xpdf_objs.dir/Parser.cc.s" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf/Parser.cc -o CMakeFiles/xpdf_objs.dir/Parser.cc.s + +xpdf/CMakeFiles/xpdf_objs.dir/PDF417Barcode.cc.o: xpdf/CMakeFiles/xpdf_objs.dir/flags.make +xpdf/CMakeFiles/xpdf_objs.dir/PDF417Barcode.cc.o: xpdf/PDF417Barcode.cc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_30) "Building CXX object xpdf/CMakeFiles/xpdf_objs.dir/PDF417Barcode.cc.o" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/xpdf_objs.dir/PDF417Barcode.cc.o -c /home/calvin/src/xpdf-4.04/xpdf/PDF417Barcode.cc + +xpdf/CMakeFiles/xpdf_objs.dir/PDF417Barcode.cc.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/xpdf_objs.dir/PDF417Barcode.cc.i" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf/PDF417Barcode.cc > CMakeFiles/xpdf_objs.dir/PDF417Barcode.cc.i + +xpdf/CMakeFiles/xpdf_objs.dir/PDF417Barcode.cc.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/xpdf_objs.dir/PDF417Barcode.cc.s" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf/PDF417Barcode.cc -o CMakeFiles/xpdf_objs.dir/PDF417Barcode.cc.s + +xpdf/CMakeFiles/xpdf_objs.dir/PDFDoc.cc.o: xpdf/CMakeFiles/xpdf_objs.dir/flags.make +xpdf/CMakeFiles/xpdf_objs.dir/PDFDoc.cc.o: xpdf/PDFDoc.cc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_31) "Building CXX object xpdf/CMakeFiles/xpdf_objs.dir/PDFDoc.cc.o" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/xpdf_objs.dir/PDFDoc.cc.o -c /home/calvin/src/xpdf-4.04/xpdf/PDFDoc.cc + +xpdf/CMakeFiles/xpdf_objs.dir/PDFDoc.cc.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/xpdf_objs.dir/PDFDoc.cc.i" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf/PDFDoc.cc > CMakeFiles/xpdf_objs.dir/PDFDoc.cc.i + +xpdf/CMakeFiles/xpdf_objs.dir/PDFDoc.cc.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/xpdf_objs.dir/PDFDoc.cc.s" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf/PDFDoc.cc -o CMakeFiles/xpdf_objs.dir/PDFDoc.cc.s + +xpdf/CMakeFiles/xpdf_objs.dir/PDFDocEncoding.cc.o: xpdf/CMakeFiles/xpdf_objs.dir/flags.make +xpdf/CMakeFiles/xpdf_objs.dir/PDFDocEncoding.cc.o: xpdf/PDFDocEncoding.cc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_32) "Building CXX object xpdf/CMakeFiles/xpdf_objs.dir/PDFDocEncoding.cc.o" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/xpdf_objs.dir/PDFDocEncoding.cc.o -c /home/calvin/src/xpdf-4.04/xpdf/PDFDocEncoding.cc + +xpdf/CMakeFiles/xpdf_objs.dir/PDFDocEncoding.cc.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/xpdf_objs.dir/PDFDocEncoding.cc.i" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf/PDFDocEncoding.cc > CMakeFiles/xpdf_objs.dir/PDFDocEncoding.cc.i + +xpdf/CMakeFiles/xpdf_objs.dir/PDFDocEncoding.cc.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/xpdf_objs.dir/PDFDocEncoding.cc.s" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf/PDFDocEncoding.cc -o CMakeFiles/xpdf_objs.dir/PDFDocEncoding.cc.s + +xpdf/CMakeFiles/xpdf_objs.dir/PSTokenizer.cc.o: xpdf/CMakeFiles/xpdf_objs.dir/flags.make +xpdf/CMakeFiles/xpdf_objs.dir/PSTokenizer.cc.o: xpdf/PSTokenizer.cc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_33) "Building CXX object xpdf/CMakeFiles/xpdf_objs.dir/PSTokenizer.cc.o" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/xpdf_objs.dir/PSTokenizer.cc.o -c /home/calvin/src/xpdf-4.04/xpdf/PSTokenizer.cc + +xpdf/CMakeFiles/xpdf_objs.dir/PSTokenizer.cc.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/xpdf_objs.dir/PSTokenizer.cc.i" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf/PSTokenizer.cc > CMakeFiles/xpdf_objs.dir/PSTokenizer.cc.i + +xpdf/CMakeFiles/xpdf_objs.dir/PSTokenizer.cc.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/xpdf_objs.dir/PSTokenizer.cc.s" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf/PSTokenizer.cc -o CMakeFiles/xpdf_objs.dir/PSTokenizer.cc.s + +xpdf/CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.o: xpdf/CMakeFiles/xpdf_objs.dir/flags.make +xpdf/CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.o: xpdf/SecurityHandler.cc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_34) "Building CXX object xpdf/CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.o" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.o -c /home/calvin/src/xpdf-4.04/xpdf/SecurityHandler.cc + +xpdf/CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.i" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf/SecurityHandler.cc > CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.i + +xpdf/CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.s" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf/SecurityHandler.cc -o CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.s + +xpdf/CMakeFiles/xpdf_objs.dir/Stream.cc.o: xpdf/CMakeFiles/xpdf_objs.dir/flags.make +xpdf/CMakeFiles/xpdf_objs.dir/Stream.cc.o: xpdf/Stream.cc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_35) "Building CXX object xpdf/CMakeFiles/xpdf_objs.dir/Stream.cc.o" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/xpdf_objs.dir/Stream.cc.o -c /home/calvin/src/xpdf-4.04/xpdf/Stream.cc + +xpdf/CMakeFiles/xpdf_objs.dir/Stream.cc.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/xpdf_objs.dir/Stream.cc.i" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf/Stream.cc > CMakeFiles/xpdf_objs.dir/Stream.cc.i + +xpdf/CMakeFiles/xpdf_objs.dir/Stream.cc.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/xpdf_objs.dir/Stream.cc.s" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf/Stream.cc -o CMakeFiles/xpdf_objs.dir/Stream.cc.s + +xpdf/CMakeFiles/xpdf_objs.dir/TextString.cc.o: xpdf/CMakeFiles/xpdf_objs.dir/flags.make +xpdf/CMakeFiles/xpdf_objs.dir/TextString.cc.o: xpdf/TextString.cc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_36) "Building CXX object xpdf/CMakeFiles/xpdf_objs.dir/TextString.cc.o" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/xpdf_objs.dir/TextString.cc.o -c /home/calvin/src/xpdf-4.04/xpdf/TextString.cc + +xpdf/CMakeFiles/xpdf_objs.dir/TextString.cc.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/xpdf_objs.dir/TextString.cc.i" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf/TextString.cc > CMakeFiles/xpdf_objs.dir/TextString.cc.i + +xpdf/CMakeFiles/xpdf_objs.dir/TextString.cc.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/xpdf_objs.dir/TextString.cc.s" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf/TextString.cc -o CMakeFiles/xpdf_objs.dir/TextString.cc.s + +xpdf/CMakeFiles/xpdf_objs.dir/UnicodeMap.cc.o: xpdf/CMakeFiles/xpdf_objs.dir/flags.make +xpdf/CMakeFiles/xpdf_objs.dir/UnicodeMap.cc.o: xpdf/UnicodeMap.cc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_37) "Building CXX object xpdf/CMakeFiles/xpdf_objs.dir/UnicodeMap.cc.o" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/xpdf_objs.dir/UnicodeMap.cc.o -c /home/calvin/src/xpdf-4.04/xpdf/UnicodeMap.cc + +xpdf/CMakeFiles/xpdf_objs.dir/UnicodeMap.cc.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/xpdf_objs.dir/UnicodeMap.cc.i" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf/UnicodeMap.cc > CMakeFiles/xpdf_objs.dir/UnicodeMap.cc.i + +xpdf/CMakeFiles/xpdf_objs.dir/UnicodeMap.cc.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/xpdf_objs.dir/UnicodeMap.cc.s" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf/UnicodeMap.cc -o CMakeFiles/xpdf_objs.dir/UnicodeMap.cc.s + +xpdf/CMakeFiles/xpdf_objs.dir/UnicodeRemapping.cc.o: xpdf/CMakeFiles/xpdf_objs.dir/flags.make +xpdf/CMakeFiles/xpdf_objs.dir/UnicodeRemapping.cc.o: xpdf/UnicodeRemapping.cc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_38) "Building CXX object xpdf/CMakeFiles/xpdf_objs.dir/UnicodeRemapping.cc.o" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/xpdf_objs.dir/UnicodeRemapping.cc.o -c /home/calvin/src/xpdf-4.04/xpdf/UnicodeRemapping.cc + +xpdf/CMakeFiles/xpdf_objs.dir/UnicodeRemapping.cc.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/xpdf_objs.dir/UnicodeRemapping.cc.i" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf/UnicodeRemapping.cc > CMakeFiles/xpdf_objs.dir/UnicodeRemapping.cc.i + +xpdf/CMakeFiles/xpdf_objs.dir/UnicodeRemapping.cc.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/xpdf_objs.dir/UnicodeRemapping.cc.s" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf/UnicodeRemapping.cc -o CMakeFiles/xpdf_objs.dir/UnicodeRemapping.cc.s + +xpdf/CMakeFiles/xpdf_objs.dir/UnicodeTypeTable.cc.o: xpdf/CMakeFiles/xpdf_objs.dir/flags.make +xpdf/CMakeFiles/xpdf_objs.dir/UnicodeTypeTable.cc.o: xpdf/UnicodeTypeTable.cc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_39) "Building CXX object xpdf/CMakeFiles/xpdf_objs.dir/UnicodeTypeTable.cc.o" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/xpdf_objs.dir/UnicodeTypeTable.cc.o -c /home/calvin/src/xpdf-4.04/xpdf/UnicodeTypeTable.cc + +xpdf/CMakeFiles/xpdf_objs.dir/UnicodeTypeTable.cc.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/xpdf_objs.dir/UnicodeTypeTable.cc.i" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf/UnicodeTypeTable.cc > CMakeFiles/xpdf_objs.dir/UnicodeTypeTable.cc.i + +xpdf/CMakeFiles/xpdf_objs.dir/UnicodeTypeTable.cc.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/xpdf_objs.dir/UnicodeTypeTable.cc.s" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf/UnicodeTypeTable.cc -o CMakeFiles/xpdf_objs.dir/UnicodeTypeTable.cc.s + +xpdf/CMakeFiles/xpdf_objs.dir/UTF8.cc.o: xpdf/CMakeFiles/xpdf_objs.dir/flags.make +xpdf/CMakeFiles/xpdf_objs.dir/UTF8.cc.o: xpdf/UTF8.cc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_40) "Building CXX object xpdf/CMakeFiles/xpdf_objs.dir/UTF8.cc.o" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/xpdf_objs.dir/UTF8.cc.o -c /home/calvin/src/xpdf-4.04/xpdf/UTF8.cc + +xpdf/CMakeFiles/xpdf_objs.dir/UTF8.cc.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/xpdf_objs.dir/UTF8.cc.i" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf/UTF8.cc > CMakeFiles/xpdf_objs.dir/UTF8.cc.i + +xpdf/CMakeFiles/xpdf_objs.dir/UTF8.cc.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/xpdf_objs.dir/UTF8.cc.s" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf/UTF8.cc -o CMakeFiles/xpdf_objs.dir/UTF8.cc.s + +xpdf/CMakeFiles/xpdf_objs.dir/XFAScanner.cc.o: xpdf/CMakeFiles/xpdf_objs.dir/flags.make +xpdf/CMakeFiles/xpdf_objs.dir/XFAScanner.cc.o: xpdf/XFAScanner.cc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_41) "Building CXX object xpdf/CMakeFiles/xpdf_objs.dir/XFAScanner.cc.o" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/xpdf_objs.dir/XFAScanner.cc.o -c /home/calvin/src/xpdf-4.04/xpdf/XFAScanner.cc + +xpdf/CMakeFiles/xpdf_objs.dir/XFAScanner.cc.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/xpdf_objs.dir/XFAScanner.cc.i" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf/XFAScanner.cc > CMakeFiles/xpdf_objs.dir/XFAScanner.cc.i + +xpdf/CMakeFiles/xpdf_objs.dir/XFAScanner.cc.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/xpdf_objs.dir/XFAScanner.cc.s" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf/XFAScanner.cc -o CMakeFiles/xpdf_objs.dir/XFAScanner.cc.s + +xpdf/CMakeFiles/xpdf_objs.dir/XRef.cc.o: xpdf/CMakeFiles/xpdf_objs.dir/flags.make +xpdf/CMakeFiles/xpdf_objs.dir/XRef.cc.o: xpdf/XRef.cc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_42) "Building CXX object xpdf/CMakeFiles/xpdf_objs.dir/XRef.cc.o" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/xpdf_objs.dir/XRef.cc.o -c /home/calvin/src/xpdf-4.04/xpdf/XRef.cc + +xpdf/CMakeFiles/xpdf_objs.dir/XRef.cc.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/xpdf_objs.dir/XRef.cc.i" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf/XRef.cc > CMakeFiles/xpdf_objs.dir/XRef.cc.i + +xpdf/CMakeFiles/xpdf_objs.dir/XRef.cc.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/xpdf_objs.dir/XRef.cc.s" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf/XRef.cc -o CMakeFiles/xpdf_objs.dir/XRef.cc.s + +xpdf/CMakeFiles/xpdf_objs.dir/Zoox.cc.o: xpdf/CMakeFiles/xpdf_objs.dir/flags.make +xpdf/CMakeFiles/xpdf_objs.dir/Zoox.cc.o: xpdf/Zoox.cc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_43) "Building CXX object xpdf/CMakeFiles/xpdf_objs.dir/Zoox.cc.o" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/xpdf_objs.dir/Zoox.cc.o -c /home/calvin/src/xpdf-4.04/xpdf/Zoox.cc + +xpdf/CMakeFiles/xpdf_objs.dir/Zoox.cc.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/xpdf_objs.dir/Zoox.cc.i" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf/Zoox.cc > CMakeFiles/xpdf_objs.dir/Zoox.cc.i + +xpdf/CMakeFiles/xpdf_objs.dir/Zoox.cc.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/xpdf_objs.dir/Zoox.cc.s" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf/Zoox.cc -o CMakeFiles/xpdf_objs.dir/Zoox.cc.s + +xpdf_objs: xpdf/CMakeFiles/xpdf_objs.dir/AcroForm.cc.o +xpdf_objs: xpdf/CMakeFiles/xpdf_objs.dir/Annot.cc.o +xpdf_objs: xpdf/CMakeFiles/xpdf_objs.dir/Array.cc.o +xpdf_objs: xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFont.cc.o +xpdf_objs: xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFontTables.cc.o +xpdf_objs: xpdf/CMakeFiles/xpdf_objs.dir/Catalog.cc.o +xpdf_objs: xpdf/CMakeFiles/xpdf_objs.dir/CharCodeToUnicode.cc.o +xpdf_objs: xpdf/CMakeFiles/xpdf_objs.dir/CMap.cc.o +xpdf_objs: xpdf/CMakeFiles/xpdf_objs.dir/Decrypt.cc.o +xpdf_objs: xpdf/CMakeFiles/xpdf_objs.dir/Dict.cc.o +xpdf_objs: xpdf/CMakeFiles/xpdf_objs.dir/Error.cc.o +xpdf_objs: xpdf/CMakeFiles/xpdf_objs.dir/FontEncodingTables.cc.o +xpdf_objs: xpdf/CMakeFiles/xpdf_objs.dir/Function.cc.o +xpdf_objs: xpdf/CMakeFiles/xpdf_objs.dir/Gfx.cc.o +xpdf_objs: xpdf/CMakeFiles/xpdf_objs.dir/GfxFont.cc.o +xpdf_objs: xpdf/CMakeFiles/xpdf_objs.dir/GfxState.cc.o +xpdf_objs: xpdf/CMakeFiles/xpdf_objs.dir/GlobalParams.cc.o +xpdf_objs: xpdf/CMakeFiles/xpdf_objs.dir/JArithmeticDecoder.cc.o +xpdf_objs: xpdf/CMakeFiles/xpdf_objs.dir/JBIG2Stream.cc.o +xpdf_objs: xpdf/CMakeFiles/xpdf_objs.dir/JPXStream.cc.o +xpdf_objs: xpdf/CMakeFiles/xpdf_objs.dir/Lexer.cc.o +xpdf_objs: xpdf/CMakeFiles/xpdf_objs.dir/Link.cc.o +xpdf_objs: xpdf/CMakeFiles/xpdf_objs.dir/NameToCharCode.cc.o +xpdf_objs: xpdf/CMakeFiles/xpdf_objs.dir/Object.cc.o +xpdf_objs: xpdf/CMakeFiles/xpdf_objs.dir/OptionalContent.cc.o +xpdf_objs: xpdf/CMakeFiles/xpdf_objs.dir/Outline.cc.o +xpdf_objs: xpdf/CMakeFiles/xpdf_objs.dir/OutputDev.cc.o +xpdf_objs: xpdf/CMakeFiles/xpdf_objs.dir/Page.cc.o +xpdf_objs: xpdf/CMakeFiles/xpdf_objs.dir/Parser.cc.o +xpdf_objs: xpdf/CMakeFiles/xpdf_objs.dir/PDF417Barcode.cc.o +xpdf_objs: xpdf/CMakeFiles/xpdf_objs.dir/PDFDoc.cc.o +xpdf_objs: xpdf/CMakeFiles/xpdf_objs.dir/PDFDocEncoding.cc.o +xpdf_objs: xpdf/CMakeFiles/xpdf_objs.dir/PSTokenizer.cc.o +xpdf_objs: xpdf/CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.o +xpdf_objs: xpdf/CMakeFiles/xpdf_objs.dir/Stream.cc.o +xpdf_objs: xpdf/CMakeFiles/xpdf_objs.dir/TextString.cc.o +xpdf_objs: xpdf/CMakeFiles/xpdf_objs.dir/UnicodeMap.cc.o +xpdf_objs: xpdf/CMakeFiles/xpdf_objs.dir/UnicodeRemapping.cc.o +xpdf_objs: xpdf/CMakeFiles/xpdf_objs.dir/UnicodeTypeTable.cc.o +xpdf_objs: xpdf/CMakeFiles/xpdf_objs.dir/UTF8.cc.o +xpdf_objs: xpdf/CMakeFiles/xpdf_objs.dir/XFAScanner.cc.o +xpdf_objs: xpdf/CMakeFiles/xpdf_objs.dir/XRef.cc.o +xpdf_objs: xpdf/CMakeFiles/xpdf_objs.dir/Zoox.cc.o +xpdf_objs: xpdf/CMakeFiles/xpdf_objs.dir/build.make + +.PHONY : xpdf_objs + +# Rule to build all files generated by this target. +xpdf/CMakeFiles/xpdf_objs.dir/build: xpdf_objs + +.PHONY : xpdf/CMakeFiles/xpdf_objs.dir/build + +xpdf/CMakeFiles/xpdf_objs.dir/clean: + cd /home/calvin/src/xpdf-4.04/xpdf && $(CMAKE_COMMAND) -P CMakeFiles/xpdf_objs.dir/cmake_clean.cmake +.PHONY : xpdf/CMakeFiles/xpdf_objs.dir/clean + +xpdf/CMakeFiles/xpdf_objs.dir/depend: + cd /home/calvin/src/xpdf-4.04 && $(CMAKE_COMMAND) -E cmake_depends "Unix Makefiles" /home/calvin/src/xpdf-4.04 /home/calvin/src/xpdf-4.04/xpdf /home/calvin/src/xpdf-4.04 /home/calvin/src/xpdf-4.04/xpdf /home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir/DependInfo.cmake --color=$(COLOR) +.PHONY : xpdf/CMakeFiles/xpdf_objs.dir/depend + diff --git a/xpdf/CMakeFiles/xpdf_objs.dir/cmake_clean.cmake b/xpdf/CMakeFiles/xpdf_objs.dir/cmake_clean.cmake new file mode 100644 index 0000000..8f46743 --- /dev/null +++ b/xpdf/CMakeFiles/xpdf_objs.dir/cmake_clean.cmake @@ -0,0 +1,50 @@ +file(REMOVE_RECURSE + "CMakeFiles/xpdf_objs.dir/AcroForm.cc.o" + "CMakeFiles/xpdf_objs.dir/Annot.cc.o" + "CMakeFiles/xpdf_objs.dir/Array.cc.o" + "CMakeFiles/xpdf_objs.dir/BuiltinFont.cc.o" + "CMakeFiles/xpdf_objs.dir/BuiltinFontTables.cc.o" + "CMakeFiles/xpdf_objs.dir/CMap.cc.o" + "CMakeFiles/xpdf_objs.dir/Catalog.cc.o" + "CMakeFiles/xpdf_objs.dir/CharCodeToUnicode.cc.o" + "CMakeFiles/xpdf_objs.dir/Decrypt.cc.o" + "CMakeFiles/xpdf_objs.dir/Dict.cc.o" + "CMakeFiles/xpdf_objs.dir/Error.cc.o" + "CMakeFiles/xpdf_objs.dir/FontEncodingTables.cc.o" + "CMakeFiles/xpdf_objs.dir/Function.cc.o" + "CMakeFiles/xpdf_objs.dir/Gfx.cc.o" + "CMakeFiles/xpdf_objs.dir/GfxFont.cc.o" + "CMakeFiles/xpdf_objs.dir/GfxState.cc.o" + "CMakeFiles/xpdf_objs.dir/GlobalParams.cc.o" + "CMakeFiles/xpdf_objs.dir/JArithmeticDecoder.cc.o" + "CMakeFiles/xpdf_objs.dir/JBIG2Stream.cc.o" + "CMakeFiles/xpdf_objs.dir/JPXStream.cc.o" + "CMakeFiles/xpdf_objs.dir/Lexer.cc.o" + "CMakeFiles/xpdf_objs.dir/Link.cc.o" + "CMakeFiles/xpdf_objs.dir/NameToCharCode.cc.o" + "CMakeFiles/xpdf_objs.dir/Object.cc.o" + "CMakeFiles/xpdf_objs.dir/OptionalContent.cc.o" + "CMakeFiles/xpdf_objs.dir/Outline.cc.o" + "CMakeFiles/xpdf_objs.dir/OutputDev.cc.o" + "CMakeFiles/xpdf_objs.dir/PDF417Barcode.cc.o" + "CMakeFiles/xpdf_objs.dir/PDFDoc.cc.o" + "CMakeFiles/xpdf_objs.dir/PDFDocEncoding.cc.o" + "CMakeFiles/xpdf_objs.dir/PSTokenizer.cc.o" + "CMakeFiles/xpdf_objs.dir/Page.cc.o" + "CMakeFiles/xpdf_objs.dir/Parser.cc.o" + "CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.o" + "CMakeFiles/xpdf_objs.dir/Stream.cc.o" + "CMakeFiles/xpdf_objs.dir/TextString.cc.o" + "CMakeFiles/xpdf_objs.dir/UTF8.cc.o" + "CMakeFiles/xpdf_objs.dir/UnicodeMap.cc.o" + "CMakeFiles/xpdf_objs.dir/UnicodeRemapping.cc.o" + "CMakeFiles/xpdf_objs.dir/UnicodeTypeTable.cc.o" + "CMakeFiles/xpdf_objs.dir/XFAScanner.cc.o" + "CMakeFiles/xpdf_objs.dir/XRef.cc.o" + "CMakeFiles/xpdf_objs.dir/Zoox.cc.o" +) + +# Per-language clean rules from dependency scanning. +foreach(lang CXX) + include(CMakeFiles/xpdf_objs.dir/cmake_clean_${lang}.cmake OPTIONAL) +endforeach() diff --git a/xpdf/CMakeFiles/xpdf_objs.dir/depend.internal b/xpdf/CMakeFiles/xpdf_objs.dir/depend.internal new file mode 100644 index 0000000..da5c3c7 --- /dev/null +++ b/xpdf/CMakeFiles/xpdf_objs.dir/depend.internal @@ -0,0 +1,786 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +xpdf/CMakeFiles/xpdf_objs.dir/AcroForm.cc.o + /home/calvin/src/xpdf-4.04/xpdf/AcroForm.cc + /home/calvin/src/xpdf-4.04/xpdf/AcroForm.h + /home/calvin/src/xpdf-4.04/xpdf/Annot.h + /home/calvin/src/xpdf-4.04/xpdf/Array.h + /home/calvin/src/xpdf-4.04/xpdf/Catalog.h + /home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + /home/calvin/src/xpdf-4.04/xpdf/Dict.h + /home/calvin/src/xpdf-4.04/xpdf/Error.h + /home/calvin/src/xpdf-4.04/xpdf/Function.h + /home/calvin/src/xpdf-4.04/xpdf/Gfx.h + /home/calvin/src/xpdf-4.04/xpdf/GfxFont.h + /home/calvin/src/xpdf-4.04/xpdf/GfxState.h + /home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h + /home/calvin/src/xpdf-4.04/xpdf/Lexer.h + /home/calvin/src/xpdf-4.04/xpdf/Object.h + /home/calvin/src/xpdf-4.04/xpdf/OptionalContent.h + /home/calvin/src/xpdf-4.04/xpdf/PDF417Barcode.h + /home/calvin/src/xpdf-4.04/xpdf/PDFDoc.h + /home/calvin/src/xpdf-4.04/xpdf/Page.h + /home/calvin/src/xpdf-4.04/xpdf/Stream.h + /home/calvin/src/xpdf-4.04/xpdf/TextString.h + /home/calvin/src/xpdf-4.04/xpdf/UTF8.h + /home/calvin/src/xpdf-4.04/xpdf/XFAScanner.h + /home/calvin/src/xpdf-4.04/xpdf/XRef.h + /home/calvin/src/xpdf-4.04/xpdf/config.h + aconf.h + aconf2.h + goo/GList.h + goo/GMutex.h + goo/GString.h + goo/gfile.h + goo/gmem.h + goo/gmempp.h + goo/gtypes.h +xpdf/CMakeFiles/xpdf_objs.dir/Annot.cc.o + /home/calvin/src/xpdf-4.04/xpdf/AcroForm.h + /home/calvin/src/xpdf-4.04/xpdf/Annot.cc + /home/calvin/src/xpdf-4.04/xpdf/Annot.h + /home/calvin/src/xpdf-4.04/xpdf/Array.h + /home/calvin/src/xpdf-4.04/xpdf/BuiltinFont.h + /home/calvin/src/xpdf-4.04/xpdf/BuiltinFontTables.h + /home/calvin/src/xpdf-4.04/xpdf/Catalog.h + /home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + /home/calvin/src/xpdf-4.04/xpdf/Dict.h + /home/calvin/src/xpdf-4.04/xpdf/Error.h + /home/calvin/src/xpdf-4.04/xpdf/FontEncodingTables.h + /home/calvin/src/xpdf-4.04/xpdf/Function.h + /home/calvin/src/xpdf-4.04/xpdf/Gfx.h + /home/calvin/src/xpdf-4.04/xpdf/GfxFont.h + /home/calvin/src/xpdf-4.04/xpdf/GfxState.h + /home/calvin/src/xpdf-4.04/xpdf/Lexer.h + /home/calvin/src/xpdf-4.04/xpdf/Object.h + /home/calvin/src/xpdf-4.04/xpdf/OptionalContent.h + /home/calvin/src/xpdf-4.04/xpdf/PDFDoc.h + /home/calvin/src/xpdf-4.04/xpdf/Page.h + /home/calvin/src/xpdf-4.04/xpdf/Stream.h + /home/calvin/src/xpdf-4.04/xpdf/XRef.h + /home/calvin/src/xpdf-4.04/xpdf/config.h + aconf.h + aconf2.h + goo/GList.h + goo/GMutex.h + goo/GString.h + goo/gfile.h + goo/gmem.h + goo/gmempp.h + goo/gtypes.h +xpdf/CMakeFiles/xpdf_objs.dir/Array.cc.o + /home/calvin/src/xpdf-4.04/xpdf/Array.cc + /home/calvin/src/xpdf-4.04/xpdf/Array.h + /home/calvin/src/xpdf-4.04/xpdf/Dict.h + /home/calvin/src/xpdf-4.04/xpdf/Object.h + /home/calvin/src/xpdf-4.04/xpdf/Stream.h + aconf.h + aconf2.h + goo/GMutex.h + goo/GString.h + goo/gfile.h + goo/gmem.h + goo/gmempp.h + goo/gtypes.h +xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFont.cc.o + /home/calvin/src/xpdf-4.04/xpdf/BuiltinFont.cc + /home/calvin/src/xpdf-4.04/xpdf/BuiltinFont.h + /home/calvin/src/xpdf-4.04/xpdf/FontEncodingTables.h + aconf.h + aconf2.h + goo/gmem.h + goo/gmempp.h + goo/gtypes.h +xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFontTables.cc.o + /home/calvin/src/xpdf-4.04/xpdf/BuiltinFont.h + /home/calvin/src/xpdf-4.04/xpdf/BuiltinFontTables.cc + /home/calvin/src/xpdf-4.04/xpdf/BuiltinFontTables.h + /home/calvin/src/xpdf-4.04/xpdf/FontEncodingTables.h + aconf.h + aconf2.h + goo/gmempp.h + goo/gtypes.h +xpdf/CMakeFiles/xpdf_objs.dir/CMap.cc.o + /home/calvin/src/xpdf-4.04/xpdf/Array.h + /home/calvin/src/xpdf-4.04/xpdf/CMap.cc + /home/calvin/src/xpdf-4.04/xpdf/CMap.h + /home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + /home/calvin/src/xpdf-4.04/xpdf/Dict.h + /home/calvin/src/xpdf-4.04/xpdf/Error.h + /home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h + /home/calvin/src/xpdf-4.04/xpdf/Object.h + /home/calvin/src/xpdf-4.04/xpdf/PSTokenizer.h + /home/calvin/src/xpdf-4.04/xpdf/Stream.h + /home/calvin/src/xpdf-4.04/xpdf/config.h + aconf.h + aconf2.h + goo/GMutex.h + goo/GString.h + goo/gfile.h + goo/gmem.h + goo/gmempp.h + goo/gtypes.h +xpdf/CMakeFiles/xpdf_objs.dir/Catalog.cc.o + /home/calvin/src/xpdf-4.04/xpdf/AcroForm.h + /home/calvin/src/xpdf-4.04/xpdf/Array.h + /home/calvin/src/xpdf-4.04/xpdf/Catalog.cc + /home/calvin/src/xpdf-4.04/xpdf/Catalog.h + /home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + /home/calvin/src/xpdf-4.04/xpdf/Dict.h + /home/calvin/src/xpdf-4.04/xpdf/Error.h + /home/calvin/src/xpdf-4.04/xpdf/Link.h + /home/calvin/src/xpdf-4.04/xpdf/Object.h + /home/calvin/src/xpdf-4.04/xpdf/PDFDoc.h + /home/calvin/src/xpdf-4.04/xpdf/Page.h + /home/calvin/src/xpdf-4.04/xpdf/Stream.h + /home/calvin/src/xpdf-4.04/xpdf/TextString.h + /home/calvin/src/xpdf-4.04/xpdf/XRef.h + /home/calvin/src/xpdf-4.04/xpdf/config.h + aconf.h + aconf2.h + goo/GList.h + goo/GMutex.h + goo/GString.h + goo/gfile.h + goo/gmem.h + goo/gmempp.h + goo/gtypes.h +xpdf/CMakeFiles/xpdf_objs.dir/CharCodeToUnicode.cc.o + /home/calvin/src/xpdf-4.04/xpdf/CharCodeToUnicode.cc + /home/calvin/src/xpdf-4.04/xpdf/CharCodeToUnicode.h + /home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + /home/calvin/src/xpdf-4.04/xpdf/Error.h + /home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h + /home/calvin/src/xpdf-4.04/xpdf/PSTokenizer.h + /home/calvin/src/xpdf-4.04/xpdf/config.h + aconf.h + aconf2.h + goo/GMutex.h + goo/GString.h + goo/gfile.h + goo/gmem.h + goo/gmempp.h + goo/gtypes.h +xpdf/CMakeFiles/xpdf_objs.dir/Decrypt.cc.o + /home/calvin/src/xpdf-4.04/xpdf/Array.h + /home/calvin/src/xpdf-4.04/xpdf/Decrypt.cc + /home/calvin/src/xpdf-4.04/xpdf/Decrypt.h + /home/calvin/src/xpdf-4.04/xpdf/Dict.h + /home/calvin/src/xpdf-4.04/xpdf/Object.h + /home/calvin/src/xpdf-4.04/xpdf/Stream.h + aconf.h + aconf2.h + goo/GMutex.h + goo/GString.h + goo/gfile.h + goo/gmem.h + goo/gmempp.h + goo/gtypes.h +xpdf/CMakeFiles/xpdf_objs.dir/Dict.cc.o + /home/calvin/src/xpdf-4.04/xpdf/Array.h + /home/calvin/src/xpdf-4.04/xpdf/Dict.cc + /home/calvin/src/xpdf-4.04/xpdf/Dict.h + /home/calvin/src/xpdf-4.04/xpdf/Object.h + /home/calvin/src/xpdf-4.04/xpdf/Stream.h + /home/calvin/src/xpdf-4.04/xpdf/XRef.h + aconf.h + aconf2.h + goo/GMutex.h + goo/GString.h + goo/gfile.h + goo/gmem.h + goo/gmempp.h + goo/gtypes.h +xpdf/CMakeFiles/xpdf_objs.dir/Error.cc.o + /home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + /home/calvin/src/xpdf-4.04/xpdf/Error.cc + /home/calvin/src/xpdf-4.04/xpdf/Error.h + /home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h + /home/calvin/src/xpdf-4.04/xpdf/config.h + aconf.h + aconf2.h + goo/GMutex.h + goo/GString.h + goo/gfile.h + goo/gmempp.h + goo/gtypes.h +xpdf/CMakeFiles/xpdf_objs.dir/FontEncodingTables.cc.o + /home/calvin/src/xpdf-4.04/xpdf/FontEncodingTables.cc + /home/calvin/src/xpdf-4.04/xpdf/FontEncodingTables.h + aconf.h + aconf2.h + goo/gmempp.h +xpdf/CMakeFiles/xpdf_objs.dir/Function.cc.o + /home/calvin/src/xpdf-4.04/xpdf/Array.h + /home/calvin/src/xpdf-4.04/xpdf/Dict.h + /home/calvin/src/xpdf-4.04/xpdf/Error.h + /home/calvin/src/xpdf-4.04/xpdf/Function.cc + /home/calvin/src/xpdf-4.04/xpdf/Function.h + /home/calvin/src/xpdf-4.04/xpdf/Object.h + /home/calvin/src/xpdf-4.04/xpdf/Stream.h + /home/calvin/src/xpdf-4.04/xpdf/config.h + aconf.h + aconf2.h + goo/GList.h + goo/GMutex.h + goo/GString.h + goo/gfile.h + goo/gmem.h + goo/gmempp.h + goo/gtypes.h +xpdf/CMakeFiles/xpdf_objs.dir/Gfx.cc.o + /home/calvin/src/xpdf-4.04/xpdf/Annot.h + /home/calvin/src/xpdf-4.04/xpdf/Array.h + /home/calvin/src/xpdf-4.04/xpdf/Catalog.h + /home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + /home/calvin/src/xpdf-4.04/xpdf/Dict.h + /home/calvin/src/xpdf-4.04/xpdf/Error.h + /home/calvin/src/xpdf-4.04/xpdf/Function.h + /home/calvin/src/xpdf-4.04/xpdf/Gfx.cc + /home/calvin/src/xpdf-4.04/xpdf/Gfx.h + /home/calvin/src/xpdf-4.04/xpdf/GfxFont.h + /home/calvin/src/xpdf-4.04/xpdf/GfxState.h + /home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h + /home/calvin/src/xpdf-4.04/xpdf/Lexer.h + /home/calvin/src/xpdf-4.04/xpdf/Object.h + /home/calvin/src/xpdf-4.04/xpdf/OptionalContent.h + /home/calvin/src/xpdf-4.04/xpdf/OutputDev.h + /home/calvin/src/xpdf-4.04/xpdf/PDFDoc.h + /home/calvin/src/xpdf-4.04/xpdf/Page.h + /home/calvin/src/xpdf-4.04/xpdf/Parser.h + /home/calvin/src/xpdf-4.04/xpdf/Stream.h + /home/calvin/src/xpdf-4.04/xpdf/TextString.h + /home/calvin/src/xpdf-4.04/xpdf/XRef.h + /home/calvin/src/xpdf-4.04/xpdf/config.h + aconf.h + aconf2.h + goo/GList.h + goo/GMutex.h + goo/GString.h + goo/Trace.h + goo/gfile.h + goo/gmem.h + goo/gmempp.h + goo/gtypes.h +xpdf/CMakeFiles/xpdf_objs.dir/GfxFont.cc.o + /home/calvin/src/xpdf-4.04/xpdf/Array.h + /home/calvin/src/xpdf-4.04/xpdf/BuiltinFont.h + /home/calvin/src/xpdf-4.04/xpdf/BuiltinFontTables.h + /home/calvin/src/xpdf-4.04/xpdf/CMap.h + /home/calvin/src/xpdf-4.04/xpdf/CharCodeToUnicode.h + /home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + /home/calvin/src/xpdf-4.04/xpdf/Dict.h + /home/calvin/src/xpdf-4.04/xpdf/Error.h + /home/calvin/src/xpdf-4.04/xpdf/FontEncodingTables.h + /home/calvin/src/xpdf-4.04/xpdf/GfxFont.cc + /home/calvin/src/xpdf-4.04/xpdf/GfxFont.h + /home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h + /home/calvin/src/xpdf-4.04/xpdf/Object.h + /home/calvin/src/xpdf-4.04/xpdf/Stream.h + /home/calvin/src/xpdf-4.04/xpdf/config.h + aconf.h + aconf2.h + fofi/FoFiBase.h + fofi/FoFiIdentifier.h + fofi/FoFiTrueType.h + fofi/FoFiType1.h + fofi/FoFiType1C.h + goo/GHash.h + goo/GList.h + goo/GMutex.h + goo/GString.h + goo/gfile.h + goo/gmem.h + goo/gmempp.h + goo/gtypes.h +xpdf/CMakeFiles/xpdf_objs.dir/GfxState.cc.o + /home/calvin/src/xpdf-4.04/xpdf/Array.h + /home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + /home/calvin/src/xpdf-4.04/xpdf/Dict.h + /home/calvin/src/xpdf-4.04/xpdf/Error.h + /home/calvin/src/xpdf-4.04/xpdf/Function.h + /home/calvin/src/xpdf-4.04/xpdf/GfxState.cc + /home/calvin/src/xpdf-4.04/xpdf/GfxState.h + /home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h + /home/calvin/src/xpdf-4.04/xpdf/Object.h + /home/calvin/src/xpdf-4.04/xpdf/Page.h + /home/calvin/src/xpdf-4.04/xpdf/Stream.h + /home/calvin/src/xpdf-4.04/xpdf/XRef.h + /home/calvin/src/xpdf-4.04/xpdf/config.h + aconf.h + aconf2.h + goo/GMutex.h + goo/GString.h + goo/gfile.h + goo/gmem.h + goo/gmempp.h + goo/gtypes.h +xpdf/CMakeFiles/xpdf_objs.dir/GlobalParams.cc.o + /home/calvin/src/xpdf-4.04/xpdf/BuiltinFont.h + /home/calvin/src/xpdf-4.04/xpdf/BuiltinFontTables.h + /home/calvin/src/xpdf-4.04/xpdf/CMap.h + /home/calvin/src/xpdf-4.04/xpdf/CharCodeToUnicode.h + /home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + /home/calvin/src/xpdf-4.04/xpdf/Error.h + /home/calvin/src/xpdf-4.04/xpdf/FontEncodingTables.h + /home/calvin/src/xpdf-4.04/xpdf/GlobalParams.cc + /home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h + /home/calvin/src/xpdf-4.04/xpdf/NameToCharCode.h + /home/calvin/src/xpdf-4.04/xpdf/NameToUnicodeTable.h + /home/calvin/src/xpdf-4.04/xpdf/UTF8.h + /home/calvin/src/xpdf-4.04/xpdf/UnicodeMap.h + /home/calvin/src/xpdf-4.04/xpdf/UnicodeMapTables.h + /home/calvin/src/xpdf-4.04/xpdf/UnicodeRemapping.h + /home/calvin/src/xpdf-4.04/xpdf/config.h + aconf.h + aconf2.h + fofi/FoFiIdentifier.h + goo/GHash.h + goo/GList.h + goo/GMutex.h + goo/GString.h + goo/gfile.h + goo/gmem.h + goo/gmempp.h + goo/gtypes.h +xpdf/CMakeFiles/xpdf_objs.dir/JArithmeticDecoder.cc.o + /home/calvin/src/xpdf-4.04/xpdf/Array.h + /home/calvin/src/xpdf-4.04/xpdf/Dict.h + /home/calvin/src/xpdf-4.04/xpdf/JArithmeticDecoder.cc + /home/calvin/src/xpdf-4.04/xpdf/JArithmeticDecoder.h + /home/calvin/src/xpdf-4.04/xpdf/Object.h + /home/calvin/src/xpdf-4.04/xpdf/Stream.h + aconf.h + aconf2.h + goo/GMutex.h + goo/GString.h + goo/gfile.h + goo/gmem.h + goo/gmempp.h + goo/gtypes.h +xpdf/CMakeFiles/xpdf_objs.dir/JBIG2Stream.cc.o + /home/calvin/src/xpdf-4.04/xpdf/Array.h + /home/calvin/src/xpdf-4.04/xpdf/Dict.h + /home/calvin/src/xpdf-4.04/xpdf/Error.h + /home/calvin/src/xpdf-4.04/xpdf/JArithmeticDecoder.h + /home/calvin/src/xpdf-4.04/xpdf/JBIG2Stream.cc + /home/calvin/src/xpdf-4.04/xpdf/JBIG2Stream.h + /home/calvin/src/xpdf-4.04/xpdf/Object.h + /home/calvin/src/xpdf-4.04/xpdf/Stream-CCITT.h + /home/calvin/src/xpdf-4.04/xpdf/Stream.h + /home/calvin/src/xpdf-4.04/xpdf/config.h + aconf.h + aconf2.h + goo/GList.h + goo/GMutex.h + goo/GString.h + goo/gfile.h + goo/gmem.h + goo/gmempp.h + goo/gtypes.h +xpdf/CMakeFiles/xpdf_objs.dir/JPXStream.cc.o + /home/calvin/src/xpdf-4.04/xpdf/Array.h + /home/calvin/src/xpdf-4.04/xpdf/Dict.h + /home/calvin/src/xpdf-4.04/xpdf/Error.h + /home/calvin/src/xpdf-4.04/xpdf/JArithmeticDecoder.h + /home/calvin/src/xpdf-4.04/xpdf/JPXStream.cc + /home/calvin/src/xpdf-4.04/xpdf/JPXStream.h + /home/calvin/src/xpdf-4.04/xpdf/Object.h + /home/calvin/src/xpdf-4.04/xpdf/Stream.h + /home/calvin/src/xpdf-4.04/xpdf/config.h + aconf.h + aconf2.h + goo/GMutex.h + goo/GString.h + goo/gfile.h + goo/gmem.h + goo/gmempp.h + goo/gtypes.h +xpdf/CMakeFiles/xpdf_objs.dir/Lexer.cc.o + /home/calvin/src/xpdf-4.04/xpdf/Array.h + /home/calvin/src/xpdf-4.04/xpdf/Dict.h + /home/calvin/src/xpdf-4.04/xpdf/Error.h + /home/calvin/src/xpdf-4.04/xpdf/Lexer.cc + /home/calvin/src/xpdf-4.04/xpdf/Lexer.h + /home/calvin/src/xpdf-4.04/xpdf/Object.h + /home/calvin/src/xpdf-4.04/xpdf/Stream.h + /home/calvin/src/xpdf-4.04/xpdf/config.h + aconf.h + aconf2.h + goo/GMutex.h + goo/GString.h + goo/gfile.h + goo/gmem.h + goo/gmempp.h + goo/gtypes.h +xpdf/CMakeFiles/xpdf_objs.dir/Link.cc.o + /home/calvin/src/xpdf-4.04/xpdf/Array.h + /home/calvin/src/xpdf-4.04/xpdf/Dict.h + /home/calvin/src/xpdf-4.04/xpdf/Error.h + /home/calvin/src/xpdf-4.04/xpdf/Link.cc + /home/calvin/src/xpdf-4.04/xpdf/Link.h + /home/calvin/src/xpdf-4.04/xpdf/Object.h + /home/calvin/src/xpdf-4.04/xpdf/Stream.h + /home/calvin/src/xpdf-4.04/xpdf/config.h + aconf.h + aconf2.h + goo/GMutex.h + goo/GString.h + goo/gfile.h + goo/gmem.h + goo/gmempp.h + goo/gtypes.h +xpdf/CMakeFiles/xpdf_objs.dir/NameToCharCode.cc.o + /home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + /home/calvin/src/xpdf-4.04/xpdf/NameToCharCode.cc + /home/calvin/src/xpdf-4.04/xpdf/NameToCharCode.h + aconf.h + aconf2.h + goo/gmem.h + goo/gmempp.h +xpdf/CMakeFiles/xpdf_objs.dir/Object.cc.o + /home/calvin/src/xpdf-4.04/xpdf/Array.h + /home/calvin/src/xpdf-4.04/xpdf/Dict.h + /home/calvin/src/xpdf-4.04/xpdf/Error.h + /home/calvin/src/xpdf-4.04/xpdf/Object.cc + /home/calvin/src/xpdf-4.04/xpdf/Object.h + /home/calvin/src/xpdf-4.04/xpdf/Stream.h + /home/calvin/src/xpdf-4.04/xpdf/XRef.h + /home/calvin/src/xpdf-4.04/xpdf/config.h + aconf.h + aconf2.h + goo/GMutex.h + goo/GString.h + goo/gfile.h + goo/gmem.h + goo/gmempp.h + goo/gtypes.h +xpdf/CMakeFiles/xpdf_objs.dir/OptionalContent.cc.o + /home/calvin/src/xpdf-4.04/xpdf/Array.h + /home/calvin/src/xpdf-4.04/xpdf/Catalog.h + /home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + /home/calvin/src/xpdf-4.04/xpdf/Dict.h + /home/calvin/src/xpdf-4.04/xpdf/Error.h + /home/calvin/src/xpdf-4.04/xpdf/Object.h + /home/calvin/src/xpdf-4.04/xpdf/OptionalContent.cc + /home/calvin/src/xpdf-4.04/xpdf/OptionalContent.h + /home/calvin/src/xpdf-4.04/xpdf/PDFDoc.h + /home/calvin/src/xpdf-4.04/xpdf/Page.h + /home/calvin/src/xpdf-4.04/xpdf/Stream.h + /home/calvin/src/xpdf-4.04/xpdf/TextString.h + /home/calvin/src/xpdf-4.04/xpdf/XRef.h + /home/calvin/src/xpdf-4.04/xpdf/config.h + aconf.h + aconf2.h + goo/GList.h + goo/GMutex.h + goo/GString.h + goo/gfile.h + goo/gmem.h + goo/gmempp.h + goo/gtypes.h +xpdf/CMakeFiles/xpdf_objs.dir/Outline.cc.o + /home/calvin/src/xpdf-4.04/xpdf/Array.h + /home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + /home/calvin/src/xpdf-4.04/xpdf/Dict.h + /home/calvin/src/xpdf-4.04/xpdf/Error.h + /home/calvin/src/xpdf-4.04/xpdf/Link.h + /home/calvin/src/xpdf-4.04/xpdf/Object.h + /home/calvin/src/xpdf-4.04/xpdf/Outline.cc + /home/calvin/src/xpdf-4.04/xpdf/Outline.h + /home/calvin/src/xpdf-4.04/xpdf/Stream.h + /home/calvin/src/xpdf-4.04/xpdf/TextString.h + /home/calvin/src/xpdf-4.04/xpdf/config.h + aconf.h + aconf2.h + goo/GList.h + goo/GMutex.h + goo/GString.h + goo/gfile.h + goo/gmem.h + goo/gmempp.h + goo/gtypes.h +xpdf/CMakeFiles/xpdf_objs.dir/OutputDev.cc.o + /home/calvin/src/xpdf-4.04/xpdf/Array.h + /home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + /home/calvin/src/xpdf-4.04/xpdf/Dict.h + /home/calvin/src/xpdf-4.04/xpdf/Function.h + /home/calvin/src/xpdf-4.04/xpdf/GfxState.h + /home/calvin/src/xpdf-4.04/xpdf/Object.h + /home/calvin/src/xpdf-4.04/xpdf/OutputDev.cc + /home/calvin/src/xpdf-4.04/xpdf/OutputDev.h + /home/calvin/src/xpdf-4.04/xpdf/Stream.h + aconf.h + aconf2.h + goo/GMutex.h + goo/GString.h + goo/gfile.h + goo/gmem.h + goo/gmempp.h + goo/gtypes.h +xpdf/CMakeFiles/xpdf_objs.dir/PDF417Barcode.cc.o + /home/calvin/src/xpdf-4.04/xpdf/Error.h + /home/calvin/src/xpdf-4.04/xpdf/PDF417Barcode.cc + /home/calvin/src/xpdf-4.04/xpdf/PDF417Barcode.h + /home/calvin/src/xpdf-4.04/xpdf/config.h + aconf.h + aconf2.h + goo/GList.h + goo/GString.h + goo/gfile.h + goo/gtypes.h +xpdf/CMakeFiles/xpdf_objs.dir/PDFDoc.cc.o + /home/calvin/src/xpdf-4.04/xpdf/Array.h + /home/calvin/src/xpdf-4.04/xpdf/Catalog.h + /home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + /home/calvin/src/xpdf-4.04/xpdf/Dict.h + /home/calvin/src/xpdf-4.04/xpdf/Error.h + /home/calvin/src/xpdf-4.04/xpdf/ErrorCodes.h + /home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h + /home/calvin/src/xpdf-4.04/xpdf/Lexer.h + /home/calvin/src/xpdf-4.04/xpdf/Link.h + /home/calvin/src/xpdf-4.04/xpdf/Object.h + /home/calvin/src/xpdf-4.04/xpdf/OptionalContent.h + /home/calvin/src/xpdf-4.04/xpdf/Outline.h + /home/calvin/src/xpdf-4.04/xpdf/OutputDev.h + /home/calvin/src/xpdf-4.04/xpdf/PDFDoc.cc + /home/calvin/src/xpdf-4.04/xpdf/PDFDoc.h + /home/calvin/src/xpdf-4.04/xpdf/Page.h + /home/calvin/src/xpdf-4.04/xpdf/Parser.h + /home/calvin/src/xpdf-4.04/xpdf/SecurityHandler.h + /home/calvin/src/xpdf-4.04/xpdf/Stream.h + /home/calvin/src/xpdf-4.04/xpdf/UTF8.h + /home/calvin/src/xpdf-4.04/xpdf/XRef.h + /home/calvin/src/xpdf-4.04/xpdf/config.h + aconf.h + aconf2.h + goo/GMutex.h + goo/GString.h + goo/gfile.h + goo/gmem.h + goo/gmempp.h + goo/gtypes.h +xpdf/CMakeFiles/xpdf_objs.dir/PDFDocEncoding.cc.o + /home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + /home/calvin/src/xpdf-4.04/xpdf/PDFDocEncoding.cc + /home/calvin/src/xpdf-4.04/xpdf/PDFDocEncoding.h + aconf.h + aconf2.h + goo/gmempp.h +xpdf/CMakeFiles/xpdf_objs.dir/PSTokenizer.cc.o + /home/calvin/src/xpdf-4.04/xpdf/PSTokenizer.cc + /home/calvin/src/xpdf-4.04/xpdf/PSTokenizer.h + aconf.h + aconf2.h + goo/gmempp.h + goo/gtypes.h +xpdf/CMakeFiles/xpdf_objs.dir/Page.cc.o + /home/calvin/src/xpdf-4.04/xpdf/AcroForm.h + /home/calvin/src/xpdf-4.04/xpdf/Annot.h + /home/calvin/src/xpdf-4.04/xpdf/Array.h + /home/calvin/src/xpdf-4.04/xpdf/Catalog.h + /home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + /home/calvin/src/xpdf-4.04/xpdf/Dict.h + /home/calvin/src/xpdf-4.04/xpdf/Error.h + /home/calvin/src/xpdf-4.04/xpdf/Function.h + /home/calvin/src/xpdf-4.04/xpdf/Gfx.h + /home/calvin/src/xpdf-4.04/xpdf/GfxState.h + /home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h + /home/calvin/src/xpdf-4.04/xpdf/Link.h + /home/calvin/src/xpdf-4.04/xpdf/Object.h + /home/calvin/src/xpdf-4.04/xpdf/OutputDev.h + /home/calvin/src/xpdf-4.04/xpdf/PDFDoc.h + /home/calvin/src/xpdf-4.04/xpdf/Page.cc + /home/calvin/src/xpdf-4.04/xpdf/Page.h + /home/calvin/src/xpdf-4.04/xpdf/Stream.h + /home/calvin/src/xpdf-4.04/xpdf/XRef.h + /home/calvin/src/xpdf-4.04/xpdf/config.h + aconf.h + aconf2.h + goo/GMutex.h + goo/GString.h + goo/Trace.h + goo/gfile.h + goo/gmem.h + goo/gmempp.h + goo/gtypes.h +xpdf/CMakeFiles/xpdf_objs.dir/Parser.cc.o + /home/calvin/src/xpdf-4.04/xpdf/Array.h + /home/calvin/src/xpdf-4.04/xpdf/Decrypt.h + /home/calvin/src/xpdf-4.04/xpdf/Dict.h + /home/calvin/src/xpdf-4.04/xpdf/Error.h + /home/calvin/src/xpdf-4.04/xpdf/Lexer.h + /home/calvin/src/xpdf-4.04/xpdf/Object.h + /home/calvin/src/xpdf-4.04/xpdf/Parser.cc + /home/calvin/src/xpdf-4.04/xpdf/Parser.h + /home/calvin/src/xpdf-4.04/xpdf/Stream.h + /home/calvin/src/xpdf-4.04/xpdf/XRef.h + /home/calvin/src/xpdf-4.04/xpdf/config.h + aconf.h + aconf2.h + goo/GMutex.h + goo/GString.h + goo/gfile.h + goo/gmem.h + goo/gmempp.h + goo/gtypes.h +xpdf/CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.o + /home/calvin/src/xpdf-4.04/xpdf/Array.h + /home/calvin/src/xpdf-4.04/xpdf/Catalog.h + /home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + /home/calvin/src/xpdf-4.04/xpdf/Decrypt.h + /home/calvin/src/xpdf-4.04/xpdf/Dict.h + /home/calvin/src/xpdf-4.04/xpdf/DisplayState.h + /home/calvin/src/xpdf-4.04/xpdf/Error.h + /home/calvin/src/xpdf-4.04/xpdf/GfxFont.h + /home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h + /home/calvin/src/xpdf-4.04/xpdf/Object.h + /home/calvin/src/xpdf-4.04/xpdf/OutputDev.h + /home/calvin/src/xpdf-4.04/xpdf/PDFCore.h + /home/calvin/src/xpdf-4.04/xpdf/PDFDoc.h + /home/calvin/src/xpdf-4.04/xpdf/Page.h + /home/calvin/src/xpdf-4.04/xpdf/SecurityHandler.cc + /home/calvin/src/xpdf-4.04/xpdf/SecurityHandler.h + /home/calvin/src/xpdf-4.04/xpdf/Stream.h + /home/calvin/src/xpdf-4.04/xpdf/TextOutputDev.h + /home/calvin/src/xpdf-4.04/xpdf/XRef.h + /home/calvin/src/xpdf-4.04/xpdf/config.h + aconf.h + aconf2.h + goo/FixedPoint.h + goo/GMutex.h + goo/GString.h + goo/gfile.h + goo/gmem.h + goo/gmempp.h + goo/gtypes.h + splash/SplashTypes.h +xpdf/CMakeFiles/xpdf_objs.dir/Stream.cc.o + /home/calvin/src/xpdf-4.04/xpdf/Array.h + /home/calvin/src/xpdf-4.04/xpdf/Dict.h + /home/calvin/src/xpdf-4.04/xpdf/Error.h + /home/calvin/src/xpdf-4.04/xpdf/Function.h + /home/calvin/src/xpdf-4.04/xpdf/GfxState.h + /home/calvin/src/xpdf-4.04/xpdf/JBIG2Stream.h + /home/calvin/src/xpdf-4.04/xpdf/JPXStream.h + /home/calvin/src/xpdf-4.04/xpdf/Lexer.h + /home/calvin/src/xpdf-4.04/xpdf/Object.h + /home/calvin/src/xpdf-4.04/xpdf/Stream-CCITT.h + /home/calvin/src/xpdf-4.04/xpdf/Stream.cc + /home/calvin/src/xpdf-4.04/xpdf/Stream.h + /home/calvin/src/xpdf-4.04/xpdf/config.h + aconf.h + aconf2.h + goo/GMutex.h + goo/GString.h + goo/gfile.h + goo/gmem.h + goo/gmempp.h + goo/gtypes.h +xpdf/CMakeFiles/xpdf_objs.dir/TextString.cc.o + /home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + /home/calvin/src/xpdf-4.04/xpdf/PDFDocEncoding.h + /home/calvin/src/xpdf-4.04/xpdf/TextString.cc + /home/calvin/src/xpdf-4.04/xpdf/TextString.h + /home/calvin/src/xpdf-4.04/xpdf/UTF8.h + aconf.h + aconf2.h + goo/GString.h + goo/gmem.h + goo/gmempp.h + goo/gtypes.h +xpdf/CMakeFiles/xpdf_objs.dir/UTF8.cc.o + /home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + /home/calvin/src/xpdf-4.04/xpdf/UTF8.cc + /home/calvin/src/xpdf-4.04/xpdf/UTF8.h + aconf.h + aconf2.h + goo/GString.h + goo/gtypes.h +xpdf/CMakeFiles/xpdf_objs.dir/UnicodeMap.cc.o + /home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + /home/calvin/src/xpdf-4.04/xpdf/Error.h + /home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h + /home/calvin/src/xpdf-4.04/xpdf/UnicodeMap.cc + /home/calvin/src/xpdf-4.04/xpdf/UnicodeMap.h + /home/calvin/src/xpdf-4.04/xpdf/config.h + aconf.h + aconf2.h + goo/GList.h + goo/GMutex.h + goo/GString.h + goo/gfile.h + goo/gmem.h + goo/gmempp.h + goo/gtypes.h +xpdf/CMakeFiles/xpdf_objs.dir/UnicodeRemapping.cc.o + /home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + /home/calvin/src/xpdf-4.04/xpdf/Error.h + /home/calvin/src/xpdf-4.04/xpdf/UnicodeRemapping.cc + /home/calvin/src/xpdf-4.04/xpdf/UnicodeRemapping.h + /home/calvin/src/xpdf-4.04/xpdf/config.h + aconf.h + aconf2.h + goo/GString.h + goo/gfile.h + goo/gmem.h + goo/gmempp.h + goo/gtypes.h +xpdf/CMakeFiles/xpdf_objs.dir/UnicodeTypeTable.cc.o + /home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + /home/calvin/src/xpdf-4.04/xpdf/UnicodeTypeTable.cc + /home/calvin/src/xpdf-4.04/xpdf/UnicodeTypeTable.h + aconf.h + aconf2.h + goo/gmempp.h + goo/gtypes.h +xpdf/CMakeFiles/xpdf_objs.dir/XFAScanner.cc.o + /home/calvin/src/xpdf-4.04/xpdf/Array.h + /home/calvin/src/xpdf-4.04/xpdf/Dict.h + /home/calvin/src/xpdf-4.04/xpdf/Error.h + /home/calvin/src/xpdf-4.04/xpdf/Object.h + /home/calvin/src/xpdf-4.04/xpdf/Stream.h + /home/calvin/src/xpdf-4.04/xpdf/XFAScanner.cc + /home/calvin/src/xpdf-4.04/xpdf/XFAScanner.h + /home/calvin/src/xpdf-4.04/xpdf/Zoox.h + /home/calvin/src/xpdf-4.04/xpdf/config.h + aconf.h + aconf2.h + goo/GHash.h + goo/GMutex.h + goo/GString.h + goo/gfile.h + goo/gmem.h + goo/gtypes.h +xpdf/CMakeFiles/xpdf_objs.dir/XRef.cc.o + /home/calvin/src/xpdf-4.04/xpdf/Array.h + /home/calvin/src/xpdf-4.04/xpdf/Dict.h + /home/calvin/src/xpdf-4.04/xpdf/Error.h + /home/calvin/src/xpdf-4.04/xpdf/ErrorCodes.h + /home/calvin/src/xpdf-4.04/xpdf/Lexer.h + /home/calvin/src/xpdf-4.04/xpdf/Object.h + /home/calvin/src/xpdf-4.04/xpdf/Parser.h + /home/calvin/src/xpdf-4.04/xpdf/Stream.h + /home/calvin/src/xpdf-4.04/xpdf/XRef.cc + /home/calvin/src/xpdf-4.04/xpdf/XRef.h + /home/calvin/src/xpdf-4.04/xpdf/config.h + aconf.h + aconf2.h + goo/GMutex.h + goo/GString.h + goo/gfile.h + goo/gmem.h + goo/gmempp.h + goo/gtypes.h +xpdf/CMakeFiles/xpdf_objs.dir/Zoox.cc.o + /home/calvin/src/xpdf-4.04/xpdf/Zoox.cc + /home/calvin/src/xpdf-4.04/xpdf/Zoox.h + aconf.h + aconf2.h + goo/GHash.h + goo/GList.h + goo/GString.h + goo/gmem.h + goo/gmempp.h + goo/gtypes.h diff --git a/xpdf/CMakeFiles/xpdf_objs.dir/depend.make b/xpdf/CMakeFiles/xpdf_objs.dir/depend.make new file mode 100644 index 0000000..ef93aef --- /dev/null +++ b/xpdf/CMakeFiles/xpdf_objs.dir/depend.make @@ -0,0 +1,786 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +xpdf/CMakeFiles/xpdf_objs.dir/AcroForm.cc.o: xpdf/AcroForm.cc +xpdf/CMakeFiles/xpdf_objs.dir/AcroForm.cc.o: xpdf/AcroForm.h +xpdf/CMakeFiles/xpdf_objs.dir/AcroForm.cc.o: xpdf/Annot.h +xpdf/CMakeFiles/xpdf_objs.dir/AcroForm.cc.o: xpdf/Array.h +xpdf/CMakeFiles/xpdf_objs.dir/AcroForm.cc.o: xpdf/Catalog.h +xpdf/CMakeFiles/xpdf_objs.dir/AcroForm.cc.o: xpdf/CharTypes.h +xpdf/CMakeFiles/xpdf_objs.dir/AcroForm.cc.o: xpdf/Dict.h +xpdf/CMakeFiles/xpdf_objs.dir/AcroForm.cc.o: xpdf/Error.h +xpdf/CMakeFiles/xpdf_objs.dir/AcroForm.cc.o: xpdf/Function.h +xpdf/CMakeFiles/xpdf_objs.dir/AcroForm.cc.o: xpdf/Gfx.h +xpdf/CMakeFiles/xpdf_objs.dir/AcroForm.cc.o: xpdf/GfxFont.h +xpdf/CMakeFiles/xpdf_objs.dir/AcroForm.cc.o: xpdf/GfxState.h +xpdf/CMakeFiles/xpdf_objs.dir/AcroForm.cc.o: xpdf/GlobalParams.h +xpdf/CMakeFiles/xpdf_objs.dir/AcroForm.cc.o: xpdf/Lexer.h +xpdf/CMakeFiles/xpdf_objs.dir/AcroForm.cc.o: xpdf/Object.h +xpdf/CMakeFiles/xpdf_objs.dir/AcroForm.cc.o: xpdf/OptionalContent.h +xpdf/CMakeFiles/xpdf_objs.dir/AcroForm.cc.o: xpdf/PDF417Barcode.h +xpdf/CMakeFiles/xpdf_objs.dir/AcroForm.cc.o: xpdf/PDFDoc.h +xpdf/CMakeFiles/xpdf_objs.dir/AcroForm.cc.o: xpdf/Page.h +xpdf/CMakeFiles/xpdf_objs.dir/AcroForm.cc.o: xpdf/Stream.h +xpdf/CMakeFiles/xpdf_objs.dir/AcroForm.cc.o: xpdf/TextString.h +xpdf/CMakeFiles/xpdf_objs.dir/AcroForm.cc.o: xpdf/UTF8.h +xpdf/CMakeFiles/xpdf_objs.dir/AcroForm.cc.o: xpdf/XFAScanner.h +xpdf/CMakeFiles/xpdf_objs.dir/AcroForm.cc.o: xpdf/XRef.h +xpdf/CMakeFiles/xpdf_objs.dir/AcroForm.cc.o: xpdf/config.h +xpdf/CMakeFiles/xpdf_objs.dir/AcroForm.cc.o: aconf.h +xpdf/CMakeFiles/xpdf_objs.dir/AcroForm.cc.o: aconf2.h +xpdf/CMakeFiles/xpdf_objs.dir/AcroForm.cc.o: goo/GList.h +xpdf/CMakeFiles/xpdf_objs.dir/AcroForm.cc.o: goo/GMutex.h +xpdf/CMakeFiles/xpdf_objs.dir/AcroForm.cc.o: goo/GString.h +xpdf/CMakeFiles/xpdf_objs.dir/AcroForm.cc.o: goo/gfile.h +xpdf/CMakeFiles/xpdf_objs.dir/AcroForm.cc.o: goo/gmem.h +xpdf/CMakeFiles/xpdf_objs.dir/AcroForm.cc.o: goo/gmempp.h +xpdf/CMakeFiles/xpdf_objs.dir/AcroForm.cc.o: goo/gtypes.h + +xpdf/CMakeFiles/xpdf_objs.dir/Annot.cc.o: xpdf/AcroForm.h +xpdf/CMakeFiles/xpdf_objs.dir/Annot.cc.o: xpdf/Annot.cc +xpdf/CMakeFiles/xpdf_objs.dir/Annot.cc.o: xpdf/Annot.h +xpdf/CMakeFiles/xpdf_objs.dir/Annot.cc.o: xpdf/Array.h +xpdf/CMakeFiles/xpdf_objs.dir/Annot.cc.o: xpdf/BuiltinFont.h +xpdf/CMakeFiles/xpdf_objs.dir/Annot.cc.o: xpdf/BuiltinFontTables.h +xpdf/CMakeFiles/xpdf_objs.dir/Annot.cc.o: xpdf/Catalog.h +xpdf/CMakeFiles/xpdf_objs.dir/Annot.cc.o: xpdf/CharTypes.h +xpdf/CMakeFiles/xpdf_objs.dir/Annot.cc.o: xpdf/Dict.h +xpdf/CMakeFiles/xpdf_objs.dir/Annot.cc.o: xpdf/Error.h +xpdf/CMakeFiles/xpdf_objs.dir/Annot.cc.o: xpdf/FontEncodingTables.h +xpdf/CMakeFiles/xpdf_objs.dir/Annot.cc.o: xpdf/Function.h +xpdf/CMakeFiles/xpdf_objs.dir/Annot.cc.o: xpdf/Gfx.h +xpdf/CMakeFiles/xpdf_objs.dir/Annot.cc.o: xpdf/GfxFont.h +xpdf/CMakeFiles/xpdf_objs.dir/Annot.cc.o: xpdf/GfxState.h +xpdf/CMakeFiles/xpdf_objs.dir/Annot.cc.o: xpdf/Lexer.h +xpdf/CMakeFiles/xpdf_objs.dir/Annot.cc.o: xpdf/Object.h +xpdf/CMakeFiles/xpdf_objs.dir/Annot.cc.o: xpdf/OptionalContent.h +xpdf/CMakeFiles/xpdf_objs.dir/Annot.cc.o: xpdf/PDFDoc.h +xpdf/CMakeFiles/xpdf_objs.dir/Annot.cc.o: xpdf/Page.h +xpdf/CMakeFiles/xpdf_objs.dir/Annot.cc.o: xpdf/Stream.h +xpdf/CMakeFiles/xpdf_objs.dir/Annot.cc.o: xpdf/XRef.h +xpdf/CMakeFiles/xpdf_objs.dir/Annot.cc.o: xpdf/config.h +xpdf/CMakeFiles/xpdf_objs.dir/Annot.cc.o: aconf.h +xpdf/CMakeFiles/xpdf_objs.dir/Annot.cc.o: aconf2.h +xpdf/CMakeFiles/xpdf_objs.dir/Annot.cc.o: goo/GList.h +xpdf/CMakeFiles/xpdf_objs.dir/Annot.cc.o: goo/GMutex.h +xpdf/CMakeFiles/xpdf_objs.dir/Annot.cc.o: goo/GString.h +xpdf/CMakeFiles/xpdf_objs.dir/Annot.cc.o: goo/gfile.h +xpdf/CMakeFiles/xpdf_objs.dir/Annot.cc.o: goo/gmem.h +xpdf/CMakeFiles/xpdf_objs.dir/Annot.cc.o: goo/gmempp.h +xpdf/CMakeFiles/xpdf_objs.dir/Annot.cc.o: goo/gtypes.h + +xpdf/CMakeFiles/xpdf_objs.dir/Array.cc.o: xpdf/Array.cc +xpdf/CMakeFiles/xpdf_objs.dir/Array.cc.o: xpdf/Array.h +xpdf/CMakeFiles/xpdf_objs.dir/Array.cc.o: xpdf/Dict.h +xpdf/CMakeFiles/xpdf_objs.dir/Array.cc.o: xpdf/Object.h +xpdf/CMakeFiles/xpdf_objs.dir/Array.cc.o: xpdf/Stream.h +xpdf/CMakeFiles/xpdf_objs.dir/Array.cc.o: aconf.h +xpdf/CMakeFiles/xpdf_objs.dir/Array.cc.o: aconf2.h +xpdf/CMakeFiles/xpdf_objs.dir/Array.cc.o: goo/GMutex.h +xpdf/CMakeFiles/xpdf_objs.dir/Array.cc.o: goo/GString.h +xpdf/CMakeFiles/xpdf_objs.dir/Array.cc.o: goo/gfile.h +xpdf/CMakeFiles/xpdf_objs.dir/Array.cc.o: goo/gmem.h +xpdf/CMakeFiles/xpdf_objs.dir/Array.cc.o: goo/gmempp.h +xpdf/CMakeFiles/xpdf_objs.dir/Array.cc.o: goo/gtypes.h + +xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFont.cc.o: xpdf/BuiltinFont.cc +xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFont.cc.o: xpdf/BuiltinFont.h +xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFont.cc.o: xpdf/FontEncodingTables.h +xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFont.cc.o: aconf.h +xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFont.cc.o: aconf2.h +xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFont.cc.o: goo/gmem.h +xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFont.cc.o: goo/gmempp.h +xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFont.cc.o: goo/gtypes.h + +xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFontTables.cc.o: xpdf/BuiltinFont.h +xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFontTables.cc.o: xpdf/BuiltinFontTables.cc +xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFontTables.cc.o: xpdf/BuiltinFontTables.h +xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFontTables.cc.o: xpdf/FontEncodingTables.h +xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFontTables.cc.o: aconf.h +xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFontTables.cc.o: aconf2.h +xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFontTables.cc.o: goo/gmempp.h +xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFontTables.cc.o: goo/gtypes.h + +xpdf/CMakeFiles/xpdf_objs.dir/CMap.cc.o: xpdf/Array.h +xpdf/CMakeFiles/xpdf_objs.dir/CMap.cc.o: xpdf/CMap.cc +xpdf/CMakeFiles/xpdf_objs.dir/CMap.cc.o: xpdf/CMap.h +xpdf/CMakeFiles/xpdf_objs.dir/CMap.cc.o: xpdf/CharTypes.h +xpdf/CMakeFiles/xpdf_objs.dir/CMap.cc.o: xpdf/Dict.h +xpdf/CMakeFiles/xpdf_objs.dir/CMap.cc.o: xpdf/Error.h +xpdf/CMakeFiles/xpdf_objs.dir/CMap.cc.o: xpdf/GlobalParams.h +xpdf/CMakeFiles/xpdf_objs.dir/CMap.cc.o: xpdf/Object.h +xpdf/CMakeFiles/xpdf_objs.dir/CMap.cc.o: xpdf/PSTokenizer.h +xpdf/CMakeFiles/xpdf_objs.dir/CMap.cc.o: xpdf/Stream.h +xpdf/CMakeFiles/xpdf_objs.dir/CMap.cc.o: xpdf/config.h +xpdf/CMakeFiles/xpdf_objs.dir/CMap.cc.o: aconf.h +xpdf/CMakeFiles/xpdf_objs.dir/CMap.cc.o: aconf2.h +xpdf/CMakeFiles/xpdf_objs.dir/CMap.cc.o: goo/GMutex.h +xpdf/CMakeFiles/xpdf_objs.dir/CMap.cc.o: goo/GString.h +xpdf/CMakeFiles/xpdf_objs.dir/CMap.cc.o: goo/gfile.h +xpdf/CMakeFiles/xpdf_objs.dir/CMap.cc.o: goo/gmem.h +xpdf/CMakeFiles/xpdf_objs.dir/CMap.cc.o: goo/gmempp.h +xpdf/CMakeFiles/xpdf_objs.dir/CMap.cc.o: goo/gtypes.h + +xpdf/CMakeFiles/xpdf_objs.dir/Catalog.cc.o: xpdf/AcroForm.h +xpdf/CMakeFiles/xpdf_objs.dir/Catalog.cc.o: xpdf/Array.h +xpdf/CMakeFiles/xpdf_objs.dir/Catalog.cc.o: xpdf/Catalog.cc +xpdf/CMakeFiles/xpdf_objs.dir/Catalog.cc.o: xpdf/Catalog.h +xpdf/CMakeFiles/xpdf_objs.dir/Catalog.cc.o: xpdf/CharTypes.h +xpdf/CMakeFiles/xpdf_objs.dir/Catalog.cc.o: xpdf/Dict.h +xpdf/CMakeFiles/xpdf_objs.dir/Catalog.cc.o: xpdf/Error.h +xpdf/CMakeFiles/xpdf_objs.dir/Catalog.cc.o: xpdf/Link.h +xpdf/CMakeFiles/xpdf_objs.dir/Catalog.cc.o: xpdf/Object.h +xpdf/CMakeFiles/xpdf_objs.dir/Catalog.cc.o: xpdf/PDFDoc.h +xpdf/CMakeFiles/xpdf_objs.dir/Catalog.cc.o: xpdf/Page.h +xpdf/CMakeFiles/xpdf_objs.dir/Catalog.cc.o: xpdf/Stream.h +xpdf/CMakeFiles/xpdf_objs.dir/Catalog.cc.o: xpdf/TextString.h +xpdf/CMakeFiles/xpdf_objs.dir/Catalog.cc.o: xpdf/XRef.h +xpdf/CMakeFiles/xpdf_objs.dir/Catalog.cc.o: xpdf/config.h +xpdf/CMakeFiles/xpdf_objs.dir/Catalog.cc.o: aconf.h +xpdf/CMakeFiles/xpdf_objs.dir/Catalog.cc.o: aconf2.h +xpdf/CMakeFiles/xpdf_objs.dir/Catalog.cc.o: goo/GList.h +xpdf/CMakeFiles/xpdf_objs.dir/Catalog.cc.o: goo/GMutex.h +xpdf/CMakeFiles/xpdf_objs.dir/Catalog.cc.o: goo/GString.h +xpdf/CMakeFiles/xpdf_objs.dir/Catalog.cc.o: goo/gfile.h +xpdf/CMakeFiles/xpdf_objs.dir/Catalog.cc.o: goo/gmem.h +xpdf/CMakeFiles/xpdf_objs.dir/Catalog.cc.o: goo/gmempp.h +xpdf/CMakeFiles/xpdf_objs.dir/Catalog.cc.o: goo/gtypes.h + +xpdf/CMakeFiles/xpdf_objs.dir/CharCodeToUnicode.cc.o: xpdf/CharCodeToUnicode.cc +xpdf/CMakeFiles/xpdf_objs.dir/CharCodeToUnicode.cc.o: xpdf/CharCodeToUnicode.h +xpdf/CMakeFiles/xpdf_objs.dir/CharCodeToUnicode.cc.o: xpdf/CharTypes.h +xpdf/CMakeFiles/xpdf_objs.dir/CharCodeToUnicode.cc.o: xpdf/Error.h +xpdf/CMakeFiles/xpdf_objs.dir/CharCodeToUnicode.cc.o: xpdf/GlobalParams.h +xpdf/CMakeFiles/xpdf_objs.dir/CharCodeToUnicode.cc.o: xpdf/PSTokenizer.h +xpdf/CMakeFiles/xpdf_objs.dir/CharCodeToUnicode.cc.o: xpdf/config.h +xpdf/CMakeFiles/xpdf_objs.dir/CharCodeToUnicode.cc.o: aconf.h +xpdf/CMakeFiles/xpdf_objs.dir/CharCodeToUnicode.cc.o: aconf2.h +xpdf/CMakeFiles/xpdf_objs.dir/CharCodeToUnicode.cc.o: goo/GMutex.h +xpdf/CMakeFiles/xpdf_objs.dir/CharCodeToUnicode.cc.o: goo/GString.h +xpdf/CMakeFiles/xpdf_objs.dir/CharCodeToUnicode.cc.o: goo/gfile.h +xpdf/CMakeFiles/xpdf_objs.dir/CharCodeToUnicode.cc.o: goo/gmem.h +xpdf/CMakeFiles/xpdf_objs.dir/CharCodeToUnicode.cc.o: goo/gmempp.h +xpdf/CMakeFiles/xpdf_objs.dir/CharCodeToUnicode.cc.o: goo/gtypes.h + +xpdf/CMakeFiles/xpdf_objs.dir/Decrypt.cc.o: xpdf/Array.h +xpdf/CMakeFiles/xpdf_objs.dir/Decrypt.cc.o: xpdf/Decrypt.cc +xpdf/CMakeFiles/xpdf_objs.dir/Decrypt.cc.o: xpdf/Decrypt.h +xpdf/CMakeFiles/xpdf_objs.dir/Decrypt.cc.o: xpdf/Dict.h +xpdf/CMakeFiles/xpdf_objs.dir/Decrypt.cc.o: xpdf/Object.h +xpdf/CMakeFiles/xpdf_objs.dir/Decrypt.cc.o: xpdf/Stream.h +xpdf/CMakeFiles/xpdf_objs.dir/Decrypt.cc.o: aconf.h +xpdf/CMakeFiles/xpdf_objs.dir/Decrypt.cc.o: aconf2.h +xpdf/CMakeFiles/xpdf_objs.dir/Decrypt.cc.o: goo/GMutex.h +xpdf/CMakeFiles/xpdf_objs.dir/Decrypt.cc.o: goo/GString.h +xpdf/CMakeFiles/xpdf_objs.dir/Decrypt.cc.o: goo/gfile.h +xpdf/CMakeFiles/xpdf_objs.dir/Decrypt.cc.o: goo/gmem.h +xpdf/CMakeFiles/xpdf_objs.dir/Decrypt.cc.o: goo/gmempp.h +xpdf/CMakeFiles/xpdf_objs.dir/Decrypt.cc.o: goo/gtypes.h + +xpdf/CMakeFiles/xpdf_objs.dir/Dict.cc.o: xpdf/Array.h +xpdf/CMakeFiles/xpdf_objs.dir/Dict.cc.o: xpdf/Dict.cc +xpdf/CMakeFiles/xpdf_objs.dir/Dict.cc.o: xpdf/Dict.h +xpdf/CMakeFiles/xpdf_objs.dir/Dict.cc.o: xpdf/Object.h +xpdf/CMakeFiles/xpdf_objs.dir/Dict.cc.o: xpdf/Stream.h +xpdf/CMakeFiles/xpdf_objs.dir/Dict.cc.o: xpdf/XRef.h +xpdf/CMakeFiles/xpdf_objs.dir/Dict.cc.o: aconf.h +xpdf/CMakeFiles/xpdf_objs.dir/Dict.cc.o: aconf2.h +xpdf/CMakeFiles/xpdf_objs.dir/Dict.cc.o: goo/GMutex.h +xpdf/CMakeFiles/xpdf_objs.dir/Dict.cc.o: goo/GString.h +xpdf/CMakeFiles/xpdf_objs.dir/Dict.cc.o: goo/gfile.h +xpdf/CMakeFiles/xpdf_objs.dir/Dict.cc.o: goo/gmem.h +xpdf/CMakeFiles/xpdf_objs.dir/Dict.cc.o: goo/gmempp.h +xpdf/CMakeFiles/xpdf_objs.dir/Dict.cc.o: goo/gtypes.h + +xpdf/CMakeFiles/xpdf_objs.dir/Error.cc.o: xpdf/CharTypes.h +xpdf/CMakeFiles/xpdf_objs.dir/Error.cc.o: xpdf/Error.cc +xpdf/CMakeFiles/xpdf_objs.dir/Error.cc.o: xpdf/Error.h +xpdf/CMakeFiles/xpdf_objs.dir/Error.cc.o: xpdf/GlobalParams.h +xpdf/CMakeFiles/xpdf_objs.dir/Error.cc.o: xpdf/config.h +xpdf/CMakeFiles/xpdf_objs.dir/Error.cc.o: aconf.h +xpdf/CMakeFiles/xpdf_objs.dir/Error.cc.o: aconf2.h +xpdf/CMakeFiles/xpdf_objs.dir/Error.cc.o: goo/GMutex.h +xpdf/CMakeFiles/xpdf_objs.dir/Error.cc.o: goo/GString.h +xpdf/CMakeFiles/xpdf_objs.dir/Error.cc.o: goo/gfile.h +xpdf/CMakeFiles/xpdf_objs.dir/Error.cc.o: goo/gmempp.h +xpdf/CMakeFiles/xpdf_objs.dir/Error.cc.o: goo/gtypes.h + +xpdf/CMakeFiles/xpdf_objs.dir/FontEncodingTables.cc.o: xpdf/FontEncodingTables.cc +xpdf/CMakeFiles/xpdf_objs.dir/FontEncodingTables.cc.o: xpdf/FontEncodingTables.h +xpdf/CMakeFiles/xpdf_objs.dir/FontEncodingTables.cc.o: aconf.h +xpdf/CMakeFiles/xpdf_objs.dir/FontEncodingTables.cc.o: aconf2.h +xpdf/CMakeFiles/xpdf_objs.dir/FontEncodingTables.cc.o: goo/gmempp.h + +xpdf/CMakeFiles/xpdf_objs.dir/Function.cc.o: xpdf/Array.h +xpdf/CMakeFiles/xpdf_objs.dir/Function.cc.o: xpdf/Dict.h +xpdf/CMakeFiles/xpdf_objs.dir/Function.cc.o: xpdf/Error.h +xpdf/CMakeFiles/xpdf_objs.dir/Function.cc.o: xpdf/Function.cc +xpdf/CMakeFiles/xpdf_objs.dir/Function.cc.o: xpdf/Function.h +xpdf/CMakeFiles/xpdf_objs.dir/Function.cc.o: xpdf/Object.h +xpdf/CMakeFiles/xpdf_objs.dir/Function.cc.o: xpdf/Stream.h +xpdf/CMakeFiles/xpdf_objs.dir/Function.cc.o: xpdf/config.h +xpdf/CMakeFiles/xpdf_objs.dir/Function.cc.o: aconf.h +xpdf/CMakeFiles/xpdf_objs.dir/Function.cc.o: aconf2.h +xpdf/CMakeFiles/xpdf_objs.dir/Function.cc.o: goo/GList.h +xpdf/CMakeFiles/xpdf_objs.dir/Function.cc.o: goo/GMutex.h +xpdf/CMakeFiles/xpdf_objs.dir/Function.cc.o: goo/GString.h +xpdf/CMakeFiles/xpdf_objs.dir/Function.cc.o: goo/gfile.h +xpdf/CMakeFiles/xpdf_objs.dir/Function.cc.o: goo/gmem.h +xpdf/CMakeFiles/xpdf_objs.dir/Function.cc.o: goo/gmempp.h +xpdf/CMakeFiles/xpdf_objs.dir/Function.cc.o: goo/gtypes.h + +xpdf/CMakeFiles/xpdf_objs.dir/Gfx.cc.o: xpdf/Annot.h +xpdf/CMakeFiles/xpdf_objs.dir/Gfx.cc.o: xpdf/Array.h +xpdf/CMakeFiles/xpdf_objs.dir/Gfx.cc.o: xpdf/Catalog.h +xpdf/CMakeFiles/xpdf_objs.dir/Gfx.cc.o: xpdf/CharTypes.h +xpdf/CMakeFiles/xpdf_objs.dir/Gfx.cc.o: xpdf/Dict.h +xpdf/CMakeFiles/xpdf_objs.dir/Gfx.cc.o: xpdf/Error.h +xpdf/CMakeFiles/xpdf_objs.dir/Gfx.cc.o: xpdf/Function.h +xpdf/CMakeFiles/xpdf_objs.dir/Gfx.cc.o: xpdf/Gfx.cc +xpdf/CMakeFiles/xpdf_objs.dir/Gfx.cc.o: xpdf/Gfx.h +xpdf/CMakeFiles/xpdf_objs.dir/Gfx.cc.o: xpdf/GfxFont.h +xpdf/CMakeFiles/xpdf_objs.dir/Gfx.cc.o: xpdf/GfxState.h +xpdf/CMakeFiles/xpdf_objs.dir/Gfx.cc.o: xpdf/GlobalParams.h +xpdf/CMakeFiles/xpdf_objs.dir/Gfx.cc.o: xpdf/Lexer.h +xpdf/CMakeFiles/xpdf_objs.dir/Gfx.cc.o: xpdf/Object.h +xpdf/CMakeFiles/xpdf_objs.dir/Gfx.cc.o: xpdf/OptionalContent.h +xpdf/CMakeFiles/xpdf_objs.dir/Gfx.cc.o: xpdf/OutputDev.h +xpdf/CMakeFiles/xpdf_objs.dir/Gfx.cc.o: xpdf/PDFDoc.h +xpdf/CMakeFiles/xpdf_objs.dir/Gfx.cc.o: xpdf/Page.h +xpdf/CMakeFiles/xpdf_objs.dir/Gfx.cc.o: xpdf/Parser.h +xpdf/CMakeFiles/xpdf_objs.dir/Gfx.cc.o: xpdf/Stream.h +xpdf/CMakeFiles/xpdf_objs.dir/Gfx.cc.o: xpdf/TextString.h +xpdf/CMakeFiles/xpdf_objs.dir/Gfx.cc.o: xpdf/XRef.h +xpdf/CMakeFiles/xpdf_objs.dir/Gfx.cc.o: xpdf/config.h +xpdf/CMakeFiles/xpdf_objs.dir/Gfx.cc.o: aconf.h +xpdf/CMakeFiles/xpdf_objs.dir/Gfx.cc.o: aconf2.h +xpdf/CMakeFiles/xpdf_objs.dir/Gfx.cc.o: goo/GList.h +xpdf/CMakeFiles/xpdf_objs.dir/Gfx.cc.o: goo/GMutex.h +xpdf/CMakeFiles/xpdf_objs.dir/Gfx.cc.o: goo/GString.h +xpdf/CMakeFiles/xpdf_objs.dir/Gfx.cc.o: goo/Trace.h +xpdf/CMakeFiles/xpdf_objs.dir/Gfx.cc.o: goo/gfile.h +xpdf/CMakeFiles/xpdf_objs.dir/Gfx.cc.o: goo/gmem.h +xpdf/CMakeFiles/xpdf_objs.dir/Gfx.cc.o: goo/gmempp.h +xpdf/CMakeFiles/xpdf_objs.dir/Gfx.cc.o: goo/gtypes.h + +xpdf/CMakeFiles/xpdf_objs.dir/GfxFont.cc.o: xpdf/Array.h +xpdf/CMakeFiles/xpdf_objs.dir/GfxFont.cc.o: xpdf/BuiltinFont.h +xpdf/CMakeFiles/xpdf_objs.dir/GfxFont.cc.o: xpdf/BuiltinFontTables.h +xpdf/CMakeFiles/xpdf_objs.dir/GfxFont.cc.o: xpdf/CMap.h +xpdf/CMakeFiles/xpdf_objs.dir/GfxFont.cc.o: xpdf/CharCodeToUnicode.h +xpdf/CMakeFiles/xpdf_objs.dir/GfxFont.cc.o: xpdf/CharTypes.h +xpdf/CMakeFiles/xpdf_objs.dir/GfxFont.cc.o: xpdf/Dict.h +xpdf/CMakeFiles/xpdf_objs.dir/GfxFont.cc.o: xpdf/Error.h +xpdf/CMakeFiles/xpdf_objs.dir/GfxFont.cc.o: xpdf/FontEncodingTables.h +xpdf/CMakeFiles/xpdf_objs.dir/GfxFont.cc.o: xpdf/GfxFont.cc +xpdf/CMakeFiles/xpdf_objs.dir/GfxFont.cc.o: xpdf/GfxFont.h +xpdf/CMakeFiles/xpdf_objs.dir/GfxFont.cc.o: xpdf/GlobalParams.h +xpdf/CMakeFiles/xpdf_objs.dir/GfxFont.cc.o: xpdf/Object.h +xpdf/CMakeFiles/xpdf_objs.dir/GfxFont.cc.o: xpdf/Stream.h +xpdf/CMakeFiles/xpdf_objs.dir/GfxFont.cc.o: xpdf/config.h +xpdf/CMakeFiles/xpdf_objs.dir/GfxFont.cc.o: aconf.h +xpdf/CMakeFiles/xpdf_objs.dir/GfxFont.cc.o: aconf2.h +xpdf/CMakeFiles/xpdf_objs.dir/GfxFont.cc.o: fofi/FoFiBase.h +xpdf/CMakeFiles/xpdf_objs.dir/GfxFont.cc.o: fofi/FoFiIdentifier.h +xpdf/CMakeFiles/xpdf_objs.dir/GfxFont.cc.o: fofi/FoFiTrueType.h +xpdf/CMakeFiles/xpdf_objs.dir/GfxFont.cc.o: fofi/FoFiType1.h +xpdf/CMakeFiles/xpdf_objs.dir/GfxFont.cc.o: fofi/FoFiType1C.h +xpdf/CMakeFiles/xpdf_objs.dir/GfxFont.cc.o: goo/GHash.h +xpdf/CMakeFiles/xpdf_objs.dir/GfxFont.cc.o: goo/GList.h +xpdf/CMakeFiles/xpdf_objs.dir/GfxFont.cc.o: goo/GMutex.h +xpdf/CMakeFiles/xpdf_objs.dir/GfxFont.cc.o: goo/GString.h +xpdf/CMakeFiles/xpdf_objs.dir/GfxFont.cc.o: goo/gfile.h +xpdf/CMakeFiles/xpdf_objs.dir/GfxFont.cc.o: goo/gmem.h +xpdf/CMakeFiles/xpdf_objs.dir/GfxFont.cc.o: goo/gmempp.h +xpdf/CMakeFiles/xpdf_objs.dir/GfxFont.cc.o: goo/gtypes.h + +xpdf/CMakeFiles/xpdf_objs.dir/GfxState.cc.o: xpdf/Array.h +xpdf/CMakeFiles/xpdf_objs.dir/GfxState.cc.o: xpdf/CharTypes.h +xpdf/CMakeFiles/xpdf_objs.dir/GfxState.cc.o: xpdf/Dict.h +xpdf/CMakeFiles/xpdf_objs.dir/GfxState.cc.o: xpdf/Error.h +xpdf/CMakeFiles/xpdf_objs.dir/GfxState.cc.o: xpdf/Function.h +xpdf/CMakeFiles/xpdf_objs.dir/GfxState.cc.o: xpdf/GfxState.cc +xpdf/CMakeFiles/xpdf_objs.dir/GfxState.cc.o: xpdf/GfxState.h +xpdf/CMakeFiles/xpdf_objs.dir/GfxState.cc.o: xpdf/GlobalParams.h +xpdf/CMakeFiles/xpdf_objs.dir/GfxState.cc.o: xpdf/Object.h +xpdf/CMakeFiles/xpdf_objs.dir/GfxState.cc.o: xpdf/Page.h +xpdf/CMakeFiles/xpdf_objs.dir/GfxState.cc.o: xpdf/Stream.h +xpdf/CMakeFiles/xpdf_objs.dir/GfxState.cc.o: xpdf/XRef.h +xpdf/CMakeFiles/xpdf_objs.dir/GfxState.cc.o: xpdf/config.h +xpdf/CMakeFiles/xpdf_objs.dir/GfxState.cc.o: aconf.h +xpdf/CMakeFiles/xpdf_objs.dir/GfxState.cc.o: aconf2.h +xpdf/CMakeFiles/xpdf_objs.dir/GfxState.cc.o: goo/GMutex.h +xpdf/CMakeFiles/xpdf_objs.dir/GfxState.cc.o: goo/GString.h +xpdf/CMakeFiles/xpdf_objs.dir/GfxState.cc.o: goo/gfile.h +xpdf/CMakeFiles/xpdf_objs.dir/GfxState.cc.o: goo/gmem.h +xpdf/CMakeFiles/xpdf_objs.dir/GfxState.cc.o: goo/gmempp.h +xpdf/CMakeFiles/xpdf_objs.dir/GfxState.cc.o: goo/gtypes.h + +xpdf/CMakeFiles/xpdf_objs.dir/GlobalParams.cc.o: xpdf/BuiltinFont.h +xpdf/CMakeFiles/xpdf_objs.dir/GlobalParams.cc.o: xpdf/BuiltinFontTables.h +xpdf/CMakeFiles/xpdf_objs.dir/GlobalParams.cc.o: xpdf/CMap.h +xpdf/CMakeFiles/xpdf_objs.dir/GlobalParams.cc.o: xpdf/CharCodeToUnicode.h +xpdf/CMakeFiles/xpdf_objs.dir/GlobalParams.cc.o: xpdf/CharTypes.h +xpdf/CMakeFiles/xpdf_objs.dir/GlobalParams.cc.o: xpdf/Error.h +xpdf/CMakeFiles/xpdf_objs.dir/GlobalParams.cc.o: xpdf/FontEncodingTables.h +xpdf/CMakeFiles/xpdf_objs.dir/GlobalParams.cc.o: xpdf/GlobalParams.cc +xpdf/CMakeFiles/xpdf_objs.dir/GlobalParams.cc.o: xpdf/GlobalParams.h +xpdf/CMakeFiles/xpdf_objs.dir/GlobalParams.cc.o: xpdf/NameToCharCode.h +xpdf/CMakeFiles/xpdf_objs.dir/GlobalParams.cc.o: xpdf/NameToUnicodeTable.h +xpdf/CMakeFiles/xpdf_objs.dir/GlobalParams.cc.o: xpdf/UTF8.h +xpdf/CMakeFiles/xpdf_objs.dir/GlobalParams.cc.o: xpdf/UnicodeMap.h +xpdf/CMakeFiles/xpdf_objs.dir/GlobalParams.cc.o: xpdf/UnicodeMapTables.h +xpdf/CMakeFiles/xpdf_objs.dir/GlobalParams.cc.o: xpdf/UnicodeRemapping.h +xpdf/CMakeFiles/xpdf_objs.dir/GlobalParams.cc.o: xpdf/config.h +xpdf/CMakeFiles/xpdf_objs.dir/GlobalParams.cc.o: aconf.h +xpdf/CMakeFiles/xpdf_objs.dir/GlobalParams.cc.o: aconf2.h +xpdf/CMakeFiles/xpdf_objs.dir/GlobalParams.cc.o: fofi/FoFiIdentifier.h +xpdf/CMakeFiles/xpdf_objs.dir/GlobalParams.cc.o: goo/GHash.h +xpdf/CMakeFiles/xpdf_objs.dir/GlobalParams.cc.o: goo/GList.h +xpdf/CMakeFiles/xpdf_objs.dir/GlobalParams.cc.o: goo/GMutex.h +xpdf/CMakeFiles/xpdf_objs.dir/GlobalParams.cc.o: goo/GString.h +xpdf/CMakeFiles/xpdf_objs.dir/GlobalParams.cc.o: goo/gfile.h +xpdf/CMakeFiles/xpdf_objs.dir/GlobalParams.cc.o: goo/gmem.h +xpdf/CMakeFiles/xpdf_objs.dir/GlobalParams.cc.o: goo/gmempp.h +xpdf/CMakeFiles/xpdf_objs.dir/GlobalParams.cc.o: goo/gtypes.h + +xpdf/CMakeFiles/xpdf_objs.dir/JArithmeticDecoder.cc.o: xpdf/Array.h +xpdf/CMakeFiles/xpdf_objs.dir/JArithmeticDecoder.cc.o: xpdf/Dict.h +xpdf/CMakeFiles/xpdf_objs.dir/JArithmeticDecoder.cc.o: xpdf/JArithmeticDecoder.cc +xpdf/CMakeFiles/xpdf_objs.dir/JArithmeticDecoder.cc.o: xpdf/JArithmeticDecoder.h +xpdf/CMakeFiles/xpdf_objs.dir/JArithmeticDecoder.cc.o: xpdf/Object.h +xpdf/CMakeFiles/xpdf_objs.dir/JArithmeticDecoder.cc.o: xpdf/Stream.h +xpdf/CMakeFiles/xpdf_objs.dir/JArithmeticDecoder.cc.o: aconf.h +xpdf/CMakeFiles/xpdf_objs.dir/JArithmeticDecoder.cc.o: aconf2.h +xpdf/CMakeFiles/xpdf_objs.dir/JArithmeticDecoder.cc.o: goo/GMutex.h +xpdf/CMakeFiles/xpdf_objs.dir/JArithmeticDecoder.cc.o: goo/GString.h +xpdf/CMakeFiles/xpdf_objs.dir/JArithmeticDecoder.cc.o: goo/gfile.h +xpdf/CMakeFiles/xpdf_objs.dir/JArithmeticDecoder.cc.o: goo/gmem.h +xpdf/CMakeFiles/xpdf_objs.dir/JArithmeticDecoder.cc.o: goo/gmempp.h +xpdf/CMakeFiles/xpdf_objs.dir/JArithmeticDecoder.cc.o: goo/gtypes.h + +xpdf/CMakeFiles/xpdf_objs.dir/JBIG2Stream.cc.o: xpdf/Array.h +xpdf/CMakeFiles/xpdf_objs.dir/JBIG2Stream.cc.o: xpdf/Dict.h +xpdf/CMakeFiles/xpdf_objs.dir/JBIG2Stream.cc.o: xpdf/Error.h +xpdf/CMakeFiles/xpdf_objs.dir/JBIG2Stream.cc.o: xpdf/JArithmeticDecoder.h +xpdf/CMakeFiles/xpdf_objs.dir/JBIG2Stream.cc.o: xpdf/JBIG2Stream.cc +xpdf/CMakeFiles/xpdf_objs.dir/JBIG2Stream.cc.o: xpdf/JBIG2Stream.h +xpdf/CMakeFiles/xpdf_objs.dir/JBIG2Stream.cc.o: xpdf/Object.h +xpdf/CMakeFiles/xpdf_objs.dir/JBIG2Stream.cc.o: xpdf/Stream-CCITT.h +xpdf/CMakeFiles/xpdf_objs.dir/JBIG2Stream.cc.o: xpdf/Stream.h +xpdf/CMakeFiles/xpdf_objs.dir/JBIG2Stream.cc.o: xpdf/config.h +xpdf/CMakeFiles/xpdf_objs.dir/JBIG2Stream.cc.o: aconf.h +xpdf/CMakeFiles/xpdf_objs.dir/JBIG2Stream.cc.o: aconf2.h +xpdf/CMakeFiles/xpdf_objs.dir/JBIG2Stream.cc.o: goo/GList.h +xpdf/CMakeFiles/xpdf_objs.dir/JBIG2Stream.cc.o: goo/GMutex.h +xpdf/CMakeFiles/xpdf_objs.dir/JBIG2Stream.cc.o: goo/GString.h +xpdf/CMakeFiles/xpdf_objs.dir/JBIG2Stream.cc.o: goo/gfile.h +xpdf/CMakeFiles/xpdf_objs.dir/JBIG2Stream.cc.o: goo/gmem.h +xpdf/CMakeFiles/xpdf_objs.dir/JBIG2Stream.cc.o: goo/gmempp.h +xpdf/CMakeFiles/xpdf_objs.dir/JBIG2Stream.cc.o: goo/gtypes.h + +xpdf/CMakeFiles/xpdf_objs.dir/JPXStream.cc.o: xpdf/Array.h +xpdf/CMakeFiles/xpdf_objs.dir/JPXStream.cc.o: xpdf/Dict.h +xpdf/CMakeFiles/xpdf_objs.dir/JPXStream.cc.o: xpdf/Error.h +xpdf/CMakeFiles/xpdf_objs.dir/JPXStream.cc.o: xpdf/JArithmeticDecoder.h +xpdf/CMakeFiles/xpdf_objs.dir/JPXStream.cc.o: xpdf/JPXStream.cc +xpdf/CMakeFiles/xpdf_objs.dir/JPXStream.cc.o: xpdf/JPXStream.h +xpdf/CMakeFiles/xpdf_objs.dir/JPXStream.cc.o: xpdf/Object.h +xpdf/CMakeFiles/xpdf_objs.dir/JPXStream.cc.o: xpdf/Stream.h +xpdf/CMakeFiles/xpdf_objs.dir/JPXStream.cc.o: xpdf/config.h +xpdf/CMakeFiles/xpdf_objs.dir/JPXStream.cc.o: aconf.h +xpdf/CMakeFiles/xpdf_objs.dir/JPXStream.cc.o: aconf2.h +xpdf/CMakeFiles/xpdf_objs.dir/JPXStream.cc.o: goo/GMutex.h +xpdf/CMakeFiles/xpdf_objs.dir/JPXStream.cc.o: goo/GString.h +xpdf/CMakeFiles/xpdf_objs.dir/JPXStream.cc.o: goo/gfile.h +xpdf/CMakeFiles/xpdf_objs.dir/JPXStream.cc.o: goo/gmem.h +xpdf/CMakeFiles/xpdf_objs.dir/JPXStream.cc.o: goo/gmempp.h +xpdf/CMakeFiles/xpdf_objs.dir/JPXStream.cc.o: goo/gtypes.h + +xpdf/CMakeFiles/xpdf_objs.dir/Lexer.cc.o: xpdf/Array.h +xpdf/CMakeFiles/xpdf_objs.dir/Lexer.cc.o: xpdf/Dict.h +xpdf/CMakeFiles/xpdf_objs.dir/Lexer.cc.o: xpdf/Error.h +xpdf/CMakeFiles/xpdf_objs.dir/Lexer.cc.o: xpdf/Lexer.cc +xpdf/CMakeFiles/xpdf_objs.dir/Lexer.cc.o: xpdf/Lexer.h +xpdf/CMakeFiles/xpdf_objs.dir/Lexer.cc.o: xpdf/Object.h +xpdf/CMakeFiles/xpdf_objs.dir/Lexer.cc.o: xpdf/Stream.h +xpdf/CMakeFiles/xpdf_objs.dir/Lexer.cc.o: xpdf/config.h +xpdf/CMakeFiles/xpdf_objs.dir/Lexer.cc.o: aconf.h +xpdf/CMakeFiles/xpdf_objs.dir/Lexer.cc.o: aconf2.h +xpdf/CMakeFiles/xpdf_objs.dir/Lexer.cc.o: goo/GMutex.h +xpdf/CMakeFiles/xpdf_objs.dir/Lexer.cc.o: goo/GString.h +xpdf/CMakeFiles/xpdf_objs.dir/Lexer.cc.o: goo/gfile.h +xpdf/CMakeFiles/xpdf_objs.dir/Lexer.cc.o: goo/gmem.h +xpdf/CMakeFiles/xpdf_objs.dir/Lexer.cc.o: goo/gmempp.h +xpdf/CMakeFiles/xpdf_objs.dir/Lexer.cc.o: goo/gtypes.h + +xpdf/CMakeFiles/xpdf_objs.dir/Link.cc.o: xpdf/Array.h +xpdf/CMakeFiles/xpdf_objs.dir/Link.cc.o: xpdf/Dict.h +xpdf/CMakeFiles/xpdf_objs.dir/Link.cc.o: xpdf/Error.h +xpdf/CMakeFiles/xpdf_objs.dir/Link.cc.o: xpdf/Link.cc +xpdf/CMakeFiles/xpdf_objs.dir/Link.cc.o: xpdf/Link.h +xpdf/CMakeFiles/xpdf_objs.dir/Link.cc.o: xpdf/Object.h +xpdf/CMakeFiles/xpdf_objs.dir/Link.cc.o: xpdf/Stream.h +xpdf/CMakeFiles/xpdf_objs.dir/Link.cc.o: xpdf/config.h +xpdf/CMakeFiles/xpdf_objs.dir/Link.cc.o: aconf.h +xpdf/CMakeFiles/xpdf_objs.dir/Link.cc.o: aconf2.h +xpdf/CMakeFiles/xpdf_objs.dir/Link.cc.o: goo/GMutex.h +xpdf/CMakeFiles/xpdf_objs.dir/Link.cc.o: goo/GString.h +xpdf/CMakeFiles/xpdf_objs.dir/Link.cc.o: goo/gfile.h +xpdf/CMakeFiles/xpdf_objs.dir/Link.cc.o: goo/gmem.h +xpdf/CMakeFiles/xpdf_objs.dir/Link.cc.o: goo/gmempp.h +xpdf/CMakeFiles/xpdf_objs.dir/Link.cc.o: goo/gtypes.h + +xpdf/CMakeFiles/xpdf_objs.dir/NameToCharCode.cc.o: xpdf/CharTypes.h +xpdf/CMakeFiles/xpdf_objs.dir/NameToCharCode.cc.o: xpdf/NameToCharCode.cc +xpdf/CMakeFiles/xpdf_objs.dir/NameToCharCode.cc.o: xpdf/NameToCharCode.h +xpdf/CMakeFiles/xpdf_objs.dir/NameToCharCode.cc.o: aconf.h +xpdf/CMakeFiles/xpdf_objs.dir/NameToCharCode.cc.o: aconf2.h +xpdf/CMakeFiles/xpdf_objs.dir/NameToCharCode.cc.o: goo/gmem.h +xpdf/CMakeFiles/xpdf_objs.dir/NameToCharCode.cc.o: goo/gmempp.h + +xpdf/CMakeFiles/xpdf_objs.dir/Object.cc.o: xpdf/Array.h +xpdf/CMakeFiles/xpdf_objs.dir/Object.cc.o: xpdf/Dict.h +xpdf/CMakeFiles/xpdf_objs.dir/Object.cc.o: xpdf/Error.h +xpdf/CMakeFiles/xpdf_objs.dir/Object.cc.o: xpdf/Object.cc +xpdf/CMakeFiles/xpdf_objs.dir/Object.cc.o: xpdf/Object.h +xpdf/CMakeFiles/xpdf_objs.dir/Object.cc.o: xpdf/Stream.h +xpdf/CMakeFiles/xpdf_objs.dir/Object.cc.o: xpdf/XRef.h +xpdf/CMakeFiles/xpdf_objs.dir/Object.cc.o: xpdf/config.h +xpdf/CMakeFiles/xpdf_objs.dir/Object.cc.o: aconf.h +xpdf/CMakeFiles/xpdf_objs.dir/Object.cc.o: aconf2.h +xpdf/CMakeFiles/xpdf_objs.dir/Object.cc.o: goo/GMutex.h +xpdf/CMakeFiles/xpdf_objs.dir/Object.cc.o: goo/GString.h +xpdf/CMakeFiles/xpdf_objs.dir/Object.cc.o: goo/gfile.h +xpdf/CMakeFiles/xpdf_objs.dir/Object.cc.o: goo/gmem.h +xpdf/CMakeFiles/xpdf_objs.dir/Object.cc.o: goo/gmempp.h +xpdf/CMakeFiles/xpdf_objs.dir/Object.cc.o: goo/gtypes.h + +xpdf/CMakeFiles/xpdf_objs.dir/OptionalContent.cc.o: xpdf/Array.h +xpdf/CMakeFiles/xpdf_objs.dir/OptionalContent.cc.o: xpdf/Catalog.h +xpdf/CMakeFiles/xpdf_objs.dir/OptionalContent.cc.o: xpdf/CharTypes.h +xpdf/CMakeFiles/xpdf_objs.dir/OptionalContent.cc.o: xpdf/Dict.h +xpdf/CMakeFiles/xpdf_objs.dir/OptionalContent.cc.o: xpdf/Error.h +xpdf/CMakeFiles/xpdf_objs.dir/OptionalContent.cc.o: xpdf/Object.h +xpdf/CMakeFiles/xpdf_objs.dir/OptionalContent.cc.o: xpdf/OptionalContent.cc +xpdf/CMakeFiles/xpdf_objs.dir/OptionalContent.cc.o: xpdf/OptionalContent.h +xpdf/CMakeFiles/xpdf_objs.dir/OptionalContent.cc.o: xpdf/PDFDoc.h +xpdf/CMakeFiles/xpdf_objs.dir/OptionalContent.cc.o: xpdf/Page.h +xpdf/CMakeFiles/xpdf_objs.dir/OptionalContent.cc.o: xpdf/Stream.h +xpdf/CMakeFiles/xpdf_objs.dir/OptionalContent.cc.o: xpdf/TextString.h +xpdf/CMakeFiles/xpdf_objs.dir/OptionalContent.cc.o: xpdf/XRef.h +xpdf/CMakeFiles/xpdf_objs.dir/OptionalContent.cc.o: xpdf/config.h +xpdf/CMakeFiles/xpdf_objs.dir/OptionalContent.cc.o: aconf.h +xpdf/CMakeFiles/xpdf_objs.dir/OptionalContent.cc.o: aconf2.h +xpdf/CMakeFiles/xpdf_objs.dir/OptionalContent.cc.o: goo/GList.h +xpdf/CMakeFiles/xpdf_objs.dir/OptionalContent.cc.o: goo/GMutex.h +xpdf/CMakeFiles/xpdf_objs.dir/OptionalContent.cc.o: goo/GString.h +xpdf/CMakeFiles/xpdf_objs.dir/OptionalContent.cc.o: goo/gfile.h +xpdf/CMakeFiles/xpdf_objs.dir/OptionalContent.cc.o: goo/gmem.h +xpdf/CMakeFiles/xpdf_objs.dir/OptionalContent.cc.o: goo/gmempp.h +xpdf/CMakeFiles/xpdf_objs.dir/OptionalContent.cc.o: goo/gtypes.h + +xpdf/CMakeFiles/xpdf_objs.dir/Outline.cc.o: xpdf/Array.h +xpdf/CMakeFiles/xpdf_objs.dir/Outline.cc.o: xpdf/CharTypes.h +xpdf/CMakeFiles/xpdf_objs.dir/Outline.cc.o: xpdf/Dict.h +xpdf/CMakeFiles/xpdf_objs.dir/Outline.cc.o: xpdf/Error.h +xpdf/CMakeFiles/xpdf_objs.dir/Outline.cc.o: xpdf/Link.h +xpdf/CMakeFiles/xpdf_objs.dir/Outline.cc.o: xpdf/Object.h +xpdf/CMakeFiles/xpdf_objs.dir/Outline.cc.o: xpdf/Outline.cc +xpdf/CMakeFiles/xpdf_objs.dir/Outline.cc.o: xpdf/Outline.h +xpdf/CMakeFiles/xpdf_objs.dir/Outline.cc.o: xpdf/Stream.h +xpdf/CMakeFiles/xpdf_objs.dir/Outline.cc.o: xpdf/TextString.h +xpdf/CMakeFiles/xpdf_objs.dir/Outline.cc.o: xpdf/config.h +xpdf/CMakeFiles/xpdf_objs.dir/Outline.cc.o: aconf.h +xpdf/CMakeFiles/xpdf_objs.dir/Outline.cc.o: aconf2.h +xpdf/CMakeFiles/xpdf_objs.dir/Outline.cc.o: goo/GList.h +xpdf/CMakeFiles/xpdf_objs.dir/Outline.cc.o: goo/GMutex.h +xpdf/CMakeFiles/xpdf_objs.dir/Outline.cc.o: goo/GString.h +xpdf/CMakeFiles/xpdf_objs.dir/Outline.cc.o: goo/gfile.h +xpdf/CMakeFiles/xpdf_objs.dir/Outline.cc.o: goo/gmem.h +xpdf/CMakeFiles/xpdf_objs.dir/Outline.cc.o: goo/gmempp.h +xpdf/CMakeFiles/xpdf_objs.dir/Outline.cc.o: goo/gtypes.h + +xpdf/CMakeFiles/xpdf_objs.dir/OutputDev.cc.o: xpdf/Array.h +xpdf/CMakeFiles/xpdf_objs.dir/OutputDev.cc.o: xpdf/CharTypes.h +xpdf/CMakeFiles/xpdf_objs.dir/OutputDev.cc.o: xpdf/Dict.h +xpdf/CMakeFiles/xpdf_objs.dir/OutputDev.cc.o: xpdf/Function.h +xpdf/CMakeFiles/xpdf_objs.dir/OutputDev.cc.o: xpdf/GfxState.h +xpdf/CMakeFiles/xpdf_objs.dir/OutputDev.cc.o: xpdf/Object.h +xpdf/CMakeFiles/xpdf_objs.dir/OutputDev.cc.o: xpdf/OutputDev.cc +xpdf/CMakeFiles/xpdf_objs.dir/OutputDev.cc.o: xpdf/OutputDev.h +xpdf/CMakeFiles/xpdf_objs.dir/OutputDev.cc.o: xpdf/Stream.h +xpdf/CMakeFiles/xpdf_objs.dir/OutputDev.cc.o: aconf.h +xpdf/CMakeFiles/xpdf_objs.dir/OutputDev.cc.o: aconf2.h +xpdf/CMakeFiles/xpdf_objs.dir/OutputDev.cc.o: goo/GMutex.h +xpdf/CMakeFiles/xpdf_objs.dir/OutputDev.cc.o: goo/GString.h +xpdf/CMakeFiles/xpdf_objs.dir/OutputDev.cc.o: goo/gfile.h +xpdf/CMakeFiles/xpdf_objs.dir/OutputDev.cc.o: goo/gmem.h +xpdf/CMakeFiles/xpdf_objs.dir/OutputDev.cc.o: goo/gmempp.h +xpdf/CMakeFiles/xpdf_objs.dir/OutputDev.cc.o: goo/gtypes.h + +xpdf/CMakeFiles/xpdf_objs.dir/PDF417Barcode.cc.o: xpdf/Error.h +xpdf/CMakeFiles/xpdf_objs.dir/PDF417Barcode.cc.o: xpdf/PDF417Barcode.cc +xpdf/CMakeFiles/xpdf_objs.dir/PDF417Barcode.cc.o: xpdf/PDF417Barcode.h +xpdf/CMakeFiles/xpdf_objs.dir/PDF417Barcode.cc.o: xpdf/config.h +xpdf/CMakeFiles/xpdf_objs.dir/PDF417Barcode.cc.o: aconf.h +xpdf/CMakeFiles/xpdf_objs.dir/PDF417Barcode.cc.o: aconf2.h +xpdf/CMakeFiles/xpdf_objs.dir/PDF417Barcode.cc.o: goo/GList.h +xpdf/CMakeFiles/xpdf_objs.dir/PDF417Barcode.cc.o: goo/GString.h +xpdf/CMakeFiles/xpdf_objs.dir/PDF417Barcode.cc.o: goo/gfile.h +xpdf/CMakeFiles/xpdf_objs.dir/PDF417Barcode.cc.o: goo/gtypes.h + +xpdf/CMakeFiles/xpdf_objs.dir/PDFDoc.cc.o: xpdf/Array.h +xpdf/CMakeFiles/xpdf_objs.dir/PDFDoc.cc.o: xpdf/Catalog.h +xpdf/CMakeFiles/xpdf_objs.dir/PDFDoc.cc.o: xpdf/CharTypes.h +xpdf/CMakeFiles/xpdf_objs.dir/PDFDoc.cc.o: xpdf/Dict.h +xpdf/CMakeFiles/xpdf_objs.dir/PDFDoc.cc.o: xpdf/Error.h +xpdf/CMakeFiles/xpdf_objs.dir/PDFDoc.cc.o: xpdf/ErrorCodes.h +xpdf/CMakeFiles/xpdf_objs.dir/PDFDoc.cc.o: xpdf/GlobalParams.h +xpdf/CMakeFiles/xpdf_objs.dir/PDFDoc.cc.o: xpdf/Lexer.h +xpdf/CMakeFiles/xpdf_objs.dir/PDFDoc.cc.o: xpdf/Link.h +xpdf/CMakeFiles/xpdf_objs.dir/PDFDoc.cc.o: xpdf/Object.h +xpdf/CMakeFiles/xpdf_objs.dir/PDFDoc.cc.o: xpdf/OptionalContent.h +xpdf/CMakeFiles/xpdf_objs.dir/PDFDoc.cc.o: xpdf/Outline.h +xpdf/CMakeFiles/xpdf_objs.dir/PDFDoc.cc.o: xpdf/OutputDev.h +xpdf/CMakeFiles/xpdf_objs.dir/PDFDoc.cc.o: xpdf/PDFDoc.cc +xpdf/CMakeFiles/xpdf_objs.dir/PDFDoc.cc.o: xpdf/PDFDoc.h +xpdf/CMakeFiles/xpdf_objs.dir/PDFDoc.cc.o: xpdf/Page.h +xpdf/CMakeFiles/xpdf_objs.dir/PDFDoc.cc.o: xpdf/Parser.h +xpdf/CMakeFiles/xpdf_objs.dir/PDFDoc.cc.o: xpdf/SecurityHandler.h +xpdf/CMakeFiles/xpdf_objs.dir/PDFDoc.cc.o: xpdf/Stream.h +xpdf/CMakeFiles/xpdf_objs.dir/PDFDoc.cc.o: xpdf/UTF8.h +xpdf/CMakeFiles/xpdf_objs.dir/PDFDoc.cc.o: xpdf/XRef.h +xpdf/CMakeFiles/xpdf_objs.dir/PDFDoc.cc.o: xpdf/config.h +xpdf/CMakeFiles/xpdf_objs.dir/PDFDoc.cc.o: aconf.h +xpdf/CMakeFiles/xpdf_objs.dir/PDFDoc.cc.o: aconf2.h +xpdf/CMakeFiles/xpdf_objs.dir/PDFDoc.cc.o: goo/GMutex.h +xpdf/CMakeFiles/xpdf_objs.dir/PDFDoc.cc.o: goo/GString.h +xpdf/CMakeFiles/xpdf_objs.dir/PDFDoc.cc.o: goo/gfile.h +xpdf/CMakeFiles/xpdf_objs.dir/PDFDoc.cc.o: goo/gmem.h +xpdf/CMakeFiles/xpdf_objs.dir/PDFDoc.cc.o: goo/gmempp.h +xpdf/CMakeFiles/xpdf_objs.dir/PDFDoc.cc.o: goo/gtypes.h + +xpdf/CMakeFiles/xpdf_objs.dir/PDFDocEncoding.cc.o: xpdf/CharTypes.h +xpdf/CMakeFiles/xpdf_objs.dir/PDFDocEncoding.cc.o: xpdf/PDFDocEncoding.cc +xpdf/CMakeFiles/xpdf_objs.dir/PDFDocEncoding.cc.o: xpdf/PDFDocEncoding.h +xpdf/CMakeFiles/xpdf_objs.dir/PDFDocEncoding.cc.o: aconf.h +xpdf/CMakeFiles/xpdf_objs.dir/PDFDocEncoding.cc.o: aconf2.h +xpdf/CMakeFiles/xpdf_objs.dir/PDFDocEncoding.cc.o: goo/gmempp.h + +xpdf/CMakeFiles/xpdf_objs.dir/PSTokenizer.cc.o: xpdf/PSTokenizer.cc +xpdf/CMakeFiles/xpdf_objs.dir/PSTokenizer.cc.o: xpdf/PSTokenizer.h +xpdf/CMakeFiles/xpdf_objs.dir/PSTokenizer.cc.o: aconf.h +xpdf/CMakeFiles/xpdf_objs.dir/PSTokenizer.cc.o: aconf2.h +xpdf/CMakeFiles/xpdf_objs.dir/PSTokenizer.cc.o: goo/gmempp.h +xpdf/CMakeFiles/xpdf_objs.dir/PSTokenizer.cc.o: goo/gtypes.h + +xpdf/CMakeFiles/xpdf_objs.dir/Page.cc.o: xpdf/AcroForm.h +xpdf/CMakeFiles/xpdf_objs.dir/Page.cc.o: xpdf/Annot.h +xpdf/CMakeFiles/xpdf_objs.dir/Page.cc.o: xpdf/Array.h +xpdf/CMakeFiles/xpdf_objs.dir/Page.cc.o: xpdf/Catalog.h +xpdf/CMakeFiles/xpdf_objs.dir/Page.cc.o: xpdf/CharTypes.h +xpdf/CMakeFiles/xpdf_objs.dir/Page.cc.o: xpdf/Dict.h +xpdf/CMakeFiles/xpdf_objs.dir/Page.cc.o: xpdf/Error.h +xpdf/CMakeFiles/xpdf_objs.dir/Page.cc.o: xpdf/Function.h +xpdf/CMakeFiles/xpdf_objs.dir/Page.cc.o: xpdf/Gfx.h +xpdf/CMakeFiles/xpdf_objs.dir/Page.cc.o: xpdf/GfxState.h +xpdf/CMakeFiles/xpdf_objs.dir/Page.cc.o: xpdf/GlobalParams.h +xpdf/CMakeFiles/xpdf_objs.dir/Page.cc.o: xpdf/Link.h +xpdf/CMakeFiles/xpdf_objs.dir/Page.cc.o: xpdf/Object.h +xpdf/CMakeFiles/xpdf_objs.dir/Page.cc.o: xpdf/OutputDev.h +xpdf/CMakeFiles/xpdf_objs.dir/Page.cc.o: xpdf/PDFDoc.h +xpdf/CMakeFiles/xpdf_objs.dir/Page.cc.o: xpdf/Page.cc +xpdf/CMakeFiles/xpdf_objs.dir/Page.cc.o: xpdf/Page.h +xpdf/CMakeFiles/xpdf_objs.dir/Page.cc.o: xpdf/Stream.h +xpdf/CMakeFiles/xpdf_objs.dir/Page.cc.o: xpdf/XRef.h +xpdf/CMakeFiles/xpdf_objs.dir/Page.cc.o: xpdf/config.h +xpdf/CMakeFiles/xpdf_objs.dir/Page.cc.o: aconf.h +xpdf/CMakeFiles/xpdf_objs.dir/Page.cc.o: aconf2.h +xpdf/CMakeFiles/xpdf_objs.dir/Page.cc.o: goo/GMutex.h +xpdf/CMakeFiles/xpdf_objs.dir/Page.cc.o: goo/GString.h +xpdf/CMakeFiles/xpdf_objs.dir/Page.cc.o: goo/Trace.h +xpdf/CMakeFiles/xpdf_objs.dir/Page.cc.o: goo/gfile.h +xpdf/CMakeFiles/xpdf_objs.dir/Page.cc.o: goo/gmem.h +xpdf/CMakeFiles/xpdf_objs.dir/Page.cc.o: goo/gmempp.h +xpdf/CMakeFiles/xpdf_objs.dir/Page.cc.o: goo/gtypes.h + +xpdf/CMakeFiles/xpdf_objs.dir/Parser.cc.o: xpdf/Array.h +xpdf/CMakeFiles/xpdf_objs.dir/Parser.cc.o: xpdf/Decrypt.h +xpdf/CMakeFiles/xpdf_objs.dir/Parser.cc.o: xpdf/Dict.h +xpdf/CMakeFiles/xpdf_objs.dir/Parser.cc.o: xpdf/Error.h +xpdf/CMakeFiles/xpdf_objs.dir/Parser.cc.o: xpdf/Lexer.h +xpdf/CMakeFiles/xpdf_objs.dir/Parser.cc.o: xpdf/Object.h +xpdf/CMakeFiles/xpdf_objs.dir/Parser.cc.o: xpdf/Parser.cc +xpdf/CMakeFiles/xpdf_objs.dir/Parser.cc.o: xpdf/Parser.h +xpdf/CMakeFiles/xpdf_objs.dir/Parser.cc.o: xpdf/Stream.h +xpdf/CMakeFiles/xpdf_objs.dir/Parser.cc.o: xpdf/XRef.h +xpdf/CMakeFiles/xpdf_objs.dir/Parser.cc.o: xpdf/config.h +xpdf/CMakeFiles/xpdf_objs.dir/Parser.cc.o: aconf.h +xpdf/CMakeFiles/xpdf_objs.dir/Parser.cc.o: aconf2.h +xpdf/CMakeFiles/xpdf_objs.dir/Parser.cc.o: goo/GMutex.h +xpdf/CMakeFiles/xpdf_objs.dir/Parser.cc.o: goo/GString.h +xpdf/CMakeFiles/xpdf_objs.dir/Parser.cc.o: goo/gfile.h +xpdf/CMakeFiles/xpdf_objs.dir/Parser.cc.o: goo/gmem.h +xpdf/CMakeFiles/xpdf_objs.dir/Parser.cc.o: goo/gmempp.h +xpdf/CMakeFiles/xpdf_objs.dir/Parser.cc.o: goo/gtypes.h + +xpdf/CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.o: xpdf/Array.h +xpdf/CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.o: xpdf/Catalog.h +xpdf/CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.o: xpdf/CharTypes.h +xpdf/CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.o: xpdf/Decrypt.h +xpdf/CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.o: xpdf/Dict.h +xpdf/CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.o: xpdf/DisplayState.h +xpdf/CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.o: xpdf/Error.h +xpdf/CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.o: xpdf/GfxFont.h +xpdf/CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.o: xpdf/GlobalParams.h +xpdf/CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.o: xpdf/Object.h +xpdf/CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.o: xpdf/OutputDev.h +xpdf/CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.o: xpdf/PDFCore.h +xpdf/CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.o: xpdf/PDFDoc.h +xpdf/CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.o: xpdf/Page.h +xpdf/CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.o: xpdf/SecurityHandler.cc +xpdf/CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.o: xpdf/SecurityHandler.h +xpdf/CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.o: xpdf/Stream.h +xpdf/CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.o: xpdf/TextOutputDev.h +xpdf/CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.o: xpdf/XRef.h +xpdf/CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.o: xpdf/config.h +xpdf/CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.o: aconf.h +xpdf/CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.o: aconf2.h +xpdf/CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.o: goo/FixedPoint.h +xpdf/CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.o: goo/GMutex.h +xpdf/CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.o: goo/GString.h +xpdf/CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.o: goo/gfile.h +xpdf/CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.o: goo/gmem.h +xpdf/CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.o: goo/gmempp.h +xpdf/CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.o: goo/gtypes.h +xpdf/CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.o: splash/SplashTypes.h + +xpdf/CMakeFiles/xpdf_objs.dir/Stream.cc.o: xpdf/Array.h +xpdf/CMakeFiles/xpdf_objs.dir/Stream.cc.o: xpdf/Dict.h +xpdf/CMakeFiles/xpdf_objs.dir/Stream.cc.o: xpdf/Error.h +xpdf/CMakeFiles/xpdf_objs.dir/Stream.cc.o: xpdf/Function.h +xpdf/CMakeFiles/xpdf_objs.dir/Stream.cc.o: xpdf/GfxState.h +xpdf/CMakeFiles/xpdf_objs.dir/Stream.cc.o: xpdf/JBIG2Stream.h +xpdf/CMakeFiles/xpdf_objs.dir/Stream.cc.o: xpdf/JPXStream.h +xpdf/CMakeFiles/xpdf_objs.dir/Stream.cc.o: xpdf/Lexer.h +xpdf/CMakeFiles/xpdf_objs.dir/Stream.cc.o: xpdf/Object.h +xpdf/CMakeFiles/xpdf_objs.dir/Stream.cc.o: xpdf/Stream-CCITT.h +xpdf/CMakeFiles/xpdf_objs.dir/Stream.cc.o: xpdf/Stream.cc +xpdf/CMakeFiles/xpdf_objs.dir/Stream.cc.o: xpdf/Stream.h +xpdf/CMakeFiles/xpdf_objs.dir/Stream.cc.o: xpdf/config.h +xpdf/CMakeFiles/xpdf_objs.dir/Stream.cc.o: aconf.h +xpdf/CMakeFiles/xpdf_objs.dir/Stream.cc.o: aconf2.h +xpdf/CMakeFiles/xpdf_objs.dir/Stream.cc.o: goo/GMutex.h +xpdf/CMakeFiles/xpdf_objs.dir/Stream.cc.o: goo/GString.h +xpdf/CMakeFiles/xpdf_objs.dir/Stream.cc.o: goo/gfile.h +xpdf/CMakeFiles/xpdf_objs.dir/Stream.cc.o: goo/gmem.h +xpdf/CMakeFiles/xpdf_objs.dir/Stream.cc.o: goo/gmempp.h +xpdf/CMakeFiles/xpdf_objs.dir/Stream.cc.o: goo/gtypes.h + +xpdf/CMakeFiles/xpdf_objs.dir/TextString.cc.o: xpdf/CharTypes.h +xpdf/CMakeFiles/xpdf_objs.dir/TextString.cc.o: xpdf/PDFDocEncoding.h +xpdf/CMakeFiles/xpdf_objs.dir/TextString.cc.o: xpdf/TextString.cc +xpdf/CMakeFiles/xpdf_objs.dir/TextString.cc.o: xpdf/TextString.h +xpdf/CMakeFiles/xpdf_objs.dir/TextString.cc.o: xpdf/UTF8.h +xpdf/CMakeFiles/xpdf_objs.dir/TextString.cc.o: aconf.h +xpdf/CMakeFiles/xpdf_objs.dir/TextString.cc.o: aconf2.h +xpdf/CMakeFiles/xpdf_objs.dir/TextString.cc.o: goo/GString.h +xpdf/CMakeFiles/xpdf_objs.dir/TextString.cc.o: goo/gmem.h +xpdf/CMakeFiles/xpdf_objs.dir/TextString.cc.o: goo/gmempp.h +xpdf/CMakeFiles/xpdf_objs.dir/TextString.cc.o: goo/gtypes.h + +xpdf/CMakeFiles/xpdf_objs.dir/UTF8.cc.o: xpdf/CharTypes.h +xpdf/CMakeFiles/xpdf_objs.dir/UTF8.cc.o: xpdf/UTF8.cc +xpdf/CMakeFiles/xpdf_objs.dir/UTF8.cc.o: xpdf/UTF8.h +xpdf/CMakeFiles/xpdf_objs.dir/UTF8.cc.o: aconf.h +xpdf/CMakeFiles/xpdf_objs.dir/UTF8.cc.o: aconf2.h +xpdf/CMakeFiles/xpdf_objs.dir/UTF8.cc.o: goo/GString.h +xpdf/CMakeFiles/xpdf_objs.dir/UTF8.cc.o: goo/gtypes.h + +xpdf/CMakeFiles/xpdf_objs.dir/UnicodeMap.cc.o: xpdf/CharTypes.h +xpdf/CMakeFiles/xpdf_objs.dir/UnicodeMap.cc.o: xpdf/Error.h +xpdf/CMakeFiles/xpdf_objs.dir/UnicodeMap.cc.o: xpdf/GlobalParams.h +xpdf/CMakeFiles/xpdf_objs.dir/UnicodeMap.cc.o: xpdf/UnicodeMap.cc +xpdf/CMakeFiles/xpdf_objs.dir/UnicodeMap.cc.o: xpdf/UnicodeMap.h +xpdf/CMakeFiles/xpdf_objs.dir/UnicodeMap.cc.o: xpdf/config.h +xpdf/CMakeFiles/xpdf_objs.dir/UnicodeMap.cc.o: aconf.h +xpdf/CMakeFiles/xpdf_objs.dir/UnicodeMap.cc.o: aconf2.h +xpdf/CMakeFiles/xpdf_objs.dir/UnicodeMap.cc.o: goo/GList.h +xpdf/CMakeFiles/xpdf_objs.dir/UnicodeMap.cc.o: goo/GMutex.h +xpdf/CMakeFiles/xpdf_objs.dir/UnicodeMap.cc.o: goo/GString.h +xpdf/CMakeFiles/xpdf_objs.dir/UnicodeMap.cc.o: goo/gfile.h +xpdf/CMakeFiles/xpdf_objs.dir/UnicodeMap.cc.o: goo/gmem.h +xpdf/CMakeFiles/xpdf_objs.dir/UnicodeMap.cc.o: goo/gmempp.h +xpdf/CMakeFiles/xpdf_objs.dir/UnicodeMap.cc.o: goo/gtypes.h + +xpdf/CMakeFiles/xpdf_objs.dir/UnicodeRemapping.cc.o: xpdf/CharTypes.h +xpdf/CMakeFiles/xpdf_objs.dir/UnicodeRemapping.cc.o: xpdf/Error.h +xpdf/CMakeFiles/xpdf_objs.dir/UnicodeRemapping.cc.o: xpdf/UnicodeRemapping.cc +xpdf/CMakeFiles/xpdf_objs.dir/UnicodeRemapping.cc.o: xpdf/UnicodeRemapping.h +xpdf/CMakeFiles/xpdf_objs.dir/UnicodeRemapping.cc.o: xpdf/config.h +xpdf/CMakeFiles/xpdf_objs.dir/UnicodeRemapping.cc.o: aconf.h +xpdf/CMakeFiles/xpdf_objs.dir/UnicodeRemapping.cc.o: aconf2.h +xpdf/CMakeFiles/xpdf_objs.dir/UnicodeRemapping.cc.o: goo/GString.h +xpdf/CMakeFiles/xpdf_objs.dir/UnicodeRemapping.cc.o: goo/gfile.h +xpdf/CMakeFiles/xpdf_objs.dir/UnicodeRemapping.cc.o: goo/gmem.h +xpdf/CMakeFiles/xpdf_objs.dir/UnicodeRemapping.cc.o: goo/gmempp.h +xpdf/CMakeFiles/xpdf_objs.dir/UnicodeRemapping.cc.o: goo/gtypes.h + +xpdf/CMakeFiles/xpdf_objs.dir/UnicodeTypeTable.cc.o: xpdf/CharTypes.h +xpdf/CMakeFiles/xpdf_objs.dir/UnicodeTypeTable.cc.o: xpdf/UnicodeTypeTable.cc +xpdf/CMakeFiles/xpdf_objs.dir/UnicodeTypeTable.cc.o: xpdf/UnicodeTypeTable.h +xpdf/CMakeFiles/xpdf_objs.dir/UnicodeTypeTable.cc.o: aconf.h +xpdf/CMakeFiles/xpdf_objs.dir/UnicodeTypeTable.cc.o: aconf2.h +xpdf/CMakeFiles/xpdf_objs.dir/UnicodeTypeTable.cc.o: goo/gmempp.h +xpdf/CMakeFiles/xpdf_objs.dir/UnicodeTypeTable.cc.o: goo/gtypes.h + +xpdf/CMakeFiles/xpdf_objs.dir/XFAScanner.cc.o: xpdf/Array.h +xpdf/CMakeFiles/xpdf_objs.dir/XFAScanner.cc.o: xpdf/Dict.h +xpdf/CMakeFiles/xpdf_objs.dir/XFAScanner.cc.o: xpdf/Error.h +xpdf/CMakeFiles/xpdf_objs.dir/XFAScanner.cc.o: xpdf/Object.h +xpdf/CMakeFiles/xpdf_objs.dir/XFAScanner.cc.o: xpdf/Stream.h +xpdf/CMakeFiles/xpdf_objs.dir/XFAScanner.cc.o: xpdf/XFAScanner.cc +xpdf/CMakeFiles/xpdf_objs.dir/XFAScanner.cc.o: xpdf/XFAScanner.h +xpdf/CMakeFiles/xpdf_objs.dir/XFAScanner.cc.o: xpdf/Zoox.h +xpdf/CMakeFiles/xpdf_objs.dir/XFAScanner.cc.o: xpdf/config.h +xpdf/CMakeFiles/xpdf_objs.dir/XFAScanner.cc.o: aconf.h +xpdf/CMakeFiles/xpdf_objs.dir/XFAScanner.cc.o: aconf2.h +xpdf/CMakeFiles/xpdf_objs.dir/XFAScanner.cc.o: goo/GHash.h +xpdf/CMakeFiles/xpdf_objs.dir/XFAScanner.cc.o: goo/GMutex.h +xpdf/CMakeFiles/xpdf_objs.dir/XFAScanner.cc.o: goo/GString.h +xpdf/CMakeFiles/xpdf_objs.dir/XFAScanner.cc.o: goo/gfile.h +xpdf/CMakeFiles/xpdf_objs.dir/XFAScanner.cc.o: goo/gmem.h +xpdf/CMakeFiles/xpdf_objs.dir/XFAScanner.cc.o: goo/gtypes.h + +xpdf/CMakeFiles/xpdf_objs.dir/XRef.cc.o: xpdf/Array.h +xpdf/CMakeFiles/xpdf_objs.dir/XRef.cc.o: xpdf/Dict.h +xpdf/CMakeFiles/xpdf_objs.dir/XRef.cc.o: xpdf/Error.h +xpdf/CMakeFiles/xpdf_objs.dir/XRef.cc.o: xpdf/ErrorCodes.h +xpdf/CMakeFiles/xpdf_objs.dir/XRef.cc.o: xpdf/Lexer.h +xpdf/CMakeFiles/xpdf_objs.dir/XRef.cc.o: xpdf/Object.h +xpdf/CMakeFiles/xpdf_objs.dir/XRef.cc.o: xpdf/Parser.h +xpdf/CMakeFiles/xpdf_objs.dir/XRef.cc.o: xpdf/Stream.h +xpdf/CMakeFiles/xpdf_objs.dir/XRef.cc.o: xpdf/XRef.cc +xpdf/CMakeFiles/xpdf_objs.dir/XRef.cc.o: xpdf/XRef.h +xpdf/CMakeFiles/xpdf_objs.dir/XRef.cc.o: xpdf/config.h +xpdf/CMakeFiles/xpdf_objs.dir/XRef.cc.o: aconf.h +xpdf/CMakeFiles/xpdf_objs.dir/XRef.cc.o: aconf2.h +xpdf/CMakeFiles/xpdf_objs.dir/XRef.cc.o: goo/GMutex.h +xpdf/CMakeFiles/xpdf_objs.dir/XRef.cc.o: goo/GString.h +xpdf/CMakeFiles/xpdf_objs.dir/XRef.cc.o: goo/gfile.h +xpdf/CMakeFiles/xpdf_objs.dir/XRef.cc.o: goo/gmem.h +xpdf/CMakeFiles/xpdf_objs.dir/XRef.cc.o: goo/gmempp.h +xpdf/CMakeFiles/xpdf_objs.dir/XRef.cc.o: goo/gtypes.h + +xpdf/CMakeFiles/xpdf_objs.dir/Zoox.cc.o: xpdf/Zoox.cc +xpdf/CMakeFiles/xpdf_objs.dir/Zoox.cc.o: xpdf/Zoox.h +xpdf/CMakeFiles/xpdf_objs.dir/Zoox.cc.o: aconf.h +xpdf/CMakeFiles/xpdf_objs.dir/Zoox.cc.o: aconf2.h +xpdf/CMakeFiles/xpdf_objs.dir/Zoox.cc.o: goo/GHash.h +xpdf/CMakeFiles/xpdf_objs.dir/Zoox.cc.o: goo/GList.h +xpdf/CMakeFiles/xpdf_objs.dir/Zoox.cc.o: goo/GString.h +xpdf/CMakeFiles/xpdf_objs.dir/Zoox.cc.o: goo/gmem.h +xpdf/CMakeFiles/xpdf_objs.dir/Zoox.cc.o: goo/gmempp.h +xpdf/CMakeFiles/xpdf_objs.dir/Zoox.cc.o: goo/gtypes.h + diff --git a/xpdf/CMakeFiles/xpdf_objs.dir/flags.make b/xpdf/CMakeFiles/xpdf_objs.dir/flags.make new file mode 100644 index 0000000..fb6d504 --- /dev/null +++ b/xpdf/CMakeFiles/xpdf_objs.dir/flags.make @@ -0,0 +1,10 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +# compile CXX with /usr/bin/c++ +CXX_DEFINES = + +CXX_INCLUDES = -I/home/calvin/src/xpdf-4.04 -I/home/calvin/src/xpdf-4.04/goo -I/home/calvin/src/xpdf-4.04/fofi -I/home/calvin/src/xpdf-4.04/splash + +CXX_FLAGS = -fPIC + diff --git a/xpdf/CMakeFiles/xpdf_objs.dir/progress.make b/xpdf/CMakeFiles/xpdf_objs.dir/progress.make new file mode 100644 index 0000000..48e2d70 --- /dev/null +++ b/xpdf/CMakeFiles/xpdf_objs.dir/progress.make @@ -0,0 +1,44 @@ +CMAKE_PROGRESS_1 = 61 +CMAKE_PROGRESS_2 = 62 +CMAKE_PROGRESS_3 = +CMAKE_PROGRESS_4 = 63 +CMAKE_PROGRESS_5 = 64 +CMAKE_PROGRESS_6 = 65 +CMAKE_PROGRESS_7 = +CMAKE_PROGRESS_8 = 66 +CMAKE_PROGRESS_9 = 67 +CMAKE_PROGRESS_10 = 68 +CMAKE_PROGRESS_11 = +CMAKE_PROGRESS_12 = 69 +CMAKE_PROGRESS_13 = 70 +CMAKE_PROGRESS_14 = 71 +CMAKE_PROGRESS_15 = +CMAKE_PROGRESS_16 = 72 +CMAKE_PROGRESS_17 = 73 +CMAKE_PROGRESS_18 = 74 +CMAKE_PROGRESS_19 = +CMAKE_PROGRESS_20 = 75 +CMAKE_PROGRESS_21 = 76 +CMAKE_PROGRESS_22 = 77 +CMAKE_PROGRESS_23 = +CMAKE_PROGRESS_24 = 78 +CMAKE_PROGRESS_25 = 79 +CMAKE_PROGRESS_26 = 80 +CMAKE_PROGRESS_27 = +CMAKE_PROGRESS_28 = 81 +CMAKE_PROGRESS_29 = 82 +CMAKE_PROGRESS_30 = +CMAKE_PROGRESS_31 = 83 +CMAKE_PROGRESS_32 = 84 +CMAKE_PROGRESS_33 = 85 +CMAKE_PROGRESS_34 = +CMAKE_PROGRESS_35 = 86 +CMAKE_PROGRESS_36 = 87 +CMAKE_PROGRESS_37 = 88 +CMAKE_PROGRESS_38 = +CMAKE_PROGRESS_39 = 89 +CMAKE_PROGRESS_40 = 90 +CMAKE_PROGRESS_41 = 91 +CMAKE_PROGRESS_42 = +CMAKE_PROGRESS_43 = 92 + diff --git a/xpdf/CMakeFiles/xpdf_widget_objs.dir/CXX.includecache b/xpdf/CMakeFiles/xpdf_widget_objs.dir/CXX.includecache new file mode 100644 index 0000000..f910c29 --- /dev/null +++ b/xpdf/CMakeFiles/xpdf_widget_objs.dir/CXX.includecache @@ -0,0 +1,952 @@ +#IncludeRegexLine: ^[ ]*[#%][ ]*(include|import)[ ]*[<"]([^">]+)([">]) + +#IncludeRegexScan: ^.*$ + +#IncludeRegexComplain: ^$ + +#IncludeRegexTransform: + +/home/calvin/src/xpdf-4.04/xpdf/AcroForm.h +aconf.h +- + +/home/calvin/src/xpdf-4.04/xpdf/Annot.h +aconf.h +- + +/home/calvin/src/xpdf-4.04/xpdf/Array.h +aconf.h +- +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h + +/home/calvin/src/xpdf-4.04/xpdf/BuiltinFont.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h + +/home/calvin/src/xpdf-4.04/xpdf/BuiltinFontTables.h +BuiltinFont.h +/home/calvin/src/xpdf-4.04/xpdf/BuiltinFont.h + +/home/calvin/src/xpdf-4.04/xpdf/Catalog.h +aconf.h +- +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h +CharTypes.h +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + +/home/calvin/src/xpdf-4.04/xpdf/CharCodeToUnicode.h +aconf.h +- +CharTypes.h +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h + +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + +/home/calvin/src/xpdf-4.04/xpdf/Dict.h +aconf.h +- +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h + +/home/calvin/src/xpdf-4.04/xpdf/DisplayState.cc +aconf.h +- +stdlib.h +- +gmempp.h +/home/calvin/src/xpdf-4.04/xpdf/gmempp.h +GString.h +/home/calvin/src/xpdf-4.04/xpdf/GString.h +GList.h +/home/calvin/src/xpdf-4.04/xpdf/GList.h +TileMap.h +/home/calvin/src/xpdf-4.04/xpdf/TileMap.h +TileCache.h +/home/calvin/src/xpdf-4.04/xpdf/TileCache.h +TileCompositor.h +/home/calvin/src/xpdf-4.04/xpdf/TileCompositor.h +DisplayState.h +/home/calvin/src/xpdf-4.04/xpdf/DisplayState.h + +/home/calvin/src/xpdf-4.04/xpdf/DisplayState.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +SplashTypes.h +/home/calvin/src/xpdf-4.04/xpdf/SplashTypes.h + +/home/calvin/src/xpdf-4.04/xpdf/Error.h +aconf.h +- +stdio.h +- +config.h +/home/calvin/src/xpdf-4.04/xpdf/config.h +gfile.h +/home/calvin/src/xpdf-4.04/xpdf/gfile.h + +/home/calvin/src/xpdf-4.04/xpdf/ErrorCodes.h + +/home/calvin/src/xpdf-4.04/xpdf/FontEncodingTables.h + +/home/calvin/src/xpdf-4.04/xpdf/Function.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h + +/home/calvin/src/xpdf-4.04/xpdf/Gfx.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +gfile.h +/home/calvin/src/xpdf-4.04/xpdf/gfile.h +GfxState.h +/home/calvin/src/xpdf-4.04/xpdf/GfxState.h + +/home/calvin/src/xpdf-4.04/xpdf/GfxFont.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +GString.h +/home/calvin/src/xpdf-4.04/xpdf/GString.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h +CharTypes.h +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + +/home/calvin/src/xpdf-4.04/xpdf/GfxState.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h +Function.h +/home/calvin/src/xpdf-4.04/xpdf/Function.h + +/home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h +aconf.h +- +stdio.h +- +windows.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +CharTypes.h +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h + +/home/calvin/src/xpdf-4.04/xpdf/JPXStream.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h +Stream.h +/home/calvin/src/xpdf-4.04/xpdf/Stream.h + +/home/calvin/src/xpdf-4.04/xpdf/Link.h +aconf.h +- +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h + +/home/calvin/src/xpdf-4.04/xpdf/Object.h +aconf.h +- +stdio.h +- +string.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +gmem.h +/home/calvin/src/xpdf-4.04/xpdf/gmem.h +gfile.h +/home/calvin/src/xpdf-4.04/xpdf/gfile.h +GString.h +/home/calvin/src/xpdf-4.04/xpdf/GString.h +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h +Array.h +/home/calvin/src/xpdf-4.04/xpdf/Array.h +Dict.h +/home/calvin/src/xpdf-4.04/xpdf/Dict.h +Stream.h +/home/calvin/src/xpdf-4.04/xpdf/Stream.h + +/home/calvin/src/xpdf-4.04/xpdf/OptionalContent.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h +CharTypes.h +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + +/home/calvin/src/xpdf-4.04/xpdf/OutputDev.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +CharTypes.h +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + +/home/calvin/src/xpdf-4.04/xpdf/PDFCore.cc +aconf.h +- +math.h +- +gmempp.h +/home/calvin/src/xpdf-4.04/xpdf/gmempp.h +GString.h +/home/calvin/src/xpdf-4.04/xpdf/GString.h +GList.h +/home/calvin/src/xpdf-4.04/xpdf/GList.h +GlobalParams.h +/home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h +Splash.h +/home/calvin/src/xpdf-4.04/xpdf/Splash.h +SplashBitmap.h +/home/calvin/src/xpdf-4.04/xpdf/SplashBitmap.h +SplashPattern.h +/home/calvin/src/xpdf-4.04/xpdf/SplashPattern.h +SplashPath.h +/home/calvin/src/xpdf-4.04/xpdf/SplashPath.h +Error.h +/home/calvin/src/xpdf-4.04/xpdf/Error.h +ErrorCodes.h +/home/calvin/src/xpdf-4.04/xpdf/ErrorCodes.h +PDFDoc.h +/home/calvin/src/xpdf-4.04/xpdf/PDFDoc.h +Link.h +/home/calvin/src/xpdf-4.04/xpdf/Link.h +Annot.h +/home/calvin/src/xpdf-4.04/xpdf/Annot.h +AcroForm.h +/home/calvin/src/xpdf-4.04/xpdf/AcroForm.h +OptionalContent.h +/home/calvin/src/xpdf-4.04/xpdf/OptionalContent.h +TileMap.h +/home/calvin/src/xpdf-4.04/xpdf/TileMap.h +TileCache.h +/home/calvin/src/xpdf-4.04/xpdf/TileCache.h +TileCompositor.h +/home/calvin/src/xpdf-4.04/xpdf/TileCompositor.h +PDFCore.h +/home/calvin/src/xpdf-4.04/xpdf/PDFCore.h + +/home/calvin/src/xpdf-4.04/xpdf/PDFCore.h +aconf.h +- +stdlib.h +- +SplashTypes.h +/home/calvin/src/xpdf-4.04/xpdf/SplashTypes.h +CharTypes.h +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h +DisplayState.h +/home/calvin/src/xpdf-4.04/xpdf/DisplayState.h +TextOutputDev.h +/home/calvin/src/xpdf-4.04/xpdf/TextOutputDev.h + +/home/calvin/src/xpdf-4.04/xpdf/PDFDoc.h +aconf.h +- +stdio.h +- +XRef.h +/home/calvin/src/xpdf-4.04/xpdf/XRef.h +Catalog.h +/home/calvin/src/xpdf-4.04/xpdf/Catalog.h +Page.h +/home/calvin/src/xpdf-4.04/xpdf/Page.h + +/home/calvin/src/xpdf-4.04/xpdf/PSOutputDev.cc +aconf.h +- +stdio.h +- +stddef.h +- +stdarg.h +- +signal.h +- +math.h +- +gmempp.h +/home/calvin/src/xpdf-4.04/xpdf/gmempp.h +GString.h +/home/calvin/src/xpdf-4.04/xpdf/GString.h +GList.h +/home/calvin/src/xpdf-4.04/xpdf/GList.h +GHash.h +/home/calvin/src/xpdf-4.04/xpdf/GHash.h +config.h +/home/calvin/src/xpdf-4.04/xpdf/config.h +GlobalParams.h +/home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h +Error.h +/home/calvin/src/xpdf-4.04/xpdf/Error.h +Function.h +/home/calvin/src/xpdf-4.04/xpdf/Function.h +Gfx.h +/home/calvin/src/xpdf-4.04/xpdf/Gfx.h +GfxState.h +/home/calvin/src/xpdf-4.04/xpdf/GfxState.h +GfxFont.h +/home/calvin/src/xpdf-4.04/xpdf/GfxFont.h +UnicodeMap.h +/home/calvin/src/xpdf-4.04/xpdf/UnicodeMap.h +FoFiType1C.h +/home/calvin/src/xpdf-4.04/xpdf/FoFiType1C.h +FoFiTrueType.h +/home/calvin/src/xpdf-4.04/xpdf/FoFiTrueType.h +Catalog.h +/home/calvin/src/xpdf-4.04/xpdf/Catalog.h +Page.h +/home/calvin/src/xpdf-4.04/xpdf/Page.h +Stream.h +/home/calvin/src/xpdf-4.04/xpdf/Stream.h +Annot.h +/home/calvin/src/xpdf-4.04/xpdf/Annot.h +PDFDoc.h +/home/calvin/src/xpdf-4.04/xpdf/PDFDoc.h +XRef.h +/home/calvin/src/xpdf-4.04/xpdf/XRef.h +PreScanOutputDev.h +/home/calvin/src/xpdf-4.04/xpdf/PreScanOutputDev.h +CharCodeToUnicode.h +/home/calvin/src/xpdf-4.04/xpdf/CharCodeToUnicode.h +AcroForm.h +/home/calvin/src/xpdf-4.04/xpdf/AcroForm.h +TextString.h +/home/calvin/src/xpdf-4.04/xpdf/TextString.h +Splash.h +/home/calvin/src/xpdf-4.04/xpdf/Splash.h +SplashBitmap.h +/home/calvin/src/xpdf-4.04/xpdf/SplashBitmap.h +SplashOutputDev.h +/home/calvin/src/xpdf-4.04/xpdf/SplashOutputDev.h +PSOutputDev.h +/home/calvin/src/xpdf-4.04/xpdf/PSOutputDev.h + +/home/calvin/src/xpdf-4.04/xpdf/PSOutputDev.h +aconf.h +- +stddef.h +- +config.h +/home/calvin/src/xpdf-4.04/xpdf/config.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h +GlobalParams.h +/home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h +OutputDev.h +/home/calvin/src/xpdf-4.04/xpdf/OutputDev.h + +/home/calvin/src/xpdf-4.04/xpdf/Page.h +aconf.h +- +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h + +/home/calvin/src/xpdf-4.04/xpdf/PreScanOutputDev.cc +aconf.h +- +math.h +- +gmempp.h +/home/calvin/src/xpdf-4.04/xpdf/gmempp.h +GlobalParams.h +/home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h +Page.h +/home/calvin/src/xpdf-4.04/xpdf/Page.h +Gfx.h +/home/calvin/src/xpdf-4.04/xpdf/Gfx.h +GfxFont.h +/home/calvin/src/xpdf-4.04/xpdf/GfxFont.h +Link.h +/home/calvin/src/xpdf-4.04/xpdf/Link.h +PreScanOutputDev.h +/home/calvin/src/xpdf-4.04/xpdf/PreScanOutputDev.h + +/home/calvin/src/xpdf-4.04/xpdf/PreScanOutputDev.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +GfxState.h +/home/calvin/src/xpdf-4.04/xpdf/GfxState.h +OutputDev.h +/home/calvin/src/xpdf-4.04/xpdf/OutputDev.h + +/home/calvin/src/xpdf-4.04/xpdf/ShadingImage.cc +aconf.h +- +math.h +- +Trace.h +/home/calvin/src/xpdf-4.04/xpdf/Trace.h +GfxState.h +/home/calvin/src/xpdf-4.04/xpdf/GfxState.h +SplashBitmap.h +/home/calvin/src/xpdf-4.04/xpdf/SplashBitmap.h +SplashPattern.h +/home/calvin/src/xpdf-4.04/xpdf/SplashPattern.h +SplashPath.h +/home/calvin/src/xpdf-4.04/xpdf/SplashPath.h +Splash.h +/home/calvin/src/xpdf-4.04/xpdf/Splash.h +ShadingImage.h +/home/calvin/src/xpdf-4.04/xpdf/ShadingImage.h + +/home/calvin/src/xpdf-4.04/xpdf/ShadingImage.h +aconf.h +- +SplashTypes.h +/home/calvin/src/xpdf-4.04/xpdf/SplashTypes.h + +/home/calvin/src/xpdf-4.04/xpdf/SplashOutputDev.cc +aconf.h +- +string.h +- +math.h +- +limits.h +- +gmempp.h +/home/calvin/src/xpdf-4.04/xpdf/gmempp.h +gfile.h +/home/calvin/src/xpdf-4.04/xpdf/gfile.h +Trace.h +/home/calvin/src/xpdf-4.04/xpdf/Trace.h +GlobalParams.h +/home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h +Error.h +/home/calvin/src/xpdf-4.04/xpdf/Error.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h +Gfx.h +/home/calvin/src/xpdf-4.04/xpdf/Gfx.h +GfxFont.h +/home/calvin/src/xpdf-4.04/xpdf/GfxFont.h +ShadingImage.h +/home/calvin/src/xpdf-4.04/xpdf/ShadingImage.h +Link.h +/home/calvin/src/xpdf-4.04/xpdf/Link.h +CharCodeToUnicode.h +/home/calvin/src/xpdf-4.04/xpdf/CharCodeToUnicode.h +FontEncodingTables.h +/home/calvin/src/xpdf-4.04/xpdf/FontEncodingTables.h +BuiltinFont.h +/home/calvin/src/xpdf-4.04/xpdf/BuiltinFont.h +BuiltinFontTables.h +/home/calvin/src/xpdf-4.04/xpdf/BuiltinFontTables.h +FoFiTrueType.h +/home/calvin/src/xpdf-4.04/xpdf/FoFiTrueType.h +FoFiType1C.h +/home/calvin/src/xpdf-4.04/xpdf/FoFiType1C.h +JPXStream.h +/home/calvin/src/xpdf-4.04/xpdf/JPXStream.h +SplashBitmap.h +/home/calvin/src/xpdf-4.04/xpdf/SplashBitmap.h +SplashGlyphBitmap.h +/home/calvin/src/xpdf-4.04/xpdf/SplashGlyphBitmap.h +SplashPattern.h +/home/calvin/src/xpdf-4.04/xpdf/SplashPattern.h +SplashScreen.h +/home/calvin/src/xpdf-4.04/xpdf/SplashScreen.h +SplashPath.h +/home/calvin/src/xpdf-4.04/xpdf/SplashPath.h +SplashState.h +/home/calvin/src/xpdf-4.04/xpdf/SplashState.h +SplashErrorCodes.h +/home/calvin/src/xpdf-4.04/xpdf/SplashErrorCodes.h +SplashFontEngine.h +/home/calvin/src/xpdf-4.04/xpdf/SplashFontEngine.h +SplashFont.h +/home/calvin/src/xpdf-4.04/xpdf/SplashFont.h +SplashFontFile.h +/home/calvin/src/xpdf-4.04/xpdf/SplashFontFile.h +SplashFontFileID.h +/home/calvin/src/xpdf-4.04/xpdf/SplashFontFileID.h +Splash.h +/home/calvin/src/xpdf-4.04/xpdf/Splash.h +SplashOutputDev.h +/home/calvin/src/xpdf-4.04/xpdf/SplashOutputDev.h + +/home/calvin/src/xpdf-4.04/xpdf/SplashOutputDev.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +SplashTypes.h +/home/calvin/src/xpdf-4.04/xpdf/SplashTypes.h +config.h +/home/calvin/src/xpdf-4.04/xpdf/config.h +OutputDev.h +/home/calvin/src/xpdf-4.04/xpdf/OutputDev.h +GfxState.h +/home/calvin/src/xpdf-4.04/xpdf/GfxState.h + +/home/calvin/src/xpdf-4.04/xpdf/Stream.h +aconf.h +- +stdio.h +- +jpeglib.h +- +setjmp.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +gfile.h +/home/calvin/src/xpdf-4.04/xpdf/gfile.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h + +/home/calvin/src/xpdf-4.04/xpdf/TextOutputDev.cc +aconf.h +- +stdio.h +- +stdlib.h +- +stddef.h +- +math.h +- +limits.h +- +ctype.h +- +fcntl.h +- +io.h +- +gmem.h +/home/calvin/src/xpdf-4.04/xpdf/gmem.h +gmempp.h +/home/calvin/src/xpdf-4.04/xpdf/gmempp.h +GString.h +/home/calvin/src/xpdf-4.04/xpdf/GString.h +GList.h +/home/calvin/src/xpdf-4.04/xpdf/GList.h +gfile.h +/home/calvin/src/xpdf-4.04/xpdf/gfile.h +config.h +/home/calvin/src/xpdf-4.04/xpdf/config.h +Error.h +/home/calvin/src/xpdf-4.04/xpdf/Error.h +GlobalParams.h +/home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h +UnicodeMap.h +/home/calvin/src/xpdf-4.04/xpdf/UnicodeMap.h +UnicodeRemapping.h +/home/calvin/src/xpdf-4.04/xpdf/UnicodeRemapping.h +UnicodeTypeTable.h +/home/calvin/src/xpdf-4.04/xpdf/UnicodeTypeTable.h +GfxState.h +/home/calvin/src/xpdf-4.04/xpdf/GfxState.h +Link.h +/home/calvin/src/xpdf-4.04/xpdf/Link.h +TextOutputDev.h +/home/calvin/src/xpdf-4.04/xpdf/TextOutputDev.h + +/home/calvin/src/xpdf-4.04/xpdf/TextOutputDev.h +aconf.h +- +stdio.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +GfxFont.h +/home/calvin/src/xpdf-4.04/xpdf/GfxFont.h +OutputDev.h +/home/calvin/src/xpdf-4.04/xpdf/OutputDev.h + +/home/calvin/src/xpdf-4.04/xpdf/TextString.h +aconf.h +- +CharTypes.h +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + +/home/calvin/src/xpdf-4.04/xpdf/TileCache.cc +aconf.h +- +gmem.h +/home/calvin/src/xpdf-4.04/xpdf/gmem.h +gmempp.h +/home/calvin/src/xpdf-4.04/xpdf/gmempp.h +GList.h +/home/calvin/src/xpdf-4.04/xpdf/GList.h +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h +windows.h +- +pthread.h +- +unistd.h +- +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h +PDFDoc.h +/home/calvin/src/xpdf-4.04/xpdf/PDFDoc.h +SplashBitmap.h +/home/calvin/src/xpdf-4.04/xpdf/SplashBitmap.h +SplashOutputDev.h +/home/calvin/src/xpdf-4.04/xpdf/SplashOutputDev.h +DisplayState.h +/home/calvin/src/xpdf-4.04/xpdf/DisplayState.h +GfxState.h +/home/calvin/src/xpdf-4.04/xpdf/GfxState.h +TileMap.h +/home/calvin/src/xpdf-4.04/xpdf/TileMap.h +TileCache.h +/home/calvin/src/xpdf-4.04/xpdf/TileCache.h + +/home/calvin/src/xpdf-4.04/xpdf/TileCache.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +SplashTypes.h +/home/calvin/src/xpdf-4.04/xpdf/SplashTypes.h + +/home/calvin/src/xpdf-4.04/xpdf/TileCompositor.cc +aconf.h +- +string.h +- +math.h +- +gmempp.h +/home/calvin/src/xpdf-4.04/xpdf/gmempp.h +GString.h +/home/calvin/src/xpdf-4.04/xpdf/GString.h +GList.h +/home/calvin/src/xpdf-4.04/xpdf/GList.h +SplashBitmap.h +/home/calvin/src/xpdf-4.04/xpdf/SplashBitmap.h +GlobalParams.h +/home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h +DisplayState.h +/home/calvin/src/xpdf-4.04/xpdf/DisplayState.h +TileMap.h +/home/calvin/src/xpdf-4.04/xpdf/TileMap.h +TileCache.h +/home/calvin/src/xpdf-4.04/xpdf/TileCache.h +TileCompositor.h +/home/calvin/src/xpdf-4.04/xpdf/TileCompositor.h + +/home/calvin/src/xpdf-4.04/xpdf/TileCompositor.h +aconf.h +- +SplashTypes.h +/home/calvin/src/xpdf-4.04/xpdf/SplashTypes.h + +/home/calvin/src/xpdf-4.04/xpdf/TileMap.cc +aconf.h +- +gmem.h +/home/calvin/src/xpdf-4.04/xpdf/gmem.h +gmempp.h +/home/calvin/src/xpdf-4.04/xpdf/gmempp.h +GList.h +/home/calvin/src/xpdf-4.04/xpdf/GList.h +PDFDoc.h +/home/calvin/src/xpdf-4.04/xpdf/PDFDoc.h +DisplayState.h +/home/calvin/src/xpdf-4.04/xpdf/DisplayState.h +TileMap.h +/home/calvin/src/xpdf-4.04/xpdf/TileMap.h + +/home/calvin/src/xpdf-4.04/xpdf/TileMap.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h + +/home/calvin/src/xpdf-4.04/xpdf/UnicodeMap.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +CharTypes.h +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h + +/home/calvin/src/xpdf-4.04/xpdf/UnicodeRemapping.h +aconf.h +- +CharTypes.h +/home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + +/home/calvin/src/xpdf-4.04/xpdf/UnicodeTypeTable.h +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h + +/home/calvin/src/xpdf-4.04/xpdf/XRef.h +aconf.h +- +gtypes.h +/home/calvin/src/xpdf-4.04/xpdf/gtypes.h +gfile.h +/home/calvin/src/xpdf-4.04/xpdf/gfile.h +Object.h +/home/calvin/src/xpdf-4.04/xpdf/Object.h +GMutex.h +/home/calvin/src/xpdf-4.04/xpdf/GMutex.h + +/home/calvin/src/xpdf-4.04/xpdf/config.h + +aconf.h +aconf2.h +- + +aconf2.h +AvailabilityMacros.h +- + +fofi/FoFiBase.h +aconf.h +- +gtypes.h +fofi/gtypes.h + +fofi/FoFiTrueType.h +aconf.h +- +gtypes.h +fofi/gtypes.h +FoFiBase.h +fofi/FoFiBase.h + +fofi/FoFiType1C.h +aconf.h +- +gtypes.h +fofi/gtypes.h +FoFiBase.h +fofi/FoFiBase.h + +goo/FixedPoint.h +aconf.h +- +stdio.h +- +stdlib.h +- +gtypes.h +goo/gtypes.h + +goo/GHash.h +aconf.h +- +gtypes.h +goo/gtypes.h + +goo/GList.h +aconf.h +- +gtypes.h +goo/gtypes.h + +goo/GMutex.h +aconf.h +- +windows.h +- +intrin.h +- +pthread.h +- + +goo/GString.h +aconf.h +- +limits.h +- +stdarg.h +- +gtypes.h +goo/gtypes.h + +goo/Trace.h +aconf.h +- + +goo/gfile.h +aconf.h +- +stdio.h +- +stdlib.h +- +stddef.h +- +sys/stat.h +- +win32lib.h +- +windows.h +- +unistd.h +- +sys/types.h +- +gtypes.h +goo/gtypes.h + +goo/gmem.h +stdio.h +- +aconf.h +- + +goo/gmempp.h +stdlib.h +- + +goo/gtypes.h + +splash/Splash.h +aconf.h +- +SplashTypes.h +splash/SplashTypes.h +SplashClip.h +splash/SplashClip.h + +splash/SplashBitmap.h +aconf.h +- +stdio.h +- +limits.h +- +stdint.h +- +SplashTypes.h +splash/SplashTypes.h + +splash/SplashClip.h +aconf.h +- +SplashTypes.h +splash/SplashTypes.h +SplashMath.h +splash/SplashMath.h + +splash/SplashErrorCodes.h +aconf.h +- + +splash/SplashFont.h +aconf.h +- +gtypes.h +splash/gtypes.h +SplashTypes.h +splash/SplashTypes.h +SplashMath.h +splash/SplashMath.h + +splash/SplashFontEngine.h +aconf.h +- +gtypes.h +splash/gtypes.h + +splash/SplashFontFile.h +aconf.h +- +gtypes.h +splash/gtypes.h +SplashTypes.h +splash/SplashTypes.h +GMutex.h +splash/GMutex.h + +splash/SplashFontFileID.h +aconf.h +- +gtypes.h +splash/gtypes.h + +splash/SplashGlyphBitmap.h +aconf.h +- +gtypes.h +splash/gtypes.h + +splash/SplashMath.h +aconf.h +- +FixedPoint.h +splash/FixedPoint.h +math.h +- +emmintrin.h +- +SplashTypes.h +splash/SplashTypes.h + +splash/SplashPath.h +aconf.h +- +SplashTypes.h +splash/SplashTypes.h + +splash/SplashPattern.h +aconf.h +- +SplashTypes.h +splash/SplashTypes.h + +splash/SplashScreen.h +aconf.h +- +SplashTypes.h +splash/SplashTypes.h + +splash/SplashState.h +aconf.h +- +SplashTypes.h +splash/SplashTypes.h + +splash/SplashTypes.h +aconf.h +- +gtypes.h +splash/gtypes.h +FixedPoint.h +splash/FixedPoint.h + diff --git a/xpdf/CMakeFiles/xpdf_widget_objs.dir/DependInfo.cmake b/xpdf/CMakeFiles/xpdf_widget_objs.dir/DependInfo.cmake new file mode 100644 index 0000000..606dff0 --- /dev/null +++ b/xpdf/CMakeFiles/xpdf_widget_objs.dir/DependInfo.cmake @@ -0,0 +1,33 @@ +# The set of languages for which implicit dependencies are needed: +set(CMAKE_DEPENDS_LANGUAGES + "CXX" + ) +# The set of files for implicit dependencies of each language: +set(CMAKE_DEPENDS_CHECK_CXX + "/home/calvin/src/xpdf-4.04/xpdf/DisplayState.cc" "/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_widget_objs.dir/DisplayState.cc.o" + "/home/calvin/src/xpdf-4.04/xpdf/PDFCore.cc" "/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_widget_objs.dir/PDFCore.cc.o" + "/home/calvin/src/xpdf-4.04/xpdf/PSOutputDev.cc" "/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_widget_objs.dir/PSOutputDev.cc.o" + "/home/calvin/src/xpdf-4.04/xpdf/PreScanOutputDev.cc" "/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_widget_objs.dir/PreScanOutputDev.cc.o" + "/home/calvin/src/xpdf-4.04/xpdf/ShadingImage.cc" "/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_widget_objs.dir/ShadingImage.cc.o" + "/home/calvin/src/xpdf-4.04/xpdf/SplashOutputDev.cc" "/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_widget_objs.dir/SplashOutputDev.cc.o" + "/home/calvin/src/xpdf-4.04/xpdf/TextOutputDev.cc" "/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_widget_objs.dir/TextOutputDev.cc.o" + "/home/calvin/src/xpdf-4.04/xpdf/TileCache.cc" "/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCache.cc.o" + "/home/calvin/src/xpdf-4.04/xpdf/TileCompositor.cc" "/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCompositor.cc.o" + "/home/calvin/src/xpdf-4.04/xpdf/TileMap.cc" "/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_widget_objs.dir/TileMap.cc.o" + ) +set(CMAKE_CXX_COMPILER_ID "GNU") + +# The include file search paths: +set(CMAKE_CXX_TARGET_INCLUDE_PATH + "." + "goo" + "fofi" + "splash" + ) + +# Targets to which this target links. +set(CMAKE_TARGET_LINKED_INFO_FILES + ) + +# Fortran module output directory. +set(CMAKE_Fortran_TARGET_MODULE_DIR "") diff --git a/xpdf/CMakeFiles/xpdf_widget_objs.dir/DisplayState.cc.o b/xpdf/CMakeFiles/xpdf_widget_objs.dir/DisplayState.cc.o new file mode 100644 index 0000000..44bdcc2 Binary files /dev/null and b/xpdf/CMakeFiles/xpdf_widget_objs.dir/DisplayState.cc.o differ diff --git a/xpdf/CMakeFiles/xpdf_widget_objs.dir/PDFCore.cc.o b/xpdf/CMakeFiles/xpdf_widget_objs.dir/PDFCore.cc.o new file mode 100644 index 0000000..c92353c Binary files /dev/null and b/xpdf/CMakeFiles/xpdf_widget_objs.dir/PDFCore.cc.o differ diff --git a/xpdf/CMakeFiles/xpdf_widget_objs.dir/PSOutputDev.cc.o b/xpdf/CMakeFiles/xpdf_widget_objs.dir/PSOutputDev.cc.o new file mode 100644 index 0000000..d720413 Binary files /dev/null and b/xpdf/CMakeFiles/xpdf_widget_objs.dir/PSOutputDev.cc.o differ diff --git a/xpdf/CMakeFiles/xpdf_widget_objs.dir/PreScanOutputDev.cc.o b/xpdf/CMakeFiles/xpdf_widget_objs.dir/PreScanOutputDev.cc.o new file mode 100644 index 0000000..fb5c669 Binary files /dev/null and b/xpdf/CMakeFiles/xpdf_widget_objs.dir/PreScanOutputDev.cc.o differ diff --git a/xpdf/CMakeFiles/xpdf_widget_objs.dir/ShadingImage.cc.o b/xpdf/CMakeFiles/xpdf_widget_objs.dir/ShadingImage.cc.o new file mode 100644 index 0000000..6a417fb Binary files /dev/null and b/xpdf/CMakeFiles/xpdf_widget_objs.dir/ShadingImage.cc.o differ diff --git a/xpdf/CMakeFiles/xpdf_widget_objs.dir/SplashOutputDev.cc.o b/xpdf/CMakeFiles/xpdf_widget_objs.dir/SplashOutputDev.cc.o new file mode 100644 index 0000000..61f53f3 Binary files /dev/null and b/xpdf/CMakeFiles/xpdf_widget_objs.dir/SplashOutputDev.cc.o differ diff --git a/xpdf/CMakeFiles/xpdf_widget_objs.dir/TextOutputDev.cc.o b/xpdf/CMakeFiles/xpdf_widget_objs.dir/TextOutputDev.cc.o new file mode 100644 index 0000000..f49f60f Binary files /dev/null and b/xpdf/CMakeFiles/xpdf_widget_objs.dir/TextOutputDev.cc.o differ diff --git a/xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCache.cc.o b/xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCache.cc.o new file mode 100644 index 0000000..6372783 Binary files /dev/null and b/xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCache.cc.o differ diff --git a/xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCompositor.cc.o b/xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCompositor.cc.o new file mode 100644 index 0000000..5125bc1 Binary files /dev/null and b/xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCompositor.cc.o differ diff --git a/xpdf/CMakeFiles/xpdf_widget_objs.dir/TileMap.cc.o b/xpdf/CMakeFiles/xpdf_widget_objs.dir/TileMap.cc.o new file mode 100644 index 0000000..6b97958 Binary files /dev/null and b/xpdf/CMakeFiles/xpdf_widget_objs.dir/TileMap.cc.o differ diff --git a/xpdf/CMakeFiles/xpdf_widget_objs.dir/build.make b/xpdf/CMakeFiles/xpdf_widget_objs.dir/build.make new file mode 100644 index 0000000..669378a --- /dev/null +++ b/xpdf/CMakeFiles/xpdf_widget_objs.dir/build.make @@ -0,0 +1,235 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +# Delete rule output on recipe failure. +.DELETE_ON_ERROR: + + +#============================================================================= +# Special targets provided by cmake. + +# Disable implicit rules so canonical targets will work. +.SUFFIXES: + + +# Disable VCS-based implicit rules. +% : %,v + + +# Disable VCS-based implicit rules. +% : RCS/% + + +# Disable VCS-based implicit rules. +% : RCS/%,v + + +# Disable VCS-based implicit rules. +% : SCCS/s.% + + +# Disable VCS-based implicit rules. +% : s.% + + +.SUFFIXES: .hpux_make_needs_suffix_list + + +# Command-line flag to silence nested $(MAKE). +$(VERBOSE)MAKESILENT = -s + +#Suppress display of executed commands. +$(VERBOSE).SILENT: + +# A target that is always out of date. +cmake_force: + +.PHONY : cmake_force + +#============================================================================= +# Set environment variables for the build. + +# The shell in which to execute make rules. +SHELL = /bin/sh + +# The CMake executable. +CMAKE_COMMAND = /usr/bin/cmake + +# The command to remove a file. +RM = /usr/bin/cmake -E rm -f + +# Escaping for special characters. +EQUALS = = + +# The top-level source directory on which CMake was run. +CMAKE_SOURCE_DIR = /home/calvin/src/xpdf-4.04 + +# The top-level build directory on which CMake was run. +CMAKE_BINARY_DIR = /home/calvin/src/xpdf-4.04 + +# Include any dependencies generated for this target. +include xpdf/CMakeFiles/xpdf_widget_objs.dir/depend.make + +# Include the progress variables for this target. +include xpdf/CMakeFiles/xpdf_widget_objs.dir/progress.make + +# Include the compile flags for this target's objects. +include xpdf/CMakeFiles/xpdf_widget_objs.dir/flags.make + +xpdf/CMakeFiles/xpdf_widget_objs.dir/DisplayState.cc.o: xpdf/CMakeFiles/xpdf_widget_objs.dir/flags.make +xpdf/CMakeFiles/xpdf_widget_objs.dir/DisplayState.cc.o: xpdf/DisplayState.cc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_1) "Building CXX object xpdf/CMakeFiles/xpdf_widget_objs.dir/DisplayState.cc.o" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/xpdf_widget_objs.dir/DisplayState.cc.o -c /home/calvin/src/xpdf-4.04/xpdf/DisplayState.cc + +xpdf/CMakeFiles/xpdf_widget_objs.dir/DisplayState.cc.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/xpdf_widget_objs.dir/DisplayState.cc.i" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf/DisplayState.cc > CMakeFiles/xpdf_widget_objs.dir/DisplayState.cc.i + +xpdf/CMakeFiles/xpdf_widget_objs.dir/DisplayState.cc.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/xpdf_widget_objs.dir/DisplayState.cc.s" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf/DisplayState.cc -o CMakeFiles/xpdf_widget_objs.dir/DisplayState.cc.s + +xpdf/CMakeFiles/xpdf_widget_objs.dir/PDFCore.cc.o: xpdf/CMakeFiles/xpdf_widget_objs.dir/flags.make +xpdf/CMakeFiles/xpdf_widget_objs.dir/PDFCore.cc.o: xpdf/PDFCore.cc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_2) "Building CXX object xpdf/CMakeFiles/xpdf_widget_objs.dir/PDFCore.cc.o" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/xpdf_widget_objs.dir/PDFCore.cc.o -c /home/calvin/src/xpdf-4.04/xpdf/PDFCore.cc + +xpdf/CMakeFiles/xpdf_widget_objs.dir/PDFCore.cc.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/xpdf_widget_objs.dir/PDFCore.cc.i" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf/PDFCore.cc > CMakeFiles/xpdf_widget_objs.dir/PDFCore.cc.i + +xpdf/CMakeFiles/xpdf_widget_objs.dir/PDFCore.cc.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/xpdf_widget_objs.dir/PDFCore.cc.s" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf/PDFCore.cc -o CMakeFiles/xpdf_widget_objs.dir/PDFCore.cc.s + +xpdf/CMakeFiles/xpdf_widget_objs.dir/PreScanOutputDev.cc.o: xpdf/CMakeFiles/xpdf_widget_objs.dir/flags.make +xpdf/CMakeFiles/xpdf_widget_objs.dir/PreScanOutputDev.cc.o: xpdf/PreScanOutputDev.cc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_3) "Building CXX object xpdf/CMakeFiles/xpdf_widget_objs.dir/PreScanOutputDev.cc.o" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/xpdf_widget_objs.dir/PreScanOutputDev.cc.o -c /home/calvin/src/xpdf-4.04/xpdf/PreScanOutputDev.cc + +xpdf/CMakeFiles/xpdf_widget_objs.dir/PreScanOutputDev.cc.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/xpdf_widget_objs.dir/PreScanOutputDev.cc.i" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf/PreScanOutputDev.cc > CMakeFiles/xpdf_widget_objs.dir/PreScanOutputDev.cc.i + +xpdf/CMakeFiles/xpdf_widget_objs.dir/PreScanOutputDev.cc.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/xpdf_widget_objs.dir/PreScanOutputDev.cc.s" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf/PreScanOutputDev.cc -o CMakeFiles/xpdf_widget_objs.dir/PreScanOutputDev.cc.s + +xpdf/CMakeFiles/xpdf_widget_objs.dir/PSOutputDev.cc.o: xpdf/CMakeFiles/xpdf_widget_objs.dir/flags.make +xpdf/CMakeFiles/xpdf_widget_objs.dir/PSOutputDev.cc.o: xpdf/PSOutputDev.cc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_4) "Building CXX object xpdf/CMakeFiles/xpdf_widget_objs.dir/PSOutputDev.cc.o" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/xpdf_widget_objs.dir/PSOutputDev.cc.o -c /home/calvin/src/xpdf-4.04/xpdf/PSOutputDev.cc + +xpdf/CMakeFiles/xpdf_widget_objs.dir/PSOutputDev.cc.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/xpdf_widget_objs.dir/PSOutputDev.cc.i" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf/PSOutputDev.cc > CMakeFiles/xpdf_widget_objs.dir/PSOutputDev.cc.i + +xpdf/CMakeFiles/xpdf_widget_objs.dir/PSOutputDev.cc.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/xpdf_widget_objs.dir/PSOutputDev.cc.s" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf/PSOutputDev.cc -o CMakeFiles/xpdf_widget_objs.dir/PSOutputDev.cc.s + +xpdf/CMakeFiles/xpdf_widget_objs.dir/ShadingImage.cc.o: xpdf/CMakeFiles/xpdf_widget_objs.dir/flags.make +xpdf/CMakeFiles/xpdf_widget_objs.dir/ShadingImage.cc.o: xpdf/ShadingImage.cc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_5) "Building CXX object xpdf/CMakeFiles/xpdf_widget_objs.dir/ShadingImage.cc.o" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/xpdf_widget_objs.dir/ShadingImage.cc.o -c /home/calvin/src/xpdf-4.04/xpdf/ShadingImage.cc + +xpdf/CMakeFiles/xpdf_widget_objs.dir/ShadingImage.cc.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/xpdf_widget_objs.dir/ShadingImage.cc.i" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf/ShadingImage.cc > CMakeFiles/xpdf_widget_objs.dir/ShadingImage.cc.i + +xpdf/CMakeFiles/xpdf_widget_objs.dir/ShadingImage.cc.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/xpdf_widget_objs.dir/ShadingImage.cc.s" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf/ShadingImage.cc -o CMakeFiles/xpdf_widget_objs.dir/ShadingImage.cc.s + +xpdf/CMakeFiles/xpdf_widget_objs.dir/SplashOutputDev.cc.o: xpdf/CMakeFiles/xpdf_widget_objs.dir/flags.make +xpdf/CMakeFiles/xpdf_widget_objs.dir/SplashOutputDev.cc.o: xpdf/SplashOutputDev.cc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_6) "Building CXX object xpdf/CMakeFiles/xpdf_widget_objs.dir/SplashOutputDev.cc.o" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/xpdf_widget_objs.dir/SplashOutputDev.cc.o -c /home/calvin/src/xpdf-4.04/xpdf/SplashOutputDev.cc + +xpdf/CMakeFiles/xpdf_widget_objs.dir/SplashOutputDev.cc.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/xpdf_widget_objs.dir/SplashOutputDev.cc.i" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf/SplashOutputDev.cc > CMakeFiles/xpdf_widget_objs.dir/SplashOutputDev.cc.i + +xpdf/CMakeFiles/xpdf_widget_objs.dir/SplashOutputDev.cc.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/xpdf_widget_objs.dir/SplashOutputDev.cc.s" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf/SplashOutputDev.cc -o CMakeFiles/xpdf_widget_objs.dir/SplashOutputDev.cc.s + +xpdf/CMakeFiles/xpdf_widget_objs.dir/TextOutputDev.cc.o: xpdf/CMakeFiles/xpdf_widget_objs.dir/flags.make +xpdf/CMakeFiles/xpdf_widget_objs.dir/TextOutputDev.cc.o: xpdf/TextOutputDev.cc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_7) "Building CXX object xpdf/CMakeFiles/xpdf_widget_objs.dir/TextOutputDev.cc.o" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/xpdf_widget_objs.dir/TextOutputDev.cc.o -c /home/calvin/src/xpdf-4.04/xpdf/TextOutputDev.cc + +xpdf/CMakeFiles/xpdf_widget_objs.dir/TextOutputDev.cc.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/xpdf_widget_objs.dir/TextOutputDev.cc.i" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf/TextOutputDev.cc > CMakeFiles/xpdf_widget_objs.dir/TextOutputDev.cc.i + +xpdf/CMakeFiles/xpdf_widget_objs.dir/TextOutputDev.cc.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/xpdf_widget_objs.dir/TextOutputDev.cc.s" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf/TextOutputDev.cc -o CMakeFiles/xpdf_widget_objs.dir/TextOutputDev.cc.s + +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCache.cc.o: xpdf/CMakeFiles/xpdf_widget_objs.dir/flags.make +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCache.cc.o: xpdf/TileCache.cc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_8) "Building CXX object xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCache.cc.o" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/xpdf_widget_objs.dir/TileCache.cc.o -c /home/calvin/src/xpdf-4.04/xpdf/TileCache.cc + +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCache.cc.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/xpdf_widget_objs.dir/TileCache.cc.i" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf/TileCache.cc > CMakeFiles/xpdf_widget_objs.dir/TileCache.cc.i + +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCache.cc.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/xpdf_widget_objs.dir/TileCache.cc.s" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf/TileCache.cc -o CMakeFiles/xpdf_widget_objs.dir/TileCache.cc.s + +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCompositor.cc.o: xpdf/CMakeFiles/xpdf_widget_objs.dir/flags.make +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCompositor.cc.o: xpdf/TileCompositor.cc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_9) "Building CXX object xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCompositor.cc.o" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/xpdf_widget_objs.dir/TileCompositor.cc.o -c /home/calvin/src/xpdf-4.04/xpdf/TileCompositor.cc + +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCompositor.cc.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/xpdf_widget_objs.dir/TileCompositor.cc.i" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf/TileCompositor.cc > CMakeFiles/xpdf_widget_objs.dir/TileCompositor.cc.i + +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCompositor.cc.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/xpdf_widget_objs.dir/TileCompositor.cc.s" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf/TileCompositor.cc -o CMakeFiles/xpdf_widget_objs.dir/TileCompositor.cc.s + +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileMap.cc.o: xpdf/CMakeFiles/xpdf_widget_objs.dir/flags.make +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileMap.cc.o: xpdf/TileMap.cc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_10) "Building CXX object xpdf/CMakeFiles/xpdf_widget_objs.dir/TileMap.cc.o" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/xpdf_widget_objs.dir/TileMap.cc.o -c /home/calvin/src/xpdf-4.04/xpdf/TileMap.cc + +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileMap.cc.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/xpdf_widget_objs.dir/TileMap.cc.i" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf/TileMap.cc > CMakeFiles/xpdf_widget_objs.dir/TileMap.cc.i + +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileMap.cc.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/xpdf_widget_objs.dir/TileMap.cc.s" + cd /home/calvin/src/xpdf-4.04/xpdf && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf/TileMap.cc -o CMakeFiles/xpdf_widget_objs.dir/TileMap.cc.s + +xpdf_widget_objs: xpdf/CMakeFiles/xpdf_widget_objs.dir/DisplayState.cc.o +xpdf_widget_objs: xpdf/CMakeFiles/xpdf_widget_objs.dir/PDFCore.cc.o +xpdf_widget_objs: xpdf/CMakeFiles/xpdf_widget_objs.dir/PreScanOutputDev.cc.o +xpdf_widget_objs: xpdf/CMakeFiles/xpdf_widget_objs.dir/PSOutputDev.cc.o +xpdf_widget_objs: xpdf/CMakeFiles/xpdf_widget_objs.dir/ShadingImage.cc.o +xpdf_widget_objs: xpdf/CMakeFiles/xpdf_widget_objs.dir/SplashOutputDev.cc.o +xpdf_widget_objs: xpdf/CMakeFiles/xpdf_widget_objs.dir/TextOutputDev.cc.o +xpdf_widget_objs: xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCache.cc.o +xpdf_widget_objs: xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCompositor.cc.o +xpdf_widget_objs: xpdf/CMakeFiles/xpdf_widget_objs.dir/TileMap.cc.o +xpdf_widget_objs: xpdf/CMakeFiles/xpdf_widget_objs.dir/build.make + +.PHONY : xpdf_widget_objs + +# Rule to build all files generated by this target. +xpdf/CMakeFiles/xpdf_widget_objs.dir/build: xpdf_widget_objs + +.PHONY : xpdf/CMakeFiles/xpdf_widget_objs.dir/build + +xpdf/CMakeFiles/xpdf_widget_objs.dir/clean: + cd /home/calvin/src/xpdf-4.04/xpdf && $(CMAKE_COMMAND) -P CMakeFiles/xpdf_widget_objs.dir/cmake_clean.cmake +.PHONY : xpdf/CMakeFiles/xpdf_widget_objs.dir/clean + +xpdf/CMakeFiles/xpdf_widget_objs.dir/depend: + cd /home/calvin/src/xpdf-4.04 && $(CMAKE_COMMAND) -E cmake_depends "Unix Makefiles" /home/calvin/src/xpdf-4.04 /home/calvin/src/xpdf-4.04/xpdf /home/calvin/src/xpdf-4.04 /home/calvin/src/xpdf-4.04/xpdf /home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_widget_objs.dir/DependInfo.cmake --color=$(COLOR) +.PHONY : xpdf/CMakeFiles/xpdf_widget_objs.dir/depend + diff --git a/xpdf/CMakeFiles/xpdf_widget_objs.dir/cmake_clean.cmake b/xpdf/CMakeFiles/xpdf_widget_objs.dir/cmake_clean.cmake new file mode 100644 index 0000000..c7b755e --- /dev/null +++ b/xpdf/CMakeFiles/xpdf_widget_objs.dir/cmake_clean.cmake @@ -0,0 +1,17 @@ +file(REMOVE_RECURSE + "CMakeFiles/xpdf_widget_objs.dir/DisplayState.cc.o" + "CMakeFiles/xpdf_widget_objs.dir/PDFCore.cc.o" + "CMakeFiles/xpdf_widget_objs.dir/PSOutputDev.cc.o" + "CMakeFiles/xpdf_widget_objs.dir/PreScanOutputDev.cc.o" + "CMakeFiles/xpdf_widget_objs.dir/ShadingImage.cc.o" + "CMakeFiles/xpdf_widget_objs.dir/SplashOutputDev.cc.o" + "CMakeFiles/xpdf_widget_objs.dir/TextOutputDev.cc.o" + "CMakeFiles/xpdf_widget_objs.dir/TileCache.cc.o" + "CMakeFiles/xpdf_widget_objs.dir/TileCompositor.cc.o" + "CMakeFiles/xpdf_widget_objs.dir/TileMap.cc.o" +) + +# Per-language clean rules from dependency scanning. +foreach(lang CXX) + include(CMakeFiles/xpdf_widget_objs.dir/cmake_clean_${lang}.cmake OPTIONAL) +endforeach() diff --git a/xpdf/CMakeFiles/xpdf_widget_objs.dir/depend.internal b/xpdf/CMakeFiles/xpdf_widget_objs.dir/depend.internal new file mode 100644 index 0000000..5623121 --- /dev/null +++ b/xpdf/CMakeFiles/xpdf_widget_objs.dir/depend.internal @@ -0,0 +1,308 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +xpdf/CMakeFiles/xpdf_widget_objs.dir/DisplayState.cc.o + /home/calvin/src/xpdf-4.04/xpdf/DisplayState.cc + /home/calvin/src/xpdf-4.04/xpdf/DisplayState.h + /home/calvin/src/xpdf-4.04/xpdf/TileCache.h + /home/calvin/src/xpdf-4.04/xpdf/TileCompositor.h + /home/calvin/src/xpdf-4.04/xpdf/TileMap.h + aconf.h + aconf2.h + goo/FixedPoint.h + goo/GList.h + goo/GString.h + goo/gmempp.h + goo/gtypes.h + splash/SplashTypes.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PDFCore.cc.o + /home/calvin/src/xpdf-4.04/xpdf/AcroForm.h + /home/calvin/src/xpdf-4.04/xpdf/Annot.h + /home/calvin/src/xpdf-4.04/xpdf/Array.h + /home/calvin/src/xpdf-4.04/xpdf/Catalog.h + /home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + /home/calvin/src/xpdf-4.04/xpdf/Dict.h + /home/calvin/src/xpdf-4.04/xpdf/DisplayState.h + /home/calvin/src/xpdf-4.04/xpdf/Error.h + /home/calvin/src/xpdf-4.04/xpdf/ErrorCodes.h + /home/calvin/src/xpdf-4.04/xpdf/GfxFont.h + /home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h + /home/calvin/src/xpdf-4.04/xpdf/Link.h + /home/calvin/src/xpdf-4.04/xpdf/Object.h + /home/calvin/src/xpdf-4.04/xpdf/OptionalContent.h + /home/calvin/src/xpdf-4.04/xpdf/OutputDev.h + /home/calvin/src/xpdf-4.04/xpdf/PDFCore.cc + /home/calvin/src/xpdf-4.04/xpdf/PDFCore.h + /home/calvin/src/xpdf-4.04/xpdf/PDFDoc.h + /home/calvin/src/xpdf-4.04/xpdf/Page.h + /home/calvin/src/xpdf-4.04/xpdf/Stream.h + /home/calvin/src/xpdf-4.04/xpdf/TextOutputDev.h + /home/calvin/src/xpdf-4.04/xpdf/TileCache.h + /home/calvin/src/xpdf-4.04/xpdf/TileCompositor.h + /home/calvin/src/xpdf-4.04/xpdf/TileMap.h + /home/calvin/src/xpdf-4.04/xpdf/XRef.h + /home/calvin/src/xpdf-4.04/xpdf/config.h + aconf.h + aconf2.h + goo/FixedPoint.h + goo/GList.h + goo/GMutex.h + goo/GString.h + goo/gfile.h + goo/gmem.h + goo/gmempp.h + goo/gtypes.h + splash/Splash.h + splash/SplashBitmap.h + splash/SplashClip.h + splash/SplashMath.h + splash/SplashPath.h + splash/SplashPattern.h + splash/SplashTypes.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PSOutputDev.cc.o + /home/calvin/src/xpdf-4.04/xpdf/AcroForm.h + /home/calvin/src/xpdf-4.04/xpdf/Annot.h + /home/calvin/src/xpdf-4.04/xpdf/Array.h + /home/calvin/src/xpdf-4.04/xpdf/Catalog.h + /home/calvin/src/xpdf-4.04/xpdf/CharCodeToUnicode.h + /home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + /home/calvin/src/xpdf-4.04/xpdf/Dict.h + /home/calvin/src/xpdf-4.04/xpdf/Error.h + /home/calvin/src/xpdf-4.04/xpdf/Function.h + /home/calvin/src/xpdf-4.04/xpdf/Gfx.h + /home/calvin/src/xpdf-4.04/xpdf/GfxFont.h + /home/calvin/src/xpdf-4.04/xpdf/GfxState.h + /home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h + /home/calvin/src/xpdf-4.04/xpdf/Object.h + /home/calvin/src/xpdf-4.04/xpdf/OutputDev.h + /home/calvin/src/xpdf-4.04/xpdf/PDFDoc.h + /home/calvin/src/xpdf-4.04/xpdf/PSOutputDev.cc + /home/calvin/src/xpdf-4.04/xpdf/PSOutputDev.h + /home/calvin/src/xpdf-4.04/xpdf/Page.h + /home/calvin/src/xpdf-4.04/xpdf/PreScanOutputDev.h + /home/calvin/src/xpdf-4.04/xpdf/SplashOutputDev.h + /home/calvin/src/xpdf-4.04/xpdf/Stream.h + /home/calvin/src/xpdf-4.04/xpdf/TextString.h + /home/calvin/src/xpdf-4.04/xpdf/UnicodeMap.h + /home/calvin/src/xpdf-4.04/xpdf/XRef.h + /home/calvin/src/xpdf-4.04/xpdf/config.h + aconf.h + aconf2.h + fofi/FoFiBase.h + fofi/FoFiTrueType.h + fofi/FoFiType1C.h + goo/FixedPoint.h + goo/GHash.h + goo/GList.h + goo/GMutex.h + goo/GString.h + goo/gfile.h + goo/gmem.h + goo/gmempp.h + goo/gtypes.h + splash/Splash.h + splash/SplashBitmap.h + splash/SplashClip.h + splash/SplashMath.h + splash/SplashTypes.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PreScanOutputDev.cc.o + /home/calvin/src/xpdf-4.04/xpdf/Array.h + /home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + /home/calvin/src/xpdf-4.04/xpdf/Dict.h + /home/calvin/src/xpdf-4.04/xpdf/Function.h + /home/calvin/src/xpdf-4.04/xpdf/Gfx.h + /home/calvin/src/xpdf-4.04/xpdf/GfxFont.h + /home/calvin/src/xpdf-4.04/xpdf/GfxState.h + /home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h + /home/calvin/src/xpdf-4.04/xpdf/Link.h + /home/calvin/src/xpdf-4.04/xpdf/Object.h + /home/calvin/src/xpdf-4.04/xpdf/OutputDev.h + /home/calvin/src/xpdf-4.04/xpdf/Page.h + /home/calvin/src/xpdf-4.04/xpdf/PreScanOutputDev.cc + /home/calvin/src/xpdf-4.04/xpdf/PreScanOutputDev.h + /home/calvin/src/xpdf-4.04/xpdf/Stream.h + aconf.h + aconf2.h + goo/GMutex.h + goo/GString.h + goo/gfile.h + goo/gmem.h + goo/gmempp.h + goo/gtypes.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/ShadingImage.cc.o + /home/calvin/src/xpdf-4.04/xpdf/Array.h + /home/calvin/src/xpdf-4.04/xpdf/Dict.h + /home/calvin/src/xpdf-4.04/xpdf/Function.h + /home/calvin/src/xpdf-4.04/xpdf/GfxState.h + /home/calvin/src/xpdf-4.04/xpdf/Object.h + /home/calvin/src/xpdf-4.04/xpdf/ShadingImage.cc + /home/calvin/src/xpdf-4.04/xpdf/ShadingImage.h + /home/calvin/src/xpdf-4.04/xpdf/Stream.h + aconf.h + aconf2.h + goo/FixedPoint.h + goo/GMutex.h + goo/GString.h + goo/Trace.h + goo/gfile.h + goo/gmem.h + goo/gtypes.h + splash/Splash.h + splash/SplashBitmap.h + splash/SplashClip.h + splash/SplashMath.h + splash/SplashPath.h + splash/SplashPattern.h + splash/SplashTypes.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/SplashOutputDev.cc.o + /home/calvin/src/xpdf-4.04/xpdf/Array.h + /home/calvin/src/xpdf-4.04/xpdf/BuiltinFont.h + /home/calvin/src/xpdf-4.04/xpdf/BuiltinFontTables.h + /home/calvin/src/xpdf-4.04/xpdf/CharCodeToUnicode.h + /home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + /home/calvin/src/xpdf-4.04/xpdf/Dict.h + /home/calvin/src/xpdf-4.04/xpdf/Error.h + /home/calvin/src/xpdf-4.04/xpdf/FontEncodingTables.h + /home/calvin/src/xpdf-4.04/xpdf/Function.h + /home/calvin/src/xpdf-4.04/xpdf/Gfx.h + /home/calvin/src/xpdf-4.04/xpdf/GfxFont.h + /home/calvin/src/xpdf-4.04/xpdf/GfxState.h + /home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h + /home/calvin/src/xpdf-4.04/xpdf/JPXStream.h + /home/calvin/src/xpdf-4.04/xpdf/Link.h + /home/calvin/src/xpdf-4.04/xpdf/Object.h + /home/calvin/src/xpdf-4.04/xpdf/OutputDev.h + /home/calvin/src/xpdf-4.04/xpdf/ShadingImage.h + /home/calvin/src/xpdf-4.04/xpdf/SplashOutputDev.cc + /home/calvin/src/xpdf-4.04/xpdf/SplashOutputDev.h + /home/calvin/src/xpdf-4.04/xpdf/Stream.h + /home/calvin/src/xpdf-4.04/xpdf/config.h + aconf.h + aconf2.h + fofi/FoFiBase.h + fofi/FoFiTrueType.h + fofi/FoFiType1C.h + goo/FixedPoint.h + goo/GMutex.h + goo/GString.h + goo/Trace.h + goo/gfile.h + goo/gmem.h + goo/gmempp.h + goo/gtypes.h + splash/Splash.h + splash/SplashBitmap.h + splash/SplashClip.h + splash/SplashErrorCodes.h + splash/SplashFont.h + splash/SplashFontEngine.h + splash/SplashFontFile.h + splash/SplashFontFileID.h + splash/SplashGlyphBitmap.h + splash/SplashMath.h + splash/SplashPath.h + splash/SplashPattern.h + splash/SplashScreen.h + splash/SplashState.h + splash/SplashTypes.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TextOutputDev.cc.o + /home/calvin/src/xpdf-4.04/xpdf/Array.h + /home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + /home/calvin/src/xpdf-4.04/xpdf/Dict.h + /home/calvin/src/xpdf-4.04/xpdf/Error.h + /home/calvin/src/xpdf-4.04/xpdf/Function.h + /home/calvin/src/xpdf-4.04/xpdf/GfxFont.h + /home/calvin/src/xpdf-4.04/xpdf/GfxState.h + /home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h + /home/calvin/src/xpdf-4.04/xpdf/Link.h + /home/calvin/src/xpdf-4.04/xpdf/Object.h + /home/calvin/src/xpdf-4.04/xpdf/OutputDev.h + /home/calvin/src/xpdf-4.04/xpdf/Stream.h + /home/calvin/src/xpdf-4.04/xpdf/TextOutputDev.cc + /home/calvin/src/xpdf-4.04/xpdf/TextOutputDev.h + /home/calvin/src/xpdf-4.04/xpdf/UnicodeMap.h + /home/calvin/src/xpdf-4.04/xpdf/UnicodeRemapping.h + /home/calvin/src/xpdf-4.04/xpdf/UnicodeTypeTable.h + /home/calvin/src/xpdf-4.04/xpdf/config.h + aconf.h + aconf2.h + goo/GList.h + goo/GMutex.h + goo/GString.h + goo/gfile.h + goo/gmem.h + goo/gmempp.h + goo/gtypes.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCache.cc.o + /home/calvin/src/xpdf-4.04/xpdf/Array.h + /home/calvin/src/xpdf-4.04/xpdf/Catalog.h + /home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + /home/calvin/src/xpdf-4.04/xpdf/Dict.h + /home/calvin/src/xpdf-4.04/xpdf/DisplayState.h + /home/calvin/src/xpdf-4.04/xpdf/Function.h + /home/calvin/src/xpdf-4.04/xpdf/GfxState.h + /home/calvin/src/xpdf-4.04/xpdf/Object.h + /home/calvin/src/xpdf-4.04/xpdf/OutputDev.h + /home/calvin/src/xpdf-4.04/xpdf/PDFDoc.h + /home/calvin/src/xpdf-4.04/xpdf/Page.h + /home/calvin/src/xpdf-4.04/xpdf/SplashOutputDev.h + /home/calvin/src/xpdf-4.04/xpdf/Stream.h + /home/calvin/src/xpdf-4.04/xpdf/TileCache.cc + /home/calvin/src/xpdf-4.04/xpdf/TileCache.h + /home/calvin/src/xpdf-4.04/xpdf/TileMap.h + /home/calvin/src/xpdf-4.04/xpdf/XRef.h + /home/calvin/src/xpdf-4.04/xpdf/config.h + aconf.h + aconf2.h + goo/FixedPoint.h + goo/GList.h + goo/GMutex.h + goo/GString.h + goo/gfile.h + goo/gmem.h + goo/gmempp.h + goo/gtypes.h + splash/SplashBitmap.h + splash/SplashTypes.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCompositor.cc.o + /home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + /home/calvin/src/xpdf-4.04/xpdf/DisplayState.h + /home/calvin/src/xpdf-4.04/xpdf/GlobalParams.h + /home/calvin/src/xpdf-4.04/xpdf/TileCache.h + /home/calvin/src/xpdf-4.04/xpdf/TileCompositor.cc + /home/calvin/src/xpdf-4.04/xpdf/TileCompositor.h + /home/calvin/src/xpdf-4.04/xpdf/TileMap.h + aconf.h + aconf2.h + goo/FixedPoint.h + goo/GList.h + goo/GMutex.h + goo/GString.h + goo/gmempp.h + goo/gtypes.h + splash/SplashBitmap.h + splash/SplashTypes.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileMap.cc.o + /home/calvin/src/xpdf-4.04/xpdf/Array.h + /home/calvin/src/xpdf-4.04/xpdf/Catalog.h + /home/calvin/src/xpdf-4.04/xpdf/CharTypes.h + /home/calvin/src/xpdf-4.04/xpdf/Dict.h + /home/calvin/src/xpdf-4.04/xpdf/DisplayState.h + /home/calvin/src/xpdf-4.04/xpdf/Object.h + /home/calvin/src/xpdf-4.04/xpdf/PDFDoc.h + /home/calvin/src/xpdf-4.04/xpdf/Page.h + /home/calvin/src/xpdf-4.04/xpdf/Stream.h + /home/calvin/src/xpdf-4.04/xpdf/TileMap.cc + /home/calvin/src/xpdf-4.04/xpdf/TileMap.h + /home/calvin/src/xpdf-4.04/xpdf/XRef.h + aconf.h + aconf2.h + goo/FixedPoint.h + goo/GList.h + goo/GMutex.h + goo/GString.h + goo/gfile.h + goo/gmem.h + goo/gmempp.h + goo/gtypes.h + splash/SplashTypes.h diff --git a/xpdf/CMakeFiles/xpdf_widget_objs.dir/depend.make b/xpdf/CMakeFiles/xpdf_widget_objs.dir/depend.make new file mode 100644 index 0000000..7b5c449 --- /dev/null +++ b/xpdf/CMakeFiles/xpdf_widget_objs.dir/depend.make @@ -0,0 +1,308 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +xpdf/CMakeFiles/xpdf_widget_objs.dir/DisplayState.cc.o: xpdf/DisplayState.cc +xpdf/CMakeFiles/xpdf_widget_objs.dir/DisplayState.cc.o: xpdf/DisplayState.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/DisplayState.cc.o: xpdf/TileCache.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/DisplayState.cc.o: xpdf/TileCompositor.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/DisplayState.cc.o: xpdf/TileMap.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/DisplayState.cc.o: aconf.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/DisplayState.cc.o: aconf2.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/DisplayState.cc.o: goo/FixedPoint.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/DisplayState.cc.o: goo/GList.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/DisplayState.cc.o: goo/GString.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/DisplayState.cc.o: goo/gmempp.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/DisplayState.cc.o: goo/gtypes.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/DisplayState.cc.o: splash/SplashTypes.h + +xpdf/CMakeFiles/xpdf_widget_objs.dir/PDFCore.cc.o: xpdf/AcroForm.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PDFCore.cc.o: xpdf/Annot.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PDFCore.cc.o: xpdf/Array.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PDFCore.cc.o: xpdf/Catalog.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PDFCore.cc.o: xpdf/CharTypes.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PDFCore.cc.o: xpdf/Dict.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PDFCore.cc.o: xpdf/DisplayState.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PDFCore.cc.o: xpdf/Error.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PDFCore.cc.o: xpdf/ErrorCodes.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PDFCore.cc.o: xpdf/GfxFont.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PDFCore.cc.o: xpdf/GlobalParams.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PDFCore.cc.o: xpdf/Link.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PDFCore.cc.o: xpdf/Object.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PDFCore.cc.o: xpdf/OptionalContent.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PDFCore.cc.o: xpdf/OutputDev.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PDFCore.cc.o: xpdf/PDFCore.cc +xpdf/CMakeFiles/xpdf_widget_objs.dir/PDFCore.cc.o: xpdf/PDFCore.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PDFCore.cc.o: xpdf/PDFDoc.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PDFCore.cc.o: xpdf/Page.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PDFCore.cc.o: xpdf/Stream.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PDFCore.cc.o: xpdf/TextOutputDev.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PDFCore.cc.o: xpdf/TileCache.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PDFCore.cc.o: xpdf/TileCompositor.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PDFCore.cc.o: xpdf/TileMap.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PDFCore.cc.o: xpdf/XRef.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PDFCore.cc.o: xpdf/config.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PDFCore.cc.o: aconf.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PDFCore.cc.o: aconf2.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PDFCore.cc.o: goo/FixedPoint.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PDFCore.cc.o: goo/GList.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PDFCore.cc.o: goo/GMutex.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PDFCore.cc.o: goo/GString.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PDFCore.cc.o: goo/gfile.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PDFCore.cc.o: goo/gmem.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PDFCore.cc.o: goo/gmempp.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PDFCore.cc.o: goo/gtypes.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PDFCore.cc.o: splash/Splash.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PDFCore.cc.o: splash/SplashBitmap.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PDFCore.cc.o: splash/SplashClip.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PDFCore.cc.o: splash/SplashMath.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PDFCore.cc.o: splash/SplashPath.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PDFCore.cc.o: splash/SplashPattern.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PDFCore.cc.o: splash/SplashTypes.h + +xpdf/CMakeFiles/xpdf_widget_objs.dir/PSOutputDev.cc.o: xpdf/AcroForm.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PSOutputDev.cc.o: xpdf/Annot.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PSOutputDev.cc.o: xpdf/Array.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PSOutputDev.cc.o: xpdf/Catalog.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PSOutputDev.cc.o: xpdf/CharCodeToUnicode.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PSOutputDev.cc.o: xpdf/CharTypes.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PSOutputDev.cc.o: xpdf/Dict.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PSOutputDev.cc.o: xpdf/Error.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PSOutputDev.cc.o: xpdf/Function.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PSOutputDev.cc.o: xpdf/Gfx.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PSOutputDev.cc.o: xpdf/GfxFont.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PSOutputDev.cc.o: xpdf/GfxState.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PSOutputDev.cc.o: xpdf/GlobalParams.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PSOutputDev.cc.o: xpdf/Object.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PSOutputDev.cc.o: xpdf/OutputDev.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PSOutputDev.cc.o: xpdf/PDFDoc.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PSOutputDev.cc.o: xpdf/PSOutputDev.cc +xpdf/CMakeFiles/xpdf_widget_objs.dir/PSOutputDev.cc.o: xpdf/PSOutputDev.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PSOutputDev.cc.o: xpdf/Page.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PSOutputDev.cc.o: xpdf/PreScanOutputDev.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PSOutputDev.cc.o: xpdf/SplashOutputDev.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PSOutputDev.cc.o: xpdf/Stream.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PSOutputDev.cc.o: xpdf/TextString.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PSOutputDev.cc.o: xpdf/UnicodeMap.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PSOutputDev.cc.o: xpdf/XRef.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PSOutputDev.cc.o: xpdf/config.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PSOutputDev.cc.o: aconf.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PSOutputDev.cc.o: aconf2.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PSOutputDev.cc.o: fofi/FoFiBase.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PSOutputDev.cc.o: fofi/FoFiTrueType.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PSOutputDev.cc.o: fofi/FoFiType1C.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PSOutputDev.cc.o: goo/FixedPoint.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PSOutputDev.cc.o: goo/GHash.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PSOutputDev.cc.o: goo/GList.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PSOutputDev.cc.o: goo/GMutex.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PSOutputDev.cc.o: goo/GString.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PSOutputDev.cc.o: goo/gfile.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PSOutputDev.cc.o: goo/gmem.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PSOutputDev.cc.o: goo/gmempp.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PSOutputDev.cc.o: goo/gtypes.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PSOutputDev.cc.o: splash/Splash.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PSOutputDev.cc.o: splash/SplashBitmap.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PSOutputDev.cc.o: splash/SplashClip.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PSOutputDev.cc.o: splash/SplashMath.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PSOutputDev.cc.o: splash/SplashTypes.h + +xpdf/CMakeFiles/xpdf_widget_objs.dir/PreScanOutputDev.cc.o: xpdf/Array.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PreScanOutputDev.cc.o: xpdf/CharTypes.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PreScanOutputDev.cc.o: xpdf/Dict.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PreScanOutputDev.cc.o: xpdf/Function.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PreScanOutputDev.cc.o: xpdf/Gfx.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PreScanOutputDev.cc.o: xpdf/GfxFont.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PreScanOutputDev.cc.o: xpdf/GfxState.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PreScanOutputDev.cc.o: xpdf/GlobalParams.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PreScanOutputDev.cc.o: xpdf/Link.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PreScanOutputDev.cc.o: xpdf/Object.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PreScanOutputDev.cc.o: xpdf/OutputDev.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PreScanOutputDev.cc.o: xpdf/Page.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PreScanOutputDev.cc.o: xpdf/PreScanOutputDev.cc +xpdf/CMakeFiles/xpdf_widget_objs.dir/PreScanOutputDev.cc.o: xpdf/PreScanOutputDev.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PreScanOutputDev.cc.o: xpdf/Stream.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PreScanOutputDev.cc.o: aconf.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PreScanOutputDev.cc.o: aconf2.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PreScanOutputDev.cc.o: goo/GMutex.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PreScanOutputDev.cc.o: goo/GString.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PreScanOutputDev.cc.o: goo/gfile.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PreScanOutputDev.cc.o: goo/gmem.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PreScanOutputDev.cc.o: goo/gmempp.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/PreScanOutputDev.cc.o: goo/gtypes.h + +xpdf/CMakeFiles/xpdf_widget_objs.dir/ShadingImage.cc.o: xpdf/Array.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/ShadingImage.cc.o: xpdf/Dict.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/ShadingImage.cc.o: xpdf/Function.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/ShadingImage.cc.o: xpdf/GfxState.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/ShadingImage.cc.o: xpdf/Object.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/ShadingImage.cc.o: xpdf/ShadingImage.cc +xpdf/CMakeFiles/xpdf_widget_objs.dir/ShadingImage.cc.o: xpdf/ShadingImage.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/ShadingImage.cc.o: xpdf/Stream.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/ShadingImage.cc.o: aconf.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/ShadingImage.cc.o: aconf2.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/ShadingImage.cc.o: goo/FixedPoint.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/ShadingImage.cc.o: goo/GMutex.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/ShadingImage.cc.o: goo/GString.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/ShadingImage.cc.o: goo/Trace.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/ShadingImage.cc.o: goo/gfile.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/ShadingImage.cc.o: goo/gmem.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/ShadingImage.cc.o: goo/gtypes.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/ShadingImage.cc.o: splash/Splash.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/ShadingImage.cc.o: splash/SplashBitmap.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/ShadingImage.cc.o: splash/SplashClip.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/ShadingImage.cc.o: splash/SplashMath.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/ShadingImage.cc.o: splash/SplashPath.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/ShadingImage.cc.o: splash/SplashPattern.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/ShadingImage.cc.o: splash/SplashTypes.h + +xpdf/CMakeFiles/xpdf_widget_objs.dir/SplashOutputDev.cc.o: xpdf/Array.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/SplashOutputDev.cc.o: xpdf/BuiltinFont.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/SplashOutputDev.cc.o: xpdf/BuiltinFontTables.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/SplashOutputDev.cc.o: xpdf/CharCodeToUnicode.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/SplashOutputDev.cc.o: xpdf/CharTypes.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/SplashOutputDev.cc.o: xpdf/Dict.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/SplashOutputDev.cc.o: xpdf/Error.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/SplashOutputDev.cc.o: xpdf/FontEncodingTables.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/SplashOutputDev.cc.o: xpdf/Function.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/SplashOutputDev.cc.o: xpdf/Gfx.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/SplashOutputDev.cc.o: xpdf/GfxFont.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/SplashOutputDev.cc.o: xpdf/GfxState.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/SplashOutputDev.cc.o: xpdf/GlobalParams.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/SplashOutputDev.cc.o: xpdf/JPXStream.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/SplashOutputDev.cc.o: xpdf/Link.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/SplashOutputDev.cc.o: xpdf/Object.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/SplashOutputDev.cc.o: xpdf/OutputDev.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/SplashOutputDev.cc.o: xpdf/ShadingImage.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/SplashOutputDev.cc.o: xpdf/SplashOutputDev.cc +xpdf/CMakeFiles/xpdf_widget_objs.dir/SplashOutputDev.cc.o: xpdf/SplashOutputDev.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/SplashOutputDev.cc.o: xpdf/Stream.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/SplashOutputDev.cc.o: xpdf/config.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/SplashOutputDev.cc.o: aconf.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/SplashOutputDev.cc.o: aconf2.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/SplashOutputDev.cc.o: fofi/FoFiBase.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/SplashOutputDev.cc.o: fofi/FoFiTrueType.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/SplashOutputDev.cc.o: fofi/FoFiType1C.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/SplashOutputDev.cc.o: goo/FixedPoint.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/SplashOutputDev.cc.o: goo/GMutex.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/SplashOutputDev.cc.o: goo/GString.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/SplashOutputDev.cc.o: goo/Trace.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/SplashOutputDev.cc.o: goo/gfile.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/SplashOutputDev.cc.o: goo/gmem.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/SplashOutputDev.cc.o: goo/gmempp.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/SplashOutputDev.cc.o: goo/gtypes.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/SplashOutputDev.cc.o: splash/Splash.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/SplashOutputDev.cc.o: splash/SplashBitmap.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/SplashOutputDev.cc.o: splash/SplashClip.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/SplashOutputDev.cc.o: splash/SplashErrorCodes.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/SplashOutputDev.cc.o: splash/SplashFont.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/SplashOutputDev.cc.o: splash/SplashFontEngine.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/SplashOutputDev.cc.o: splash/SplashFontFile.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/SplashOutputDev.cc.o: splash/SplashFontFileID.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/SplashOutputDev.cc.o: splash/SplashGlyphBitmap.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/SplashOutputDev.cc.o: splash/SplashMath.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/SplashOutputDev.cc.o: splash/SplashPath.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/SplashOutputDev.cc.o: splash/SplashPattern.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/SplashOutputDev.cc.o: splash/SplashScreen.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/SplashOutputDev.cc.o: splash/SplashState.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/SplashOutputDev.cc.o: splash/SplashTypes.h + +xpdf/CMakeFiles/xpdf_widget_objs.dir/TextOutputDev.cc.o: xpdf/Array.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TextOutputDev.cc.o: xpdf/CharTypes.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TextOutputDev.cc.o: xpdf/Dict.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TextOutputDev.cc.o: xpdf/Error.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TextOutputDev.cc.o: xpdf/Function.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TextOutputDev.cc.o: xpdf/GfxFont.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TextOutputDev.cc.o: xpdf/GfxState.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TextOutputDev.cc.o: xpdf/GlobalParams.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TextOutputDev.cc.o: xpdf/Link.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TextOutputDev.cc.o: xpdf/Object.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TextOutputDev.cc.o: xpdf/OutputDev.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TextOutputDev.cc.o: xpdf/Stream.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TextOutputDev.cc.o: xpdf/TextOutputDev.cc +xpdf/CMakeFiles/xpdf_widget_objs.dir/TextOutputDev.cc.o: xpdf/TextOutputDev.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TextOutputDev.cc.o: xpdf/UnicodeMap.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TextOutputDev.cc.o: xpdf/UnicodeRemapping.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TextOutputDev.cc.o: xpdf/UnicodeTypeTable.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TextOutputDev.cc.o: xpdf/config.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TextOutputDev.cc.o: aconf.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TextOutputDev.cc.o: aconf2.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TextOutputDev.cc.o: goo/GList.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TextOutputDev.cc.o: goo/GMutex.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TextOutputDev.cc.o: goo/GString.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TextOutputDev.cc.o: goo/gfile.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TextOutputDev.cc.o: goo/gmem.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TextOutputDev.cc.o: goo/gmempp.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TextOutputDev.cc.o: goo/gtypes.h + +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCache.cc.o: xpdf/Array.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCache.cc.o: xpdf/Catalog.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCache.cc.o: xpdf/CharTypes.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCache.cc.o: xpdf/Dict.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCache.cc.o: xpdf/DisplayState.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCache.cc.o: xpdf/Function.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCache.cc.o: xpdf/GfxState.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCache.cc.o: xpdf/Object.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCache.cc.o: xpdf/OutputDev.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCache.cc.o: xpdf/PDFDoc.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCache.cc.o: xpdf/Page.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCache.cc.o: xpdf/SplashOutputDev.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCache.cc.o: xpdf/Stream.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCache.cc.o: xpdf/TileCache.cc +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCache.cc.o: xpdf/TileCache.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCache.cc.o: xpdf/TileMap.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCache.cc.o: xpdf/XRef.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCache.cc.o: xpdf/config.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCache.cc.o: aconf.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCache.cc.o: aconf2.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCache.cc.o: goo/FixedPoint.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCache.cc.o: goo/GList.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCache.cc.o: goo/GMutex.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCache.cc.o: goo/GString.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCache.cc.o: goo/gfile.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCache.cc.o: goo/gmem.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCache.cc.o: goo/gmempp.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCache.cc.o: goo/gtypes.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCache.cc.o: splash/SplashBitmap.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCache.cc.o: splash/SplashTypes.h + +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCompositor.cc.o: xpdf/CharTypes.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCompositor.cc.o: xpdf/DisplayState.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCompositor.cc.o: xpdf/GlobalParams.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCompositor.cc.o: xpdf/TileCache.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCompositor.cc.o: xpdf/TileCompositor.cc +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCompositor.cc.o: xpdf/TileCompositor.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCompositor.cc.o: xpdf/TileMap.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCompositor.cc.o: aconf.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCompositor.cc.o: aconf2.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCompositor.cc.o: goo/FixedPoint.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCompositor.cc.o: goo/GList.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCompositor.cc.o: goo/GMutex.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCompositor.cc.o: goo/GString.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCompositor.cc.o: goo/gmempp.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCompositor.cc.o: goo/gtypes.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCompositor.cc.o: splash/SplashBitmap.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCompositor.cc.o: splash/SplashTypes.h + +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileMap.cc.o: xpdf/Array.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileMap.cc.o: xpdf/Catalog.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileMap.cc.o: xpdf/CharTypes.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileMap.cc.o: xpdf/Dict.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileMap.cc.o: xpdf/DisplayState.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileMap.cc.o: xpdf/Object.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileMap.cc.o: xpdf/PDFDoc.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileMap.cc.o: xpdf/Page.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileMap.cc.o: xpdf/Stream.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileMap.cc.o: xpdf/TileMap.cc +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileMap.cc.o: xpdf/TileMap.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileMap.cc.o: xpdf/XRef.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileMap.cc.o: aconf.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileMap.cc.o: aconf2.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileMap.cc.o: goo/FixedPoint.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileMap.cc.o: goo/GList.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileMap.cc.o: goo/GMutex.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileMap.cc.o: goo/GString.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileMap.cc.o: goo/gfile.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileMap.cc.o: goo/gmem.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileMap.cc.o: goo/gmempp.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileMap.cc.o: goo/gtypes.h +xpdf/CMakeFiles/xpdf_widget_objs.dir/TileMap.cc.o: splash/SplashTypes.h + diff --git a/xpdf/CMakeFiles/xpdf_widget_objs.dir/flags.make b/xpdf/CMakeFiles/xpdf_widget_objs.dir/flags.make new file mode 100644 index 0000000..fb6d504 --- /dev/null +++ b/xpdf/CMakeFiles/xpdf_widget_objs.dir/flags.make @@ -0,0 +1,10 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +# compile CXX with /usr/bin/c++ +CXX_DEFINES = + +CXX_INCLUDES = -I/home/calvin/src/xpdf-4.04 -I/home/calvin/src/xpdf-4.04/goo -I/home/calvin/src/xpdf-4.04/fofi -I/home/calvin/src/xpdf-4.04/splash + +CXX_FLAGS = -fPIC + diff --git a/xpdf/CMakeFiles/xpdf_widget_objs.dir/progress.make b/xpdf/CMakeFiles/xpdf_widget_objs.dir/progress.make new file mode 100644 index 0000000..b8bf964 --- /dev/null +++ b/xpdf/CMakeFiles/xpdf_widget_objs.dir/progress.make @@ -0,0 +1,11 @@ +CMAKE_PROGRESS_1 = 93 +CMAKE_PROGRESS_2 = 94 +CMAKE_PROGRESS_3 = +CMAKE_PROGRESS_4 = 95 +CMAKE_PROGRESS_5 = 96 +CMAKE_PROGRESS_6 = 97 +CMAKE_PROGRESS_7 = +CMAKE_PROGRESS_8 = 98 +CMAKE_PROGRESS_9 = 99 +CMAKE_PROGRESS_10 = 100 + diff --git a/xpdf/CMakeLists.txt b/xpdf/CMakeLists.txt new file mode 100644 index 0000000..63a8dec --- /dev/null +++ b/xpdf/CMakeLists.txt @@ -0,0 +1,292 @@ +#======================================================================== +# +# xpdf/cmake-xpdf.txt +# +# CMake script for the Xpdf tools. +# +# Copyright 2015 Glyph & Cog, LLC +# +#======================================================================== + +include_directories("${PROJECT_SOURCE_DIR}") +include_directories("${PROJECT_BINARY_DIR}") +include_directories("${PROJECT_SOURCE_DIR}/goo") +include_directories("${PROJECT_SOURCE_DIR}/fofi") +include_directories("${PROJECT_SOURCE_DIR}/splash") +if (PNG_FOUND) + include_directories("${PNG_INCLUDE_DIRS}") + add_definitions("${PNG_DEFINITIONS}") +endif () +if (HAVE_LCMS) + include_directories("${LCMS_INCLUDE_DIR}") + set(COLOR_MANAGER_SOURCE "ColorManager.cc") +else () + set(COLOR_MANAGER_SOURCE "") +endif () +if (WIN32) + set(MANIFEST "winLongPath.exe.manifest") +else () + set(MANIFEST "") +endif () + +add_library(xpdf_objs OBJECT + AcroForm.cc + Annot.cc + Array.cc + BuiltinFont.cc + BuiltinFontTables.cc + Catalog.cc + CharCodeToUnicode.cc + CMap.cc + ${COLOR_MANAGER_SOURCE} + Decrypt.cc + Dict.cc + Error.cc + FontEncodingTables.cc + Function.cc + Gfx.cc + GfxFont.cc + GfxState.cc + GlobalParams.cc + JArithmeticDecoder.cc + JBIG2Stream.cc + JPXStream.cc + Lexer.cc + Link.cc + NameToCharCode.cc + Object.cc + OptionalContent.cc + Outline.cc + OutputDev.cc + Page.cc + Parser.cc + PDF417Barcode.cc + PDFDoc.cc + PDFDocEncoding.cc + PSTokenizer.cc + SecurityHandler.cc + Stream.cc + TextString.cc + UnicodeMap.cc + UnicodeRemapping.cc + UnicodeTypeTable.cc + UTF8.cc + XFAScanner.cc + XRef.cc + Zoox.cc +) +set_property(TARGET xpdf_objs + PROPERTY POSITION_INDEPENDENT_CODE True) + +#--- object files needed by XpdfWidget + +if ((QT4_FOUND OR Qt5Widgets_FOUND OR Qt6Widgets_FOUND) + AND HAVE_SPLASH AND MULTITHREADED AND USE_EXCEPTIONS) + + if (HIGHLIGHTED_REGIONS) + set(HIGHLIGHT_SRC "HighlightFile.cc") + else () + set(HIGHLIGHT_SRC "") + endif () + + add_library(xpdf_widget_objs OBJECT + DisplayState.cc + PDFCore.cc + PreScanOutputDev.cc + PSOutputDev.cc + ShadingImage.cc + SplashOutputDev.cc + TextOutputDev.cc + TileCache.cc + TileCompositor.cc + TileMap.cc + ${HIGHLIGHT_SRC} + ) + set_property(TARGET xpdf_widget_objs + PROPERTY POSITION_INDEPENDENT_CODE True) +endif () + +#--- pdftops + +if (HAVE_SPLASH) + add_executable(pdftops + $ + PreScanOutputDev.cc + PSOutputDev.cc + ShadingImage.cc + SplashOutputDev.cc + pdftops.cc + ${MANIFEST} + ) + target_link_libraries(pdftops goo fofi splash + ${PAPER_LIBRARY} + ${FREETYPE_LIBRARY} ${FREETYPE_OTHER_LIBS} + ${DTYPE_LIBRARY} + ${LCMS_LIBRARY} + ${FONTCONFIG_LIBRARY} + ${CMAKE_THREAD_LIBS_INIT}) +else () + add_executable(pdftops + $ + PreScanOutputDev.cc + PSOutputDev.cc + pdftops.cc + ${MANIFEST} + ) + target_link_libraries(pdftops goo fofi + ${PAPER_LIBRARY} + ${LCMS_LIBRARY} + ${FONTCONFIG_LIBRARY} + ${CMAKE_THREAD_LIBS_INIT}) +endif () +install(TARGETS pdftops RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) +install(FILES ${PROJECT_SOURCE_DIR}/doc/pdftops.1 DESTINATION ${CMAKE_INSTALL_MANDIR}/man1) + +#--- pdftotext + +add_executable(pdftotext + $ + TextOutputDev.cc + pdftotext.cc + ${MANIFEST} +) +target_link_libraries(pdftotext goo fofi + ${PAPER_LIBRARY} + ${LCMS_LIBRARY} + ${FONTCONFIG_LIBRARY} + ${CMAKE_THREAD_LIBS_INIT}) +install(TARGETS pdftotext RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) +install(FILES ${PROJECT_SOURCE_DIR}/doc/pdftotext.1 DESTINATION ${CMAKE_INSTALL_MANDIR}/man1) + +#--- pdftohtml + +if (HAVE_SPLASH AND PNG_FOUND) + add_executable(pdftohtml + $ + HTMLGen.cc + ShadingImage.cc + SplashOutputDev.cc + TextOutputDev.cc + WebFont.cc + pdftohtml.cc + ${MANIFEST} + ) + target_link_libraries(pdftohtml goo fofi splash + ${PAPER_LIBRARY} + ${FREETYPE_LIBRARY} ${FREETYPE_OTHER_LIBS} + ${DTYPE_LIBRARY} + ${LCMS_LIBRARY} + ${PNG_LIBRARIES} + ${FONTCONFIG_LIBRARY} + ${CMAKE_THREAD_LIBS_INIT}) + install(TARGETS pdftohtml RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + install(FILES ${PROJECT_SOURCE_DIR}/doc/pdftohtml.1 DESTINATION ${CMAKE_INSTALL_MANDIR}/man1) +endif () + +#--- pdfinfo + +add_executable(pdfinfo + $ + pdfinfo.cc + ${MANIFEST} +) +target_link_libraries(pdfinfo goo fofi + ${PAPER_LIBRARY} + ${LCMS_LIBRARY} + ${FONTCONFIG_LIBRARY} + ${CMAKE_THREAD_LIBS_INIT}) +install(TARGETS pdfinfo RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) +install(FILES ${PROJECT_SOURCE_DIR}/doc/pdfinfo.1 DESTINATION ${CMAKE_INSTALL_MANDIR}/man1) + +#--- pdffonts + +add_executable(pdffonts + $ + pdffonts.cc + ${MANIFEST} +) +target_link_libraries(pdffonts goo fofi + ${PAPER_LIBRARY} + ${LCMS_LIBRARY} + ${FONTCONFIG_LIBRARY} + ${CMAKE_THREAD_LIBS_INIT}) +install(TARGETS pdffonts RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) +install(FILES ${PROJECT_SOURCE_DIR}/doc/pdffonts.1 DESTINATION ${CMAKE_INSTALL_MANDIR}/man1) + +#--- pdfdetach + +add_executable(pdfdetach + $ + pdfdetach.cc + ${MANIFEST} +) +target_link_libraries(pdfdetach goo fofi + ${PAPER_LIBRARY} + ${LCMS_LIBRARY} + ${FONTCONFIG_LIBRARY} + ${CMAKE_THREAD_LIBS_INIT}) +install(TARGETS pdfdetach RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) +install(FILES ${PROJECT_SOURCE_DIR}/doc/pdfdetach.1 DESTINATION ${CMAKE_INSTALL_MANDIR}/man1) + +#--- pdftoppm + +if (HAVE_SPLASH) + add_executable(pdftoppm + $ + ShadingImage.cc + SplashOutputDev.cc + pdftoppm.cc + ${MANIFEST} + ) + target_link_libraries(pdftoppm goo fofi splash + ${PAPER_LIBRARY} + ${FREETYPE_LIBRARY} ${FREETYPE_OTHER_LIBS} + ${DTYPE_LIBRARY} + ${LCMS_LIBRARY} + ${FONTCONFIG_LIBRARY} + ${CMAKE_THREAD_LIBS_INIT}) + install(TARGETS pdftoppm RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + install(FILES ${PROJECT_SOURCE_DIR}/doc/pdftoppm.1 DESTINATION ${CMAKE_INSTALL_MANDIR}/man1) +endif () + +#--- pdftopng + +if (HAVE_SPLASH AND PNG_FOUND) + add_executable(pdftopng + $ + ShadingImage.cc + SplashOutputDev.cc + pdftopng.cc + ${MANIFEST} + ) + target_link_libraries(pdftopng goo fofi splash + ${PAPER_LIBRARY} + ${FREETYPE_LIBRARY} ${FREETYPE_OTHER_LIBS} + ${DTYPE_LIBRARY} + ${LCMS_LIBRARY} + ${PNG_LIBRARIES} + ${FONTCONFIG_LIBRARY} + ${CMAKE_THREAD_LIBS_INIT}) + install(TARGETS pdftopng RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + install(FILES ${PROJECT_SOURCE_DIR}/doc/pdftopng.1 DESTINATION ${CMAKE_INSTALL_MANDIR}/man1) +endif () + +#--- pdfimages + +add_executable(pdfimages + $ + ImageOutputDev.cc + pdfimages.cc + ${MANIFEST} +) +target_link_libraries(pdfimages goo fofi + ${PAPER_LIBRARY} + ${LCMS_LIBRARY} + ${FONTCONFIG_LIBRARY} + ${CMAKE_THREAD_LIBS_INIT}) +install(TARGETS pdfimages RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) +install(FILES ${PROJECT_SOURCE_DIR}/doc/pdfimages.1 DESTINATION ${CMAKE_INSTALL_MANDIR}/man1) + +#--- xpdfrc man page + +install(FILES ${PROJECT_SOURCE_DIR}/doc/xpdfrc.5 DESTINATION ${CMAKE_INSTALL_MANDIR}/man5) diff --git a/xpdf/CMap.cc b/xpdf/CMap.cc new file mode 100644 index 0000000..12632c5 --- /dev/null +++ b/xpdf/CMap.cc @@ -0,0 +1,440 @@ +//======================================================================== +// +// CMap.cc +// +// Copyright 2001-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include +#include +#include +#include "gmem.h" +#include "gmempp.h" +#include "gfile.h" +#include "GString.h" +#include "Error.h" +#include "GlobalParams.h" +#include "PSTokenizer.h" +#include "Object.h" +#include "Stream.h" +#include "CMap.h" + +//------------------------------------------------------------------------ + +struct CMapVectorEntry { + GBool isVector; + union { + CMapVectorEntry *vector; + CID cid; + }; +}; + +//------------------------------------------------------------------------ + +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; + + if (!(f = globalParams->findCMapFile(collectionA, cMapNameA))) { + + // Check for an identity CMap. + if (!cMapNameA->cmp("Identity") || !cMapNameA->cmp("Identity-H")) { + return new CMap(collectionA->copy(), cMapNameA->copy(), 0); + } + if (!cMapNameA->cmp("Identity-V")) { + return new CMap(collectionA->copy(), cMapNameA->copy(), 1); + } + + 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->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(getCharFunc, data); + pst->getToken(tok1, sizeof(tok1), &n1); + while (pst->getToken(tok2, sizeof(tok2), &n2)) { + if (!strcmp(tok2, "usecmap")) { + if (tok1[0] == '/') { + useCMap(cache, tok1 + 1); + } + pst->getToken(tok1, sizeof(tok1), &n1); + } else if (!strcmp(tok1, "/WMode")) { + wMode = atoi(tok2); + pst->getToken(tok1, sizeof(tok1), &n1); + } else if (!strcmp(tok2, "begincidchar")) { + while (pst->getToken(tok1, sizeof(tok1), &n1)) { + if (!strcmp(tok1, "endcidchar")) { + break; + } + if (!pst->getToken(tok2, sizeof(tok2), &n2) || + !strcmp(tok2, "endcidchar")) { + error(errSyntaxError, -1, "Illegal entry in cidchar block in CMap"); + break; + } + if (!(tok1[0] == '<' && tok1[n1 - 1] == '>' && + n1 >= 4 && (n1 & 1) == 0)) { + error(errSyntaxError, -1, "Illegal entry in cidchar block in CMap"); + continue; + } + tok1[n1 - 1] = '\0'; + if (sscanf(tok1 + 1, "%x", &code) != 1) { + error(errSyntaxError, -1, "Illegal entry in cidchar block in CMap"); + continue; + } + n1 = (n1 - 2) / 2; + addCIDs(code, code, n1, (CID)atoi(tok2)); + } + pst->getToken(tok1, sizeof(tok1), &n1); + } else if (!strcmp(tok2, "begincidrange")) { + while (pst->getToken(tok1, sizeof(tok1), &n1)) { + if (!strcmp(tok1, "endcidrange")) { + break; + } + if (!pst->getToken(tok2, sizeof(tok2), &n2) || + !strcmp(tok2, "endcidrange") || + !pst->getToken(tok3, sizeof(tok3), &n3) || + !strcmp(tok3, "endcidrange")) { + error(errSyntaxError, -1, "Illegal entry in cidrange 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; + addCIDs(start, end, n1, (CID)atoi(tok3)); + } + } + pst->getToken(tok1, sizeof(tok1), &n1); + } else { + strcpy(tok1, tok2); + } + } + delete pst; +} + +CMap::CMap(GString *collectionA, GString *cMapNameA) { + int i; + + collection = collectionA; + cMapName = cMapNameA; + isIdent = gFalse; + wMode = 0; + vector = (CMapVectorEntry *)gmallocn(256, sizeof(CMapVectorEntry)); + for (i = 0; i < 256; ++i) { + vector[i].isVector = gFalse; + vector[i].cid = 0; + } + refCnt = 1; +} + +CMap::CMap(GString *collectionA, GString *cMapNameA, int wModeA) { + collection = collectionA; + cMapName = cMapNameA; + isIdent = gTrue; + wMode = wModeA; + vector = NULL; + refCnt = 1; +} + +void CMap::useCMap(CMapCache *cache, char *useName) { + GString *useNameStr; + CMap *subCMap; + + useNameStr = new GString(useName); + // 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; + } + 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(); +} + +void CMap::copyVector(CMapVectorEntry *dest, CMapVectorEntry *src) { + int i, j; + + for (i = 0; i < 256; ++i) { + if (src[i].isVector) { + if (!dest[i].isVector) { + dest[i].isVector = gTrue; + dest[i].vector = + (CMapVectorEntry *)gmallocn(256, sizeof(CMapVectorEntry)); + for (j = 0; j < 256; ++j) { + dest[i].vector[j].isVector = gFalse; + dest[i].vector[j].cid = 0; + } + } + copyVector(dest[i].vector, src[i].vector); + } else { + if (dest[i].isVector) { + error(errSyntaxError, -1, "Collision in usecmap"); + } else { + dest[i].cid = src[i].cid; + } + } + } +} + +void CMap::addCIDs(Guint start, Guint end, Guint nBytes, CID firstCID) { + CMapVectorEntry *vec; + int byte, byte0, byte1; + Guint start1, end1, i, j, k; + + start1 = start & 0xffffff00; + end1 = end & 0xffffff00; + for (i = start1; i <= end1; i += 0x100) { + vec = vector; + for (j = nBytes - 1; j >= 1; --j) { + byte = (i >> (8 * j)) & 0xff; + if (!vec[byte].isVector) { + vec[byte].isVector = gTrue; + vec[byte].vector = + (CMapVectorEntry *)gmallocn(256, sizeof(CMapVectorEntry)); + for (k = 0; k < 256; ++k) { + vec[byte].vector[k].isVector = gFalse; + vec[byte].vector[k].cid = 0; + } + } + vec = vec[byte].vector; + } + byte0 = (i < start) ? (start & 0xff) : 0; + byte1 = (i + 0xff > end) ? (end & 0xff) : 0xff; + for (byte = byte0; byte <= byte1; ++byte) { + if (vec[byte].isVector) { + error(errSyntaxError, -1, "Invalid CID ({0:x} [{1:d} bytes]) in CMap", + i, nBytes); + } else { + vec[byte].cid = firstCID + ((i + byte) - start); + } + } + } +} + +CMap::~CMap() { + delete collection; + if (cMapName) { + delete cMapName; + } + if (vector) { + freeCMapVector(vector); + } +} + +void CMap::freeCMapVector(CMapVectorEntry *vec) { + int i; + + for (i = 0; i < 256; ++i) { + if (vec[i].isVector) { + freeCMapVector(vec[i].vector); + } + } + gfree(vec); +} + +void CMap::incRefCnt() { +#if MULTITHREADED + gAtomicIncrement(&refCnt); +#else + ++refCnt; +#endif +} + +void CMap::decRefCnt() { + GBool done; + +#if MULTITHREADED + done = gAtomicDecrement(&refCnt) == 0; +#else + done = --refCnt == 0; +#endif + if (done) { + delete this; + } +} + +GBool CMap::match(GString *collectionA, GString *cMapNameA) { + return !collection->cmp(collectionA) && !cMapName->cmp(cMapNameA); +} + +CID CMap::getCID(char *s, int len, CharCode *c, int *nUsed) { + CMapVectorEntry *vec; + CharCode cc; + int n, i; + + vec = vector; + cc = 0; + n = 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; +} + +//------------------------------------------------------------------------ + +CMapCache::CMapCache() { + int i; + + for (i = 0; i < cMapCacheSize; ++i) { + cache[i] = NULL; + } +} + +CMapCache::~CMapCache() { + int i; + + for (i = 0; i < cMapCacheSize; ++i) { + if (cache[i]) { + cache[i]->decRefCnt(); + } + } +} + +CMap *CMapCache::getCMap(GString *collection, GString *cMapName) { + CMap *cmap; + int i, j; + + if (cache[0] && cache[0]->match(collection, cMapName)) { + cache[0]->incRefCnt(); + return cache[0]; + } + for (i = 1; i < cMapCacheSize; ++i) { + if (cache[i] && cache[i]->match(collection, cMapName)) { + cmap = cache[i]; + for (j = i; j >= 1; --j) { + cache[j] = cache[j - 1]; + } + cache[0] = cmap; + cmap->incRefCnt(); + return cmap; + } + } + if ((cmap = CMap::parse(this, collection, cMapName))) { + if (cache[cMapCacheSize - 1]) { + cache[cMapCacheSize - 1]->decRefCnt(); + } + for (j = cMapCacheSize - 1; j >= 1; --j) { + cache[j] = cache[j - 1]; + } + cache[0] = cmap; + cmap->incRefCnt(); + return cmap; + } + return NULL; +} diff --git a/xpdf/CMap.h b/xpdf/CMap.h new file mode 100644 index 0000000..55692b4 --- /dev/null +++ b/xpdf/CMap.h @@ -0,0 +1,115 @@ +//======================================================================== +// +// CMap.h +// +// Copyright 2001-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef CMAP_H +#define CMAP_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "gtypes.h" +#include "CharTypes.h" + +#if MULTITHREADED +#include "GMutex.h" +#endif + +class GString; +class Object; +class Stream; +struct CMapVectorEntry; +class CMapCache; + +//------------------------------------------------------------------------ + +class CMap { +public: + + // Parse a CMap from , 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 and . Sets + // the initial reference count to 1. Returns NULL on failure. + static CMap *parse(CMapCache *cache, GString *collectionA, + GString *cMapNameA); + + // Parse a CMap from . Sets the initial reference count to 1. + // Returns NULL on failure. + static CMap *parse(CMapCache *cache, GString *collectionA, Stream *str); + + ~CMap(); + + void incRefCnt(); + void decRefCnt(); + + // Return collection name (-). + GString *getCollection() { return collection; } + + // Return true if this CMap matches the specified , and + // . + GBool match(GString *collectionA, GString *cMapNameA); + + // Return the CID corresponding to the character code starting at + // , which contains bytes. Sets * to the char code, and + // * 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 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) +#if MULTITHREADED + GAtomicCounter refCnt; +#else + int refCnt; +#endif +}; + +//------------------------------------------------------------------------ + +#define cMapCacheSize 4 + +class CMapCache { +public: + + CMapCache(); + ~CMapCache(); + + // Get the CMap for the specified character collection. + // Increments its reference count; there will be one reference for + // the cache plus one for the caller of this function. Returns NULL + // on failure. + CMap *getCMap(GString *collection, GString *cMapName); + +private: + + CMap *cache[cMapCacheSize]; +}; + +#endif diff --git a/xpdf/Catalog.cc b/xpdf/Catalog.cc new file mode 100644 index 0000000..ddcbad5 --- /dev/null +++ b/xpdf/Catalog.cc @@ -0,0 +1,1197 @@ +//======================================================================== +// +// Catalog.cc +// +// Copyright 1996-2013 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include +#include +#include "gmem.h" +#include "gmempp.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 "AcroForm.h" +#include "TextString.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(TextString *nameA, Object *streamRefA); + ~EmbeddedFile(); + + TextString *name; + Object streamRef; +}; + +EmbeddedFile::EmbeddedFile(TextString *nameA, Object *streamRefA) { + name = nameA; + streamRefA->copy(&streamRef); +} + +EmbeddedFile::~EmbeddedFile() { + delete name; + streamRef.free(); +} + +//------------------------------------------------------------------------ +// PageLabelNode +//------------------------------------------------------------------------ + +class PageLabelNode { +public: + + PageLabelNode(int firstPageA, Dict *dict); + ~PageLabelNode(); + + int firstPage; // first page number covered by this node + int lastPage; // last page number covered by this node + TextString *prefix; // label prefix (may be empty) + int start; // value of the numeric portion of this + // label for the first page in the range + char style; // page label style +}; + +PageLabelNode::PageLabelNode(int firstPageA, Dict *dict) { + Object prefixObj, styleObj, startObj; + + // convert page index to page number + firstPage = firstPageA + 1; + + // lastPage will be filled in later + lastPage = -1; + + if (dict->lookup("P", &prefixObj)->isString()) { + prefix = new TextString(prefixObj.getString()); + } else { + prefix = new TextString(); + } + prefixObj.free(); + + style = '\0'; + if (dict->lookup("S", &styleObj)->isName()) { + if (strlen(styleObj.getName()) == 1) { + style = styleObj.getName()[0]; + } + } + styleObj.free(); + + start = 1; + if (dict->lookup("St", &startObj)->isInt()) { + start = startObj.getInt(); + } + startObj.free(); +} + +PageLabelNode::~PageLabelNode() { + delete prefix; +} + +//------------------------------------------------------------------------ +// Catalog +//------------------------------------------------------------------------ + +Catalog::Catalog(PDFDoc *docA) { + Object catDict; + Object obj, obj2; + + ok = gTrue; + doc = docA; + xref = doc->getXRef(); + pageTree = NULL; + pages = NULL; + pageRefs = NULL; + numPages = 0; + baseURI = NULL; + form = NULL; + embeddedFiles = NULL; + pageLabels = NULL; +#if MULTITHREADED + gInitMutex(&pageMutex); +#endif + + xref->getCatalog(&catDict); + if (!catDict.isDict()) { + error(errSyntaxError, -1, "Catalog object is wrong type ({0:s})", + catDict.getTypeName()); + goto err1; + } + + // read page tree + if (!readPageTree(&catDict)) { + goto err1; + } + + // read named destination dictionary + catDict.dictLookup("Dests", &dests); + + // read root of named destination tree + if (catDict.dictLookup("Names", &obj)->isDict()) + obj.dictLookup("Dests", &nameTree); + else + nameTree.initNull(); + obj.free(); + + // read base URI + if (catDict.dictLookup("URI", &obj)->isDict()) { + if (obj.dictLookup("Base", &obj2)->isString()) { + baseURI = obj2.getString()->copy(); + } + 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); + + // get the structure tree root + catDict.dictLookup("StructTreeRoot", &structTreeRoot); + + // get the outline dictionary + catDict.dictLookup("Outlines", &outline); + + // get the AcroForm dictionary + catDict.dictLookup("AcroForm", &acroForm); + + // get the NeedsRendering flag + // NB: AcroForm::load() uses this value + needsRendering = catDict.dictLookup("NeedsRendering", &obj)->isBool() && + obj.getBool(); + obj.free(); + + // create the Form + // (if acroForm is a null object, this will still create an AcroForm + // if there are unattached Widget-type annots) + form = AcroForm::load(doc, this, &acroForm); + + // get the OCProperties dictionary + catDict.dictLookup("OCProperties", &ocProperties); + + // get the list of embedded files + readEmbeddedFileList(catDict.getDict()); + + // get the ViewerPreferences object + catDict.dictLookupNF("ViewerPreferences", &viewerPrefs); + + if (catDict.dictLookup("PageLabels", &obj)->isDict()) { + readPageLabelTree(&obj); + } + obj.free(); + + catDict.free(); + return; + + err1: + catDict.free(); + dests.initNull(); + nameTree.initNull(); + ok = gFalse; +} + +Catalog::~Catalog() { + int i; + + if (pageTree) { + delete pageTree; + } + if (pages) { + for (i = 0; i < numPages; ++i) { + if (pages[i]) { + delete pages[i]; + } + } + gfree(pages); + gfree(pageRefs); + } +#if MULTITHREADED + gDestroyMutex(&pageMutex); +#endif + dests.free(); + nameTree.free(); + if (baseURI) { + delete baseURI; + } + metadata.free(); + structTreeRoot.free(); + outline.free(); + acroForm.free(); + if (form) { + delete form; + } + ocProperties.free(); + if (embeddedFiles) { + deleteGList(embeddedFiles, EmbeddedFile); + } + if (pageLabels) { + deleteGList(pageLabels, PageLabelNode); + } + viewerPrefs.free(); +} + +Page *Catalog::getPage(int i) { + Page *page; + +#if MULTITHREADED + gLockMutex(&pageMutex); +#endif + if (!pages[i-1]) { + loadPage(i); + } + page = pages[i-1]; +#if MULTITHREADED + gUnlockMutex(&pageMutex); +#endif + return page; +} + +Ref *Catalog::getPageRef(int i) { + Ref *pageRef; + +#if MULTITHREADED + gLockMutex(&pageMutex); +#endif + if (!pages[i-1]) { + loadPage(i); + } + pageRef = &pageRefs[i-1]; +#if MULTITHREADED + gUnlockMutex(&pageMutex); +#endif + return pageRef; +} + +void Catalog::doneWithPage(int i) { +#if MULTITHREADED + gLockMutex(&pageMutex); +#endif + if (pages[i-1]) { + delete pages[i-1]; + pages[i-1] = NULL; + } +#if MULTITHREADED + gUnlockMutex(&pageMutex); +#endif +} + +GString *Catalog::readMetadata() { + GString *s; + Dict *dict; + Object obj; + char buf[4096]; + int n; + + if (!metadata.isStream()) { + return NULL; + } + dict = metadata.streamGetDict(); + if (!dict->lookup("Subtype", &obj)->isName("XML")) { + error(errSyntaxWarning, -1, "Unknown Metadata type: '{0:s}'", + obj.isName() ? obj.getName() : "???"); + } + obj.free(); + s = new GString(); + metadata.streamReset(); + while ((n = metadata.streamGetBlock(buf, sizeof(buf))) > 0) { + s->append(buf, n); + } + metadata.streamClose(); + return s; +} + +int Catalog::findPage(int num, int gen) { + int i; + +#if MULTITHREADED + gLockMutex(&pageMutex); +#endif + for (i = 0; i < numPages; ++i) { + if (!pages[i]) { + loadPage(i+1); + } + if (pageRefs[i].num == num && pageRefs[i].gen == gen) { +#if MULTITHREADED + gUnlockMutex(&pageMutex); +#endif + return i + 1; + } + } +#if MULTITHREADED + gUnlockMutex(&pageMutex); +#endif + return 0; +} + +LinkDest *Catalog::findDest(GString *name) { + LinkDest *dest; + Object obj1, obj2; + GBool found; + + // try named destination dictionary then name tree + found = gFalse; + if (dests.isDict()) { + if (!dests.dictLookup(name->getCString(), &obj1)->isNull()) { + found = gTrue; + } else { + obj1.free(); + } + } + if (!found && nameTree.isDict()) { + if (!findDestInTree(&nameTree, name, &obj1)->isNull()) { + found = gTrue; + } else { + obj1.free(); + } + } + if (!found) { + return NULL; + } + + // construct LinkDest + dest = NULL; + if (obj1.isArray()) { + dest = new LinkDest(obj1.getArray()); + } else if (obj1.isDict()) { + if (obj1.dictLookup("D", &obj2)->isArray()) { + dest = new LinkDest(obj2.getArray()); + } else { + error(errSyntaxWarning, -1, "Bad named destination value"); + } + obj2.free(); + } else { + error(errSyntaxWarning, -1, "Bad named destination value"); + } + obj1.free(); + if (dest && !dest->isOk()) { + delete dest; + dest = NULL; + } + + return dest; +} + +Object *Catalog::findDestInTree(Object *tree, GString *name, Object *obj) { + Object names, name1; + Object kids, kid, limits, low, high; + GBool done, found; + int cmp, i; + + // leaf node + if (tree->dictLookup("Names", &names)->isArray()) { + done = found = gFalse; + for (i = 0; !done && i < names.arrayGetLength(); i += 2) { + if (names.arrayGet(i, &name1)->isString()) { + cmp = name->cmp(name1.getString()); + if (cmp == 0) { + names.arrayGet(i+1, obj); + found = gTrue; + done = gTrue; + } else if (cmp < 0) { + done = gTrue; + } + } + name1.free(); + } + names.free(); + if (!found) { + obj->initNull(); + } + return obj; + } + names.free(); + + // root or intermediate node + done = gFalse; + if (tree->dictLookup("Kids", &kids)->isArray()) { + for (i = 0; !done && i < kids.arrayGetLength(); ++i) { + if (kids.arrayGet(i, &kid)->isDict()) { + if (kid.dictLookup("Limits", &limits)->isArray()) { + if (limits.arrayGet(0, &low)->isString() && + name->cmp(low.getString()) >= 0) { + if (limits.arrayGet(1, &high)->isString() && + name->cmp(high.getString()) <= 0) { + findDestInTree(&kid, name, obj); + done = gTrue; + } + high.free(); + } + low.free(); + } + limits.free(); + } + kid.free(); + } + } + kids.free(); + + // name was outside of ranges of all kids + if (!done) { + obj->initNull(); + } + + 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 || numPages > 50000) { + // 1. Acrobat apparently scans the page tree if it sees a zero + // count. + // 2. Absurdly large page counts result in very slow loading, + // because other code tries to fetch pages 1 through n. + // In both cases: ignore the given page count and scan the tree + // instead. + 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(), xref); + + // 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); + } + } +} + +Object *Catalog::getDestOutputProfile(Object *destOutProf) { + Object catDict, intents, intent, subtype; + int i; + + if (!xref->getCatalog(&catDict)->isDict()) { + goto err1; + } + if (!catDict.dictLookup("OutputIntents", &intents)->isArray()) { + goto err2; + } + for (i = 0; i < intents.arrayGetLength(); ++i) { + intents.arrayGet(i, &intent); + if (!intent.isDict()) { + intent.free(); + continue; + } + if (!intent.dictLookup("S", &subtype)->isName("GTS_PDFX")) { + subtype.free(); + intent.free(); + continue; + } + subtype.free(); + if (!intent.dictLookup("DestOutputProfile", destOutProf)->isStream()) { + destOutProf->free(); + intent.free(); + goto err2; + } + intent.free(); + intents.free(); + catDict.free(); + return destOutProf; + } + + err2: + intents.free(); + err1: + catDict.free(); + return NULL; +} + +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 an invalid object reference (e.g., in a damaged PDF file) + if (pageNodeRef->getRefNum() < 0 || + pageNodeRef->getRefNum() >= xref->getNumObjects()) { + return; + } + + // check for a page tree loop + if (pageNodeRef->isRef()) { + if (touchedObjs[pageNodeRef->getRefNum()]) { + 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; + TextString *name; + + if (fileSpec->isDict()) { + if (fileSpec->dictLookup("UF", &name2)->isString()) { + name = new TextString(name2.getString()); + } else { + name2.free(); + if (fileSpec->dictLookup("F", &name2)->isString()) { + name = new TextString(name2.getString()); + } else if (name1 && name1->isString()) { + name = new TextString(name1->getString()); + } else { + s = new GString("?"); + name = new TextString(s); + delete s; + } + } + name2.free(); + if (fileSpec->dictLookup("EF", &efObj)->isDict()) { + if (efObj.dictLookupNF("F", &streamObj)->isRef()) { + if (!embeddedFiles) { + embeddedFiles = new GList(); + } + embeddedFiles->append(new EmbeddedFile(name, &streamObj)); + } else { + delete name; + } + streamObj.free(); + } else { + delete name; + } + efObj.free(); + } +} + +int Catalog::getNumEmbeddedFiles() { + return embeddedFiles ? embeddedFiles->getLength() : 0; +} + +Unicode *Catalog::getEmbeddedFileName(int idx) { + return ((EmbeddedFile *)embeddedFiles->get(idx))->name->getUnicode(); +} + +int Catalog::getEmbeddedFileNameLength(int idx) { + return ((EmbeddedFile *)embeddedFiles->get(idx))->name->getLength(); +} + +Object *Catalog::getEmbeddedFileStreamRef(int idx) { + return &((EmbeddedFile *)embeddedFiles->get(idx))->streamRef; +} + +Object *Catalog::getEmbeddedFileStreamObj(int idx, Object *strObj) { + ((EmbeddedFile *)embeddedFiles->get(idx))->streamRef.fetch(xref, strObj); + if (!strObj->isStream()) { + strObj->free(); + return NULL; + } + return strObj; +} + +void Catalog::readPageLabelTree(Object *root) { + PageLabelNode *label0, *label1; + int i; + + pageLabels = new GList(); + readPageLabelTree2(root); + + if (pageLabels->getLength() == 0) { + deleteGList(pageLabels, PageLabelNode); + pageLabels = NULL; + return; + } + + // set lastPage in each node + label0 = (PageLabelNode *)pageLabels->get(0); + for (i = 1; i < pageLabels->getLength(); ++i) { + label1 = (PageLabelNode *)pageLabels->get(i); + label0->lastPage = label1->firstPage - 1; + label0 = label1; + } + label0->lastPage = numPages; +} + +void Catalog::readPageLabelTree2(Object *node) { + Object nums, num, labelObj, kids, kid; + int i; + + if (!node->isDict()) { + return; + } + + if (node->dictLookup("Nums", &nums)->isArray()) { + for (i = 0; i < nums.arrayGetLength() - 1; i += 2) { + if (nums.arrayGet(i, &num)->isInt()) { + if (nums.arrayGet(i+1, &labelObj)->isDict()) { + pageLabels->append(new PageLabelNode(num.getInt(), + labelObj.getDict())); + } + labelObj.free(); + } + num.free(); + } + } + nums.free(); + + if (node->dictLookup("Kids", &kids)->isArray()) { + for (i = 0; i < kids.arrayGetLength(); ++i) { + kids.arrayGet(i, &kid); + readPageLabelTree2(&kid); + kid.free(); + } + } + kids.free(); +} + +TextString *Catalog::getPageLabel(int pageNum) { + PageLabelNode *label; + TextString *ts; + int pageRangeNum; + GString *suffix; + + if (!pageLabels || !(label = findPageLabel(pageNum))) { + return NULL; + } + + ts = new TextString(label->prefix); + + pageRangeNum = label->start + (pageNum - label->firstPage); + + suffix = NULL; + if (label->style == 'D') { + suffix = GString::format("{0:d}", pageRangeNum); + } else if (label->style == 'R') { + suffix = makeRomanNumeral(pageRangeNum, gTrue); + } else if (label->style == 'r') { + suffix = makeRomanNumeral(pageRangeNum, gFalse); + } else if (label->style == 'A') { + suffix = makeLetterLabel(pageRangeNum, gTrue); + } else if (label->style == 'a') { + suffix = makeLetterLabel(pageRangeNum, gFalse); + } + if (suffix) { + ts->append(suffix); + delete suffix; + } + + return ts; +} + +PageLabelNode *Catalog::findPageLabel(int pageNum) { + PageLabelNode *label; + int i; + + //~ this could use a binary search + for (i = 0; i < pageLabels->getLength(); ++i) { + label = (PageLabelNode *)pageLabels->get(i); + if (pageNum >= label->firstPage && pageNum <= label->lastPage) { + return label; + } + } + return NULL; +} + +GString *Catalog::makeRomanNumeral(int num, GBool uppercase) { + GString *s; + + s = new GString(); + while (num >= 1000) { + s->append(uppercase ? 'M' : 'm'); + num -= 1000; + } + if (num >= 900) { + s->append(uppercase ? "CM" : "cm"); + num -= 900; + } else if (num >= 500) { + s->append(uppercase ? 'D' : 'd'); + num -= 500; + } else if (num >= 400) { + s->append(uppercase ? "CD" : "cd"); + num -= 400; + } + while (num >= 100) { + s->append(uppercase ? 'C' : 'c'); + num -= 100; + } + if (num >= 90) { + s->append(uppercase ? "XC" : "xc"); + num -= 90; + } else if (num >= 50) { + s->append(uppercase ? 'L' : 'l'); + num -= 50; + } else if (num >= 40) { + s->append(uppercase ? "XL" : "xl"); + num -= 40; + } + while (num >= 10) { + s->append(uppercase ? 'X' : 'x'); + num -= 10; + } + if (num >= 9) { + s->append(uppercase ? "IX" : "ix"); + num -= 9; + } else if (num >= 5) { + s->append(uppercase ? 'V' : 'v'); + num -= 5; + } else if (num >= 4) { + s->append(uppercase ? "IV" : "iv"); + num -= 4; + } + while (num >= 1) { + s->append(uppercase ? 'I' : 'i'); + num -= 1; + } + return s; +} + +GString *Catalog::makeLetterLabel(int num, GBool uppercase) { + GString *s; + int m, n, i; + + m = (num - 1) / 26 + 1; + n = (num - 1) % 26; + s = new GString(); + for (i = 0; i < m; ++i) { + s->append((char)((uppercase ? 'A' : 'a') + n)); + } + return s; +} + +int Catalog::getPageNumFromPageLabel(TextString *pageLabel) { + PageLabelNode *label; + int pageNum, prefixLength, i, n; + + if (!pageLabels) { + return -1; + } + for (i = 0; i < pageLabels->getLength(); ++i) { + label = (PageLabelNode *)pageLabels->get(i); + prefixLength = label->prefix->getLength(); + if (pageLabel->getLength() < prefixLength || + memcmp(pageLabel->getUnicode(), label->prefix->getUnicode(), + prefixLength * sizeof(Unicode))) { + continue; + } + if (label->style == '\0' && pageLabel->getLength() == prefixLength) { + return label->firstPage; + } + if (!convertPageLabelToInt(pageLabel, prefixLength, label->style, &n)) { + continue; + } + if (n < label->start) { + continue; + } + pageNum = label->firstPage + n - label->start; + if (pageNum <= label->lastPage) { + return pageNum; + } + } + return -1; +} + +// Attempts to convert pageLabel[prefixLength .. end] to an integer, +// following the specified page label style. If successful, sets *n +// and returns true; else returns false. +GBool Catalog::convertPageLabelToInt(TextString *pageLabel, int prefixLength, + char style, int *n) { + Unicode *u; + Unicode delta; + int len, i; + + len = pageLabel->getLength(); + if (len <= prefixLength) { + return gFalse; + } + u = pageLabel->getUnicode(); + if (style == 'D') { + *n = 0; + for (i = prefixLength; i < len; ++i) { + if (u[i] < (Unicode)'0' || u[i] > (Unicode)'9') { + return gFalse; + } + *n = *n * 10 + (u[i] - (Unicode)'0'); + } + return gTrue; + } else if (style == 'R' || style == 'r') { + delta = style - 'R'; + *n = 0; + i = prefixLength; + while (i < len && u[i] == (Unicode)'M' + delta) { + *n += 1000; + ++i; + } + if (i+1 < len && u[i] == (Unicode)'C' + delta && + u[i+1] == (Unicode)'M' + delta) { + *n += 900; + i += 2; + } else if (i < len && u[i] == (Unicode)'D' + delta) { + *n += 500; + ++i; + } else if (i+1 < len && u[i] == (Unicode)'C' + delta && + u[i+1] == (Unicode)'D' + delta) { + *n += 400; + i += 2; + } + while (i < len && u[i] == (Unicode)'C' + delta) { + *n += 100; + ++i; + } + if (i+1 < len && u[i] == (Unicode)'X' + delta && + u[i+1] == (Unicode)'C' + delta) { + *n += 90; + i += 2; + } else if (i < len && u[i] == (Unicode)'L' + delta) { + *n += 50; + ++i; + } else if (i+1 < len && u[i] == (Unicode)'X' + delta && + u[i+1] == (Unicode)'L' + delta) { + *n += 40; + i += 2; + } + while (i < len && u[i] == (Unicode)'X' + delta) { + *n += 10; + ++i; + } + if (i+1 < len && u[i] == (Unicode)'I' + delta && + u[i+1] == (Unicode)'X' + delta) { + *n += 9; + i += 2; + } else if (i < len && u[i] == (Unicode)'V' + delta) { + *n += 5; + ++i; + } else if (i+1 < len && u[i] == (Unicode)'I' + delta && + u[i+1] == (Unicode)'V' + delta) { + *n += 4; + i += 2; + } + while (i < len && u[i] == (Unicode)'I' + delta) { + *n += 1; + ++i; + } + return i == len; + } else if (style == 'A' || style == 'a') { + if (u[prefixLength] < (Unicode)style || + u[prefixLength] > (Unicode)style + 25) { + return gFalse; + } + for (i = prefixLength + 1; i < len; ++i) { + if (u[i] != u[prefixLength]) { + return gFalse; + } + } + *n = (len - prefixLength - 1) * 26 + (u[prefixLength] - (Unicode)style) + 1; + return gTrue; + } + return gFalse; +} diff --git a/xpdf/Catalog.h b/xpdf/Catalog.h new file mode 100644 index 0000000..0acdd2d --- /dev/null +++ b/xpdf/Catalog.h @@ -0,0 +1,166 @@ +//======================================================================== +// +// Catalog.h +// +// Copyright 1996-2007 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef CATALOG_H +#define CATALOG_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#if MULTITHREADED +#include "GMutex.h" +#endif +#include "CharTypes.h" + +class GList; +class PDFDoc; +class XRef; +class Object; +class Page; +class PageAttrs; +struct Ref; +class LinkDest; +class PageTreeNode; +class PageLabelNode; +class AcroForm; +class TextString; + +//------------------------------------------------------------------------ +// Catalog +//------------------------------------------------------------------------ + +class Catalog { +public: + + // Constructor. + Catalog(PDFDoc *docA); + + // Destructor. + ~Catalog(); + + // Is catalog valid? + GBool isOk() { return ok; } + + // Get number of pages. + int getNumPages() { return numPages; } + + // Get a page. + Page *getPage(int i); + + // Get the reference for a page object. + 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; } + + // Return the contents of the metadata stream, or NULL if there is + // no metadata. + GString *readMetadata(); + + // Return the structure tree root object. + Object *getStructTreeRoot() { return &structTreeRoot; } + + // Find a page, given its object ID. Returns page number, or 0 if + // not found. + int findPage(int num, int gen); + + // Find a named destination. Returns the link destination, or + // NULL if is not a destination. + LinkDest *findDest(GString *name); + + Object *getDests() { return &dests; } + + Object *getNameTree() { return &nameTree; } + + Object *getOutline() { return &outline; } + + Object *getAcroForm() { return &acroForm; } + + AcroForm *getForm() { return form; } + + GBool getNeedsRendering() { return needsRendering; } + + Object *getOCProperties() { return &ocProperties; } + + // Return the DestOutputProfile stream, or NULL if there isn't one. + Object *getDestOutputProfile(Object *destOutProf); + + // Get the list of embedded files. + int getNumEmbeddedFiles(); + Unicode *getEmbeddedFileName(int idx); + int getEmbeddedFileNameLength(int idx); + Object *getEmbeddedFileStreamRef(int idx); + Object *getEmbeddedFileStreamObj(int idx, Object *strObj); + + // Return true if the document has page labels. + GBool hasPageLabels() { return pageLabels != NULL; } + + // Get the page label for page number [pageNum]. Returns NULL if + // the PDF file doesn't have page labels. + TextString *getPageLabel(int pageNum); + + // Returns the page number corresponding to [pageLabel]. Returns -1 + // if there is no matching page label, or if the document doesn't + // have page labels. + int getPageNumFromPageLabel(TextString *pageLabel); + + Object *getViewerPreferences() { return &viewerPrefs; } + +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 +#if MULTITHREADED + GMutex pageMutex; +#endif + int numPages; // number of pages + Object dests; // named destination dictionary + Object nameTree; // name tree + GString *baseURI; // base URI for URI-type links + Object metadata; // metadata stream + Object structTreeRoot; // structure tree root dictionary + Object outline; // outline dictionary + Object acroForm; // AcroForm dictionary + GBool needsRendering; // NeedsRendering flag + AcroForm *form; // parsed form + Object ocProperties; // OCProperties dictionary + GList *embeddedFiles; // embedded file list [EmbeddedFile] + GList *pageLabels; // page labels [PageLabelNode] + Object viewerPrefs; // ViewerPreferences object + GBool ok; // true if catalog is valid + + 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); + void readPageLabelTree(Object *root); + void readPageLabelTree2(Object *node); + PageLabelNode *findPageLabel(int pageNum); + GString *makeRomanNumeral(int num, GBool uppercase); + GString *makeLetterLabel(int num, GBool uppercase); + GBool convertPageLabelToInt(TextString *pageLabel, int prefixLength, + char style, int *n); +}; + +#endif diff --git a/xpdf/CharCodeToUnicode.cc b/xpdf/CharCodeToUnicode.cc new file mode 100644 index 0000000..0a2100f --- /dev/null +++ b/xpdf/CharCodeToUnicode.cc @@ -0,0 +1,755 @@ +//======================================================================== +// +// CharCodeToUnicode.cc +// +// Copyright 2001-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include +#include "gmem.h" +#include "gmempp.h" +#include "gfile.h" +#include "GString.h" +#include "Error.h" +#include "GlobalParams.h" +#include "PSTokenizer.h" +#include "CharCodeToUnicode.h" + +//------------------------------------------------------------------------ + +#define maxUnicodeString 8 + +struct CharCodeToUnicodeString { + CharCode c; + Unicode u[maxUnicodeString]; + int len; +}; + +//------------------------------------------------------------------------ + +struct GStringIndex { + GString *s; + int i; +}; + +static int getCharFromGString(void *data) { + GStringIndex *idx = (GStringIndex *)data; + if (idx->i >= idx->s->getLength()) { + return EOF; + } + return idx->s->getChar(idx->i++) & 0xff; +} + +static int getCharFromFile(void *data) { + return fgetc((FILE *)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 -byte hex string into *. 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; + Unicode *mapA; + CharCode size, mapLenA; + char buf[64]; + Unicode u; + CharCodeToUnicode *ctu; + + if (!(f = openFile(fileName->getCString(), "r"))) { + error(errSyntaxError, -1, "Couldn't open cidToUnicode file '{0:t}'", + fileName); + return NULL; + } + + size = 32768; + mapA = (Unicode *)gmallocn(size, sizeof(Unicode)); + mapLenA = 0; + + while (getLine(buf, sizeof(buf), f)) { + if (mapLenA == size) { + size *= 2; + mapA = (Unicode *)greallocn(mapA, size, sizeof(Unicode)); + } + if (sscanf(buf, "%x", &u) == 1) { + mapA[mapLenA] = u; + } else { + error(errSyntaxWarning, -1, + "Bad line ({0:d}) in cidToUnicode file '{1:t}'", + (int)(mapLenA + 1), fileName); + mapA[mapLenA] = 0; + } + ++mapLenA; + } + fclose(f); + + ctu = new CharCodeToUnicode(collection->copy(), mapA, mapLenA, gTrue, + NULL, 0, 0); + gfree(mapA); + return ctu; +} + +CharCodeToUnicode *CharCodeToUnicode::parseUnicodeToUnicode( + GString *fileName) { + FILE *f; + Unicode *mapA; + CharCodeToUnicodeString *sMapA; + CharCode size, oldSize, len, sMapSizeA, sMapLenA; + char buf[256]; + char *tok; + Unicode u0; + Unicode uBuf[maxUnicodeString]; + CharCodeToUnicode *ctu; + int line, n, i; + + if (!(f = openFile(fileName->getCString(), "r"))) { + error(errSyntaxError, -1, "Couldn't open unicodeToUnicode file '{0:t}'", + fileName); + return NULL; + } + + size = 4096; + mapA = (Unicode *)gmallocn(size, sizeof(Unicode)); + memset(mapA, 0, size * sizeof(Unicode)); + len = 0; + sMapA = NULL; + sMapSizeA = sMapLenA = 0; + + line = 0; + while (getLine(buf, sizeof(buf), f)) { + ++line; + if (!(tok = strtok(buf, " \t\r\n")) || + !parseHex(tok, (int)strlen(tok), &u0)) { + error(errSyntaxWarning, -1, + "Bad line ({0:d}) in unicodeToUnicode file '{1:t}'", + line, fileName); + continue; + } + n = 0; + while (n < maxUnicodeString) { + if (!(tok = strtok(NULL, " \t\r\n"))) { + break; + } + if (!parseHex(tok, (int)strlen(tok), &uBuf[n])) { + error(errSyntaxWarning, -1, + "Bad line ({0:d}) in unicodeToUnicode file '{1:t}'", + line, fileName); + break; + } + ++n; + } + if (n < 1) { + error(errSyntaxWarning, -1, + "Bad line ({0:d}) in unicodeToUnicode file '{1:t}'", + line, fileName); + continue; + } + if (u0 >= size) { + oldSize = size; + while (u0 >= size) { + size *= 2; + } + mapA = (Unicode *)greallocn(mapA, size, sizeof(Unicode)); + memset(mapA + oldSize, 0, (size - oldSize) * sizeof(Unicode)); + } + if (n == 1) { + mapA[u0] = uBuf[0]; + } else { + mapA[u0] = 0; + if (sMapLenA == sMapSizeA) { + sMapSizeA += 16; + sMapA = (CharCodeToUnicodeString *) + greallocn(sMapA, sMapSizeA, sizeof(CharCodeToUnicodeString)); + } + sMapA[sMapLenA].c = u0; + for (i = 0; i < n; ++i) { + sMapA[sMapLenA].u[i] = uBuf[i]; + } + sMapA[sMapLenA].len = n; + ++sMapLenA; + } + if (u0 >= len) { + len = u0 + 1; + } + } + fclose(f); + + ctu = new CharCodeToUnicode(fileName->copy(), mapA, len, gTrue, + sMapA, sMapLenA, sMapSizeA); + gfree(mapA); + return ctu; +} + +CharCodeToUnicode *CharCodeToUnicode::make8BitToUnicode(Unicode *toUnicode) { + return new CharCodeToUnicode(NULL, toUnicode, 256, gTrue, NULL, 0, 0); +} + +CharCodeToUnicode *CharCodeToUnicode::make16BitToUnicode(Unicode *toUnicode) { + return new CharCodeToUnicode(NULL, toUnicode, 65536, gTrue, NULL, 0, 0); +} + +CharCodeToUnicode *CharCodeToUnicode::parseCMap(GString *buf, int nBits) { + CharCodeToUnicode *ctu; + GStringIndex idx; + + ctu = new CharCodeToUnicode(NULL); + idx.s = buf; + idx.i = 0; + if (!ctu->parseCMap1(&getCharFromGString, &idx, nBits)) { + delete ctu; + return NULL; + } + return ctu; +} + +void CharCodeToUnicode::mergeCMap(GString *buf, int nBits) { + GStringIndex idx; + + idx.s = buf; + idx.i = 0; + parseCMap1(&getCharFromGString, &idx, nBits); +} + +GBool CharCodeToUnicode::parseCMap1(int (*getCharFunc)(void *), void *data, + int nBits) { + PSTokenizer *pst; + char tok1[256], tok2[256], tok3[256]; + int n1, n2, n3; + CharCode i; + CharCode maxCode, code1, code2; + GString *name; + FILE *f; + GBool ok; + + ok = gFalse; + 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)) { + if (!strcmp(tok2, "usecmap")) { + if (tok1[0] == '/') { + name = new GString(tok1 + 1); + if ((f = globalParams->findToUnicodeFile(name))) { + if (parseCMap1(&getCharFromFile, f, nBits)) { + ok = gTrue; + } + fclose(f); + } else { + error(errSyntaxError, -1, + "Couldn't find ToUnicode CMap file for '{1:t}'", + name); + } + delete name; + } + pst->getToken(tok1, sizeof(tok1), &n1); + } else if (!strcmp(tok2, "beginbfchar")) { + while (pst->getToken(tok1, sizeof(tok1), &n1)) { + if (!strcmp(tok1, "endbfchar")) { + break; + } + if (!pst->getToken(tok2, sizeof(tok2), &n2) || + !strcmp(tok2, "endbfchar")) { + error(errSyntaxWarning, -1, + "Illegal entry in bfchar block in ToUnicode CMap"); + break; + } + if (!(tok1[0] == '<' && tok1[n1 - 1] == '>' && + tok2[0] == '<' && tok2[n2 - 1] == '>')) { + error(errSyntaxWarning, -1, + "Illegal entry in bfchar block in ToUnicode CMap"); + continue; + } + tok1[n1 - 1] = tok2[n2 - 1] = '\0'; + 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); + ok = gTrue; + } + pst->getToken(tok1, sizeof(tok1), &n1); + } else if (!strcmp(tok2, "beginbfrange")) { + while (pst->getToken(tok1, sizeof(tok1), &n1)) { + if (!strcmp(tok1, "endbfrange")) { + break; + } + if (!pst->getToken(tok2, sizeof(tok2), &n2) || + !strcmp(tok2, "endbfrange") || + !pst->getToken(tok3, sizeof(tok3), &n3) || + !strcmp(tok3, "endbfrange")) { + error(errSyntaxWarning, -1, + "Illegal entry in bfrange block in ToUnicode CMap"); + break; + } + 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 (!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 (code2 > maxCode) { + code2 = maxCode; + } + } + if (!strcmp(tok3, "[")) { + i = 0; + while (pst->getToken(tok1, sizeof(tok1), &n1)) { + if (!strcmp(tok1, "]")) { + break; + } + if (tok1[0] == '<' && tok1[n1 - 1] == '>') { + if (code1 + i <= code2) { + tok1[n1 - 1] = '\0'; + addMapping(code1 + i, tok1 + 1, n1 - 2, 0); + ok = gTrue; + } + } else { + error(errSyntaxWarning, -1, + "Illegal entry in bfrange block in ToUnicode CMap"); + } + ++i; + } + } else if (tok3[0] == '<' && tok3[n3 - 1] == '>') { + tok3[n3 - 1] = '\0'; + for (i = 0; code1 <= code2; ++code1, ++i) { + addMapping(code1, tok3 + 1, n3 - 2, i); + ok = gTrue; + } + } else { + error(errSyntaxWarning, -1, + "Illegal entry in bfrange block in ToUnicode CMap"); + } + } + pst->getToken(tok1, sizeof(tok1), &n1); + } else if (!strcmp(tok2, "begincidchar")) { + // the begincidchar operator is not allowed in ToUnicode CMaps, + // but some buggy PDF generators incorrectly use + // code-to-CID-type CMaps here + error(errSyntaxWarning, -1, + "Invalid 'begincidchar' operator in ToUnicode CMap"); + while (pst->getToken(tok1, sizeof(tok1), &n1)) { + if (!strcmp(tok1, "endcidchar")) { + break; + } + if (!pst->getToken(tok2, sizeof(tok2), &n2) || + !strcmp(tok2, "endcidchar")) { + error(errSyntaxWarning, -1, + "Illegal entry in cidchar block in ToUnicode CMap"); + break; + } + if (!(tok1[0] == '<' && tok1[n1 - 1] == '>')) { + error(errSyntaxWarning, -1, + "Illegal entry in cidchar block in ToUnicode CMap"); + continue; + } + tok1[n1 - 1] = '\0'; + if (!parseHex(tok1 + 1, n1 - 2, &code1)) { + error(errSyntaxWarning, -1, + "Illegal entry in cidchar block in ToUnicode CMap"); + continue; + } + if (code1 > maxCode) { + error(errSyntaxWarning, -1, + "Invalid entry in cidchar block in ToUnicode CMap"); + } + addMappingInt(code1, atoi(tok2)); + ok = gTrue; + } + pst->getToken(tok1, sizeof(tok1), &n1); + } else if (!strcmp(tok2, "begincidrange")) { + // the begincidrange operator is not allowed in ToUnicode CMaps, + // but some buggy PDF generators incorrectly use + // code-to-CID-type CMaps here + error(errSyntaxWarning, -1, + "Invalid 'begincidrange' operator in ToUnicode CMap"); + while (pst->getToken(tok1, sizeof(tok1), &n1)) { + if (!strcmp(tok1, "endcidrange")) { + break; + } + if (!pst->getToken(tok2, sizeof(tok2), &n2) || + !strcmp(tok2, "endcidrange") || + !pst->getToken(tok3, sizeof(tok3), &n3) || + !strcmp(tok3, "endcidrange")) { + error(errSyntaxWarning, -1, + "Illegal entry in cidrange block in ToUnicode CMap"); + break; + } + if (!(tok1[0] == '<' && tok1[n1 - 1] == '>' && + tok2[0] == '<' && tok2[n2 - 1] == '>')) { + error(errSyntaxWarning, + -1, "Illegal entry in cidrange block in ToUnicode CMap"); + continue; + } + tok1[n1 - 1] = tok2[n2 - 1] = '\0'; + if (!parseHex(tok1 + 1, n1 - 2, &code1) || + !parseHex(tok2 + 1, n2 - 2, &code2)) { + error(errSyntaxWarning, -1, + "Illegal entry in cidrange block in ToUnicode CMap"); + continue; + } + if (code1 > maxCode || code2 > maxCode) { + error(errSyntaxWarning, -1, + "Invalid entry in cidrange block in ToUnicode CMap"); + if (code2 > maxCode) { + code2 = maxCode; + } + } + for (i = atoi(tok3); code1 <= code2; ++code1, ++i) { + addMappingInt(code1, i); + ok = gTrue; + } + } + pst->getToken(tok1, sizeof(tok1), &n1); + } else { + strcpy(tok1, tok2); + } + } + delete pst; + return ok; +} + +void CharCodeToUnicode::addMapping(CharCode code, char *uStr, int n, + int offset) { + CharCode oldLen, i; + Unicode u[maxUnicodeString]; + int uLen, j; + + if (code > 0xffffff) { + // This is an arbitrary limit to avoid integer overflow issues. + // (I've seen CMaps with mappings for .) + return; + } + if ((uLen = parseUTF16String(uStr, n, u)) == 0) { + return; + } + if (code >= mapLen) { + oldLen = mapLen; + 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 (uLen == 1) { + map[code] = u[0] + offset; + } else { + if (sMapLen >= sMapSize) { + sMapSize = sMapSize + 16; + sMap = (CharCodeToUnicodeString *) + greallocn(sMap, sMapSize, sizeof(CharCodeToUnicodeString)); + } + map[code] = 0; + sMap[sMapLen].c = code; + for (j = 0; j < uLen; ++j) { + sMap[sMapLen].u[j] = u[j]; + } + sMap[sMapLen].u[uLen - 1] += offset; + sMap[sMapLen].len = uLen; + ++sMapLen; + } +} + +// Convert a UTF-16BE hex string into a sequence of up to +// maxUnicodeString Unicode chars. +int CharCodeToUnicode::parseUTF16String(char *uStr, int n, Unicode *uOut) { + int i = 0; + int uLen = 0; + while (i < n) { + Unicode u; + int j = n; + if (j - i > 4) { + j = i + 4; + } + if (!parseHex(uStr + i, j - i, &u)) { + error(errSyntaxWarning, -1, "Illegal entry in ToUnicode CMap"); + return 0; + } + // look for a UTF-16 pair + if (uLen > 0 && uOut[uLen-1] >= 0xd800 && uOut[uLen-1] <= 0xdbff && + u >= 0xdc00 && u <= 0xdfff) { + uOut[uLen-1] = 0x10000 + ((uOut[uLen-1] & 0x03ff) << 10) + (u & 0x03ff); + } else { + if (uLen < maxUnicodeString) { + uOut[uLen++] = u; + } + } + i = j; + } + return uLen; +} + +void CharCodeToUnicode::addMappingInt(CharCode code, Unicode u) { + CharCode oldLen, i; + + if (code > 0xffffff) { + // This is an arbitrary limit to avoid integer overflow issues. + // (I've seen CMaps with mappings for .) + return; + } + if (code >= mapLen) { + oldLen = mapLen; + 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; + } + } + map[code] = u; +} + +CharCodeToUnicode::CharCodeToUnicode() { + tag = NULL; + map = NULL; + mapLen = 0; + sMap = NULL; + sMapLen = sMapSize = 0; + refCnt = 1; +} + +CharCodeToUnicode::CharCodeToUnicode(GString *tagA) { + CharCode i; + + tag = tagA; + mapLen = 256; + map = (Unicode *)gmallocn(mapLen, sizeof(Unicode)); + for (i = 0; i < mapLen; ++i) { + map[i] = 0; + } + sMap = NULL; + sMapLen = sMapSize = 0; + refCnt = 1; +} + +CharCodeToUnicode::CharCodeToUnicode(GString *tagA, Unicode *mapA, + CharCode mapLenA, GBool copyMap, + CharCodeToUnicodeString *sMapA, + int sMapLenA, int sMapSizeA) { + tag = tagA; + mapLen = mapLenA; + if (copyMap) { + map = (Unicode *)gmallocn(mapLen, sizeof(Unicode)); + memcpy(map, mapA, mapLen * sizeof(Unicode)); + } else { + map = mapA; + } + sMap = sMapA; + sMapLen = sMapLenA; + sMapSize = sMapSizeA; + refCnt = 1; +} + +CharCodeToUnicode::~CharCodeToUnicode() { + if (tag) { + delete tag; + } + gfree(map); + gfree(sMap); +} + +void CharCodeToUnicode::incRefCnt() { +#if MULTITHREADED + gAtomicIncrement(&refCnt); +#else + ++refCnt; +#endif +} + +void CharCodeToUnicode::decRefCnt() { + GBool done; + +#if MULTITHREADED + done = gAtomicDecrement(&refCnt) == 0; +#else + done = --refCnt == 0; +#endif + if (done) { + delete this; + } +} + +GBool CharCodeToUnicode::match(GString *tagA) { + return tag && !tag->cmp(tagA); +} + +void CharCodeToUnicode::setMapping(CharCode c, Unicode *u, int len) { + int i, j; + + if (!map) { + return; + } + if (len == 1) { + map[c] = u[0]; + } else { + for (i = 0; i < sMapLen; ++i) { + if (sMap[i].c == c) { + break; + } + } + if (i == sMapLen) { + if (sMapLen == sMapSize) { + sMapSize += 8; + sMap = (CharCodeToUnicodeString *) + greallocn(sMap, sMapSize, sizeof(CharCodeToUnicodeString)); + } + ++sMapLen; + } + map[c] = 0; + sMap[i].c = c; + sMap[i].len = len; + for (j = 0; j < len && j < maxUnicodeString; ++j) { + sMap[i].u[j] = u[j]; + } + } +} + +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; + } + if (map[c]) { + u[0] = map[c]; + return 1; + } + for (i = 0; i < sMapLen; ++i) { + if (sMap[i].c == c) { + for (j = 0; j < sMap[i].len && j < size; ++j) { + u[j] = sMap[i].u[j]; + } + return j; + } + } + return 0; +} + +//------------------------------------------------------------------------ + +CharCodeToUnicodeCache::CharCodeToUnicodeCache(int sizeA) { + int i; + + size = sizeA; + cache = (CharCodeToUnicode **)gmallocn(size, sizeof(CharCodeToUnicode *)); + for (i = 0; i < size; ++i) { + cache[i] = NULL; + } +} + +CharCodeToUnicodeCache::~CharCodeToUnicodeCache() { + int i; + + for (i = 0; i < size; ++i) { + if (cache[i]) { + cache[i]->decRefCnt(); + } + } + gfree(cache); +} + +CharCodeToUnicode *CharCodeToUnicodeCache::getCharCodeToUnicode(GString *tag) { + CharCodeToUnicode *ctu; + int i, j; + + if (cache[0] && cache[0]->match(tag)) { + cache[0]->incRefCnt(); + return cache[0]; + } + for (i = 1; i < size; ++i) { + if (cache[i] && cache[i]->match(tag)) { + ctu = cache[i]; + for (j = i; j >= 1; --j) { + cache[j] = cache[j - 1]; + } + cache[0] = ctu; + ctu->incRefCnt(); + return ctu; + } + } + return NULL; +} + +void CharCodeToUnicodeCache::add(CharCodeToUnicode *ctu) { + int i; + + if (cache[size - 1]) { + cache[size - 1]->decRefCnt(); + } + for (i = size - 1; i >= 1; --i) { + cache[i] = cache[i - 1]; + } + cache[0] = ctu; + ctu->incRefCnt(); +} diff --git a/xpdf/CharCodeToUnicode.h b/xpdf/CharCodeToUnicode.h new file mode 100644 index 0000000..be90251 --- /dev/null +++ b/xpdf/CharCodeToUnicode.h @@ -0,0 +1,131 @@ +//======================================================================== +// +// CharCodeToUnicode.h +// +// Mapping from character codes to Unicode. +// +// Copyright 2001-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef CHARCODETOUNICODE_H +#define CHARCODETOUNICODE_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "CharTypes.h" + +#if MULTITHREADED +#include "GMutex.h" +#endif + +struct CharCodeToUnicodeString; + +//------------------------------------------------------------------------ + +class CharCodeToUnicode { +public: + + // Create an identity mapping (Unicode = CharCode). + static CharCodeToUnicode *makeIdentityMapping(); + + // Read the CID-to-Unicode mapping for from the file + // specified by . Sets the initial reference count to 1. + // Returns NULL on failure. + static CharCodeToUnicode *parseCIDToUnicode(GString *fileName, + GString *collection); + + // Create a Unicode-to-Unicode mapping from the file specified by + // . Sets the initial reference count to 1. Returns NULL + // on failure. + static CharCodeToUnicode *parseUnicodeToUnicode(GString *fileName); + + // Create the CharCode-to-Unicode mapping for an 8-bit font. + // is an array of 256 Unicode indexes. Sets the initial + // reference count to 1. + static CharCodeToUnicode *make8BitToUnicode(Unicode *toUnicode); + + // Create the CharCode-to-Unicode mapping for a 16-bit font. + // is an array of 65536 Unicode indexes. Sets the + // initial reference count to 1. + static CharCodeToUnicode *make16BitToUnicode(Unicode *toUnicode); + + // Parse a ToUnicode CMap for an 8- or 16-bit font. + static CharCodeToUnicode *parseCMap(GString *buf, int nBits); + + // Parse a ToUnicode CMap for an 8- or 16-bit font, merging it into + // . + void mergeCMap(GString *buf, int nBits); + + ~CharCodeToUnicode(); + + void incRefCnt(); + void decRefCnt(); + + // Return true if this mapping matches the specified . + GBool match(GString *tagA); + + // Set the mapping for . + void setMapping(CharCode c, Unicode *u, int len); + + // Map a CharCode to Unicode. + int mapToUnicode(CharCode c, Unicode *u, int size); + + // Return the mapping's length, i.e., one more than the max char + // code supported by the mapping. + CharCode getLength() { return mapLen; } + + GBool isIdentity() { return !map; } + +private: + + GBool parseCMap1(int (*getCharFunc)(void *), void *data, int nBits); + void addMapping(CharCode code, char *uStr, int n, int offset); + int parseUTF16String(char *uStr, int n, Unicode *uOut); + void addMappingInt(CharCode code, Unicode u); + CharCodeToUnicode(); + CharCodeToUnicode(GString *tagA); + CharCodeToUnicode(GString *tagA, Unicode *mapA, + CharCode mapLenA, GBool copyMap, + CharCodeToUnicodeString *sMapA, + int sMapLenA, int sMapSizeA); + + GString *tag; + Unicode *map; + CharCode mapLen; + CharCodeToUnicodeString *sMap; + int sMapLen, sMapSize; +#if MULTITHREADED + GAtomicCounter refCnt; +#else + int refCnt; +#endif +}; + +//------------------------------------------------------------------------ + +class CharCodeToUnicodeCache { +public: + + CharCodeToUnicodeCache(int sizeA); + ~CharCodeToUnicodeCache(); + + // Get the CharCodeToUnicode object for . Increments its + // reference count; there will be one reference for the cache plus + // one for the caller of this function. Returns NULL on failure. + CharCodeToUnicode *getCharCodeToUnicode(GString *tag); + + // Insert into the cache, in the most-recently-used position. + void add(CharCodeToUnicode *ctu); + +private: + + CharCodeToUnicode **cache; + int size; +}; + +#endif diff --git a/xpdf/CharTypes.h b/xpdf/CharTypes.h new file mode 100644 index 0000000..d0df630 --- /dev/null +++ b/xpdf/CharTypes.h @@ -0,0 +1,24 @@ +//======================================================================== +// +// CharTypes.h +// +// Copyright 2001-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef CHARTYPES_H +#define CHARTYPES_H + +// Unicode character. +typedef unsigned int Unicode; + +// Character ID for CID character collections. +typedef unsigned int CID; + +// This is large enough to hold any of the following: +// - 8-bit char code +// - 16-bit CID +// - Unicode +typedef unsigned int CharCode; + +#endif diff --git a/xpdf/CompactFontTables.h b/xpdf/CompactFontTables.h new file mode 100644 index 0000000..28e16e7 --- /dev/null +++ b/xpdf/CompactFontTables.h @@ -0,0 +1,464 @@ +//======================================================================== +// +// CompactFontTables.h +// +// Copyright 1999-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef COMPACTFONTINFO_H +#define COMPACTFONTINFO_H + +static char *type1CStdStrings[391] = { + ".notdef", + "space", + "exclam", + "quotedbl", + "numbersign", + "dollar", + "percent", + "ampersand", + "quoteright", + "parenleft", + "parenright", + "asterisk", + "plus", + "comma", + "hyphen", + "period", + "slash", + "zero", + "one", + "two", + "three", + "four", + "five", + "six", + "seven", + "eight", + "nine", + "colon", + "semicolon", + "less", + "equal", + "greater", + "question", + "at", + "A", + "B", + "C", + "D", + "E", + "F", + "G", + "H", + "I", + "J", + "K", + "L", + "M", + "N", + "O", + "P", + "Q", + "R", + "S", + "T", + "U", + "V", + "W", + "X", + "Y", + "Z", + "bracketleft", + "backslash", + "bracketright", + "asciicircum", + "underscore", + "quoteleft", + "a", + "b", + "c", + "d", + "e", + "f", + "g", + "h", + "i", + "j", + "k", + "l", + "m", + "n", + "o", + "p", + "q", + "r", + "s", + "t", + "u", + "v", + "w", + "x", + "y", + "z", + "braceleft", + "bar", + "braceright", + "asciitilde", + "exclamdown", + "cent", + "sterling", + "fraction", + "yen", + "florin", + "section", + "currency", + "quotesingle", + "quotedblleft", + "guillemotleft", + "guilsinglleft", + "guilsinglright", + "fi", + "fl", + "endash", + "dagger", + "daggerdbl", + "periodcentered", + "paragraph", + "bullet", + "quotesinglbase", + "quotedblbase", + "quotedblright", + "guillemotright", + "ellipsis", + "perthousand", + "questiondown", + "grave", + "acute", + "circumflex", + "tilde", + "macron", + "breve", + "dotaccent", + "dieresis", + "ring", + "cedilla", + "hungarumlaut", + "ogonek", + "caron", + "emdash", + "AE", + "ordfeminine", + "Lslash", + "Oslash", + "OE", + "ordmasculine", + "ae", + "dotlessi", + "lslash", + "oslash", + "oe", + "germandbls", + "onesuperior", + "logicalnot", + "mu", + "trademark", + "Eth", + "onehalf", + "plusminus", + "Thorn", + "onequarter", + "divide", + "brokenbar", + "degree", + "thorn", + "threequarters", + "twosuperior", + "registered", + "minus", + "eth", + "multiply", + "threesuperior", + "copyright", + "Aacute", + "Acircumflex", + "Adieresis", + "Agrave", + "Aring", + "Atilde", + "Ccedilla", + "Eacute", + "Ecircumflex", + "Edieresis", + "Egrave", + "Iacute", + "Icircumflex", + "Idieresis", + "Igrave", + "Ntilde", + "Oacute", + "Ocircumflex", + "Odieresis", + "Ograve", + "Otilde", + "Scaron", + "Uacute", + "Ucircumflex", + "Udieresis", + "Ugrave", + "Yacute", + "Ydieresis", + "Zcaron", + "aacute", + "acircumflex", + "adieresis", + "agrave", + "aring", + "atilde", + "ccedilla", + "eacute", + "ecircumflex", + "edieresis", + "egrave", + "iacute", + "icircumflex", + "idieresis", + "igrave", + "ntilde", + "oacute", + "ocircumflex", + "odieresis", + "ograve", + "otilde", + "scaron", + "uacute", + "ucircumflex", + "udieresis", + "ugrave", + "yacute", + "ydieresis", + "zcaron", + "exclamsmall", + "Hungarumlautsmall", + "dollaroldstyle", + "dollarsuperior", + "ampersandsmall", + "Acutesmall", + "parenleftsuperior", + "parenrightsuperior", + "twodotenleader", + "onedotenleader", + "zerooldstyle", + "oneoldstyle", + "twooldstyle", + "threeoldstyle", + "fouroldstyle", + "fiveoldstyle", + "sixoldstyle", + "sevenoldstyle", + "eightoldstyle", + "nineoldstyle", + "commasuperior", + "threequartersemdash", + "periodsuperior", + "questionsmall", + "asuperior", + "bsuperior", + "centsuperior", + "dsuperior", + "esuperior", + "isuperior", + "lsuperior", + "msuperior", + "nsuperior", + "osuperior", + "rsuperior", + "ssuperior", + "tsuperior", + "ff", + "ffi", + "ffl", + "parenleftinferior", + "parenrightinferior", + "Circumflexsmall", + "hyphensuperior", + "Gravesmall", + "Asmall", + "Bsmall", + "Csmall", + "Dsmall", + "Esmall", + "Fsmall", + "Gsmall", + "Hsmall", + "Ismall", + "Jsmall", + "Ksmall", + "Lsmall", + "Msmall", + "Nsmall", + "Osmall", + "Psmall", + "Qsmall", + "Rsmall", + "Ssmall", + "Tsmall", + "Usmall", + "Vsmall", + "Wsmall", + "Xsmall", + "Ysmall", + "Zsmall", + "colonmonetary", + "onefitted", + "rupiah", + "Tildesmall", + "exclamdownsmall", + "centoldstyle", + "Lslashsmall", + "Scaronsmall", + "Zcaronsmall", + "Dieresissmall", + "Brevesmall", + "Caronsmall", + "Dotaccentsmall", + "Macronsmall", + "figuredash", + "hypheninferior", + "Ogoneksmall", + "Ringsmall", + "Cedillasmall", + "questiondownsmall", + "oneeighth", + "threeeighths", + "fiveeighths", + "seveneighths", + "onethird", + "twothirds", + "zerosuperior", + "foursuperior", + "fivesuperior", + "sixsuperior", + "sevensuperior", + "eightsuperior", + "ninesuperior", + "zeroinferior", + "oneinferior", + "twoinferior", + "threeinferior", + "fourinferior", + "fiveinferior", + "sixinferior", + "seveninferior", + "eightinferior", + "nineinferior", + "centinferior", + "dollarinferior", + "periodinferior", + "commainferior", + "Agravesmall", + "Aacutesmall", + "Acircumflexsmall", + "Atildesmall", + "Adieresissmall", + "Aringsmall", + "AEsmall", + "Ccedillasmall", + "Egravesmall", + "Eacutesmall", + "Ecircumflexsmall", + "Edieresissmall", + "Igravesmall", + "Iacutesmall", + "Icircumflexsmall", + "Idieresissmall", + "Ethsmall", + "Ntildesmall", + "Ogravesmall", + "Oacutesmall", + "Ocircumflexsmall", + "Otildesmall", + "Odieresissmall", + "OEsmall", + "Oslashsmall", + "Ugravesmall", + "Uacutesmall", + "Ucircumflexsmall", + "Udieresissmall", + "Yacutesmall", + "Thornsmall", + "Ydieresissmall", + "001.000", + "001.001", + "001.002", + "001.003", + "Black", + "Bold", + "Book", + "Light", + "Medium", + "Regular", + "Roman", + "Semibold" +}; + +static Gushort type1CISOAdobeCharset[229] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, + 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, + 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, + 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, + 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, + 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, + 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, + 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, + 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, + 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, + 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, + 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, + 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, + 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, + 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, + 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, + 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, + 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, + 220, 221, 222, 223, 224, 225, 226, 227, 228 +}; + +static Gushort type1CExpertCharset[166] = { + 0, 1, 229, 230, 231, 232, 233, 234, 235, 236, + 237, 238, 13, 14, 15, 99, 239, 240, 241, 242, + 243, 244, 245, 246, 247, 248, 27, 28, 249, 250, + 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, + 261, 262, 263, 264, 265, 266, 109, 110, 267, 268, + 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, + 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, + 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, + 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, + 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, + 158, 155, 163, 319, 320, 321, 322, 323, 324, 325, + 326, 150, 164, 169, 327, 328, 329, 330, 331, 332, + 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, + 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, + 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, + 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, + 373, 374, 375, 376, 377, 378 +}; + +static Gushort type1CExpertSubsetCharset[87] = { + 0, 1, 231, 232, 235, 236, 237, 238, 13, 14, + 15, 99, 239, 240, 241, 242, 243, 244, 245, 246, + 247, 248, 27, 28, 249, 250, 251, 253, 254, 255, + 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, + 266, 109, 110, 267, 268, 269, 270, 272, 300, 301, + 302, 305, 314, 315, 158, 155, 163, 320, 321, 322, + 323, 324, 325, 326, 150, 164, 169, 327, 328, 329, + 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, + 340, 341, 342, 343, 344, 345, 346 +}; + +#endif diff --git a/xpdf/Decrypt.cc b/xpdf/Decrypt.cc new file mode 100644 index 0000000..d4f8d4e --- /dev/null +++ b/xpdf/Decrypt.cc @@ -0,0 +1,1620 @@ +//======================================================================== +// +// Decrypt.cc +// +// Copyright 1996-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include "gmem.h" +#include "gmempp.h" +#include "Decrypt.h" + +static void aes256KeyExpansion(DecryptAES256State *s, + Guchar *objKey, int objKeyLen); +static void aes256DecryptBlock(DecryptAES256State *s, Guchar *in, GBool last); +static void sha256(Guchar *msg, int msgLen, Guchar *hash); +static void sha384(Guchar *msg, int msgLen, Guchar *hash); +static void sha512(Guchar *msg, int msgLen, Guchar *hash); + +static Guchar passwordPad[32] = { + 0x28, 0xbf, 0x4e, 0x5e, 0x4e, 0x75, 0x8a, 0x41, + 0x64, 0x00, 0x4e, 0x56, 0xff, 0xfa, 0x01, 0x08, + 0x2e, 0x2e, 0x00, 0xb6, 0xd0, 0x68, 0x3e, 0x80, + 0x2f, 0x0c, 0xa9, 0xfe, 0x64, 0x53, 0x69, 0x7a +}; + +//------------------------------------------------------------------------ +// Decrypt +//------------------------------------------------------------------------ + +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) { + DecryptAES256State state; + Guchar test[127 + 56], test2[32]; + GString *userPassword2; + const char *userPW; + Guchar fState[256]; + Guchar tmpKey[16]; + Guchar fx, fy; + int len, i, j; + + *ownerPasswordOk = gFalse; + + if (encRevision == 5 || encRevision == 6) { + + // 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, ownerKey->getCString() + 32, 8); + memcpy(test + len + 8, userKey->getCString(), 48); + sha256(test, len + 56, test); + if (encRevision == 6) { + r6Hash(test, 32, ownerPassword->getCString(), len, + userKey->getCString()); + } + if (!memcmp(test, ownerKey->getCString(), 32)) { + + // compute the file key from the owner password + memcpy(test, ownerPassword->getCString(), len); + memcpy(test + len, ownerKey->getCString() + 40, 8); + memcpy(test + len + 8, userKey->getCString(), 48); + sha256(test, len + 56, test); + if (encRevision == 6) { + r6Hash(test, 32, ownerPassword->getCString(), len, + userKey->getCString()); + } + aes256KeyExpansion(&state, test, 32); + for (i = 0; i < 16; ++i) { + state.cbc[i] = 0; + } + 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; + } + } + + // check the user password + if (userPassword) { + //~ this is supposed to convert the password to UTF-8 using "SASLprep" + userPW = userPassword->getCString(); + len = userPassword->getLength(); + if (len > 127) { + len = 127; + } + } else { + userPW = ""; + len = 0; + } + memcpy(test, userPW, len); + memcpy(test + len, userKey->getCString() + 32, 8); + sha256(test, len + 8, test); + if (encRevision == 6) { + r6Hash(test, 32, userPW, len, NULL); + } + if (!memcmp(test, userKey->getCString(), 32)) { + + // compute the file key from the user password + memcpy(test, userPW, len); + memcpy(test + len, userKey->getCString() + 40, 8); + sha256(test, len + 8, test); + if (encRevision == 6) { + r6Hash(test, 32, userPW, len, NULL); + } + aes256KeyExpansion(&state, test, 32); + for (i = 0; i < 16; ++i) { + state.cbc[i] = 0; + } + aes256DecryptBlock(&state, (Guchar *)userEnc->getCString(), gFalse); + memcpy(fileKey, state.buf, 16); + aes256DecryptBlock(&state, (Guchar *)userEnc->getCString() + 16, + gFalse); + memcpy(fileKey + 16, state.buf, 16); + + return gTrue; + } + + return gFalse; + + } else { + + // try using the supplied owner password to generate the user password + 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); + } + md5(test, 32, test); + if (encRevision == 3) { + for (i = 0; i < 50; ++i) { + md5(test, keyLength, test); + } + } + 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)); + } + } else { + memcpy(test2, ownerKey->getCString(), 32); + for (i = 19; i >= 0; --i) { + for (j = 0; j < keyLength; ++j) { + tmpKey[j] = (Guchar)(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; + delete userPassword2; + return gTrue; + } + delete userPassword2; + } + + // try using the supplied user password + return makeFileKey2(encVersion, encRevision, keyLength, ownerKey, userKey, + permissions, fileID, userPassword, fileKey, + encryptMetadata); + } +} + +void Decrypt::r6Hash(Guchar *key, int keyLen, const char *pwd, int pwdLen, + char *userKey) { + Guchar key1[64*(127+64+48)]; + DecryptAESState state128; + int n, i, j, k; + + i = 0; + while (1) { + memcpy(key1, pwd, pwdLen); + memcpy(key1 + pwdLen, key, keyLen); + n = pwdLen + keyLen; + if (userKey) { + memcpy(key1 + pwdLen + keyLen, userKey, 48); + n += 48; + } + for (j = 1; j < 64; ++j) { + memcpy(key1 + j * n, key1, n); + } + n *= 64; + aesKeyExpansion(&state128, key, 16, gFalse); + for (j = 0; j < 16; ++j) { + state128.cbc[j] = key[16+j]; + } + for (j = 0; j < n; j += 16) { + aesEncryptBlock(&state128, key1 + j); + memcpy(key1 + j, state128.buf, 16); + } + k = 0; + for (j = 0; j < 16; ++j) { + k += key1[j] % 3; + } + k %= 3; + switch (k) { + case 0: + sha256(key1, n, key); + keyLen = 32; + break; + case 1: + sha384(key1, n, key); + keyLen = 48; + break; + case 2: + sha512(key1, n, key); + keyLen = 64; + break; + } + // from the spec, it appears that i should be incremented after + // the test, but that doesn't match what Adobe does + ++i; + if (i >= 64 && key1[n - 1] <= i - 32) { + break; + } + } +} + +GBool Decrypt::makeFileKey2(int encVersion, int encRevision, int keyLength, + GString *ownerKey, GString *userKey, + int permissions, GString *fileID, + GString *userPassword, Guchar *fileKey, + GBool encryptMetadata) { + Guchar *buf; + Guchar test[32]; + Guchar fState[256]; + Guchar tmpKey[16]; + Guchar fx, fy; + int len, i, j; + GBool ok; + + // generate file key + buf = (Guchar *)gmalloc(72 + fileID->getLength()); + if (userPassword) { + len = userPassword->getLength(); + if (len < 32) { + memcpy(buf, userPassword->getCString(), len); + memcpy(buf + len, passwordPad, 32 - len); + } else { + memcpy(buf, userPassword->getCString(), 32); + } + } else { + memcpy(buf, passwordPad, 32); + } + memcpy(buf + 32, ownerKey->getCString(), 32); + buf[64] = (Guchar)(permissions & 0xff); + buf[65] = (Guchar)((permissions >> 8) & 0xff); + buf[66] = (Guchar)((permissions >> 16) & 0xff); + buf[67] = (Guchar)((permissions >> 24) & 0xff); + memcpy(buf + 68, fileID->getCString(), fileID->getLength()); + len = 68 + fileID->getLength(); + if (!encryptMetadata) { + buf[len++] = 0xff; + buf[len++] = 0xff; + buf[len++] = 0xff; + buf[len++] = 0xff; + } + md5(buf, len, fileKey); + if (encRevision == 3) { + for (i = 0; i < 50; ++i) { + md5(fileKey, keyLength, fileKey); + } + } + + // test user password + if (encRevision == 2) { + rc4InitKey(fileKey, keyLength, fState); + fx = fy = 0; + for (i = 0; i < 32; ++i) { + test[i] = rc4DecryptByte(fState, &fx, &fy, userKey->getChar(i)); + } + ok = memcmp(test, passwordPad, 32) == 0; + } else if (encRevision == 3) { + memcpy(test, userKey->getCString(), 32); + for (i = 19; i >= 0; --i) { + for (j = 0; j < keyLength; ++j) { + tmpKey[j] = (Guchar)(fileKey[j] ^ i); + } + rc4InitKey(tmpKey, keyLength, fState); + fx = fy = 0; + for (j = 0; j < 32; ++j) { + test[j] = rc4DecryptByte(fState, &fx, &fy, test[j]); + } + } + memcpy(buf, passwordPad, 32); + memcpy(buf + 32, fileID->getCString(), fileID->getLength()); + md5(buf, 32 + fileID->getLength(), buf); + ok = memcmp(test, buf, 16) == 0; + } else { + ok = gFalse; + } + + gfree(buf); + return ok; +} + +//------------------------------------------------------------------------ +// DecryptStream +//------------------------------------------------------------------------ + +DecryptStream::DecryptStream(Stream *strA, Guchar *fileKeyA, + CryptAlgorithm algoA, int keyLengthA, + int objNumA, int objGenA): + FilterStream(strA) +{ + int i; + + memcpy(fileKey, fileKeyA, keyLengthA); + algo = algoA; + keyLength = keyLengthA; + objNum = objNumA; + objGen = objGenA; + + // construct object key + for (i = 0; i < keyLength; ++i) { + objKey[i] = fileKey[i]; + } + switch (algo) { + case cryptRC4: + objKey[keyLength] = (Guchar)(objNum & 0xff); + objKey[keyLength + 1] = (Guchar)((objNum >> 8) & 0xff); + objKey[keyLength + 2] = (Guchar)((objNum >> 16) & 0xff); + objKey[keyLength + 3] = (Guchar)(objGen & 0xff); + objKey[keyLength + 4] = (Guchar)((objGen >> 8) & 0xff); + md5(objKey, keyLength + 5, objKey); + if ((objKeyLength = keyLength + 5) > 16) { + objKeyLength = 16; + } + break; + case cryptAES: + objKey[keyLength] = (Guchar)(objNum & 0xff); + objKey[keyLength + 1] = (Guchar)((objNum >> 8) & 0xff); + objKey[keyLength + 2] = (Guchar)((objNum >> 16) & 0xff); + objKey[keyLength + 3] = (Guchar)(objGen & 0xff); + objKey[keyLength + 4] = (Guchar)((objGen >> 8) & 0xff); + objKey[keyLength + 5] = 0x73; // 's' + objKey[keyLength + 6] = 0x41; // 'A' + objKey[keyLength + 7] = 0x6c; // 'l' + objKey[keyLength + 8] = 0x54; // 'T' + md5(objKey, keyLength + 9, objKey); + if ((objKeyLength = keyLength + 5) > 16) { + objKeyLength = 16; + } + break; + case cryptAES256: + objKeyLength = keyLength; + break; + } +} + +DecryptStream::~DecryptStream() { + delete str; +} + +Stream *DecryptStream::copy() { + return new DecryptStream(str->copy(), fileKey, algo, keyLength, + objNum, objGen); +} + +void DecryptStream::reset() { + str->reset(); + switch (algo) { + case cryptRC4: + state.rc4.x = state.rc4.y = 0; + rc4InitKey(objKey, objKeyLength, state.rc4.state); + state.rc4.buf = EOF; + break; + case cryptAES: + aesKeyExpansion(&state.aes, objKey, objKeyLength, gTrue); + str->getBlock((char *)state.aes.cbc, 16); + state.aes.bufIdx = 16; + break; + case cryptAES256: + aes256KeyExpansion(&state.aes256, objKey, objKeyLength); + str->getBlock((char *)state.aes256.cbc, 16); + state.aes256.bufIdx = 16; + break; + } +} + +int DecryptStream::getChar() { + Guchar in[16]; + int c; + + c = EOF; // make gcc happy + switch (algo) { + case cryptRC4: + if (state.rc4.buf == EOF) { + c = str->getChar(); + if (c != EOF) { + state.rc4.buf = rc4DecryptByte(state.rc4.state, &state.rc4.x, + &state.rc4.y, (Guchar)c); + } + } + c = state.rc4.buf; + state.rc4.buf = EOF; + break; + case cryptAES: + if (state.aes.bufIdx == 16) { + if (str->getBlock((char *)in, 16) != 16) { + return EOF; + } + aesDecryptBlock(&state.aes, in, str->lookChar() == EOF); + } + if (state.aes.bufIdx == 16) { + c = EOF; + } else { + c = state.aes.buf[state.aes.bufIdx++]; + } + break; + case cryptAES256: + if (state.aes256.bufIdx == 16) { + if (str->getBlock((char *)in, 16) != 16) { + return EOF; + } + 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; +} + +int DecryptStream::lookChar() { + Guchar in[16]; + int c; + + c = EOF; // make gcc happy + switch (algo) { + case cryptRC4: + if (state.rc4.buf == EOF) { + c = str->getChar(); + if (c != EOF) { + state.rc4.buf = rc4DecryptByte(state.rc4.state, &state.rc4.x, + &state.rc4.y, (Guchar)c); + } + } + c = state.rc4.buf; + break; + case cryptAES: + if (state.aes.bufIdx == 16) { + if (str->getBlock((char *)in, 16) != 16) { + return EOF; + } + aesDecryptBlock(&state.aes, in, str->lookChar() == EOF); + } + if (state.aes.bufIdx == 16) { + c = EOF; + } else { + c = state.aes.buf[state.aes.bufIdx]; + } + break; + case cryptAES256: + if (state.aes256.bufIdx == 16) { + if (str->getBlock((char *)in, 16) != 16) { + return EOF; + } + 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; +} + +GBool DecryptStream::isBinary(GBool last) { + return str->isBinary(last); +} + +//------------------------------------------------------------------------ +// RC4-compatible decryption +//------------------------------------------------------------------------ + +void rc4InitKey(Guchar *key, int keyLen, Guchar *state) { + Guchar index1, index2; + Guchar t; + int i; + + for (i = 0; i < 256; ++i) + state[i] = (Guchar)i; + index1 = index2 = 0; + for (i = 0; i < 256; ++i) { + index2 = (Guchar)(key[index1] + state[i] + index2); + t = state[i]; + state[i] = state[index2]; + state[index2] = t; + index1 = (Guchar)((index1 + 1) % keyLen); + } +} + +Guchar rc4DecryptByte(Guchar *state, Guchar *x, Guchar *y, Guchar c) { + Guchar x1, y1, tx, ty; + + x1 = *x = (Guchar)(*x + 1); + y1 = *y = (Guchar)(state[*x] + *y); + tx = state[x1]; + ty = state[y1]; + state[x1] = ty; + state[y1] = tx; + return c ^ state[(tx + ty) % 256]; +} + +//------------------------------------------------------------------------ +// AES decryption +//------------------------------------------------------------------------ + +static Guchar sbox[256] = { + 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, + 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, + 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, + 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, + 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, + 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, + 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, + 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, + 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, + 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, + 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, + 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, + 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, + 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, + 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, + 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 +}; + +static Guchar invSbox[256] = { + 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, + 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, + 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, + 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, + 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, + 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, + 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, + 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, + 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, + 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, + 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, + 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, + 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, + 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, + 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, + 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d +}; + +static Guint rcon[11] = { + 0x00000000, // unused + 0x01000000, + 0x02000000, + 0x04000000, + 0x08000000, + 0x10000000, + 0x20000000, + 0x40000000, + 0x80000000, + 0x1b000000, + 0x36000000 +}; + +static inline Guint subWord(Guint x) { + return (sbox[x >> 24] << 24) + | (sbox[(x >> 16) & 0xff] << 16) + | (sbox[(x >> 8) & 0xff] << 8) + | sbox[x & 0xff]; +} + +static inline Guint rotWord(Guint x) { + return ((x << 8) & 0xffffffff) | (x >> 24); +} + +static inline void subBytes(Guchar *state) { + int i; + + for (i = 0; i < 16; ++i) { + state[i] = sbox[state[i]]; + } +} + +static inline void invSubBytes(Guchar *state) { + int i; + + for (i = 0; i < 16; ++i) { + state[i] = invSbox[state[i]]; + } +} + +static inline void shiftRows(Guchar *state) { + Guchar t; + + t = state[4]; + state[4] = state[5]; + state[5] = state[6]; + state[6] = state[7]; + state[7] = t; + + t = state[8]; + state[8] = state[10]; + state[10] = t; + t = state[9]; + state[9] = state[11]; + state[11] = t; + + t = state[15]; + state[15] = state[14]; + state[14] = state[13]; + state[13] = state[12]; + state[12] = t; +} + +static inline void invShiftRows(Guchar *state) { + Guchar t; + + t = state[7]; + state[7] = state[6]; + state[6] = state[5]; + state[5] = state[4]; + state[4] = t; + + t = state[8]; + state[8] = state[10]; + state[10] = t; + t = state[9]; + state[9] = state[11]; + state[11] = t; + + t = state[12]; + state[12] = state[13]; + state[13] = state[14]; + state[14] = state[15]; + state[15] = t; +} + +// {02} \cdot s +static inline Guchar mul02(Guchar s) { + Guchar s2; + + s2 = (Guchar)((s & 0x80) ? ((s << 1) ^ 0x1b) : (s << 1)); + return s2; +} + +// {03} \cdot s +static inline Guchar mul03(Guchar s) { + Guchar s2; + + s2 = (Guchar)((s & 0x80) ? ((s << 1) ^ 0x1b) : (s << 1)); + return s ^ s2; +} + +// {09} \cdot s +static inline Guchar mul09(Guchar s) { + Guchar s2, s4, s8; + + s2 = (Guchar)((s & 0x80) ? ((s << 1) ^ 0x1b) : (s << 1)); + s4 = (Guchar)((s2 & 0x80) ? ((s2 << 1) ^ 0x1b) : (s2 << 1)); + s8 = (Guchar)((s4 & 0x80) ? ((s4 << 1) ^ 0x1b) : (s4 << 1)); + return s ^ s8; +} + +// {0b} \cdot s +static inline Guchar mul0b(Guchar s) { + Guchar s2, s4, s8; + + s2 = (Guchar)((s & 0x80) ? ((s << 1) ^ 0x1b) : (s << 1)); + s4 = (Guchar)((s2 & 0x80) ? ((s2 << 1) ^ 0x1b) : (s2 << 1)); + s8 = (Guchar)((s4 & 0x80) ? ((s4 << 1) ^ 0x1b) : (s4 << 1)); + return s ^ s2 ^ s8; +} + +// {0d} \cdot s +static inline Guchar mul0d(Guchar s) { + Guchar s2, s4, s8; + + s2 = (Guchar)((s & 0x80) ? ((s << 1) ^ 0x1b) : (s << 1)); + s4 = (Guchar)((s2 & 0x80) ? ((s2 << 1) ^ 0x1b) : (s2 << 1)); + s8 = (Guchar)((s4 & 0x80) ? ((s4 << 1) ^ 0x1b) : (s4 << 1)); + return s ^ s4 ^ s8; +} + +// {0e} \cdot s +static inline Guchar mul0e(Guchar s) { + Guchar s2, s4, s8; + + s2 = (Guchar)((s & 0x80) ? ((s << 1) ^ 0x1b) : (s << 1)); + s4 = (Guchar)((s2 & 0x80) ? ((s2 << 1) ^ 0x1b) : (s2 << 1)); + s8 = (Guchar)((s4 & 0x80) ? ((s4 << 1) ^ 0x1b) : (s4 << 1)); + return s2 ^ s4 ^ s8; +} + +static inline void mixColumns(Guchar *state) { + int c; + Guchar s0, s1, s2, s3; + + for (c = 0; c < 4; ++c) { + s0 = state[c]; + s1 = state[4+c]; + s2 = state[8+c]; + s3 = state[12+c]; + state[c] = mul02(s0) ^ mul03(s1) ^ s2 ^ s3; + state[4+c] = s0 ^ mul02(s1) ^ mul03(s2) ^ s3; + state[8+c] = s0 ^ s1 ^ mul02(s2) ^ mul03(s3); + state[12+c] = mul03(s0) ^ s1 ^ s2 ^ mul02(s3); + } +} + +static inline void invMixColumns(Guchar *state) { + int c; + Guchar s0, s1, s2, s3; + + for (c = 0; c < 4; ++c) { + s0 = state[c]; + s1 = state[4+c]; + s2 = state[8+c]; + s3 = state[12+c]; + state[c] = mul0e(s0) ^ mul0b(s1) ^ mul0d(s2) ^ mul09(s3); + state[4+c] = mul09(s0) ^ mul0e(s1) ^ mul0b(s2) ^ mul0d(s3); + state[8+c] = mul0d(s0) ^ mul09(s1) ^ mul0e(s2) ^ mul0b(s3); + state[12+c] = mul0b(s0) ^ mul0d(s1) ^ mul09(s2) ^ mul0e(s3); + } +} + +static inline void invMixColumnsW(Guint *w) { + int c; + Guchar s0, s1, s2, s3; + + for (c = 0; c < 4; ++c) { + s0 = (Guchar)(w[c] >> 24); + s1 = (Guchar)(w[c] >> 16); + s2 = (Guchar)(w[c] >> 8); + s3 = (Guchar)w[c]; + w[c] = ((mul0e(s0) ^ mul0b(s1) ^ mul0d(s2) ^ mul09(s3)) << 24) + | ((mul09(s0) ^ mul0e(s1) ^ mul0b(s2) ^ mul0d(s3)) << 16) + | ((mul0d(s0) ^ mul09(s1) ^ mul0e(s2) ^ mul0b(s3)) << 8) + | (mul0b(s0) ^ mul0d(s1) ^ mul09(s2) ^ mul0e(s3)); + } +} + +static inline void addRoundKey(Guchar *state, Guint *w) { + int c; + + for (c = 0; c < 4; ++c) { + state[c] ^= (Guchar)(w[c] >> 24); + state[4+c] ^= (Guchar)(w[c] >> 16); + state[8+c] ^= (Guchar)(w[c] >> 8); + state[12+c] ^= (Guchar)w[c]; + } +} + +void aesKeyExpansion(DecryptAESState *s, + Guchar *objKey, int objKeyLen, + GBool decrypt) { + Guint temp; + int i, round; + + //~ this assumes objKeyLen == 16 + + for (i = 0; i < 4; ++i) { + s->w[i] = (objKey[4*i] << 24) + (objKey[4*i+1] << 16) + + (objKey[4*i+2] << 8) + objKey[4*i+3]; + } + for (i = 4; i < 44; ++i) { + temp = s->w[i-1]; + if (!(i & 3)) { + temp = subWord(rotWord(temp)) ^ rcon[i/4]; + } + s->w[i] = s->w[i-4] ^ temp; + } + if (decrypt) { + for (round = 1; round <= 9; ++round) { + invMixColumnsW(&s->w[round * 4]); + } + } +} + +void aesEncryptBlock(DecryptAESState *s, Guchar *in) { + int c, round; + + // initial state + CBC + for (c = 0; c < 4; ++c) { + s->state[c] = in[4*c] ^ s->cbc[4*c]; + s->state[4+c] = in[4*c+1] ^ s->cbc[4*c+1]; + s->state[8+c] = in[4*c+2] ^ s->cbc[4*c+2]; + s->state[12+c] = in[4*c+3] ^ s->cbc[4*c+3]; + } + + // round 0 + addRoundKey(s->state, &s->w[0]); + + // rounds 1 .. 9 + for (round = 1; round <= 9; ++round) { + subBytes(s->state); + shiftRows(s->state); + mixColumns(s->state); + addRoundKey(s->state, &s->w[round * 4]); + } + + // round 10 + subBytes(s->state); + shiftRows(s->state); + addRoundKey(s->state, &s->w[10 * 4]); + + // output + save for next CBC + for (c = 0; c < 4; ++c) { + s->buf[4*c] = s->cbc[4*c] = s->state[c]; + s->buf[4*c+1] = s->cbc[4*c+1] = s->state[4+c]; + s->buf[4*c+2] = s->cbc[4*c+2] = s->state[8+c]; + s->buf[4*c+3] = s->cbc[4*c+3] = s->state[12+c]; + } +} + +void aesDecryptBlock(DecryptAESState *s, Guchar *in, GBool last) { + int c, round, n, i; + + // initial state + for (c = 0; c < 4; ++c) { + s->state[c] = in[4*c]; + s->state[4+c] = in[4*c+1]; + s->state[8+c] = in[4*c+2]; + s->state[12+c] = in[4*c+3]; + } + + // round 0 + addRoundKey(s->state, &s->w[10 * 4]); + + // rounds 1-9 + for (round = 9; round >= 1; --round) { + invSubBytes(s->state); + invShiftRows(s->state); + invMixColumns(s->state); + addRoundKey(s->state, &s->w[round * 4]); + } + + // round 10 + invSubBytes(s->state); + invShiftRows(s->state); + addRoundKey(s->state, &s->w[0]); + + // CBC + for (c = 0; c < 4; ++c) { + s->buf[4*c] = s->state[c] ^ s->cbc[4*c]; + s->buf[4*c+1] = s->state[4+c] ^ s->cbc[4*c+1]; + s->buf[4*c+2] = s->state[8+c] ^ s->cbc[4*c+2]; + s->buf[4*c+3] = s->state[12+c] ^ s->cbc[4*c+3]; + } + + // save the input block for the next CBC + for (i = 0; i < 16; ++i) { + s->cbc[i] = in[i]; + } + + // remove padding + s->bufIdx = 0; + if (last) { + n = s->buf[15]; + 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]; + } + s->bufIdx = n; + } +} + +//------------------------------------------------------------------------ +// MD5 message digest +//------------------------------------------------------------------------ + +// this works around a bug in older Sun compilers +static inline Gulong rotateLeft(Gulong x, int r) { + x &= 0xffffffff; + return ((x << r) | (x >> (32 - r))) & 0xffffffff; +} + +static inline Gulong md5Round1(Gulong a, Gulong b, Gulong c, Gulong d, + Gulong Xk, int s, Gulong Ti) { + return b + rotateLeft((a + ((b & c) | (~b & d)) + Xk + Ti), s); +} + +static inline Gulong md5Round2(Gulong a, Gulong b, Gulong c, Gulong d, + Gulong Xk, int s, Gulong Ti) { + return b + rotateLeft((a + ((b & d) | (c & ~d)) + Xk + Ti), s); +} + +static inline Gulong md5Round3(Gulong a, Gulong b, Gulong c, Gulong d, + Gulong Xk, int s, Gulong Ti) { + return b + rotateLeft((a + (b ^ c ^ d) + Xk + Ti), s); +} + +static inline Gulong md5Round4(Gulong a, Gulong b, Gulong c, Gulong d, + Gulong Xk, int s, Gulong Ti) { + return b + rotateLeft((a + (c ^ (b | ~d)) + Xk + Ti), s); +} + +void md5Start(MD5State *state) { + state->a = 0x67452301; + state->b = 0xefcdab89; + state->c = 0x98badcfe; + state->d = 0x10325476; + state->bufLen = 0; + state->msgLen = 0; +} + +static void md5ProcessBlock(MD5State *state) { + Gulong x[16]; + Gulong a, b, c, d; + int i; + + for (i = 0; i < 16; ++i) { + x[i] = state->buf[4*i] | (state->buf[4*i+1] << 8) | + (state->buf[4*i+2] << 16) | (state->buf[4*i+3] << 24); + } + + a = state->a; + b = state->b; + c = state->c; + d = state->d; + + // round 1 + a = md5Round1(a, b, c, d, x[0], 7, 0xd76aa478); + d = md5Round1(d, a, b, c, x[1], 12, 0xe8c7b756); + c = md5Round1(c, d, a, b, x[2], 17, 0x242070db); + b = md5Round1(b, c, d, a, x[3], 22, 0xc1bdceee); + a = md5Round1(a, b, c, d, x[4], 7, 0xf57c0faf); + d = md5Round1(d, a, b, c, x[5], 12, 0x4787c62a); + c = md5Round1(c, d, a, b, x[6], 17, 0xa8304613); + b = md5Round1(b, c, d, a, x[7], 22, 0xfd469501); + a = md5Round1(a, b, c, d, x[8], 7, 0x698098d8); + d = md5Round1(d, a, b, c, x[9], 12, 0x8b44f7af); + c = md5Round1(c, d, a, b, x[10], 17, 0xffff5bb1); + b = md5Round1(b, c, d, a, x[11], 22, 0x895cd7be); + a = md5Round1(a, b, c, d, x[12], 7, 0x6b901122); + d = md5Round1(d, a, b, c, x[13], 12, 0xfd987193); + c = md5Round1(c, d, a, b, x[14], 17, 0xa679438e); + b = md5Round1(b, c, d, a, x[15], 22, 0x49b40821); + + // round 2 + a = md5Round2(a, b, c, d, x[1], 5, 0xf61e2562); + d = md5Round2(d, a, b, c, x[6], 9, 0xc040b340); + c = md5Round2(c, d, a, b, x[11], 14, 0x265e5a51); + b = md5Round2(b, c, d, a, x[0], 20, 0xe9b6c7aa); + a = md5Round2(a, b, c, d, x[5], 5, 0xd62f105d); + d = md5Round2(d, a, b, c, x[10], 9, 0x02441453); + c = md5Round2(c, d, a, b, x[15], 14, 0xd8a1e681); + b = md5Round2(b, c, d, a, x[4], 20, 0xe7d3fbc8); + a = md5Round2(a, b, c, d, x[9], 5, 0x21e1cde6); + d = md5Round2(d, a, b, c, x[14], 9, 0xc33707d6); + c = md5Round2(c, d, a, b, x[3], 14, 0xf4d50d87); + b = md5Round2(b, c, d, a, x[8], 20, 0x455a14ed); + a = md5Round2(a, b, c, d, x[13], 5, 0xa9e3e905); + d = md5Round2(d, a, b, c, x[2], 9, 0xfcefa3f8); + c = md5Round2(c, d, a, b, x[7], 14, 0x676f02d9); + b = md5Round2(b, c, d, a, x[12], 20, 0x8d2a4c8a); + + // round 3 + a = md5Round3(a, b, c, d, x[5], 4, 0xfffa3942); + d = md5Round3(d, a, b, c, x[8], 11, 0x8771f681); + c = md5Round3(c, d, a, b, x[11], 16, 0x6d9d6122); + b = md5Round3(b, c, d, a, x[14], 23, 0xfde5380c); + a = md5Round3(a, b, c, d, x[1], 4, 0xa4beea44); + d = md5Round3(d, a, b, c, x[4], 11, 0x4bdecfa9); + c = md5Round3(c, d, a, b, x[7], 16, 0xf6bb4b60); + b = md5Round3(b, c, d, a, x[10], 23, 0xbebfbc70); + a = md5Round3(a, b, c, d, x[13], 4, 0x289b7ec6); + d = md5Round3(d, a, b, c, x[0], 11, 0xeaa127fa); + c = md5Round3(c, d, a, b, x[3], 16, 0xd4ef3085); + b = md5Round3(b, c, d, a, x[6], 23, 0x04881d05); + a = md5Round3(a, b, c, d, x[9], 4, 0xd9d4d039); + d = md5Round3(d, a, b, c, x[12], 11, 0xe6db99e5); + c = md5Round3(c, d, a, b, x[15], 16, 0x1fa27cf8); + b = md5Round3(b, c, d, a, x[2], 23, 0xc4ac5665); + + // round 4 + a = md5Round4(a, b, c, d, x[0], 6, 0xf4292244); + d = md5Round4(d, a, b, c, x[7], 10, 0x432aff97); + c = md5Round4(c, d, a, b, x[14], 15, 0xab9423a7); + b = md5Round4(b, c, d, a, x[5], 21, 0xfc93a039); + a = md5Round4(a, b, c, d, x[12], 6, 0x655b59c3); + d = md5Round4(d, a, b, c, x[3], 10, 0x8f0ccc92); + c = md5Round4(c, d, a, b, x[10], 15, 0xffeff47d); + b = md5Round4(b, c, d, a, x[1], 21, 0x85845dd1); + a = md5Round4(a, b, c, d, x[8], 6, 0x6fa87e4f); + d = md5Round4(d, a, b, c, x[15], 10, 0xfe2ce6e0); + c = md5Round4(c, d, a, b, x[6], 15, 0xa3014314); + b = md5Round4(b, c, d, a, x[13], 21, 0x4e0811a1); + a = md5Round4(a, b, c, d, x[4], 6, 0xf7537e82); + d = md5Round4(d, a, b, c, x[11], 10, 0xbd3af235); + c = md5Round4(c, d, a, b, x[2], 15, 0x2ad7d2bb); + b = md5Round4(b, c, d, a, x[9], 21, 0xeb86d391); + + // increment a, b, c, d + state->a += a; + state->b += b; + state->c += c; + state->d += d; + + state->bufLen = 0; +} + +void md5Append(MD5State *state, Guchar *data, int dataLen) { + Guchar *p; + int remain, k; + + p = data; + remain = dataLen; + while (state->bufLen + remain >= 64) { + k = 64 - state->bufLen; + memcpy(state->buf + state->bufLen, p, k); + state->bufLen = 64; + md5ProcessBlock(state); + p += k; + remain -= k; + } + if (remain > 0) { + memcpy(state->buf + state->bufLen, p, remain); + state->bufLen += remain; + } + state->msgLen += dataLen; +} + +void md5Finish(MD5State *state) { + // padding and length + state->buf[state->bufLen++] = 0x80; + if (state->bufLen > 56) { + while (state->bufLen < 64) { + state->buf[state->bufLen++] = 0x00; + } + md5ProcessBlock(state); + } + while (state->bufLen < 56) { + state->buf[state->bufLen++] = 0x00; + } + state->buf[56] = (Guchar)(state->msgLen << 3); + state->buf[57] = (Guchar)(state->msgLen >> 5); + state->buf[58] = (Guchar)(state->msgLen >> 13); + state->buf[59] = (Guchar)(state->msgLen >> 21); + state->buf[60] = (Guchar)(state->msgLen >> 29); + state->buf[61] = (Guchar)0; + state->buf[62] = (Guchar)0; + state->buf[63] = (Guchar)0; + state->bufLen = 64; + md5ProcessBlock(state); + + // break digest into bytes + state->digest[0] = (Guchar)state->a; + state->digest[1] = (Guchar)(state->a >> 8); + state->digest[2] = (Guchar)(state->a >> 16); + state->digest[3] = (Guchar)(state->a >> 24); + state->digest[4] = (Guchar)state->b; + state->digest[5] = (Guchar)(state->b >> 8); + state->digest[6] = (Guchar)(state->b >> 16); + state->digest[7] = (Guchar)(state->b >> 24); + state->digest[8] = (Guchar)state->c; + state->digest[9] = (Guchar)(state->c >> 8); + state->digest[10] = (Guchar)(state->c >> 16); + state->digest[11] = (Guchar)(state->c >> 24); + state->digest[12] = (Guchar)state->d; + state->digest[13] = (Guchar)(state->d >> 8); + state->digest[14] = (Guchar)(state->d >> 16); + state->digest[15] = (Guchar)(state->d >> 24); +} + +void md5(Guchar *msg, int msgLen, Guchar *digest) { + MD5State state; + int i; + + if (msgLen < 0) { + return; + } + md5Start(&state); + md5Append(&state, msg, msgLen); + md5Finish(&state); + for (i = 0; i < 16; ++i) { + digest[i] = state.digest[i]; + } +} + +//------------------------------------------------------------------------ +// 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); +} + +static 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]; + } +} + +//------------------------------------------------------------------------ +// SHA-384 and SHA-512 hashes +//------------------------------------------------------------------------ + +typedef unsigned long long SHA512Uint64; + +static SHA512Uint64 sha512K[80] = { + 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, + 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL, + 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, + 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, + 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL, + 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL, + 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, + 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL, + 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, + 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, + 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL, + 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL, + 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, + 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL, + 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, + 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, + 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL, + 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL, + 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, + 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL, + 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, + 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, + 0xd192e819d6ef5218ULL, 0xd69906245565a910ULL, + 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL, + 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, + 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL, + 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, + 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, + 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL, + 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL, + 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, + 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL, + 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, + 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, + 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL, + 0x113f9804bef90daeULL, 0x1b710b35131c471bULL, + 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, + 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL, + 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, + 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL +}; + +static inline SHA512Uint64 rotr64(SHA512Uint64 x, Guint n) { + return (x >> n) | (x << (64 - n)); +} + +static inline SHA512Uint64 sha512Ch(SHA512Uint64 x, SHA512Uint64 y, + SHA512Uint64 z) { + return (x & y) ^ (~x & z); +} + +static inline SHA512Uint64 sha512Maj(SHA512Uint64 x, SHA512Uint64 y, + SHA512Uint64 z) { + return (x & y) ^ (x & z) ^ (y & z); +} + +static inline SHA512Uint64 sha512Sigma0(SHA512Uint64 x) { + return rotr64(x, 28) ^ rotr64(x, 34) ^ rotr64(x, 39); +} + +static inline SHA512Uint64 sha512Sigma1(SHA512Uint64 x) { + return rotr64(x, 14) ^ rotr64(x, 18) ^ rotr64(x, 41); +} + +static inline SHA512Uint64 sha512sigma0(SHA512Uint64 x) { + return rotr64(x, 1) ^ rotr64(x, 8) ^ (x >> 7); +} + +static inline SHA512Uint64 sha512sigma1(SHA512Uint64 x) { + return rotr64(x, 19) ^ rotr64(x, 61) ^ (x >> 6); +} + +static void sha512HashBlock(Guchar *blk, SHA512Uint64 *H) { + SHA512Uint64 W[80]; + SHA512Uint64 a, b, c, d, e, f, g, h; + SHA512Uint64 T1, T2; + Guint t; + + // 1. prepare the message schedule + for (t = 0; t < 16; ++t) { + W[t] = ((SHA512Uint64)blk[t*8] << 56) | + ((SHA512Uint64)blk[t*8 + 1] << 48) | + ((SHA512Uint64)blk[t*8 + 2] << 40) | + ((SHA512Uint64)blk[t*8 + 3] << 32) | + ((SHA512Uint64)blk[t*8 + 4] << 24) | + ((SHA512Uint64)blk[t*8 + 5] << 16) | + ((SHA512Uint64)blk[t*8 + 6] << 8) | + (SHA512Uint64)blk[t*8 + 7]; + } + for (t = 16; t < 80; ++t) { + W[t] = sha512sigma1(W[t-2]) + W[t-7] + sha512sigma0(W[t-15]) + W[t-16]; + } + + // 2. initialize the eight working variables + a = H[0]; + b = H[1]; + c = H[2]; + d = H[3]; + e = H[4]; + f = H[5]; + g = H[6]; + h = H[7]; + + // 3. + for (t = 0; t < 80; ++t) { + T1 = h + sha512Sigma1(e) + sha512Ch(e,f,g) + sha512K[t] + W[t]; + T2 = sha512Sigma0(a) + sha512Maj(a,b,c); + h = g; + g = f; + f = e; + e = d + T1; + d = c; + c = b; + b = a; + a = T1 + T2; + } + + // 4. compute the intermediate hash value + H[0] += a; + H[1] += b; + H[2] += c; + H[3] += d; + H[4] += e; + H[5] += f; + H[6] += g; + H[7] += h; +} + +static void sha512(Guchar *msg, int msgLen, Guchar *hash) { + Guchar blk[128]; + SHA512Uint64 H[8]; + int blkLen, i; + + H[0] = 0x6a09e667f3bcc908LL; + H[1] = 0xbb67ae8584caa73bLL; + H[2] = 0x3c6ef372fe94f82bLL; + H[3] = 0xa54ff53a5f1d36f1LL; + H[4] = 0x510e527fade682d1LL; + H[5] = 0x9b05688c2b3e6c1fLL; + H[6] = 0x1f83d9abfb41bd6bLL; + H[7] = 0x5be0cd19137e2179LL; + + blkLen = 0; + for (i = 0; i + 128 <= msgLen; i += 128) { + sha512HashBlock(msg + i, H); + } + blkLen = msgLen - i; + if (blkLen > 0) { + memcpy(blk, msg + i, blkLen); + } + + // pad the message + blk[blkLen++] = 0x80; + if (blkLen > 112) { + while (blkLen < 128) { + blk[blkLen++] = 0; + } + sha512HashBlock(blk, H); + blkLen = 0; + } + while (blkLen < 112) { + blk[blkLen++] = 0; + } + blk[112] = 0; + blk[113] = 0; + blk[114] = 0; + blk[115] = 0; + blk[116] = 0; + blk[117] = 0; + blk[118] = 0; + blk[119] = 0; + blk[120] = 0; + blk[121] = 0; + blk[122] = 0; + blk[123] = 0; + blk[124] = (Guchar)(msgLen >> 21); + blk[125] = (Guchar)(msgLen >> 13); + blk[126] = (Guchar)(msgLen >> 5); + blk[127] = (Guchar)(msgLen << 3); + sha512HashBlock(blk, H); + + // copy the output into the buffer (convert words to bytes) + for (i = 0; i < 8; ++i) { + hash[i*8] = (Guchar)(H[i] >> 56); + hash[i*8 + 1] = (Guchar)(H[i] >> 48); + hash[i*8 + 2] = (Guchar)(H[i] >> 40); + hash[i*8 + 3] = (Guchar)(H[i] >> 32); + hash[i*8 + 4] = (Guchar)(H[i] >> 24); + hash[i*8 + 5] = (Guchar)(H[i] >> 16); + hash[i*8 + 6] = (Guchar)(H[i] >> 8); + hash[i*8 + 7] = (Guchar)H[i]; + } +} + +static void sha384(Guchar *msg, int msgLen, Guchar *hash) { + Guchar blk[128]; + SHA512Uint64 H[8]; + int blkLen, i; + + H[0] = 0xcbbb9d5dc1059ed8LL; + H[1] = 0x629a292a367cd507LL; + H[2] = 0x9159015a3070dd17LL; + H[3] = 0x152fecd8f70e5939LL; + H[4] = 0x67332667ffc00b31LL; + H[5] = 0x8eb44a8768581511LL; + H[6] = 0xdb0c2e0d64f98fa7LL; + H[7] = 0x47b5481dbefa4fa4LL; + + blkLen = 0; + for (i = 0; i + 128 <= msgLen; i += 128) { + sha512HashBlock(msg + i, H); + } + blkLen = msgLen - i; + if (blkLen > 0) { + memcpy(blk, msg + i, blkLen); + } + + // pad the message + blk[blkLen++] = 0x80; + if (blkLen > 112) { + while (blkLen < 128) { + blk[blkLen++] = 0; + } + sha512HashBlock(blk, H); + blkLen = 0; + } + while (blkLen < 112) { + blk[blkLen++] = 0; + } + blk[112] = 0; + blk[113] = 0; + blk[114] = 0; + blk[115] = 0; + blk[116] = 0; + blk[117] = 0; + blk[118] = 0; + blk[119] = 0; + blk[120] = 0; + blk[121] = 0; + blk[122] = 0; + blk[123] = 0; + blk[124] = (Guchar)(msgLen >> 21); + blk[125] = (Guchar)(msgLen >> 13); + blk[126] = (Guchar)(msgLen >> 5); + blk[127] = (Guchar)(msgLen << 3); + sha512HashBlock(blk, H); + + // copy the output into the buffer (convert words to bytes) + for (i = 0; i < 6; ++i) { + hash[i*8] = (Guchar)(H[i] >> 56); + hash[i*8 + 1] = (Guchar)(H[i] >> 48); + hash[i*8 + 2] = (Guchar)(H[i] >> 40); + hash[i*8 + 3] = (Guchar)(H[i] >> 32); + hash[i*8 + 4] = (Guchar)(H[i] >> 24); + hash[i*8 + 5] = (Guchar)(H[i] >> 16); + hash[i*8 + 6] = (Guchar)(H[i] >> 8); + hash[i*8 + 7] = (Guchar)H[i]; + } +} diff --git a/xpdf/Decrypt.h b/xpdf/Decrypt.h new file mode 100644 index 0000000..2b10abd --- /dev/null +++ b/xpdf/Decrypt.h @@ -0,0 +1,133 @@ +//======================================================================== +// +// Decrypt.h +// +// Copyright 1996-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef DECRYPT_H +#define DECRYPT_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "gtypes.h" +#include "GString.h" +#include "Object.h" +#include "Stream.h" + +//------------------------------------------------------------------------ +// Decrypt +//------------------------------------------------------------------------ + +class Decrypt { +public: + + // Generate a file key. The buffer must have space for at + // least 16 bytes. Checks and then + // and returns true if either is correct. Sets if + // the owner password was correct. Either or both of the passwords + // 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, + GBool *ownerPasswordOk); + +private: + + static void r6Hash(Guchar *key, int keyLen, const char *pwd, int pwdLen, + char *userKey); + static GBool makeFileKey2(int encVersion, int encRevision, int keyLength, + GString *ownerKey, GString *userKey, + int permissions, GString *fileID, + GString *userPassword, Guchar *fileKey, + GBool encryptMetadata); +}; + +//------------------------------------------------------------------------ +// DecryptStream +//------------------------------------------------------------------------ + +struct DecryptRC4State { + Guchar state[256]; + Guchar x, y; + int buf; +}; + +struct DecryptAESState { + Guint w[44]; + Guchar state[16]; + Guchar cbc[16]; + Guchar buf[16]; + int bufIdx; +}; + +struct DecryptAES256State { + Guint w[60]; + Guchar state[16]; + Guchar cbc[16]; + Guchar buf[16]; + int bufIdx; +}; + +class DecryptStream: public FilterStream { +public: + + DecryptStream(Stream *strA, Guchar *fileKeyA, + CryptAlgorithm algoA, int keyLengthA, + int objNumA, int objGenA); + virtual ~DecryptStream(); + virtual Stream *copy(); + virtual StreamKind getKind() { return strWeird; } + virtual void reset(); + virtual int getChar(); + virtual int lookChar(); + virtual GBool isBinary(GBool last); + virtual Stream *getUndecodedStream() { return this; } + +private: + + Guchar fileKey[32]; + CryptAlgorithm algo; + int keyLength; + int objNum, objGen; + int objKeyLength; + Guchar objKey[32]; + + union { + DecryptRC4State rc4; + DecryptAESState aes; + DecryptAES256State aes256; + } state; +}; + +//------------------------------------------------------------------------ + +struct MD5State { + Gulong a, b, c, d; + Guchar buf[64]; + int bufLen; + int msgLen; + Guchar digest[16]; +}; + +extern void rc4InitKey(Guchar *key, int keyLen, Guchar *state); +extern Guchar rc4DecryptByte(Guchar *state, Guchar *x, Guchar *y, Guchar c); +void md5Start(MD5State *state); +void md5Append(MD5State *state, Guchar *data, int dataLen); +void md5Finish(MD5State *state); +extern void md5(Guchar *msg, int msgLen, Guchar *digest); +extern void aesKeyExpansion(DecryptAESState *s, + Guchar *objKey, int objKeyLen, + GBool decrypt); +extern void aesEncryptBlock(DecryptAESState *s, Guchar *in); +extern void aesDecryptBlock(DecryptAESState *s, Guchar *in, GBool last); + +#endif diff --git a/xpdf/Dict.cc b/xpdf/Dict.cc new file mode 100644 index 0000000..c8c2973 --- /dev/null +++ b/xpdf/Dict.cc @@ -0,0 +1,145 @@ +//======================================================================== +// +// Dict.cc +// +// Copyright 1996-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include +#include "gmem.h" +#include "gmempp.h" +#include "Object.h" +#include "XRef.h" +#include "Dict.h" + +//------------------------------------------------------------------------ + +struct DictEntry { + char *key; + Object val; + DictEntry *next; +}; + +//------------------------------------------------------------------------ +// Dict +//------------------------------------------------------------------------ + +Dict::Dict(XRef *xrefA) { + xref = xrefA; + size = 8; + length = 0; + entries = (DictEntry *)gmallocn(size, sizeof(DictEntry)); + hashTab = (DictEntry **)gmallocn(2 * size - 1, sizeof(DictEntry *)); + memset(hashTab, 0, (2 * size - 1) * sizeof(DictEntry *)); + ref = 1; +} + +Dict::~Dict() { + int i; + + for (i = 0; i < length; ++i) { + gfree(entries[i].key); + entries[i].val.free(); + } + gfree(entries); + gfree(hashTab); +} + +void Dict::add(char *key, Object *val) { + DictEntry *e; + int h; + + if ((e = find(key))) { + e->val.free(); + e->val = *val; + gfree(key); + } else { + if (length == size) { + expand(); + } + h = hash(key); + entries[length].key = key; + entries[length].val = *val; + entries[length].next = hashTab[h]; + hashTab[h] = &entries[length]; + ++length; + } +} + +void Dict::expand() { + int h, i; + + size *= 2; + entries = (DictEntry *)greallocn(entries, size, sizeof(DictEntry)); + hashTab = (DictEntry **)greallocn(hashTab, 2 * size - 1, + sizeof(DictEntry *)); + memset(hashTab, 0, (2 * size - 1) * sizeof(DictEntry *)); + for (i = 0; i < length; ++i) { + h = hash(entries[i].key); + entries[i].next = hashTab[h]; + hashTab[h] = &entries[i]; + } +} + +inline DictEntry *Dict::find(const char *key) { + DictEntry *e; + int h; + + h = hash(key); + for (e = hashTab[h]; e; e = e->next) { + if (!strcmp(key, e->key)) { + return e; + } + } + return NULL; +} + +int Dict::hash(const char *key) { + const char *p; + unsigned int h; + + h = 0; + for (p = key; *p; ++p) { + h = 17 * h + (int)(*p & 0xff); + } + return (int)(h % (2 * size - 1)); +} + +GBool Dict::is(const char *type) { + DictEntry *e; + + return (e = find("Type")) && e->val.isName(type); +} + +Object *Dict::lookup(const char *key, Object *obj, int recursion) { + DictEntry *e; + + return (e = find(key)) ? e->val.fetch(xref, obj, recursion) + : obj->initNull(); +} + +Object *Dict::lookupNF(const char *key, Object *obj) { + DictEntry *e; + + return (e = find(key)) ? e->val.copy(obj) : obj->initNull(); +} + +char *Dict::getKey(int i) { + return entries[i].key; +} + +Object *Dict::getVal(int i, Object *obj) { + return entries[i].val.fetch(xref, obj); +} + +Object *Dict::getValNF(int i, Object *obj) { + return entries[i].val.copy(obj); +} diff --git a/xpdf/Dict.h b/xpdf/Dict.h new file mode 100644 index 0000000..b05f729 --- /dev/null +++ b/xpdf/Dict.h @@ -0,0 +1,89 @@ +//======================================================================== +// +// Dict.h +// +// Copyright 1996-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef DICT_H +#define DICT_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#if MULTITHREADED +#include "GMutex.h" +#endif +#include "Object.h" + +struct DictEntry; + +//------------------------------------------------------------------------ +// Dict +//------------------------------------------------------------------------ + +class Dict { +public: + + // Constructor. + Dict(XRef *xrefA); + + // Destructor. + ~Dict(); + + // Reference counting. +#if MULTITHREADED + long incRef() { return gAtomicIncrement(&ref); } + long decRef() { return gAtomicDecrement(&ref); } +#else + long incRef() { return ++ref; } + long decRef() { return --ref; } +#endif + + // Get number of entries. + int getLength() { return length; } + + // Add an entry. NB: does not copy key. + void add(char *key, Object *val); + + // Check if dictionary is of specified type. + GBool is(const char *type); + + // Look up an entry and return the value. Returns a null object + // if is not in the dictionary. + Object *lookup(const char *key, Object *obj, int recursion = 0); + Object *lookupNF(const char *key, Object *obj); + + // Iterative accessors. + char *getKey(int i); + Object *getVal(int i, Object *obj); + Object *getValNF(int i, Object *obj); + + // Set the xref pointer. This is only used in one special case: the + // trailer dictionary, which is read before the xref table is + // parsed. + void setXRef(XRef *xrefA) { xref = xrefA; } + +private: + + XRef *xref; // the xref table for this PDF file + DictEntry *entries; // array of entries + DictEntry **hashTab; // hash table pointers + int size; // size of array + int length; // number of entries in dictionary +#if MULTITHREADED + GAtomicCounter ref; // reference count +#else + long ref; // reference count +#endif + + DictEntry *find(const char *key); + void expand(); + int hash(const char *key); +}; + +#endif diff --git a/xpdf/DisplayState.cc b/xpdf/DisplayState.cc new file mode 100644 index 0000000..e0d3068 --- /dev/null +++ b/xpdf/DisplayState.cc @@ -0,0 +1,223 @@ +//======================================================================== +// +// DisplayState.cc +// +// Copyright 2014 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include "gmempp.h" +#include "GString.h" +#include "GList.h" +#include "TileMap.h" +#include "TileCache.h" +#include "TileCompositor.h" +#include "DisplayState.h" + + +//------------------------------------------------------------------------ +// DisplayState +//------------------------------------------------------------------------ + +DisplayState::DisplayState(int maxTileWidthA, int maxTileHeightA, + int tileCacheSizeA, int nWorkerThreadsA, + SplashColorMode colorModeA, int bitmapRowPadA) { + int i; + + maxTileWidth = maxTileWidthA; + maxTileHeight = maxTileHeightA; + tileCacheSize = tileCacheSizeA; + nWorkerThreads = nWorkerThreadsA; + colorMode = colorModeA; + bitmapRowPad = bitmapRowPadA; + + tileMap = NULL; + tileCache = NULL; + tileCompositor = NULL; + + for (i = 0; i < splashColorModeNComps[colorMode]; ++i) { + paperColor[i] = 0xff; + matteColor[i] = 0x80; + } + if (colorMode == splashModeRGB8 || colorMode == splashModeBGR8) { + selectColor[0] = 0x80; + selectColor[1] = 0x80; + selectColor[2] = 0xff; + } else { + for (i = 0; i < splashColorModeNComps[colorMode]; ++i) { + selectColor[i] = 0xa0; + } + } + reverseVideo = gFalse; + + doc = NULL; + + winW = winH = 100; + displayMode = displayContinuous; + zoom = 100; + rotate = 0; + scrollPage = 0; + scrollX = scrollY = 0; + + selectRects = NULL; + + +} + +DisplayState::~DisplayState() { + if (selectRects) { + deleteGList(selectRects, SelectRect); + } +} + +void DisplayState::setPaperColor(SplashColorPtr paperColorA) { + splashColorCopy(paperColor, paperColorA); + tileCache->paperColorChanged(); + tileCompositor->paperColorChanged(); +} + +void DisplayState::setMatteColor(SplashColorPtr matteColorA) { + splashColorCopy(matteColor, matteColorA); + tileCompositor->matteColorChanged(); +} + +void DisplayState::setSelectColor(SplashColorPtr selectColorA) { + splashColorCopy(selectColor, selectColorA); + tileCompositor->selectColorChanged(); +} + +void DisplayState::setReverseVideo(GBool reverseVideoA) { + if (reverseVideo != reverseVideoA) { + reverseVideo = reverseVideoA; + tileCache->reverseVideoChanged(); + tileCompositor->reverseVideoChanged(); + } +} + +void DisplayState::setDoc(PDFDoc *docA) { + doc = docA; + tileMap->docChanged(); + tileCache->docChanged(); + tileCompositor->docChanged(); +} + +void DisplayState::setWindowSize(int winWA, int winHA) { + if (winW != winWA || winH != winHA) { + winW = winWA; + winH = winHA; + tileMap->windowSizeChanged(); + tileCompositor->windowSizeChanged(); + } +} + +void DisplayState::setDisplayMode(DisplayMode displayModeA) { + if (displayMode != displayModeA) { + displayMode = displayModeA; + tileMap->displayModeChanged(); + tileCompositor->displayModeChanged(); + } +} + +void DisplayState::setZoom(double zoomA) { + if (zoom != zoomA) { + zoom = zoomA; + tileMap->zoomChanged(); + tileCompositor->zoomChanged(); + } +} + +void DisplayState::setRotate(int rotateA) { + if (rotate != rotateA) { + rotate = rotateA; + tileMap->rotateChanged(); + tileCompositor->rotateChanged(); + } +} + +void DisplayState::setScrollPosition(int scrollPageA, + int scrollXA, int scrollYA) { + if (scrollPage != scrollPageA || + scrollX != scrollXA || + scrollY != scrollYA) { + scrollPage = scrollPageA; + scrollX = scrollXA; + scrollY = scrollYA; + tileMap->scrollPositionChanged(); + tileCompositor->scrollPositionChanged(); + } +} + +void DisplayState::setSelection(int selectPage, + double selectX0, double selectY0, + double selectX1, double selectY1) { + GList *rects; + SelectRect *rect; + + rect = new SelectRect(selectPage, selectX0, selectY0, selectX1, selectY1); + rects = new GList(); + rects->append(rect); + setSelection(rects); +} + +void DisplayState::setSelection(GList *selectRectsA) { + SelectRect *rect, *rectA; + int i; + + if (!selectRects && !selectRectsA) { + return; + } + if (selectRects && selectRectsA && + selectRects->getLength() == selectRectsA->getLength()) { + for (i = 0; i < selectRects->getLength(); ++i) { + rect = (SelectRect *)selectRects->get(i); + rectA = (SelectRect *)selectRectsA->get(i); + if (*rect != *rectA) { + break; + } + } + if (i == selectRects->getLength()) { + deleteGList(selectRectsA, SelectRect); + return; + } + } + if (selectRects) { + deleteGList(selectRects, SelectRect); + } + selectRects = selectRectsA; + tileCompositor->selectionChanged(); +} + +void DisplayState::clearSelection() { + setSelection(NULL); +} + +int DisplayState::getNumSelectRects() { + if (!selectRects) { + return 0; + } + return selectRects->getLength(); +} + +SelectRect *DisplayState::getSelectRect(int idx) { + return (SelectRect *)selectRects->get(idx); +} + +void DisplayState::optionalContentChanged() { + tileCache->optionalContentChanged(); + tileCompositor->optionalContentChanged(); +} + + + +void DisplayState::forceRedraw() { + tileMap->forceRedraw(); + tileCache->forceRedraw(); + tileCompositor->forceRedraw(); +} diff --git a/xpdf/DisplayState.h b/xpdf/DisplayState.h new file mode 100644 index 0000000..12c8170 --- /dev/null +++ b/xpdf/DisplayState.h @@ -0,0 +1,173 @@ +//======================================================================== +// +// DisplayState.h +// +// Copyright 2014 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef DISPLAYSTATE_H +#define DISPLAYSTATE_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "gtypes.h" +#include "SplashTypes.h" + +class GString; +class GList; +class PDFDoc; +class TileMap; +class TileCache; +class TileCompositor; + +//------------------------------------------------------------------------ +// zoom level +//------------------------------------------------------------------------ + +// positive zoom levels are percentage of 72 dpi +// (e.g., 50 means 36dpi, 100 means 72dpi, 150 means 108 dpi) + +#define zoomPage -1 +#define zoomWidth -2 +#define zoomHeight -3 + +//------------------------------------------------------------------------ +// display mode +//------------------------------------------------------------------------ + +enum DisplayMode { + displaySingle, + displayContinuous, + displaySideBySideSingle, + displaySideBySideContinuous, + displayHorizontalContinuous +}; + +//------------------------------------------------------------------------ +// SelectRect +//------------------------------------------------------------------------ + +class SelectRect { +public: + + SelectRect(int pageA, double x0A, double y0A, double x1A, double y1A): + page(pageA), x0(x0A), y0(y0A), x1(x1A), y1(y1A) {} + int operator==(SelectRect r) + { return page == r.page && x0 == r.x0 && y0 == r.y0 && + x1 == r.x1 && y1 == r.y1; } + int operator!=(SelectRect r) + { return page != r.page || x0 != r.x0 || y0 != r.y0 || + x1 != r.x1 || y1 != r.y1; } + + int page; + double x0, y0, x1, y1; // user coords +}; + + +//------------------------------------------------------------------------ +// DisplayState +//------------------------------------------------------------------------ + +class DisplayState { +public: + + DisplayState(int maxTileWidthA, int maxTileHeightA, + int tileCacheSizeA, int nWorkerThreadsA, + SplashColorMode colorModeA, int bitmapRowPadA); + ~DisplayState(); + + void setTileMap(TileMap *tileMapA) + { tileMap = tileMapA; } + void setTileCache(TileCache *tileCacheA) + { tileCache = tileCacheA; } + void setTileCompositor(TileCompositor *tileCompositorA) + { tileCompositor = tileCompositorA; } + + void setPaperColor(SplashColorPtr paperColorA); + void setMatteColor(SplashColorPtr matteColorA); + void setSelectColor(SplashColorPtr selectColorA); + void setReverseVideo(GBool reverseVideoA); + void setDoc(PDFDoc *docA); + void setWindowSize(int winWA, int winHA); + void setDisplayMode(DisplayMode displayModeA); + void setZoom(double zoomA); + void setRotate(int rotateA); + void setScrollPosition(int scrollPageA, int scrollXA, int scrollYA); + void setSelection(int selectPage, double selectX0, double selectY0, + double selectX1, double selectY1); + void setSelection(GList *selectRectsA); + void clearSelection(); + void forceRedraw(); + + int getMaxTileWidth() { return maxTileWidth; } + int getMaxTileHeight() { return maxTileHeight; } + int getTileCacheSize() { return tileCacheSize; } + int getNWorkerThreads() { return nWorkerThreads; } + SplashColorMode getColorMode() { return colorMode; } + int getBitmapRowPad() { return bitmapRowPad; } + SplashColorPtr getPaperColor() { return paperColor; } + SplashColorPtr getMatteColor() { return matteColor; } + SplashColorPtr getSelectColor() { return selectColor; } + GBool getReverseVideo() { return reverseVideo; } + PDFDoc *getDoc() { return doc; } + int getWinW() { return winW; } + int getWinH() { return winH; } + DisplayMode getDisplayMode() { return displayMode; } + GBool displayModeIsContinuous() + { return displayMode == displayContinuous || + displayMode == displaySideBySideContinuous || + displayMode == displayHorizontalContinuous; } + GBool displayModeIsSideBySide() + { return displayMode == displaySideBySideSingle || + displayMode == displaySideBySideContinuous; } + double getZoom() { return zoom; } + int getRotate() { return rotate; } + int getScrollPage() { return scrollPage; } + int getScrollX() { return scrollX; } + int getScrollY() { return scrollY; } + GBool hasSelection() { return selectRects != NULL; } + GList *getSelectRects() { return selectRects; } + int getNumSelectRects(); + SelectRect *getSelectRect(int idx); + void optionalContentChanged(); + +private: + + int maxTileWidth, maxTileHeight; + int tileCacheSize; + int nWorkerThreads; + + SplashColorMode colorMode; + int bitmapRowPad; + + TileMap *tileMap; + TileCache *tileCache; + TileCompositor *tileCompositor; + + SplashColor paperColor; + SplashColor matteColor; + SplashColor selectColor; + GBool reverseVideo; + + PDFDoc *doc; + + int winW, winH; // window (draw area) size + DisplayMode displayMode; + double zoom; // zoom level (see zoom* defines, above) + int rotate; // rotation (0, 90, 180, or 270) + int scrollPage; // scroll page - only used in + // non-continuous modes + int scrollX, scrollY; + + GList *selectRects; // selection rectangles [SelectRect] + // (NULL if there is no selection) + + +}; + +#endif diff --git a/xpdf/Error.cc b/xpdf/Error.cc new file mode 100644 index 0000000..5a97505 --- /dev/null +++ b/xpdf/Error.cc @@ -0,0 +1,92 @@ +//======================================================================== +// +// Error.cc +// +// Copyright 1996-2013 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include +#include +#include "gmempp.h" +#include "GString.h" +#include "GlobalParams.h" +#include "Error.h" + +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 *getErrorCallbackData() { + return errorCbkData; +} + +void CDECL error(ErrorCategory category, GFileOffset pos, + const char *msg, ...) { + va_list args; + GString *s, *sanitized; + char c; + int i; + + // NB: this can be called before the globalParams object is created + if (!errorCbk && globalParams && globalParams->getErrQuiet()) { + return; + } + va_start(args, msg); + s = GString::formatv(msg, args); + va_end(args); + + // remove non-printable characters, just in case they might cause + // problems for the terminal program + sanitized = new GString(); + for (i = 0; i < s->getLength(); ++i) { + c = s->getChar(i); + if (c >= 0x20 && c <= 0x7e) { + sanitized->append(c); + } else { + sanitized->appendf("<{0:02x}>", c & 0xff); + } + } + + if (errorCbk) { + (*errorCbk)(errorCbkData, category, (int)pos, sanitized->getCString()); + } else { + fflush(stdout); + if (pos >= 0) { + fprintf(stderr, "%s (%d): %s\n", + errorCategoryNames[category], (int)pos, sanitized->getCString()); + } else { + fprintf(stderr, "%s: %s\n", + errorCategoryNames[category], sanitized->getCString()); + } + fflush(stderr); + } + + delete s; + delete sanitized; +} diff --git a/xpdf/Error.h b/xpdf/Error.h new file mode 100644 index 0000000..39e7613 --- /dev/null +++ b/xpdf/Error.h @@ -0,0 +1,48 @@ +//======================================================================== +// +// Error.h +// +// Copyright 1996-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef ERROR_H +#define ERROR_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include +#include "config.h" +#include "gfile.h" + +enum ErrorCategory { + errSyntaxWarning, // PDF syntax error which can be worked around; + // output will probably be correct + errSyntaxError, // PDF syntax error which cannot be worked around; + // output will probably be incorrect + errConfig, // error in Xpdf config info (xpdfrc file, etc.) + errCommandLine, // error in user-supplied parameters, action not + // 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 const char *errorCategoryNames[]; + +extern void setErrorCallback(void (*cbk)(void *data, ErrorCategory category, + int pos, char *msg), + void *data); + +extern void *getErrorCallbackData(); + +extern void CDECL error(ErrorCategory category, GFileOffset pos, + const char *msg, ...); + +#endif diff --git a/xpdf/ErrorCodes.h b/xpdf/ErrorCodes.h new file mode 100644 index 0000000..b28528d --- /dev/null +++ b/xpdf/ErrorCodes.h @@ -0,0 +1,36 @@ +//======================================================================== +// +// ErrorCodes.h +// +// Copyright 2002-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef ERRORCODES_H +#define ERRORCODES_H + +#define errNone 0 // no error + +#define errOpenFile 1 // couldn't open the PDF file + +#define errBadCatalog 2 // couldn't read the page catalog + +#define errDamaged 3 // PDF file was damaged and couldn't be + // repaired + +#define errEncrypted 4 // file was encrypted and password was + // incorrect or not supplied + +#define errHighlightFile 5 // nonexistent or invalid highlight file + +#define errBadPrinter 6 // invalid printer + +#define errPrinting 7 // error during printing + +#define errPermission 8 // PDF file doesn't allow that operation + +#define errBadPageNum 9 // invalid page number + +#define errFileIO 10 // file I/O error + +#endif diff --git a/xpdf/FontEncodingTables.cc b/xpdf/FontEncodingTables.cc new file mode 100644 index 0000000..d4b18ab --- /dev/null +++ b/xpdf/FontEncodingTables.cc @@ -0,0 +1,1825 @@ +//======================================================================== +// +// FontEncodingTables.cc +// +// Copyright 2001-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include +#include +#include "gmempp.h" +#include "FontEncodingTables.h" + +const char *macRomanEncoding[256] = { + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "space", + "exclam", + "quotedbl", + "numbersign", + "dollar", + "percent", + "ampersand", + "quotesingle", + "parenleft", + "parenright", + "asterisk", + "plus", + "comma", + "hyphen", + "period", + "slash", + "zero", + "one", + "two", + "three", + "four", + "five", + "six", + "seven", + "eight", + "nine", + "colon", + "semicolon", + "less", + "equal", + "greater", + "question", + "at", + "A", + "B", + "C", + "D", + "E", + "F", + "G", + "H", + "I", + "J", + "K", + "L", + "M", + "N", + "O", + "P", + "Q", + "R", + "S", + "T", + "U", + "V", + "W", + "X", + "Y", + "Z", + "bracketleft", + "backslash", + "bracketright", + "asciicircum", + "underscore", + "grave", + "a", + "b", + "c", + "d", + "e", + "f", + "g", + "h", + "i", + "j", + "k", + "l", + "m", + "n", + "o", + "p", + "q", + "r", + "s", + "t", + "u", + "v", + "w", + "x", + "y", + "z", + "braceleft", + "bar", + "braceright", + "asciitilde", + NULL, + "Adieresis", + "Aring", + "Ccedilla", + "Eacute", + "Ntilde", + "Odieresis", + "Udieresis", + "aacute", + "agrave", + "acircumflex", + "adieresis", + "atilde", + "aring", + "ccedilla", + "eacute", + "egrave", + "ecircumflex", + "edieresis", + "iacute", + "igrave", + "icircumflex", + "idieresis", + "ntilde", + "oacute", + "ograve", + "ocircumflex", + "odieresis", + "otilde", + "uacute", + "ugrave", + "ucircumflex", + "udieresis", + "dagger", + "degree", + "cent", + "sterling", + "section", + "bullet", + "paragraph", + "germandbls", + "registered", + "copyright", + "trademark", + "acute", + "dieresis", + "notequal", + "AE", + "Oslash", + "infinity", + "plusminus", + "lessequal", + "greaterequal", + "yen", + "mu", + "partialdiff", + "summation", + "product", + "pi", + "integral", + "ordfeminine", + "ordmasculine", + "Omega", + "ae", + "oslash", + "questiondown", + "exclamdown", + "logicalnot", + "radical", + "florin", + "approxequal", + "Delta", + "guillemotleft", + "guillemotright", + "ellipsis", + "space", + "Agrave", + "Atilde", + "Otilde", + "OE", + "oe", + "endash", + "emdash", + "quotedblleft", + "quotedblright", + "quoteleft", + "quoteright", + "divide", + "lozenge", + "ydieresis", + "Ydieresis", + "fraction", + "currency", + "guilsinglleft", + "guilsinglright", + "fi", + "fl", + "daggerdbl", + "periodcentered", + "quotesinglbase", + "quotedblbase", + "perthousand", + "Acircumflex", + "Ecircumflex", + "Aacute", + "Edieresis", + "Egrave", + "Iacute", + "Icircumflex", + "Idieresis", + "Igrave", + "Oacute", + "Ocircumflex", + "apple", + "Ograve", + "Uacute", + "Ucircumflex", + "Ugrave", + "dotlessi", + "circumflex", + "tilde", + "macron", + "breve", + "dotaccent", + "ring", + "cedilla", + "hungarumlaut", + "ogonek", + "caron" +}; + +const char *macExpertEncoding[256] = { + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "space", + "exclamsmall", + "Hungarumlautsmall", + "centoldstyle", + "dollaroldstyle", + "dollarsuperior", + "ampersandsmall", + "Acutesmall", + "parenleftsuperior", + "parenrightsuperior", + "twodotenleader", + "onedotenleader", + "comma", + "hyphen", + "period", + "fraction", + "zerooldstyle", + "oneoldstyle", + "twooldstyle", + "threeoldstyle", + "fouroldstyle", + "fiveoldstyle", + "sixoldstyle", + "sevenoldstyle", + "eightoldstyle", + "nineoldstyle", + "colon", + "semicolon", + NULL, + "threequartersemdash", + NULL, + "questionsmall", + NULL, + NULL, + NULL, + NULL, + "Ethsmall", + NULL, + NULL, + "onequarter", + "onehalf", + "threequarters", + "oneeighth", + "threeeighths", + "fiveeighths", + "seveneighths", + "onethird", + "twothirds", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "ff", + "fi", + "fl", + "ffi", + "ffl", + "parenleftinferior", + NULL, + "parenrightinferior", + "Circumflexsmall", + "hypheninferior", + "Gravesmall", + "Asmall", + "Bsmall", + "Csmall", + "Dsmall", + "Esmall", + "Fsmall", + "Gsmall", + "Hsmall", + "Ismall", + "Jsmall", + "Ksmall", + "Lsmall", + "Msmall", + "Nsmall", + "Osmall", + "Psmall", + "Qsmall", + "Rsmall", + "Ssmall", + "Tsmall", + "Usmall", + "Vsmall", + "Wsmall", + "Xsmall", + "Ysmall", + "Zsmall", + "colonmonetary", + "onefitted", + "rupiah", + "Tildesmall", + NULL, + NULL, + "asuperior", + "centsuperior", + NULL, + NULL, + NULL, + NULL, + "Aacutesmall", + "Agravesmall", + "Acircumflexsmall", + "Adieresissmall", + "Atildesmall", + "Aringsmall", + "Ccedillasmall", + "Eacutesmall", + "Egravesmall", + "Ecircumflexsmall", + "Edieresissmall", + "Iacutesmall", + "Igravesmall", + "Icircumflexsmall", + "Idieresissmall", + "Ntildesmall", + "Oacutesmall", + "Ogravesmall", + "Ocircumflexsmall", + "Odieresissmall", + "Otildesmall", + "Uacutesmall", + "Ugravesmall", + "Ucircumflexsmall", + "Udieresissmall", + NULL, + "eightsuperior", + "fourinferior", + "threeinferior", + "sixinferior", + "eightinferior", + "seveninferior", + "Scaronsmall", + NULL, + "centinferior", + "twoinferior", + NULL, + "Dieresissmall", + NULL, + "Caronsmall", + "osuperior", + "fiveinferior", + NULL, + "commainferior", + "periodinferior", + "Yacutesmall", + NULL, + "dollarinferior", + NULL, + NULL, + "Thornsmall", + NULL, + "nineinferior", + "zeroinferior", + "Zcaronsmall", + "AEsmall", + "Oslashsmall", + "questiondownsmall", + "oneinferior", + "Lslashsmall", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "Cedillasmall", + NULL, + NULL, + NULL, + NULL, + NULL, + "OEsmall", + "figuredash", + "hyphensuperior", + NULL, + NULL, + NULL, + NULL, + "exclamdownsmall", + NULL, + "Ydieresissmall", + NULL, + "onesuperior", + "twosuperior", + "threesuperior", + "foursuperior", + "fivesuperior", + "sixsuperior", + "sevensuperior", + "ninesuperior", + "zerosuperior", + NULL, + "esuperior", + "rsuperior", + "tsuperior", + NULL, + NULL, + "isuperior", + "ssuperior", + "dsuperior", + NULL, + NULL, + NULL, + NULL, + NULL, + "lsuperior", + "Ogoneksmall", + "Brevesmall", + "Macronsmall", + "bsuperior", + "nsuperior", + "msuperior", + "commasuperior", + "periodsuperior", + "Dotaccentsmall", + "Ringsmall", + NULL, + NULL, + NULL, + NULL +}; + +const char *winAnsiEncoding[256] = { + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "space", + "exclam", + "quotedbl", + "numbersign", + "dollar", + "percent", + "ampersand", + "quotesingle", + "parenleft", + "parenright", + "asterisk", + "plus", + "comma", + "hyphen", + "period", + "slash", + "zero", + "one", + "two", + "three", + "four", + "five", + "six", + "seven", + "eight", + "nine", + "colon", + "semicolon", + "less", + "equal", + "greater", + "question", + "at", + "A", + "B", + "C", + "D", + "E", + "F", + "G", + "H", + "I", + "J", + "K", + "L", + "M", + "N", + "O", + "P", + "Q", + "R", + "S", + "T", + "U", + "V", + "W", + "X", + "Y", + "Z", + "bracketleft", + "backslash", + "bracketright", + "asciicircum", + "underscore", + "grave", + "a", + "b", + "c", + "d", + "e", + "f", + "g", + "h", + "i", + "j", + "k", + "l", + "m", + "n", + "o", + "p", + "q", + "r", + "s", + "t", + "u", + "v", + "w", + "x", + "y", + "z", + "braceleft", + "bar", + "braceright", + "asciitilde", + "bullet", + "Euro", + "bullet", + "quotesinglbase", + "florin", + "quotedblbase", + "ellipsis", + "dagger", + "daggerdbl", + "circumflex", + "perthousand", + "Scaron", + "guilsinglleft", + "OE", + "bullet", + "Zcaron", + "bullet", + "bullet", + "quoteleft", + "quoteright", + "quotedblleft", + "quotedblright", + "bullet", + "endash", + "emdash", + "tilde", + "trademark", + "scaron", + "guilsinglright", + "oe", + "bullet", + "zcaron", + "Ydieresis", + "space", + "exclamdown", + "cent", + "sterling", + "currency", + "yen", + "brokenbar", + "section", + "dieresis", + "copyright", + "ordfeminine", + "guillemotleft", + "logicalnot", + "hyphen", + "registered", + "macron", + "degree", + "plusminus", + "twosuperior", + "threesuperior", + "acute", + "mu", + "paragraph", + "periodcentered", + "cedilla", + "onesuperior", + "ordmasculine", + "guillemotright", + "onequarter", + "onehalf", + "threequarters", + "questiondown", + "Agrave", + "Aacute", + "Acircumflex", + "Atilde", + "Adieresis", + "Aring", + "AE", + "Ccedilla", + "Egrave", + "Eacute", + "Ecircumflex", + "Edieresis", + "Igrave", + "Iacute", + "Icircumflex", + "Idieresis", + "Eth", + "Ntilde", + "Ograve", + "Oacute", + "Ocircumflex", + "Otilde", + "Odieresis", + "multiply", + "Oslash", + "Ugrave", + "Uacute", + "Ucircumflex", + "Udieresis", + "Yacute", + "Thorn", + "germandbls", + "agrave", + "aacute", + "acircumflex", + "atilde", + "adieresis", + "aring", + "ae", + "ccedilla", + "egrave", + "eacute", + "ecircumflex", + "edieresis", + "igrave", + "iacute", + "icircumflex", + "idieresis", + "eth", + "ntilde", + "ograve", + "oacute", + "ocircumflex", + "otilde", + "odieresis", + "divide", + "oslash", + "ugrave", + "uacute", + "ucircumflex", + "udieresis", + "yacute", + "thorn", + "ydieresis" +}; + +const char *standardEncoding[256] = { + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "space", + "exclam", + "quotedbl", + "numbersign", + "dollar", + "percent", + "ampersand", + "quoteright", + "parenleft", + "parenright", + "asterisk", + "plus", + "comma", + "hyphen", + "period", + "slash", + "zero", + "one", + "two", + "three", + "four", + "five", + "six", + "seven", + "eight", + "nine", + "colon", + "semicolon", + "less", + "equal", + "greater", + "question", + "at", + "A", + "B", + "C", + "D", + "E", + "F", + "G", + "H", + "I", + "J", + "K", + "L", + "M", + "N", + "O", + "P", + "Q", + "R", + "S", + "T", + "U", + "V", + "W", + "X", + "Y", + "Z", + "bracketleft", + "backslash", + "bracketright", + "asciicircum", + "underscore", + "quoteleft", + "a", + "b", + "c", + "d", + "e", + "f", + "g", + "h", + "i", + "j", + "k", + "l", + "m", + "n", + "o", + "p", + "q", + "r", + "s", + "t", + "u", + "v", + "w", + "x", + "y", + "z", + "braceleft", + "bar", + "braceright", + "asciitilde", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "exclamdown", + "cent", + "sterling", + "fraction", + "yen", + "florin", + "section", + "currency", + "quotesingle", + "quotedblleft", + "guillemotleft", + "guilsinglleft", + "guilsinglright", + "fi", + "fl", + NULL, + "endash", + "dagger", + "daggerdbl", + "periodcentered", + NULL, + "paragraph", + "bullet", + "quotesinglbase", + "quotedblbase", + "quotedblright", + "guillemotright", + "ellipsis", + "perthousand", + NULL, + "questiondown", + NULL, + "grave", + "acute", + "circumflex", + "tilde", + "macron", + "breve", + "dotaccent", + "dieresis", + NULL, + "ring", + "cedilla", + NULL, + "hungarumlaut", + "ogonek", + "caron", + "emdash", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "AE", + NULL, + "ordfeminine", + NULL, + NULL, + NULL, + NULL, + "Lslash", + "Oslash", + "OE", + "ordmasculine", + NULL, + NULL, + NULL, + NULL, + NULL, + "ae", + NULL, + NULL, + NULL, + "dotlessi", + NULL, + NULL, + "lslash", + "oslash", + "oe", + "germandbls", + NULL, + NULL, + NULL, + NULL +}; + +const char *expertEncoding[256] = { + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "space", + "exclamsmall", + "Hungarumlautsmall", + NULL, + "dollaroldstyle", + "dollarsuperior", + "ampersandsmall", + "Acutesmall", + "parenleftsuperior", + "parenrightsuperior", + "twodotenleader", + "onedotenleader", + "comma", + "hyphen", + "period", + "fraction", + "zerooldstyle", + "oneoldstyle", + "twooldstyle", + "threeoldstyle", + "fouroldstyle", + "fiveoldstyle", + "sixoldstyle", + "sevenoldstyle", + "eightoldstyle", + "nineoldstyle", + "colon", + "semicolon", + "commasuperior", + "threequartersemdash", + "periodsuperior", + "questionsmall", + NULL, + "asuperior", + "bsuperior", + "centsuperior", + "dsuperior", + "esuperior", + NULL, + NULL, + NULL, + "isuperior", + NULL, + NULL, + "lsuperior", + "msuperior", + "nsuperior", + "osuperior", + NULL, + NULL, + "rsuperior", + "ssuperior", + "tsuperior", + NULL, + "ff", + "fi", + "fl", + "ffi", + "ffl", + "parenleftinferior", + NULL, + "parenrightinferior", + "Circumflexsmall", + "hyphensuperior", + "Gravesmall", + "Asmall", + "Bsmall", + "Csmall", + "Dsmall", + "Esmall", + "Fsmall", + "Gsmall", + "Hsmall", + "Ismall", + "Jsmall", + "Ksmall", + "Lsmall", + "Msmall", + "Nsmall", + "Osmall", + "Psmall", + "Qsmall", + "Rsmall", + "Ssmall", + "Tsmall", + "Usmall", + "Vsmall", + "Wsmall", + "Xsmall", + "Ysmall", + "Zsmall", + "colonmonetary", + "onefitted", + "rupiah", + "Tildesmall", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "exclamdownsmall", + "centoldstyle", + "Lslashsmall", + NULL, + NULL, + "Scaronsmall", + "Zcaronsmall", + "Dieresissmall", + "Brevesmall", + "Caronsmall", + NULL, + "Dotaccentsmall", + NULL, + NULL, + "Macronsmall", + NULL, + NULL, + "figuredash", + "hypheninferior", + NULL, + NULL, + "Ogoneksmall", + "Ringsmall", + "Cedillasmall", + NULL, + NULL, + NULL, + "onequarter", + "onehalf", + "threequarters", + "questiondownsmall", + "oneeighth", + "threeeighths", + "fiveeighths", + "seveneighths", + "onethird", + "twothirds", + NULL, + NULL, + "zerosuperior", + "onesuperior", + "twosuperior", + "threesuperior", + "foursuperior", + "fivesuperior", + "sixsuperior", + "sevensuperior", + "eightsuperior", + "ninesuperior", + "zeroinferior", + "oneinferior", + "twoinferior", + "threeinferior", + "fourinferior", + "fiveinferior", + "sixinferior", + "seveninferior", + "eightinferior", + "nineinferior", + "centinferior", + "dollarinferior", + "periodinferior", + "commainferior", + "Agravesmall", + "Aacutesmall", + "Acircumflexsmall", + "Atildesmall", + "Adieresissmall", + "Aringsmall", + "AEsmall", + "Ccedillasmall", + "Egravesmall", + "Eacutesmall", + "Ecircumflexsmall", + "Edieresissmall", + "Igravesmall", + "Iacutesmall", + "Icircumflexsmall", + "Idieresissmall", + "Ethsmall", + "Ntildesmall", + "Ogravesmall", + "Oacutesmall", + "Ocircumflexsmall", + "Otildesmall", + "Odieresissmall", + "OEsmall", + "Oslashsmall", + "Ugravesmall", + "Uacutesmall", + "Ucircumflexsmall", + "Udieresissmall", + "Yacutesmall", + "Thornsmall", + "Ydieresissmall" +}; + +const char *symbolEncoding[256] = { + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "space", + "exclam", + "universal", + "numbersign", + "existential", + "percent", + "ampersand", + "suchthat", + "parenleft", + "parenright", + "asteriskmath", + "plus", + "comma", + "minus", + "period", + "slash", + "zero", + "one", + "two", + "three", + "four", + "five", + "six", + "seven", + "eight", + "nine", + "colon", + "semicolon", + "less", + "equal", + "greater", + "question", + "congruent", + "Alpha", + "Beta", + "Chi", + "Delta", + "Epsilon", + "Phi", + "Gamma", + "Eta", + "Iota", + "theta1", + "Kappa", + "Lambda", + "Mu", + "Nu", + "Omicron", + "Pi", + "Theta", + "Rho", + "Sigma", + "Tau", + "Upsilon", + "sigma1", + "Omega", + "Xi", + "Psi", + "Zeta", + "bracketleft", + "therefore", + "bracketright", + "perpendicular", + "underscore", + "radicalex", + "alpha", + "beta", + "chi", + "delta", + "epsilon", + "phi", + "gamma", + "eta", + "iota", + "phi1", + "kappa", + "lambda", + "mu", + "nu", + "omicron", + "pi", + "theta", + "rho", + "sigma", + "tau", + "upsilon", + "omega1", + "omega", + "xi", + "psi", + "zeta", + "braceleft", + "bar", + "braceright", + "similar", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "Upsilon1", + "minute", + "lessequal", + "fraction", + "infinity", + "florin", + "club", + "diamond", + "heart", + "spade", + "arrowboth", + "arrowleft", + "arrowup", + "arrowright", + "arrowdown", + "degree", + "plusminus", + "second", + "greaterequal", + "multiply", + "proportional", + "partialdiff", + "bullet", + "divide", + "notequal", + "equivalence", + "approxequal", + "ellipsis", + "arrowvertex", + "arrowhorizex", + "carriagereturn", + "aleph", + "Ifraktur", + "Rfraktur", + "weierstrass", + "circlemultiply", + "circleplus", + "emptyset", + "intersection", + "union", + "propersuperset", + "reflexsuperset", + "notsubset", + "propersubset", + "reflexsubset", + "element", + "notelement", + "angle", + "gradient", + "registerserif", + "copyrightserif", + "trademarkserif", + "product", + "radical", + "dotmath", + "logicalnot", + "logicaland", + "logicalor", + "arrowdblboth", + "arrowdblleft", + "arrowdblup", + "arrowdblright", + "arrowdbldown", + "lozenge", + "angleleft", + "registersans", + "copyrightsans", + "trademarksans", + "summation", + "parenlefttp", + "parenleftex", + "parenleftbt", + "bracketlefttp", + "bracketleftex", + "bracketleftbt", + "bracelefttp", + "braceleftmid", + "braceleftbt", + "braceex", + NULL, + "angleright", + "integral", + "integraltp", + "integralex", + "integralbt", + "parenrighttp", + "parenrightex", + "parenrightbt", + "bracketrighttp", + "bracketrightex", + "bracketrightbt", + "bracerighttp", + "bracerightmid", + "bracerightbt", + NULL +}; + +const char *zapfDingbatsEncoding[256] = { + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "space", + "a1", + "a2", + "a202", + "a3", + "a4", + "a5", + "a119", + "a118", + "a117", + "a11", + "a12", + "a13", + "a14", + "a15", + "a16", + "a105", + "a17", + "a18", + "a19", + "a20", + "a21", + "a22", + "a23", + "a24", + "a25", + "a26", + "a27", + "a28", + "a6", + "a7", + "a8", + "a9", + "a10", + "a29", + "a30", + "a31", + "a32", + "a33", + "a34", + "a35", + "a36", + "a37", + "a38", + "a39", + "a40", + "a41", + "a42", + "a43", + "a44", + "a45", + "a46", + "a47", + "a48", + "a49", + "a50", + "a51", + "a52", + "a53", + "a54", + "a55", + "a56", + "a57", + "a58", + "a59", + "a60", + "a61", + "a62", + "a63", + "a64", + "a65", + "a66", + "a67", + "a68", + "a69", + "a70", + "a71", + "a72", + "a73", + "a74", + "a203", + "a75", + "a204", + "a76", + "a77", + "a78", + "a79", + "a81", + "a82", + "a83", + "a84", + "a97", + "a98", + "a99", + "a100", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "a101", + "a102", + "a103", + "a104", + "a106", + "a107", + "a108", + "a112", + "a111", + "a110", + "a109", + "a120", + "a121", + "a122", + "a123", + "a124", + "a125", + "a126", + "a127", + "a128", + "a129", + "a130", + "a131", + "a132", + "a133", + "a134", + "a135", + "a136", + "a137", + "a138", + "a139", + "a140", + "a141", + "a142", + "a143", + "a144", + "a145", + "a146", + "a147", + "a148", + "a149", + "a150", + "a151", + "a152", + "a153", + "a154", + "a155", + "a156", + "a157", + "a158", + "a159", + "a160", + "a161", + "a163", + "a164", + "a196", + "a165", + "a192", + "a166", + "a167", + "a168", + "a169", + "a170", + "a171", + "a172", + "a173", + "a162", + "a174", + "a175", + "a176", + "a177", + "a178", + "a179", + "a193", + "a180", + "a199", + "a181", + "a200", + "a182", + NULL, + "a201", + "a183", + "a184", + "a197", + "a185", + "a194", + "a198", + "a186", + "a195", + "a187", + "a188", + "a189", + "a190", + "a191", + NULL +}; diff --git a/xpdf/FontEncodingTables.h b/xpdf/FontEncodingTables.h new file mode 100644 index 0000000..a417b32 --- /dev/null +++ b/xpdf/FontEncodingTables.h @@ -0,0 +1,20 @@ +//======================================================================== +// +// FontEncodingTables.h +// +// Copyright 2001-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef FONTENCODINGTABLES_H +#define FONTENCODINGTABLES_H + +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 new file mode 100644 index 0000000..82f32b9 --- /dev/null +++ b/xpdf/Function.cc @@ -0,0 +1,1602 @@ +//======================================================================== +// +// Function.cc +// +// Copyright 2001-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include +#include +#include +#include "gmem.h" +#include "gmempp.h" +#include "GList.h" +#include "Object.h" +#include "Dict.h" +#include "Stream.h" +#include "Error.h" +#include "Function.h" + +//------------------------------------------------------------------------ + +// Max depth of nested functions. This is used to catch infinite +// loops in the function object structure. +#define recursionLimit 8 + +//------------------------------------------------------------------------ +// Function +//------------------------------------------------------------------------ + +Function::Function() { +} + +Function::~Function() { +} + +Function *Function::parse(Object *funcObj, int expectedInputs, + int expectedOutputs, 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()) { + dict = funcObj->getDict(); + } else if (funcObj->isName("Identity")) { + if (expectedInputs != expectedOutputs) { + error(errSyntaxError, -1, "Invalid use of identity function"); + return NULL; + } + return new IdentityFunction(expectedInputs); + } else { + error(errSyntaxError, -1, "Expected function dictionary or stream"); + return NULL; + } + + if (!dict->lookup("FunctionType", &obj1)->isInt()) { + error(errSyntaxError, -1, "Function type is missing or wrong type"); + obj1.free(); + return NULL; + } + funcType = obj1.getInt(); + obj1.free(); + + if (funcType == 0) { + func = new SampledFunction(funcObj, dict); + } else if (funcType == 2) { + func = new ExponentialFunction(funcObj, dict); + } else if (funcType == 3) { + func = new StitchingFunction(funcObj, dict, expectedInputs, + expectedOutputs, recursion); + } else if (funcType == 4) { + func = new PostScriptFunction(funcObj, dict); + } else { + error(errSyntaxError, -1, "Unimplemented function type ({0:d})", funcType); + return NULL; + } + if (!func->isOk()) { + delete func; + return NULL; + } + + if (func->getInputSize() != expectedInputs || + (expectedOutputs >= 0 && func->getOutputSize() != expectedOutputs)) { + error(errSyntaxError, -1, + "Incorrect number of function inputs or outputs"); + delete func; + return NULL; + } + + return func; +} + +GBool Function::init(Dict *dict) { + Object obj1, obj2; + int i; + + //----- Domain + if (!dict->lookup("Domain", &obj1)->isArray()) { + error(errSyntaxError, -1, "Function is missing domain"); + goto err2; + } + m = obj1.arrayGetLength() / 2; + if (m > funcMaxInputs) { + 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(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(errSyntaxError, -1, "Illegal value in function domain array"); + goto err1; + } + domain[i][1] = obj2.getNum(); + obj2.free(); + } + obj1.free(); + + //----- Range + hasRange = gFalse; + n = 0; + if (dict->lookup("Range", &obj1)->isArray()) { + hasRange = gTrue; + n = obj1.arrayGetLength() / 2; + if (n > funcMaxOutputs) { + 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(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(errSyntaxError, -1, "Illegal value in function range array"); + goto err1; + } + range[i][1] = obj2.getNum(); + obj2.free(); + } + } + obj1.free(); + + return gTrue; + + err1: + obj2.free(); + err2: + obj1.free(); + return gFalse; +} + +//------------------------------------------------------------------------ +// IdentityFunction +//------------------------------------------------------------------------ + +IdentityFunction::IdentityFunction(int nInputs) { + int i; + + m = n = nInputs; + // domain info shouldn't be used anywhere + for (i = 0; i < nInputs; ++i) { + domain[i][0] = 0; + domain[i][1] = 1; + } + hasRange = gFalse; +} + +IdentityFunction::~IdentityFunction() { +} + +void IdentityFunction::transform(double *in, double *out) { + int i; + + for (i = 0; i < m; ++i) { + out[i] = in[i]; + } +} + +//------------------------------------------------------------------------ +// SampledFunction +//------------------------------------------------------------------------ + +SampledFunction::SampledFunction(Object *funcObj, Dict *dict) { + Stream *str; + int sampleBits; + double sampleMul; + Object obj1, obj2; + Guint buf, bitMask; + int bits; + Guint s; + double in[funcMaxInputs]; + int i, j, t, bit, idx; + + idxOffset = NULL; + samples = NULL; + sBuf = NULL; + ok = gFalse; + + //----- initialize the generic stuff + if (!init(dict)) { + goto err1; + } + if (!hasRange) { + error(errSyntaxError, -1, "Type 0 function is missing range"); + goto err1; + } + if (m > sampledFuncMaxInputs) { + error(errSyntaxError, -1, + "Sampled functions with more than {0:d} inputs are unsupported", + sampledFuncMaxInputs); + goto err1; + } + + //----- buffer + sBuf = (double *)gmallocn(1 << m, sizeof(double)); + + //----- get the stream + if (!funcObj->isStream()) { + error(errSyntaxError, -1, "Type 0 function isn't a stream"); + goto err1; + } + str = funcObj->getStream(); + + //----- Size + if (!dict->lookup("Size", &obj1)->isArray() || + obj1.arrayGetLength() != m) { + 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(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(); + idxOffset = (int *)gmallocn(1 << m, sizeof(int)); + for (i = 0; i < (1<= 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(errSyntaxError, -1, "Function has missing or invalid BitsPerSample"); + goto err2; + } + sampleBits = obj1.getInt(); + sampleMul = 1.0 / (pow(2.0, (double)sampleBits) - 1); + obj1.free(); + + //----- Encode + if (dict->lookup("Encode", &obj1)->isArray() && + obj1.arrayGetLength() == 2*m) { + for (i = 0; i < m; ++i) { + obj1.arrayGet(2*i, &obj2); + if (!obj2.isNum()) { + 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(errSyntaxError, -1, "Illegal value in function encode array"); + goto err3; + } + encode[i][1] = obj2.getNum(); + obj2.free(); + } + } else { + for (i = 0; i < m; ++i) { + encode[i][0] = 0; + encode[i][1] = sampleSize[i] - 1; + } + } + obj1.free(); + for (i = 0; i < m; ++i) { + inputMul[i] = (encode[i][1] - encode[i][0]) / + (domain[i][1] - domain[i][0]); + } + + //----- Decode + if (dict->lookup("Decode", &obj1)->isArray() && + obj1.arrayGetLength() == 2*n) { + for (i = 0; i < n; ++i) { + obj1.arrayGet(2*i, &obj2); + if (!obj2.isNum()) { + 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(errSyntaxError, -1, "Illegal value in function decode array"); + goto err3; + } + decode[i][1] = obj2.getNum(); + obj2.free(); + } + } else { + for (i = 0; i < n; ++i) { + decode[i][0] = range[i][0]; + decode[i][1] = range[i][1]; + } + } + obj1.free(); + + //----- samples + nSamples = n; + for (i = 0; i < m; ++i) { + if (nSamples > INT_MAX / sampleSize[i]) { + error(errSyntaxError, -1, "Integer overflow in sampled function setup"); + goto err1; + } + nSamples *= sampleSize[i]; + } + samples = (double *)gmallocn(nSamples, sizeof(double)); + buf = 0; + bits = 0; + bitMask = (sampleBits < 32) ? ((1 << sampleBits) - 1) : 0xffffffffU; + str->reset(); + for (i = 0; i < nSamples; ++i) { + if (sampleBits == 8) { + s = str->getChar(); + } else if (sampleBits == 16) { + s = str->getChar(); + s = (s << 8) + str->getChar(); + } else if (sampleBits == 32) { + s = str->getChar(); + s = (s << 8) + str->getChar(); + s = (s << 8) + str->getChar(); + s = (s << 8) + str->getChar(); + } else { + while (bits < sampleBits) { + buf = (buf << 8) | (str->getChar() & 0xff); + bits += 8; + } + s = (buf >> (bits - sampleBits)) & bitMask; + bits -= sampleBits; + } + samples[i] = (double)s * sampleMul; + } + 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; + + err3: + obj2.free(); + err2: + obj1.free(); + err1: + return; +} + +SampledFunction::~SampledFunction() { + if (idxOffset) { + gfree(idxOffset); + } + if (samples) { + gfree(samples); + } + if (sBuf) { + gfree(sBuf); + } +} + +SampledFunction::SampledFunction(SampledFunction *func) { + memcpy((void *)this, (void *)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)); +} + +void SampledFunction::transform(double *in, double *out) { + double x; + int e[funcMaxInputs]; + double efrac0[funcMaxInputs]; + double efrac1[funcMaxInputs]; + 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 || 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] = (int)x; + if (e[i] == sampleSize[i] - 1 && sampleSize[i] > 1) { + // this happens if in[i] = domain[i][1] + e[i] = sampleSize[i] - 2; + } + 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<>= 1) { + for (k = 0; k < t; k += 2) { + sBuf[k >> 1] = efrac0[j] * sBuf[k] + efrac1[j] * sBuf[k+1]; + } + } + + // map output value to range + out[i] = sBuf[0] * (decode[i][1] - decode[i][0]) + decode[i][0]; + if (out[i] < range[i][0]) { + out[i] = range[i][0]; + } else if (out[i] > range[i][1]) { + 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]; + } +} + +//------------------------------------------------------------------------ +// ExponentialFunction +//------------------------------------------------------------------------ + +ExponentialFunction::ExponentialFunction(Object *funcObj, Dict *dict) { + Object obj1, obj2; + int i; + + ok = gFalse; + + //----- initialize the generic stuff + if (!init(dict)) { + goto err1; + } + if (m != 1) { + 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(errSyntaxError, -1, "Function's C0 array is wrong length"); + goto err2; + } + n = obj1.arrayGetLength(); + if (n > funcMaxOutputs) { + error(errSyntaxError, -1, + "Functions with more than {0:d} outputs are unsupported", + funcMaxOutputs); + goto err2; + } + for (i = 0; i < n; ++i) { + obj1.arrayGet(i, &obj2); + if (!obj2.isNum()) { + error(errSyntaxError, -1, "Illegal value in function C0 array"); + goto err3; + } + c0[i] = obj2.getNum(); + obj2.free(); + } + } else { + if (hasRange && n != 1) { + error(errSyntaxError, -1, "Function's C0 array is wrong length"); + goto err2; + } + n = 1; + c0[0] = 0; + } + obj1.free(); + + //----- C1 + if (dict->lookup("C1", &obj1)->isArray()) { + if (obj1.arrayGetLength() != n) { + 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(errSyntaxError, -1, "Illegal value in function C1 array"); + goto err3; + } + c1[i] = obj2.getNum(); + obj2.free(); + } + } else { + if (n != 1) { + error(errSyntaxError, -1, "Function's C1 array is wrong length"); + goto err2; + } + c1[0] = 1; + } + obj1.free(); + + //----- N (exponent) + if (!dict->lookup("N", &obj1)->isNum()) { + error(errSyntaxError, -1, "Function has missing or invalid N"); + goto err2; + } + e = obj1.getNum(); + obj1.free(); + + ok = gTrue; + return; + + err3: + obj2.free(); + err2: + obj1.free(); + err1: + return; +} + +ExponentialFunction::~ExponentialFunction() { +} + +ExponentialFunction::ExponentialFunction(ExponentialFunction *func) { + memcpy((void *)this, (void *)func, sizeof(ExponentialFunction)); +} + +void ExponentialFunction::transform(double *in, double *out) { + double x; + int i; + + if (in[0] < domain[0][0]) { + x = domain[0][0]; + } else if (in[0] > domain[0][1]) { + x = domain[0][1]; + } else { + x = in[0]; + } + for (i = 0; i < n; ++i) { + out[i] = c0[i] + pow(x, e) * (c1[i] - c0[i]); + if (hasRange) { + if (out[i] < range[i][0]) { + out[i] = range[i][0]; + } else if (out[i] > range[i][1]) { + out[i] = range[i][1]; + } + } + } + return; +} + +//------------------------------------------------------------------------ +// StitchingFunction +//------------------------------------------------------------------------ + +StitchingFunction::StitchingFunction(Object *funcObj, Dict *dict, + int expectedInputs, int expectedOutputs, + int recursion) { + Object obj1, obj2; + int i; + + ok = gFalse; + funcs = NULL; + bounds = NULL; + encode = NULL; + scale = NULL; + + //----- initialize the generic stuff + if (!init(dict)) { + goto err1; + } + if (m != 1) { + error(errSyntaxError, -1, "Stitching function with more than one input"); + goto err1; + } + + //----- Functions + if (!dict->lookup("Functions", &obj1)->isArray() || + obj1.arrayGetLength() < 1) { + error(errSyntaxError, -1, + "Missing 'Functions' entry in stitching function"); + goto err1; + } + k = obj1.arrayGetLength(); + funcs = (Function **)gmallocn(k, sizeof(Function *)); + bounds = (double *)gmallocn(k + 1, sizeof(double)); + encode = (double *)gmallocn(2 * k, sizeof(double)); + scale = (double *)gmallocn(k, sizeof(double)); + for (i = 0; i < k; ++i) { + funcs[i] = NULL; + } + for (i = 0; i < k; ++i) { + if (!(funcs[i] = Function::parse(obj1.arrayGet(i, &obj2), + expectedInputs, expectedOutputs, + recursion + 1))) { + goto err2; + } + if (i == 0) { + n = funcs[0]->getOutputSize(); + } + if (funcs[i]->getInputSize() != 1 || funcs[i]->getOutputSize() != n) { + error(errSyntaxError, -1, + "Incompatible subfunctions in stitching function"); + goto err2; + } + obj2.free(); + } + obj1.free(); + + //----- Bounds + if (!dict->lookup("Bounds", &obj1)->isArray() || + obj1.arrayGetLength() != k - 1) { + 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(errSyntaxError, -1, + "Invalid type in 'Bounds' array in stitching function"); + goto err2; + } + bounds[i] = obj2.getNum(); + obj2.free(); + } + bounds[k] = domain[0][1]; + obj1.free(); + + //----- Encode + if (!dict->lookup("Encode", &obj1)->isArray() || + obj1.arrayGetLength() != 2 * k) { + 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(errSyntaxError, -1, + "Invalid type in 'Encode' array in stitching function"); + goto err2; + } + encode[i] = obj2.getNum(); + obj2.free(); + } + obj1.free(); + + //----- pre-compute the scale factors + for (i = 0; i < k; ++i) { + if (bounds[i] == bounds[i+1]) { + // avoid a divide-by-zero -- in this situation, function i will + // never be used anyway + scale[i] = 0; + } else { + scale[i] = (encode[2*i+1] - encode[2*i]) / (bounds[i+1] - bounds[i]); + } + } + + ok = gTrue; + return; + + err2: + obj2.free(); + err1: + obj1.free(); +} + +StitchingFunction::StitchingFunction(StitchingFunction *func) { + int i; + + memcpy((void *)this, (void *)func, sizeof(StitchingFunction)); + funcs = (Function **)gmallocn(k, sizeof(Function *)); + for (i = 0; i < k; ++i) { + funcs[i] = func->funcs[i]->copy(); + } + bounds = (double *)gmallocn(k + 1, sizeof(double)); + memcpy(bounds, func->bounds, (k + 1) * sizeof(double)); + encode = (double *)gmallocn(2 * k, sizeof(double)); + memcpy(encode, func->encode, 2 * k * sizeof(double)); + scale = (double *)gmallocn(k, sizeof(double)); + memcpy(scale, func->scale, k * sizeof(double)); + ok = gTrue; +} + +StitchingFunction::~StitchingFunction() { + int i; + + if (funcs) { + for (i = 0; i < k; ++i) { + if (funcs[i]) { + delete funcs[i]; + } + } + } + gfree(funcs); + gfree(bounds); + gfree(encode); + gfree(scale); +} + +void StitchingFunction::transform(double *in, double *out) { + double x; + int i; + + if (in[0] < domain[0][0]) { + x = domain[0][0]; + } else if (in[0] > domain[0][1]) { + x = domain[0][1]; + } else { + x = in[0]; + } + for (i = 0; i < k - 1; ++i) { + if (x < bounds[i+1]) { + break; + } + } + x = encode[2*i] + (x - bounds[i]) * scale[i]; + funcs[i]->transform(&x, out); +} + +//------------------------------------------------------------------------ +// PostScriptFunction +//------------------------------------------------------------------------ + +// This is not an enum, because we can't foreward-declare the enum +// type in Function.h +// +// NB: This must be kept in sync with psOpNames[] below. +#define psOpAbs 0 +#define psOpAdd 1 +#define psOpAnd 2 +#define psOpAtan 3 +#define psOpBitshift 4 +#define psOpCeiling 5 +#define psOpCopy 6 +#define psOpCos 7 +#define psOpCvi 8 +#define psOpCvr 9 +#define psOpDiv 10 +#define psOpDup 11 +#define psOpEq 12 +#define psOpExch 13 +#define psOpExp 14 +#define psOpFalse 15 +#define psOpFloor 16 +#define psOpGe 17 +#define psOpGt 18 +#define psOpIdiv 19 +#define psOpIndex 20 +#define psOpLe 21 +#define psOpLn 22 +#define psOpLog 23 +#define psOpLt 24 +#define psOpMod 25 +#define psOpMul 26 +#define psOpNe 27 +#define psOpNeg 28 +#define psOpNot 29 +#define psOpOr 30 +#define psOpPop 31 +#define psOpRoll 32 +#define psOpRound 33 +#define psOpSin 34 +#define psOpSqrt 35 +#define psOpSub 36 +#define psOpTrue 37 +#define psOpTruncate 38 +#define psOpXor 39 +// the push/j/jz ops are used internally (and are not listed in psOpNames[]) +#define psOpPush 40 +#define psOpJ 41 +#define psOpJz 42 + +#define nPSOps (sizeof(psOpNames) / sizeof(const char *)) + +// Note: 'if' and 'ifelse' are parsed separately. +// The rest are listed here in alphabetical order. +// +// NB: This must be kept in sync with the psOpXXX defines above. +static const char *psOpNames[] = { + "abs", + "add", + "and", + "atan", + "bitshift", + "ceiling", + "copy", + "cos", + "cvi", + "cvr", + "div", + "dup", + "eq", + "exch", + "exp", + "false", + "floor", + "ge", + "gt", + "idiv", + "index", + "le", + "ln", + "log", + "lt", + "mod", + "mul", + "ne", + "neg", + "not", + "or", + "pop", + "roll", + "round", + "sin", + "sqrt", + "sub", + "true", + "truncate", + "xor" +}; + +struct PSCode { + int op; + union { + double d; + int i; + } val; +}; + +#define psStackSize 100 + +PostScriptFunction::PostScriptFunction(Object *funcObj, Dict *dict) { + Stream *str; + GList *tokens; + GString *tok; + double in[funcMaxInputs]; + int tokPtr, codePtr, i; + + codeString = NULL; + code = NULL; + codeSize = 0; + ok = gFalse; + + //----- initialize the generic stuff + if (!init(dict)) { + goto err1; + } + if (!hasRange) { + error(errSyntaxError, -1, "Type 4 function is missing range"); + goto err1; + } + + //----- get the stream + if (!funcObj->isStream()) { + error(errSyntaxError, -1, "Type 4 function isn't a stream"); + goto err1; + } + str = funcObj->getStream(); + + //----- tokenize the function + codeString = new GString(); + tokens = new GList(); + str->reset(); + while ((tok = getToken(str))) { + tokens->append(tok); + } + str->close(); + + //----- parse the function + if (tokens->getLength() < 1 || + ((GString *)tokens->get(0))->cmp("{")) { + error(errSyntaxError, -1, "Expected '{{' at start of PostScript function"); + goto err2; + } + tokPtr = 1; + codePtr = 0; + if (!parseCode(tokens, &tokPtr, &codePtr)) { + goto err2; + } + codeLen = codePtr; + + //----- 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: + deleteGList(tokens, GString); + err1: + return; +} + +PostScriptFunction::PostScriptFunction(PostScriptFunction *func) { + memcpy((void *)this, (void *)func, sizeof(PostScriptFunction)); + codeString = func->codeString->copy(); + code = (PSCode *)gmallocn(codeSize, sizeof(PSCode)); + memcpy(code, func->code, codeSize * sizeof(PSCode)); +} + +PostScriptFunction::~PostScriptFunction() { + gfree(code); + if (codeString) { + delete codeString; + } +} + +void PostScriptFunction::transform(double *in, double *out) { + double stack[psStackSize]; + double x; + int sp, 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; + } + + for (i = 0; i < m; ++i) { + stack[psStackSize - 1 - i] = in[i]; + } + sp = exec(stack, psStackSize - m); + // if (sp < psStackSize - n) { + // error(errSyntaxWarning, -1, + // "Extra values on stack at end of PostScript function"); + // } + if (sp > psStackSize - n) { + error(errSyntaxError, -1, "Stack underflow in PostScript function"); + sp = psStackSize - n; + } + for (i = 0; i < n; ++i) { + x = stack[sp + n - 1 - i]; + if (x < range[i][0]) { + out[i] = range[i][0]; + } else if (x > range[i][1]) { + out[i] = range[i][1]; + } else { + out[i] = x; + } + } + + // 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(GList *tokens, int *tokPtr, int *codePtr) { + GString *tok; + char *p; + int a, b, mid, cmp; + int codePtr0, codePtr1; + + while (1) { + if (*tokPtr >= tokens->getLength()) { + error(errSyntaxError, -1, + "Unexpected end of PostScript function stream"); + return gFalse; + } + tok = (GString *)tokens->get((*tokPtr)++); + p = tok->getCString(); + if (isdigit(*p) || *p == '.' || *p == '-') { + addCodeD(codePtr, psOpPush, atof(tok->getCString())); + } else if (!tok->cmp("{")) { + codePtr0 = *codePtr; + addCodeI(codePtr, psOpJz, 0); + if (!parseCode(tokens, tokPtr, codePtr)) { + return gFalse; + } + if (*tokPtr >= tokens->getLength()) { + error(errSyntaxError, -1, + "Unexpected end of PostScript function stream"); + return gFalse; + } + tok = (GString *)tokens->get((*tokPtr)++); + if (!tok->cmp("if")) { + code[codePtr0].val.i = *codePtr; + } else if (!tok->cmp("{")) { + codePtr1 = *codePtr; + addCodeI(codePtr, psOpJ, 0); + code[codePtr0].val.i = *codePtr; + if (!parseCode(tokens, tokPtr, codePtr)) { + return gFalse; + } + if (*tokPtr >= tokens->getLength()) { + error(errSyntaxError, -1, + "Unexpected end of PostScript function stream"); + return gFalse; + } + tok = (GString *)tokens->get((*tokPtr)++); + if (!tok->cmp("ifelse")) { + code[codePtr1].val.i = *codePtr; + } else { + error(errSyntaxError, -1, + "Expected 'ifelse' in PostScript function stream"); + return gFalse; + } + } else { + error(errSyntaxError, -1, + "Expected 'if' in PostScript function stream"); + return gFalse; + } + } else if (!tok->cmp("}")) { + break; + } else if (!tok->cmp("if")) { + error(errSyntaxError, -1, + "Unexpected 'if' in PostScript function stream"); + return gFalse; + } else if (!tok->cmp("ifelse")) { + error(errSyntaxError, -1, + "Unexpected 'ifelse' in PostScript function stream"); + return gFalse; + } else { + a = -1; + b = nPSOps; + cmp = 0; // make gcc happy + // invariant: psOpNames[a] < tok < psOpNames[b] + while (b - a > 1) { + mid = (a + b) / 2; + cmp = tok->cmp(psOpNames[mid]); + if (cmp > 0) { + a = mid; + } else if (cmp < 0) { + b = mid; + } else { + a = b = mid; + } + } + if (cmp != 0) { + error(errSyntaxError, -1, + "Unknown operator '{0:t}' in PostScript function", + tok); + return gFalse; + } + addCode(codePtr, a); + } + } + return gTrue; +} + +void PostScriptFunction::addCode(int *codePtr, int op) { + if (*codePtr >= codeSize) { + if (codeSize) { + codeSize *= 2; + } else { + codeSize = 16; + } + code = (PSCode *)greallocn(code, codeSize, sizeof(PSCode)); + } + code[*codePtr].op = op; + ++(*codePtr); +} + +void PostScriptFunction::addCodeI(int *codePtr, int op, int x) { + if (*codePtr >= codeSize) { + if (codeSize) { + codeSize *= 2; + } else { + codeSize = 16; + } + code = (PSCode *)greallocn(code, codeSize, sizeof(PSCode)); + } + code[*codePtr].op = op; + code[*codePtr].val.i = x; + ++(*codePtr); +} + +void PostScriptFunction::addCodeD(int *codePtr, int op, double x) { + if (*codePtr >= codeSize) { + if (codeSize) { + codeSize *= 2; + } else { + codeSize = 16; + } + code = (PSCode *)greallocn(code, codeSize, sizeof(PSCode)); + } + code[*codePtr].op = op; + code[*codePtr].val.d = x; + ++(*codePtr); +} + +GString *PostScriptFunction::getToken(Stream *str) { + GString *s; + int c; + GBool comment; + + s = new GString(); + comment = gFalse; + while (1) { + if ((c = str->getChar()) == EOF) { + delete s; + return NULL; + } + codeString->append((char)c); + if (comment) { + if (c == '\x0a' || c == '\x0d') { + comment = gFalse; + } + } else if (c == '%') { + comment = gTrue; + } else if (!isspace(c)) { + break; + } + } + if (c == '{' || c == '}') { + s->append((char)c); + } else if (isdigit(c) || c == '.' || c == '-') { + while (1) { + s->append((char)c); + c = str->lookChar(); + if (c == EOF || !(isdigit(c) || c == '.' || c == '-')) { + break; + } + str->getChar(); + codeString->append((char)c); + } + } else { + while (1) { + s->append((char)c); + c = str->lookChar(); + if (c == EOF || !isalnum(c)) { + break; + } + str->getChar(); + codeString->append((char)c); + } + } + return s; +} + +int PostScriptFunction::exec(double *stack, int sp0) { + PSCode *c; + double tmp[psStackSize]; + double t; + int sp, ip, nn, k, i; + + sp = sp0; + ip = 0; + while (ip < codeLen) { + c = &code[ip++]; + switch(c->op) { + case psOpAbs: + if (sp >= psStackSize) { + goto underflow; + } + stack[sp] = fabs(stack[sp]); + break; + case psOpAdd: + if (sp + 1 >= psStackSize) { + goto underflow; + } + stack[sp + 1] = stack[sp + 1] + stack[sp]; + ++sp; + break; + case psOpAnd: + if (sp + 1 >= psStackSize) { + goto underflow; + } + stack[sp + 1] = (int)stack[sp + 1] & (int)stack[sp]; + ++sp; + break; + case psOpAtan: + if (sp + 1 >= psStackSize) { + goto underflow; + } + stack[sp + 1] = atan2(stack[sp + 1], stack[sp]); + ++sp; + break; + case psOpBitshift: + if (sp + 1 >= psStackSize) { + goto underflow; + } + k = (int)stack[sp + 1]; + nn = (int)stack[sp]; + if (nn > 0) { + stack[sp + 1] = k << nn; + } else if (nn < 0) { + stack[sp + 1] = k >> -nn; + } else { + stack[sp + 1] = k; + } + ++sp; + break; + case psOpCeiling: + if (sp >= psStackSize) { + goto underflow; + } + stack[sp] = ceil(stack[sp]); + break; + case psOpCopy: + if (sp >= psStackSize) { + goto underflow; + } + nn = (int)stack[sp++]; + if (nn < 0) { + goto invalidArg; + } + if (sp + nn > psStackSize) { + goto underflow; + } + if (sp - nn < 0) { + goto overflow; + } + for (i = 0; i < nn; ++i) { + stack[sp - nn + i] = stack[sp + i]; + } + sp -= nn; + break; + case psOpCos: + if (sp >= psStackSize) { + goto underflow; + } + stack[sp] = cos(stack[sp]); + break; + case psOpCvi: + if (sp >= psStackSize) { + goto underflow; + } + stack[sp] = (int)stack[sp]; + break; + case psOpCvr: + if (sp >= psStackSize) { + goto underflow; + } + break; + case psOpDiv: + if (sp + 1 >= psStackSize) { + goto underflow; + } + if (stack[sp] == 0) { + goto invalidArg; + } + stack[sp + 1] = stack[sp + 1] / stack[sp]; + ++sp; + break; + case psOpDup: + if (sp >= psStackSize) { + goto underflow; + } + if (sp < 1) { + goto overflow; + } + stack[sp - 1] = stack[sp]; + --sp; + break; + case psOpEq: + if (sp + 1 >= psStackSize) { + goto underflow; + } + stack[sp + 1] = stack[sp + 1] == stack[sp] ? 1 : 0; + ++sp; + break; + case psOpExch: + if (sp + 1 >= psStackSize) { + goto underflow; + } + t = stack[sp]; + stack[sp] = stack[sp + 1]; + stack[sp + 1] = t; + break; + case psOpExp: + if (sp + 1 >= psStackSize) { + goto underflow; + } + stack[sp + 1] = pow(stack[sp + 1], stack[sp]); + ++sp; + break; + case psOpFalse: + if (sp < 1) { + goto overflow; + } + stack[sp - 1] = 0; + --sp; + break; + case psOpFloor: + if (sp >= psStackSize) { + goto underflow; + } + stack[sp] = floor(stack[sp]); + break; + case psOpGe: + if (sp + 1 >= psStackSize) { + goto underflow; + } + stack[sp + 1] = stack[sp + 1] >= stack[sp] ? 1 : 0; + ++sp; + break; + case psOpGt: + if (sp + 1 >= psStackSize) { + goto underflow; + } + stack[sp + 1] = stack[sp + 1] > stack[sp] ? 1 : 0; + ++sp; + break; + case psOpIdiv: + if (sp + 1 >= psStackSize) { + goto underflow; + } + k = (int)stack[sp]; + if (k == 0) { + goto invalidArg; + } + stack[sp + 1] = (int)stack[sp + 1] / k; + ++sp; + break; + case psOpIndex: + if (sp >= psStackSize) { + goto underflow; + } + k = (int)stack[sp]; + if (k < 0) { + goto invalidArg; + } + if (sp + 1 + k >= psStackSize) { + goto underflow; + } + stack[sp] = stack[sp + 1 + k]; + break; + case psOpLe: + if (sp + 1 >= psStackSize) { + goto underflow; + } + stack[sp + 1] = stack[sp + 1] <= stack[sp] ? 1 : 0; + ++sp; + break; + case psOpLn: + if (sp >= psStackSize) { + goto underflow; + } + stack[sp] = log(stack[sp]); + break; + case psOpLog: + if (sp >= psStackSize) { + goto underflow; + } + stack[sp] = log10(stack[sp]); + break; + case psOpLt: + if (sp + 1 >= psStackSize) { + goto underflow; + } + stack[sp + 1] = stack[sp + 1] < stack[sp] ? 1 : 0; + ++sp; + break; + case psOpMod: + if (sp + 1 >= psStackSize) { + goto underflow; + } + k = (int)stack[sp]; + if (k == 0) { + goto invalidArg; + } + stack[sp + 1] = (int)stack[sp + 1] % k; + ++sp; + break; + case psOpMul: + if (sp + 1 >= psStackSize) { + goto underflow; + } + stack[sp + 1] = stack[sp + 1] * stack[sp]; + ++sp; + break; + case psOpNe: + if (sp + 1 >= psStackSize) { + goto underflow; + } + stack[sp + 1] = stack[sp + 1] != stack[sp] ? 1 : 0; + ++sp; + break; + case psOpNeg: + if (sp >= psStackSize) { + goto underflow; + } + stack[sp] = -stack[sp]; + break; + case psOpNot: + if (sp >= psStackSize) { + goto underflow; + } + stack[sp] = stack[sp] == 0 ? 1 : 0; + break; + case psOpOr: + if (sp + 1 >= psStackSize) { + goto underflow; + } + stack[sp + 1] = (int)stack[sp + 1] | (int)stack[sp]; + ++sp; + break; + case psOpPop: + if (sp >= psStackSize) { + goto underflow; + } + ++sp; + break; + case psOpRoll: + if (sp + 1 >= psStackSize) { + goto underflow; + } + k = (int)stack[sp++]; + nn = (int)stack[sp++]; + if (nn < 0) { + goto invalidArg; + } + if (nn > 0) { + if (sp + nn > psStackSize) { + goto underflow; + } + if (k >= 0) { + k %= nn; + } else { + k = -k % nn; + if (k) { + k = nn - k; + } + } + for (i = 0; i < nn; ++i) { + tmp[i] = stack[sp + i]; + } + for (i = 0; i < nn; ++i) { + stack[sp + i] = tmp[(i + k) % nn]; + } + } + break; + case psOpRound: + if (sp >= psStackSize) { + goto underflow; + } + t = stack[sp]; + stack[sp] = (t >= 0) ? floor(t + 0.5) : ceil(t - 0.5); + break; + case psOpSin: + if (sp >= psStackSize) { + goto underflow; + } + stack[sp] = sin(stack[sp]); + break; + case psOpSqrt: + if (sp >= psStackSize) { + goto underflow; + } + stack[sp] = sqrt(stack[sp]); + break; + case psOpSub: + if (sp + 1 >= psStackSize) { + goto underflow; + } + stack[sp + 1] = stack[sp + 1] - stack[sp]; + ++sp; + break; + case psOpTrue: + if (sp < 1) { + goto overflow; + } + stack[sp - 1] = 1; + --sp; + break; + case psOpTruncate: + if (sp >= psStackSize) { + goto underflow; + } + t = stack[sp]; + stack[sp] = (t >= 0) ? floor(t) : ceil(t); + break; + case psOpXor: + if (sp + 1 >= psStackSize) { + goto underflow; + } + stack[sp + 1] = (int)stack[sp + 1] ^ (int)stack[sp]; + ++sp; + break; + case psOpPush: + if (sp < 1) { + goto overflow; + } + stack[--sp] = c->val.d; + break; + case psOpJ: + ip = c->val.i; + break; + case psOpJz: + if (sp >= psStackSize) { + goto underflow; + } + k = (int)stack[sp++]; + if (k == 0) { + ip = c->val.i; + } + break; + } + } + return sp; + + underflow: + error(errSyntaxError, -1, "Stack underflow in PostScript function"); + return sp; + overflow: + error(errSyntaxError, -1, "Stack overflow in PostScript function"); + return sp; + invalidArg: + error(errSyntaxError, -1, "Invalid arg in PostScript function"); + return sp; +} diff --git a/xpdf/Function.h b/xpdf/Function.h new file mode 100644 index 0000000..bf1f25e --- /dev/null +++ b/xpdf/Function.h @@ -0,0 +1,240 @@ +//======================================================================== +// +// Function.h +// +// Copyright 2001-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef FUNCTION_H +#define FUNCTION_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "gtypes.h" +#include "Object.h" + +class GList; +class Dict; +class Stream; +struct PSCode; + +//------------------------------------------------------------------------ +// Function +//------------------------------------------------------------------------ + +#define funcMaxInputs 32 +#define funcMaxOutputs 32 +#define sampledFuncMaxInputs 16 + +class Function { +public: + + Function(); + + virtual ~Function(); + + // Construct a function, with [expectedInputs] inputs and + // [expectedOutputs] outputs. [expectedOutputs] can be -1 to + // indicate unknown. Returns NULL if unsuccessful. + static Function *parse(Object *funcObj, int expectedInputs, + int expectedOutputs, int recursion = 0); + + // Initialize the entries common to all function types. + GBool init(Dict *dict); + + virtual Function *copy() = 0; + + // Return the function type: + // -1 : identity + // 0 : sampled + // 2 : exponential + // 3 : stitching + // 4 : PostScript + virtual int getType() = 0; + + // Return size of input and output tuples. + int getInputSize() { return m; } + int getOutputSize() { return n; } + + double getDomainMin(int i) { return domain[i][0]; } + double getDomainMax(int i) { return domain[i][1]; } + double getRangeMin(int i) { return range[i][0]; } + double getRangeMax(int i) { return range[i][1]; } + GBool getHasRange() { return hasRange; } + + // Transform an input tuple into an output tuple. + virtual void transform(double *in, double *out) = 0; + + virtual GBool isOk() = 0; + +protected: + + int m, n; // size of input and output tuples + double // min and max values for function domain + domain[funcMaxInputs][2]; + double // min and max values for function range + range[funcMaxOutputs][2]; + GBool hasRange; // set if range is defined +}; + +//------------------------------------------------------------------------ +// IdentityFunction +//------------------------------------------------------------------------ + +class IdentityFunction: public Function { +public: + + IdentityFunction(int nInputs); + virtual ~IdentityFunction(); + virtual Function *copy() { return new IdentityFunction(m); } + virtual int getType() { return -1; } + virtual void transform(double *in, double *out); + virtual GBool isOk() { return gTrue; } + +private: +}; + +//------------------------------------------------------------------------ +// SampledFunction +//------------------------------------------------------------------------ + +class SampledFunction: public Function { +public: + + SampledFunction(Object *funcObj, Dict *dict); + virtual ~SampledFunction(); + virtual Function *copy() { return new SampledFunction(this); } + virtual int getType() { return 0; } + virtual void transform(double *in, double *out); + virtual GBool isOk() { return ok; } + + int getSampleSize(int i) { return sampleSize[i]; } + double getEncodeMin(int i) { return encode[i][0]; } + double getEncodeMax(int i) { return encode[i][1]; } + double getDecodeMin(int i) { return decode[i][0]; } + double getDecodeMax(int i) { return decode[i][1]; } + double *getSamples() { return samples; } + +private: + + SampledFunction(SampledFunction *func); + + int // number of samples for each domain element + sampleSize[funcMaxInputs]; + double // min and max values for domain encoder + encode[funcMaxInputs][2]; + double // min and max values for range decoder + decode[funcMaxOutputs][2]; + double // input multipliers + inputMul[funcMaxInputs]; + 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; +}; + +//------------------------------------------------------------------------ +// ExponentialFunction +//------------------------------------------------------------------------ + +class ExponentialFunction: public Function { +public: + + ExponentialFunction(Object *funcObj, Dict *dict); + virtual ~ExponentialFunction(); + virtual Function *copy() { return new ExponentialFunction(this); } + virtual int getType() { return 2; } + virtual void transform(double *in, double *out); + virtual GBool isOk() { return ok; } + + double *getC0() { return c0; } + double *getC1() { return c1; } + double getE() { return e; } + +private: + + ExponentialFunction(ExponentialFunction *func); + + double c0[funcMaxOutputs]; + double c1[funcMaxOutputs]; + double e; + GBool ok; +}; + +//------------------------------------------------------------------------ +// StitchingFunction +//------------------------------------------------------------------------ + +class StitchingFunction: public Function { +public: + + StitchingFunction(Object *funcObj, Dict *dict, int expectedInputs, + int expectedOutputs, int recursion); + virtual ~StitchingFunction(); + virtual Function *copy() { return new StitchingFunction(this); } + virtual int getType() { return 3; } + virtual void transform(double *in, double *out); + virtual GBool isOk() { return ok; } + + int getNumFuncs() { return k; } + Function *getFunc(int i) { return funcs[i]; } + double *getBounds() { return bounds; } + double *getEncode() { return encode; } + double *getScale() { return scale; } + +private: + + StitchingFunction(StitchingFunction *func); + + int k; + Function **funcs; + double *bounds; + double *encode; + double *scale; + GBool ok; +}; + +//------------------------------------------------------------------------ +// PostScriptFunction +//------------------------------------------------------------------------ + +class PostScriptFunction: public Function { +public: + + PostScriptFunction(Object *funcObj, Dict *dict); + virtual ~PostScriptFunction(); + virtual Function *copy() { return new PostScriptFunction(this); } + virtual int getType() { return 4; } + virtual void transform(double *in, double *out); + virtual GBool isOk() { return ok; } + + GString *getCodeString() { return codeString; } + +private: + + PostScriptFunction(PostScriptFunction *func); + GBool parseCode(GList *tokens, int *tokPtr, int *codePtr); + void addCode(int *codePtr, int op); + void addCodeI(int *codePtr, int op, int x); + void addCodeD(int *codePtr, int op, double x); + GString *getToken(Stream *str); + int exec(double *stack, int sp0); + + GString *codeString; + PSCode *code; + int codeLen; + int codeSize; + double cacheIn[funcMaxInputs]; + double cacheOut[funcMaxOutputs]; + GBool ok; +}; + +#endif diff --git a/xpdf/Gfx.cc b/xpdf/Gfx.cc new file mode 100644 index 0000000..1539b84 --- /dev/null +++ b/xpdf/Gfx.cc @@ -0,0 +1,5386 @@ +//======================================================================== +// +// Gfx.cc +// +// Copyright 1996-2016 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include +#include +#include +#include +#include "gmem.h" +#include "gmempp.h" +#include "GString.h" +#include "GList.h" +#include "Trace.h" +#include "GlobalParams.h" +#include "CharTypes.h" +#include "Object.h" +#include "PDFDoc.h" +#include "Array.h" +#include "Dict.h" +#include "Stream.h" +#include "Lexer.h" +#include "Parser.h" +#include "GfxFont.h" +#include "GfxState.h" +#include "OutputDev.h" +#include "Page.h" +#include "Annot.h" +#include "OptionalContent.h" +#include "Error.h" +#include "TextString.h" +#include "Gfx.h" + +// the MSVC math.h doesn't define this +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +//------------------------------------------------------------------------ +// constants +//------------------------------------------------------------------------ + +// Max recursive depth for a function shading fill. +#define functionMaxDepth 6 + +// Max delta allowed in any color component for a function shading fill. +#define functionColorDelta (dblToCol(1 / 256.0)) + +// Number of splits along the t axis for an axial shading fill. +#define axialSplits 256 + +// Max delta allowed in any color component for an axial shading fill. +#define axialColorDelta (dblToCol(1 / 256.0)) + +// Max number of splits along the t axis for a radial shading fill. +#define radialMaxSplits 256 + +// Max delta allowed in any color component for a radial shading fill. +#define radialColorDelta (dblToCol(1 / 256.0)) + +// Max recursive depth for a Gouraud triangle shading fill. +#define gouraudMaxDepth 6 + +// Max delta allowed in any color component for a Gouraud triangle +// shading fill. +#define gouraudColorDelta (dblToCol(1 / 256.0)) + +// Max recursive depth for a patch mesh shading fill. +#define patchMaxDepth 6 + +// Max delta allowed in any color component for a patch mesh shading +// fill. +#define patchColorDelta (dblToCol(1 / 256.0)) + +// Max errors (undefined operator, wrong number of args) allowed before +// giving up on a content stream. +#define contentStreamErrorLimit 500 + +//------------------------------------------------------------------------ +// Operator table +//------------------------------------------------------------------------ + +#ifdef _WIN32 // this works around a bug in the VC7 compiler +# pragma optimize("",off) +#endif + +Operator Gfx::opTab[] = { + {"\"", 3, {tchkNum, tchkNum, tchkString}, + &Gfx::opMoveSetShowText}, + {"'", 1, {tchkString}, + &Gfx::opMoveShowText}, + {"B", 0, {tchkNone}, + &Gfx::opFillStroke}, + {"B*", 0, {tchkNone}, + &Gfx::opEOFillStroke}, + {"BDC", 2, {tchkName, tchkProps}, + &Gfx::opBeginMarkedContent}, + {"BI", 0, {tchkNone}, + &Gfx::opBeginImage}, + {"BMC", 1, {tchkName}, + &Gfx::opBeginMarkedContent}, + {"BT", 0, {tchkNone}, + &Gfx::opBeginText}, + {"BX", 0, {tchkNone}, + &Gfx::opBeginIgnoreUndef}, + {"CS", 1, {tchkName}, + &Gfx::opSetStrokeColorSpace}, + {"DP", 2, {tchkName, tchkProps}, + &Gfx::opMarkPoint}, + {"Do", 1, {tchkName}, + &Gfx::opXObject}, + {"EI", 0, {tchkNone}, + &Gfx::opEndImage}, + {"EMC", 0, {tchkNone}, + &Gfx::opEndMarkedContent}, + {"ET", 0, {tchkNone}, + &Gfx::opEndText}, + {"EX", 0, {tchkNone}, + &Gfx::opEndIgnoreUndef}, + {"F", 0, {tchkNone}, + &Gfx::opFill}, + {"G", 1, {tchkNum}, + &Gfx::opSetStrokeGray}, + {"ID", 0, {tchkNone}, + &Gfx::opImageData}, + {"J", 1, {tchkInt}, + &Gfx::opSetLineCap}, + {"K", 4, {tchkNum, tchkNum, tchkNum, tchkNum}, + &Gfx::opSetStrokeCMYKColor}, + {"M", 1, {tchkNum}, + &Gfx::opSetMiterLimit}, + {"MP", 1, {tchkName}, + &Gfx::opMarkPoint}, + {"Q", 0, {tchkNone}, + &Gfx::opRestore}, + {"RG", 3, {tchkNum, tchkNum, tchkNum}, + &Gfx::opSetStrokeRGBColor}, + {"S", 0, {tchkNone}, + &Gfx::opStroke}, + {"SC", -4, {tchkNum, tchkNum, tchkNum, tchkNum, + tchkNum, tchkNum, tchkNum, tchkNum, + tchkNum, tchkNum, tchkNum, tchkNum, + tchkNum, tchkNum, tchkNum, tchkNum, + tchkNum, tchkNum, tchkNum, tchkNum, + tchkNum, tchkNum, tchkNum, tchkNum, + tchkNum, tchkNum, tchkNum, tchkNum, + tchkNum, tchkNum, tchkNum, tchkNum, + tchkNum}, + &Gfx::opSetStrokeColor}, + {"SCN", -33, {tchkSCN, tchkSCN, tchkSCN, tchkSCN, + tchkSCN, tchkSCN, tchkSCN, tchkSCN, + tchkSCN, tchkSCN, tchkSCN, tchkSCN, + tchkSCN, tchkSCN, tchkSCN, tchkSCN, + tchkSCN, tchkSCN, tchkSCN, tchkSCN, + tchkSCN, tchkSCN, tchkSCN, tchkSCN, + tchkSCN, tchkSCN, tchkSCN, tchkSCN, + tchkSCN, tchkSCN, tchkSCN, tchkSCN, + tchkSCN}, + &Gfx::opSetStrokeColorN}, + {"T*", 0, {tchkNone}, + &Gfx::opTextNextLine}, + {"TD", 2, {tchkNum, tchkNum}, + &Gfx::opTextMoveSet}, + {"TJ", 1, {tchkArray}, + &Gfx::opShowSpaceText}, + {"TL", 1, {tchkNum}, + &Gfx::opSetTextLeading}, + {"Tc", 1, {tchkNum}, + &Gfx::opSetCharSpacing}, + {"Td", 2, {tchkNum, tchkNum}, + &Gfx::opTextMove}, + {"Tf", 2, {tchkName, tchkNum}, + &Gfx::opSetFont}, + {"Tj", 1, {tchkString}, + &Gfx::opShowText}, + {"Tm", 6, {tchkNum, tchkNum, tchkNum, tchkNum, + tchkNum, tchkNum}, + &Gfx::opSetTextMatrix}, + {"Tr", 1, {tchkInt}, + &Gfx::opSetTextRender}, + {"Ts", 1, {tchkNum}, + &Gfx::opSetTextRise}, + {"Tw", 1, {tchkNum}, + &Gfx::opSetWordSpacing}, + {"Tz", 1, {tchkNum}, + &Gfx::opSetHorizScaling}, + {"W", 0, {tchkNone}, + &Gfx::opClip}, + {"W*", 0, {tchkNone}, + &Gfx::opEOClip}, + {"b", 0, {tchkNone}, + &Gfx::opCloseFillStroke}, + {"b*", 0, {tchkNone}, + &Gfx::opCloseEOFillStroke}, + {"c", 6, {tchkNum, tchkNum, tchkNum, tchkNum, + tchkNum, tchkNum}, + &Gfx::opCurveTo}, + {"cm", 6, {tchkNum, tchkNum, tchkNum, tchkNum, + tchkNum, tchkNum}, + &Gfx::opConcat}, + {"cs", 1, {tchkName}, + &Gfx::opSetFillColorSpace}, + {"d", 2, {tchkArray, tchkNum}, + &Gfx::opSetDash}, + {"d0", 2, {tchkNum, tchkNum}, + &Gfx::opSetCharWidth}, + {"d1", 6, {tchkNum, tchkNum, tchkNum, tchkNum, + tchkNum, tchkNum}, + &Gfx::opSetCacheDevice}, + {"f", 0, {tchkNone}, + &Gfx::opFill}, + {"f*", 0, {tchkNone}, + &Gfx::opEOFill}, + {"g", 1, {tchkNum}, + &Gfx::opSetFillGray}, + {"gs", 1, {tchkName}, + &Gfx::opSetExtGState}, + {"h", 0, {tchkNone}, + &Gfx::opClosePath}, + {"i", 1, {tchkNum}, + &Gfx::opSetFlat}, + {"j", 1, {tchkInt}, + &Gfx::opSetLineJoin}, + {"k", 4, {tchkNum, tchkNum, tchkNum, tchkNum}, + &Gfx::opSetFillCMYKColor}, + {"l", 2, {tchkNum, tchkNum}, + &Gfx::opLineTo}, + {"m", 2, {tchkNum, tchkNum}, + &Gfx::opMoveTo}, + {"n", 0, {tchkNone}, + &Gfx::opEndPath}, + {"q", 0, {tchkNone}, + &Gfx::opSave}, + {"re", 4, {tchkNum, tchkNum, tchkNum, tchkNum}, + &Gfx::opRectangle}, + {"rg", 3, {tchkNum, tchkNum, tchkNum}, + &Gfx::opSetFillRGBColor}, + {"ri", 1, {tchkName}, + &Gfx::opSetRenderingIntent}, + {"s", 0, {tchkNone}, + &Gfx::opCloseStroke}, + {"sc", -4, {tchkNum, tchkNum, tchkNum, tchkNum, + tchkNum, tchkNum, tchkNum, tchkNum, + tchkNum, tchkNum, tchkNum, tchkNum, + tchkNum, tchkNum, tchkNum, tchkNum, + tchkNum, tchkNum, tchkNum, tchkNum, + tchkNum, tchkNum, tchkNum, tchkNum, + tchkNum, tchkNum, tchkNum, tchkNum, + tchkNum, tchkNum, tchkNum, tchkNum, + tchkNum}, + &Gfx::opSetFillColor}, + {"scn", -33, {tchkSCN, tchkSCN, tchkSCN, tchkSCN, + tchkSCN, tchkSCN, tchkSCN, tchkSCN, + tchkSCN, tchkSCN, tchkSCN, tchkSCN, + tchkSCN, tchkSCN, tchkSCN, tchkSCN, + tchkSCN, tchkSCN, tchkSCN, tchkSCN, + tchkSCN, tchkSCN, tchkSCN, tchkSCN, + tchkSCN, tchkSCN, tchkSCN, tchkSCN, + tchkSCN, tchkSCN, tchkSCN, tchkSCN, + tchkSCN}, + &Gfx::opSetFillColorN}, + {"sh", 1, {tchkName}, + &Gfx::opShFill}, + {"v", 4, {tchkNum, tchkNum, tchkNum, tchkNum}, + &Gfx::opCurveTo1}, + {"w", 1, {tchkNum}, + &Gfx::opSetLineWidth}, + {"y", 4, {tchkNum, tchkNum, tchkNum, tchkNum}, + &Gfx::opCurveTo2}, +}; + +#ifdef _WIN32 // this works around a bug in the VC7 compiler +# pragma optimize("",on) +#endif + +#define numOps (sizeof(opTab) / sizeof(Operator)) + +//------------------------------------------------------------------------ +// GfxResources +//------------------------------------------------------------------------ + +GfxResources::GfxResources(XRef *xref, Dict *resDict, GfxResources *nextA) { + Object obj1, obj2; + Ref r; + + if (resDict) { + valid = gTrue; + + // build font dictionary + fonts = NULL; + resDict->lookupNF("Font", &obj1); + if (obj1.isRef()) { + obj1.fetch(xref, &obj2); + if (obj2.isDict()) { + r = obj1.getRef(); + fonts = new GfxFontDict(xref, &r, obj2.getDict()); + } + obj2.free(); + } else if (obj1.isDict()) { + fonts = new GfxFontDict(xref, NULL, obj1.getDict()); + } + obj1.free(); + + // get XObject dictionary + resDict->lookup("XObject", &xObjDict); + + // get color space dictionary + resDict->lookup("ColorSpace", &colorSpaceDict); + + // get pattern dictionary + resDict->lookup("Pattern", &patternDict); + + // get shading dictionary + resDict->lookup("Shading", &shadingDict); + + // get graphics state parameter dictionary + resDict->lookup("ExtGState", &gStateDict); + + // get properties dictionary + resDict->lookup("Properties", &propsDict); + + } else { + valid = gFalse; + fonts = NULL; + xObjDict.initNull(); + colorSpaceDict.initNull(); + patternDict.initNull(); + shadingDict.initNull(); + gStateDict.initNull(); + propsDict.initNull(); + } + + next = nextA; +} + +GfxResources::~GfxResources() { + if (fonts) { + delete fonts; + } + xObjDict.free(); + colorSpaceDict.free(); + patternDict.free(); + shadingDict.free(); + gStateDict.free(); + propsDict.free(); +} + +GfxFont *GfxResources::lookupFont(char *name) { + GfxFont *font; + GfxResources *resPtr; + + for (resPtr = this; resPtr; resPtr = resPtr->next) { + if (resPtr->fonts) { + if ((font = resPtr->fonts->lookup(name))) { + return font; + } + } + } + error(errSyntaxError, -1, "Unknown font tag '{0:s}'", name); + return NULL; +} + +GfxFont *GfxResources::lookupFontByRef(Ref ref) { + GfxFont *font; + GfxResources *resPtr; + + for (resPtr = this; resPtr; resPtr = resPtr->next) { + if (resPtr->fonts) { + if ((font = resPtr->fonts->lookupByRef(ref))) { + return font; + } + } + } + error(errSyntaxError, -1, "Unknown font ref {0:d}.{1:d}", ref.num, ref.gen); + return NULL; +} + +GBool GfxResources::lookupXObject(const char *name, Object *obj) { + GfxResources *resPtr; + + for (resPtr = this; resPtr; resPtr = resPtr->next) { + if (resPtr->xObjDict.isDict()) { + if (!resPtr->xObjDict.dictLookup(name, obj)->isNull()) + return gTrue; + obj->free(); + } + } + error(errSyntaxError, -1, "XObject '{0:s}' is unknown", name); + return gFalse; +} + +GBool GfxResources::lookupXObjectNF(const char *name, Object *obj) { + GfxResources *resPtr; + + for (resPtr = this; resPtr; resPtr = resPtr->next) { + if (resPtr->xObjDict.isDict()) { + if (!resPtr->xObjDict.dictLookupNF(name, obj)->isNull()) + return gTrue; + obj->free(); + } + } + error(errSyntaxError, -1, "XObject '{0:s}' is unknown", name); + return gFalse; +} + +void GfxResources::lookupColorSpace(const char *name, Object *obj, + GBool inherit) { + GfxResources *resPtr; + + //~ should also test for G, RGB, and CMYK - but only in inline images (?) + if (!strcmp(name, "DeviceGray") || + !strcmp(name, "DeviceRGB") || + !strcmp(name, "DeviceCMYK")) { + obj->initNull(); + return; + } + for (resPtr = this; resPtr; resPtr = resPtr->next) { + if (resPtr->colorSpaceDict.isDict()) { + if (!resPtr->colorSpaceDict.dictLookup(name, obj)->isNull()) { + return; + } + obj->free(); + } + if (!inherit && valid) { + break; + } + } + obj->initNull(); +} + +GfxPattern *GfxResources::lookupPattern(const char *name + ) { + GfxResources *resPtr; + GfxPattern *pattern; + Object objRef, obj; + + for (resPtr = this; resPtr; resPtr = resPtr->next) { + if (resPtr->patternDict.isDict()) { + if (!resPtr->patternDict.dictLookup(name, &obj)->isNull()) { + resPtr->patternDict.dictLookupNF(name, &objRef); + pattern = GfxPattern::parse(&objRef, &obj + ); + objRef.free(); + obj.free(); + return pattern; + } + obj.free(); + } + } + error(errSyntaxError, -1, "Unknown pattern '{0:s}'", name); + return NULL; +} + +GfxShading *GfxResources::lookupShading(const char *name + ) { + GfxResources *resPtr; + GfxShading *shading; + Object obj; + + for (resPtr = this; resPtr; resPtr = resPtr->next) { + if (resPtr->shadingDict.isDict()) { + if (!resPtr->shadingDict.dictLookup(name, &obj)->isNull()) { + shading = GfxShading::parse(&obj + ); + obj.free(); + return shading; + } + obj.free(); + } + } + error(errSyntaxError, -1, "Unknown shading '{0:s}'", name); + return NULL; +} + +GBool GfxResources::lookupGState(const char *name, Object *obj) { + GfxResources *resPtr; + + for (resPtr = this; resPtr; resPtr = resPtr->next) { + if (resPtr->gStateDict.isDict()) { + if (!resPtr->gStateDict.dictLookup(name, obj)->isNull()) { + return gTrue; + } + obj->free(); + } + } + error(errSyntaxError, -1, "ExtGState '{0:s}' is unknown", name); + return gFalse; +} + +GBool GfxResources::lookupPropertiesNF(const 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; +} + +//------------------------------------------------------------------------ +// Gfx +//------------------------------------------------------------------------ + +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; + + doc = docA; + xref = doc->getXRef(); + subPage = gFalse; + printCommands = globalParams->getPrintCommands(); + defaultFont = NULL; + + // start the resource stack + res = new GfxResources(xref, resDict, NULL); + + // initialize + out = outA; + state = new GfxState(hDPI, vDPI, box, rotate, out->upsideDown()); + fontChanged = gFalse; + clip = clipNone; + ignoreUndef = 0; + out->startPage(pageNum, state); + out->setDefaultCTM(state->getCTM()); + out->updateAll(state); + for (i = 0; i < 6; ++i) { + baseMatrix[i] = state->getCTM()[i]; + } + formDepth = 0; + markedContentStack = new GList(); + ocState = gTrue; + parser = NULL; + contentStreamStack = new GList(); + abortCheckCbk = abortCheckCbkA; + abortCheckCbkData = abortCheckCbkDataA; + + // set crop box + if (cropBox) { + state->moveTo(cropBox->x1, cropBox->y1); + state->lineTo(cropBox->x2, cropBox->y1); + state->lineTo(cropBox->x2, cropBox->y2); + state->lineTo(cropBox->x1, cropBox->y2); + state->closePath(); + state->clip(); + out->clip(state); + state->clearPath(); + } +} + +Gfx::Gfx(PDFDoc *docA, OutputDev *outA, Dict *resDict, + PDFRectangle *box, PDFRectangle *cropBox, + GBool (*abortCheckCbkA)(void *data), + void *abortCheckCbkDataA) { + int i; + + doc = docA; + xref = doc->getXRef(); + subPage = gTrue; + printCommands = globalParams->getPrintCommands(); + defaultFont = NULL; + + // start the resource stack + res = new GfxResources(xref, resDict, NULL); + + // initialize + out = outA; + state = new GfxState(72, 72, box, 0, gFalse); + fontChanged = gFalse; + clip = clipNone; + ignoreUndef = 0; + for (i = 0; i < 6; ++i) { + baseMatrix[i] = state->getCTM()[i]; + } + formDepth = 0; + markedContentStack = new GList(); + ocState = gTrue; + parser = NULL; + contentStreamStack = new GList(); + abortCheckCbk = abortCheckCbkA; + abortCheckCbkData = abortCheckCbkDataA; + + // set crop box + if (cropBox) { + state->moveTo(cropBox->x1, cropBox->y1); + state->lineTo(cropBox->x2, cropBox->y1); + state->lineTo(cropBox->x2, cropBox->y2); + state->lineTo(cropBox->x1, cropBox->y2); + state->closePath(); + state->clip(); + out->clip(state); + state->clearPath(); + } +} + +Gfx::~Gfx() { + if (defaultFont) { + delete defaultFont; + } + if (!subPage) { + out->endPage(); + } + while (state->hasSaves()) { + restoreState(); + } + delete state; + while (res) { + popResources(); + } + deleteGList(markedContentStack, GfxMarkedContent); + delete contentStreamStack; +} + +void Gfx::display(Object *objRef, GBool topLevel) { + Object obj1, obj2; + int i; + + objRef->fetch(xref, &obj1); + if (obj1.isArray()) { + for (i = 0; i < obj1.arrayGetLength(); ++i) { + obj1.arrayGetNF(i, &obj2); + if (checkForContentStreamLoop(&obj2)) { + obj2.free(); + obj1.free(); + return; + } + obj2.free(); + } + for (i = 0; i < obj1.arrayGetLength(); ++i) { + obj1.arrayGet(i, &obj2); + if (!obj2.isStream()) { + error(errSyntaxError, -1, "Invalid object type for content stream"); + obj2.free(); + obj1.free(); + return; + } + obj2.free(); + } + contentStreamStack->append(&obj1); + } else if (obj1.isStream()) { + if (checkForContentStreamLoop(objRef)) { + obj1.free(); + return; + } + contentStreamStack->append(objRef); + } else { + error(errSyntaxError, -1, "Invalid object type for content stream"); + obj1.free(); + return; + } + parser = new Parser(xref, new Lexer(xref, &obj1), gFalse); + go(topLevel); + delete parser; + parser = NULL; + contentStreamStack->del(contentStreamStack->getLength() - 1); + obj1.free(); +} + +// If is already on contentStreamStack, i.e., if there is a loop +// in the content streams, report an error, and return true. +GBool Gfx::checkForContentStreamLoop(Object *ref) { + Object *objPtr; + Object obj1; + int i, j; + + if (ref->isRef()) { + for (i = 0; i < contentStreamStack->getLength(); ++i) { + objPtr = (Object *)contentStreamStack->get(i); + if (objPtr->isRef()) { + if (ref->getRefNum() == objPtr->getRefNum() && + ref->getRefGen() == objPtr->getRefGen()) { + error(errSyntaxError, -1, "Loop in content streams"); + return gTrue; + } + } else if (objPtr->isArray()) { + for (j = 0; j < objPtr->arrayGetLength(); ++j) { + objPtr->arrayGetNF(j, &obj1); + if (obj1.isRef()) { + if (ref->getRefNum() == obj1.getRefNum() && + ref->getRefGen() == obj1.getRefGen()) { + error(errSyntaxError, -1, "Loop in content streams"); + obj1.free(); + return gTrue; + } + } + obj1.free(); + } + } + } + } + return gFalse; +} + +void Gfx::go(GBool topLevel) { + Object obj; + Object args[maxArgs]; + GBool aborted; + int numArgs, i; + int errCount; + + // scan a sequence of objects + opCounter = 0; + aborted = gFalse; + errCount = 0; + numArgs = 0; + getContentObj(&obj); + while (!obj.isEOF()) { + + // check for an abort + ++opCounter; + if (abortCheckCbk && opCounter > 100) { + if ((*abortCheckCbk)(abortCheckCbkData)) { + aborted = gTrue; + break; + } + opCounter = 0; + } + + // got a command - execute it + if (obj.isCmd()) { + if (printCommands) { + obj.print(stdout); + for (i = 0; i < numArgs; ++i) { + printf(" "); + args[i].print(stdout); + } + printf("\n"); + fflush(stdout); + } + if (!execOp(&obj, args, numArgs)) { + ++errCount; + } + obj.free(); + for (i = 0; i < numArgs; ++i) + args[i].free(); + numArgs = 0; + + // check for too many errors + if (errCount > contentStreamErrorLimit) { + error(errSyntaxError, -1, + "Too many errors - giving up on this content stream"); + break; + } + + // got an argument - save it + } else if (numArgs < maxArgs) { + args[numArgs++] = obj; + + // too many arguments - something is wrong + } else { + error(errSyntaxError, getPos(), "Too many args in content stream"); + if (printCommands) { + printf("throwing away arg: "); + obj.print(stdout); + printf("\n"); + fflush(stdout); + } + obj.free(); + } + + // grab the next object + getContentObj(&obj); + } + obj.free(); + + // args at end with no command + if (numArgs > 0) { + if (!aborted) { + error(errSyntaxError, getPos(), "Leftover args in content stream"); + if (printCommands) { + printf("%d leftovers:", numArgs); + for (i = 0; i < numArgs; ++i) { + printf(" "); + args[i].print(stdout); + } + printf("\n"); + fflush(stdout); + } + } + for (i = 0; i < numArgs; ++i) { + args[i].free(); + } + } +} + +void Gfx::getContentObj(Object *obj) { + parser->getObj(obj); + if (obj->isRef()) { + error(errSyntaxError, getPos(), "Indirect reference in content stream"); + obj->free(); + obj->initError(); + } +} + +// Returns true if successful, false on error. +GBool Gfx::execOp(Object *cmd, Object args[], int numArgs) { + Operator *op; + char *name; + Object *argPtr; + int i; + + // find operator + name = cmd->getCmd(); + if (!(op = findOp(name))) { + if (ignoreUndef > 0) { + return gTrue; + } + error(errSyntaxError, getPos(), "Unknown operator '{0:s}'", name); + return gFalse; + } + + // type check args + argPtr = args; + if (op->numArgs >= 0) { + if (numArgs < op->numArgs) { + error(errSyntaxError, getPos(), + "Too few ({0:d}) args to '{1:s}' operator", numArgs, name); + return gFalse; + } + if (numArgs > op->numArgs) { +#if 0 + 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(errSyntaxWarning, getPos(), + "Too many ({0:d}) args to '{1:s}' operator", + numArgs, name); + } + } + for (i = 0; i < numArgs; ++i) { + if (!checkArg(&argPtr[i], op->tchk[i])) { + error(errSyntaxError, getPos(), + "Arg #{0:d} to '{1:s}' operator is wrong type ({2:s})", + i, name, argPtr[i].getTypeName()); + return gFalse; + } + } + + // do it + (this->*op->func)(argPtr, numArgs); + + return gTrue; +} + +Operator *Gfx::findOp(char *name) { + int a, b, m, cmp; + + a = -1; + b = numOps; + cmp = 0; // make gcc happy + // invariant: opTab[a] < name < opTab[b] + while (b - a > 1) { + m = (a + b) / 2; + cmp = strcmp(opTab[m].name, name); + if (cmp < 0) + a = m; + else if (cmp > 0) + b = m; + else + a = b = m; + } + if (cmp != 0) + return NULL; + return &opTab[a]; +} + +GBool Gfx::checkArg(Object *arg, TchkType type) { + switch (type) { + case tchkBool: return arg->isBool(); + case tchkInt: return arg->isInt(); + case tchkNum: return arg->isNum(); + case tchkString: return arg->isString(); + case tchkName: return arg->isName(); + case tchkArray: return arg->isArray(); + case tchkProps: return arg->isDict() || arg->isName(); + case tchkSCN: return arg->isNum() || arg->isName(); + case tchkNone: return gFalse; + } + return gFalse; +} + +GFileOffset Gfx::getPos() { + return parser ? parser->getPos() : -1; +} + +//------------------------------------------------------------------------ +// graphics state operators +//------------------------------------------------------------------------ + +void Gfx::opSave(Object args[], int numArgs) { + saveState(); +} + +void Gfx::opRestore(Object args[], int numArgs) { + restoreState(); +} + +void Gfx::opConcat(Object args[], int numArgs) { + state->concatCTM(args[0].getNum(), args[1].getNum(), + args[2].getNum(), args[3].getNum(), + args[4].getNum(), args[5].getNum()); + out->updateCTM(state, args[0].getNum(), args[1].getNum(), + args[2].getNum(), args[3].getNum(), + args[4].getNum(), args[5].getNum()); + fontChanged = gTrue; +} + +void Gfx::opSetDash(Object args[], int numArgs) { + Array *a; + int length; + Object obj; + double *dash; + int i; + + a = args[0].getArray(); + length = a->getLength(); + if (length == 0) { + dash = NULL; + } else { + dash = (double *)gmallocn(length, sizeof(double)); + for (i = 0; i < length; ++i) { + dash[i] = a->get(i, &obj)->getNum(); + obj.free(); + } + } + state->setLineDash(dash, length, args[1].getNum()); + out->updateLineDash(state); +} + +void Gfx::opSetFlat(Object args[], int numArgs) { + state->setFlatness((int)args[0].getNum()); + out->updateFlatness(state); +} + +void Gfx::opSetLineJoin(Object args[], int numArgs) { + int lineJoin; + + lineJoin = args[0].getInt(); + if (lineJoin < 0 || lineJoin > 2) { + lineJoin = 0; + } + state->setLineJoin(lineJoin); + out->updateLineJoin(state); +} + +void Gfx::opSetLineCap(Object args[], int numArgs) { + int lineCap; + + lineCap = args[0].getInt(); + if (lineCap < 0 || lineCap > 2) { + lineCap = 0; + } + state->setLineCap(lineCap); + out->updateLineCap(state); +} + +void Gfx::opSetMiterLimit(Object args[], int numArgs) { + state->setMiterLimit(args[0].getNum()); + out->updateMiterLimit(state); +} + +void Gfx::opSetLineWidth(Object args[], int numArgs) { + state->setLineWidth(args[0].getNum()); + out->updateLineWidth(state); +} + +void Gfx::opSetExtGState(Object args[], int numArgs) { + Object obj1, obj2, obj3, objRef3, obj4, obj5, backdropColorObj; + Object args2[2]; + GfxBlendMode mode; + GBool haveFillOP; + Function *funcs[4]; + GBool alpha, knockout; + double opac; + int i; + + if (!res->lookupGState(args[0].getName(), &obj1)) { + return; + } + if (!obj1.isDict()) { + error(errSyntaxError, getPos(), + "ExtGState '{0:s}' is wrong type", args[0].getName()); + obj1.free(); + return; + } + if (printCommands) { + printf(" gfx state dict: "); + obj1.print(); + 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 (obj1.dictLookup("FL", &obj2)->isNum()) { + opSetFlat(&obj2, 1); + } + obj2.free(); + if (obj1.dictLookup("RI", &obj2)->isName()) { + opSetRenderingIntent(&obj2, 1); + } + obj2.free(); + + // font + if (obj1.dictLookup("Font", &obj2)->isArray() && + obj2.arrayGetLength() == 2) { + obj2.arrayGetNF(0, &obj3); + obj2.arrayGetNF(1, &obj4); + if (obj3.isRef() && obj4.isNum()) { + doSetFont(res->lookupFontByRef(obj3.getRef()), obj4.getNum()); + } + obj3.free(); + obj4.free(); + } + 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(errSyntaxError, getPos(), "Invalid blend mode in ExtGState"); + } + } + obj2.free(); + if (obj1.dictLookup("ca", &obj2)->isNum()) { + opac = obj2.getNum(); + state->setFillOpacity(opac < 0 ? 0 : opac > 1 ? 1 : opac); + out->updateFillOpacity(state); + } + obj2.free(); + if (obj1.dictLookup("CA", &obj2)->isNum()) { + opac = obj2.getNum(); + state->setStrokeOpacity(opac < 0 ? 0 : opac > 1 ? 1 : opac); + out->updateStrokeOpacity(state); + } + obj2.free(); + + // fill/stroke overprint, overprint mode + if ((haveFillOP = (obj1.dictLookup("op", &obj2)->isBool()))) { + if (!state->getIgnoreColorOps()) { + state->setFillOverprint(obj2.getBool()); + out->updateFillOverprint(state); + } else { + error(errSyntaxWarning, getPos(), "Ignoring overprint setting" + " in uncolored Type 3 char or tiling pattern"); + } + } + obj2.free(); + if (obj1.dictLookup("OP", &obj2)->isBool()) { + if (!state->getIgnoreColorOps()) { + state->setStrokeOverprint(obj2.getBool()); + out->updateStrokeOverprint(state); + if (!haveFillOP) { + state->setFillOverprint(obj2.getBool()); + out->updateFillOverprint(state); + } + } else { + error(errSyntaxWarning, getPos(), "Ignoring overprint setting" + " in uncolored Type 3 char or tiling pattern"); + } + } + obj2.free(); + if (obj1.dictLookup("OPM", &obj2)->isInt()) { + if (!state->getIgnoreColorOps()) { + state->setOverprintMode(obj2.getInt()); + out->updateOverprintMode(state); + } else { + error(errSyntaxWarning, getPos(), "Ignoring overprint setting" + " in uncolored Type 3 char or tiling pattern"); + } + } + obj2.free(); + + // stroke adjust + if (obj1.dictLookup("SA", &obj2)->isBool()) { + state->setStrokeAdjust(obj2.getBool()); + out->updateStrokeAdjust(state); + } + obj2.free(); + + // transfer function + if (obj1.dictLookup("TR2", &obj2)->isNull()) { + obj2.free(); + obj1.dictLookup("TR", &obj2); + } + if (!obj2.isNull()) { + if (!state->getIgnoreColorOps()) { + if (obj2.isName("Default") || + obj2.isName("Identity")) { + funcs[0] = funcs[1] = funcs[2] = funcs[3] = NULL; + state->setTransfer(funcs); + out->updateTransfer(state); + } else if (obj2.isArray() && obj2.arrayGetLength() == 4) { + for (i = 0; i < 4; ++i) { + obj2.arrayGet(i, &obj3); + funcs[i] = Function::parse(&obj3, 1, 1); + obj3.free(); + if (!funcs[i]) { + break; + } + } + if (i == 4) { + state->setTransfer(funcs); + out->updateTransfer(state); + } + } else if (obj2.isName() || obj2.isDict() || obj2.isStream()) { + if ((funcs[0] = Function::parse(&obj2, 1, 1))) { + funcs[1] = funcs[2] = funcs[3] = NULL; + state->setTransfer(funcs); + out->updateTransfer(state); + } + } else { + error(errSyntaxError, getPos(), + "Invalid transfer function in ExtGState"); + } + } else { + error(errSyntaxWarning, getPos(), "Ignoring transfer function setting" + " in uncolored Type 3 char or tiling pattern"); + } + } + obj2.free(); + + // soft mask + if (!obj1.dictLookup("SMask", &obj2)->isNull()) { + if (obj2.isName("None")) { + out->clearSoftMask(state); + } else if (obj2.isDict()) { + obj2.dictLookup("S", &obj3); + if (obj3.isName("Alpha")) { + alpha = gTrue; + } else if (obj3.isName("Luminosity")) { + alpha = gFalse; + } else { + error(errSyntaxError, getPos(), + "Missing S (subtype) entry in soft mask"); + alpha = gFalse; + } + obj3.free(); + funcs[0] = NULL; + if (!obj2.dictLookup("TR", &obj3)->isNull()) { + if (obj3.isName("Default") || + obj3.isName("Identity")) { + funcs[0] = NULL; + } else { + if (!(funcs[0] = Function::parse(&obj3, 1, 1))) { + error(errSyntaxError, getPos(), + "Invalid transfer function in soft mask in ExtGState"); + delete funcs[0]; + funcs[0] = NULL; + } + } + } + obj3.free(); + obj2.dictLookup("BC", &backdropColorObj); + if (obj2.dictLookup("G", &obj3)->isStream()) { + if (obj3.streamGetDict()->lookup("Group", &obj4)->isDict()) { + knockout = gFalse; + if (obj4.dictLookup("K", &obj5)->isBool()) { + knockout = obj5.getBool(); + } + obj5.free(); + obj2.dictLookupNF("G", &objRef3); + // it doesn't make sense for softmasks to be non-isolated, + // because they're blended with a backdrop color, rather + // than the original backdrop + doSoftMask(&obj3, &objRef3, alpha, gTrue, knockout, funcs[0], + &backdropColorObj); + objRef3.free(); + if (funcs[0]) { + delete funcs[0]; + } + } else { + error(errSyntaxError, getPos(), + "Invalid soft mask in ExtGState - missing group"); + } + obj4.free(); + } else { + error(errSyntaxError, getPos(), + "Invalid soft mask in ExtGState - missing group"); + } + obj3.free(); + backdropColorObj.free(); + } else if (!obj2.isNull()) { + error(errSyntaxError, getPos(), "Invalid soft mask in ExtGState"); + } + } + obj2.free(); + + obj1.free(); +} + +void Gfx::doSoftMask(Object *str, Object *strRef, GBool alpha, + GBool isolated, GBool knockout, + Function *transferFunc, Object *backdropColorObj) { + Dict *dict, *resDict; + double m[6], bbox[4]; + Object obj1, obj2; + int i; + + // check for excessive recursion + if (formDepth > 20) { + return; + } + + // get stream dict + dict = str->streamGetDict(); + + // check form type + dict->lookup("FormType", &obj1); + if (!(obj1.isNull() || (obj1.isInt() && obj1.getInt() == 1))) { + error(errSyntaxError, getPos(), "Unknown form type"); + } + obj1.free(); + + // get bounding box + dict->lookup("BBox", &obj1); + if (!obj1.isArray()) { + obj1.free(); + error(errSyntaxError, getPos(), "Bad form bounding box"); + return; + } + for (i = 0; i < 4; ++i) { + obj1.arrayGet(i, &obj2); + bbox[i] = obj2.getNum(); + obj2.free(); + } + obj1.free(); + + // get matrix + dict->lookup("Matrix", &obj1); + if (obj1.isArray()) { + for (i = 0; i < 6; ++i) { + obj1.arrayGet(i, &obj2); + m[i] = obj2.getNum(); + obj2.free(); + } + } else { + m[0] = 1; m[1] = 0; + m[2] = 0; m[3] = 1; + m[4] = 0; m[5] = 0; + } + obj1.free(); + + // get resources + dict->lookup("Resources", &obj1); + resDict = obj1.isDict() ? obj1.getDict() : (Dict *)NULL; + + // draw it + ++formDepth; + drawForm(strRef, resDict, m, bbox, gTrue, gTrue, isolated, knockout, + alpha, transferFunc, backdropColorObj); + --formDepth; + + obj1.free(); +} + +void Gfx::opSetRenderingIntent(Object args[], int numArgs) { + GfxRenderingIntent ri; + + if (state->getIgnoreColorOps()) { + error(errSyntaxWarning, getPos(), "Ignoring rendering intent setting" + " in uncolored Type 3 char or tiling pattern"); + return; + } + ri = parseRenderingIntent(args[0].getName()); + state->setRenderingIntent(ri); + out->updateRenderingIntent(state); +} + +GfxRenderingIntent Gfx::parseRenderingIntent(const char *name) { + if (!strcmp(name, "AbsoluteColorimetric")) { + return gfxRenderingIntentAbsoluteColorimetric; + } + if (!strcmp(name, "Saturation")) { + return gfxRenderingIntentSaturation; + } + if (!strcmp(name, "Perceptual")) { + return gfxRenderingIntentPerceptual; + } + return gfxRenderingIntentRelativeColorimetric; +} + +//------------------------------------------------------------------------ +// color operators +//------------------------------------------------------------------------ + +void Gfx::opSetFillGray(Object args[], int numArgs) { + GfxColor color; + + if (state->getIgnoreColorOps()) { + error(errSyntaxWarning, getPos(), "Ignoring color setting" + " in uncolored Type 3 char or tiling pattern"); + return; + } + state->setFillPattern(NULL); + state->setFillColorSpace(GfxColorSpace::create(csDeviceGray)); + out->updateFillColorSpace(state); + color.c[0] = dblToCol(args[0].getNum()); + state->setFillColor(&color); + out->updateFillColor(state); +} + +void Gfx::opSetStrokeGray(Object args[], int numArgs) { + GfxColor color; + + if (state->getIgnoreColorOps()) { + error(errSyntaxWarning, getPos(), "Ignoring color setting" + " in uncolored Type 3 char or tiling pattern"); + return; + } + state->setStrokePattern(NULL); + state->setStrokeColorSpace(GfxColorSpace::create(csDeviceGray)); + out->updateStrokeColorSpace(state); + color.c[0] = dblToCol(args[0].getNum()); + state->setStrokeColor(&color); + out->updateStrokeColor(state); +} + +void Gfx::opSetFillCMYKColor(Object args[], int numArgs) { + GfxColor color; + int i; + + if (state->getIgnoreColorOps()) { + error(errSyntaxWarning, getPos(), "Ignoring color setting" + " in uncolored Type 3 char or tiling pattern"); + return; + } + state->setFillPattern(NULL); + state->setFillColorSpace(GfxColorSpace::create(csDeviceCMYK)); + out->updateFillColorSpace(state); + for (i = 0; i < 4; ++i) { + color.c[i] = dblToCol(args[i].getNum()); + } + state->setFillColor(&color); + out->updateFillColor(state); +} + +void Gfx::opSetStrokeCMYKColor(Object args[], int numArgs) { + GfxColor color; + int i; + + if (state->getIgnoreColorOps()) { + error(errSyntaxWarning, getPos(), "Ignoring color setting" + " in uncolored Type 3 char or tiling pattern"); + return; + } + state->setStrokePattern(NULL); + state->setStrokeColorSpace(GfxColorSpace::create(csDeviceCMYK)); + out->updateStrokeColorSpace(state); + for (i = 0; i < 4; ++i) { + color.c[i] = dblToCol(args[i].getNum()); + } + state->setStrokeColor(&color); + out->updateStrokeColor(state); +} + +void Gfx::opSetFillRGBColor(Object args[], int numArgs) { + GfxColor color; + int i; + + if (state->getIgnoreColorOps()) { + error(errSyntaxWarning, getPos(), "Ignoring color setting" + " in uncolored Type 3 char or tiling pattern"); + return; + } + state->setFillPattern(NULL); + state->setFillColorSpace(GfxColorSpace::create(csDeviceRGB)); + out->updateFillColorSpace(state); + for (i = 0; i < 3; ++i) { + color.c[i] = dblToCol(args[i].getNum()); + } + state->setFillColor(&color); + out->updateFillColor(state); +} + +void Gfx::opSetStrokeRGBColor(Object args[], int numArgs) { + GfxColor color; + int i; + + if (state->getIgnoreColorOps()) { + error(errSyntaxWarning, getPos(), "Ignoring color setting" + " in uncolored Type 3 char or tiling pattern"); + return; + } + state->setStrokePattern(NULL); + state->setStrokeColorSpace(GfxColorSpace::create(csDeviceRGB)); + out->updateStrokeColorSpace(state); + for (i = 0; i < 3; ++i) { + color.c[i] = dblToCol(args[i].getNum()); + } + state->setStrokeColor(&color); + out->updateStrokeColor(state); +} + +void Gfx::opSetFillColorSpace(Object args[], int numArgs) { + Object obj; + GfxColorSpace *colorSpace; + GfxColor color; + + if (state->getIgnoreColorOps()) { + error(errSyntaxWarning, getPos(), "Ignoring color space setting" + " in uncolored Type 3 char or tiling pattern"); + return; + } + state->setFillPattern(NULL); + res->lookupColorSpace(args[0].getName(), &obj); + if (obj.isNull()) { + colorSpace = GfxColorSpace::parse(&args[0] + ); + } else { + colorSpace = GfxColorSpace::parse(&obj + ); + } + obj.free(); + if (colorSpace) { + state->setFillColorSpace(colorSpace); + out->updateFillColorSpace(state); + colorSpace->getDefaultColor(&color); + state->setFillColor(&color); + out->updateFillColor(state); + } else { + error(errSyntaxError, getPos(), "Bad color space (fill)"); + } +} + +void Gfx::opSetStrokeColorSpace(Object args[], int numArgs) { + Object obj; + GfxColorSpace *colorSpace; + GfxColor color; + + if (state->getIgnoreColorOps()) { + error(errSyntaxWarning, getPos(), "Ignoring color space setting" + " in uncolored Type 3 char or tiling pattern"); + return; + } + state->setStrokePattern(NULL); + res->lookupColorSpace(args[0].getName(), &obj); + if (obj.isNull()) { + colorSpace = GfxColorSpace::parse(&args[0] + ); + } else { + colorSpace = GfxColorSpace::parse(&obj + ); + } + obj.free(); + if (colorSpace) { + state->setStrokeColorSpace(colorSpace); + out->updateStrokeColorSpace(state); + colorSpace->getDefaultColor(&color); + state->setStrokeColor(&color); + out->updateStrokeColor(state); + } else { + error(errSyntaxError, getPos(), "Bad color space (stroke)"); + } +} + +// Technically, per the PDF spec, the 'sc' operator can only be used +// with device, CIE, and Indexed color spaces. Some buggy PDF +// generators use it for DeviceN, so we also allow that (same as +// 'scn', minus the optional pattern name argument). +void Gfx::opSetFillColor(Object args[], int numArgs) { + GfxColor color; + int i; + + if (state->getIgnoreColorOps()) { + error(errSyntaxWarning, getPos(), "Ignoring color setting" + " in uncolored Type 3 char or tiling pattern"); + return; + } + if (numArgs != state->getFillColorSpace()->getNComps()) { + error(errSyntaxError, getPos(), + "Incorrect number of arguments in 'sc' command"); + return; + } + state->setFillPattern(NULL); + for (i = 0; i < numArgs; ++i) { + color.c[i] = dblToCol(args[i].getNum()); + } + state->setFillColor(&color); + out->updateFillColor(state); +} + +// Technically, per the PDF spec, the 'SC' operator can only be used +// with device, CIE, and Indexed color spaces. Some buggy PDF +// generators use it for DeviceN, so we also allow that (same as +// 'SCN', minus the optional pattern name argument). +void Gfx::opSetStrokeColor(Object args[], int numArgs) { + GfxColor color; + int i; + + if (numArgs != state->getStrokeColorSpace()->getNComps()) { + error(errSyntaxError, getPos(), + "Incorrect number of arguments in 'SC' command"); + return; + } + state->setStrokePattern(NULL); + for (i = 0; i < numArgs; ++i) { + color.c[i] = dblToCol(args[i].getNum()); + } + state->setStrokeColor(&color); + out->updateStrokeColor(state); +} + +void Gfx::opSetFillColorN(Object args[], int numArgs) { + GfxColor color; + GfxPattern *pattern; + int i; + + if (state->getIgnoreColorOps()) { + error(errSyntaxWarning, getPos(), "Ignoring color setting" + " in uncolored Type 3 char or tiling pattern"); + return; + } + if (state->getFillColorSpace()->getMode() == csPattern) { + if (numArgs == 0 || !args[numArgs-1].isName()) { + error(errSyntaxError, getPos(), + "Invalid arguments in 'scn' command"); + return; + } + if (numArgs > 1) { + if (!((GfxPatternColorSpace *)state->getFillColorSpace())->getUnder() || + numArgs - 1 != ((GfxPatternColorSpace *)state->getFillColorSpace()) + ->getUnder()->getNComps()) { + error(errSyntaxError, getPos(), + "Incorrect number of arguments in 'scn' command"); + return; + } + for (i = 0; i < numArgs - 1 && i < gfxColorMaxComps; ++i) { + if (args[i].isNum()) { + color.c[i] = dblToCol(args[i].getNum()); + } + } + state->setFillColor(&color); + out->updateFillColor(state); + } + if ((pattern = res->lookupPattern(args[numArgs-1].getName() + ))) { + state->setFillPattern(pattern); + } + + } else { + if (numArgs != state->getFillColorSpace()->getNComps()) { + error(errSyntaxError, getPos(), + "Incorrect number of arguments in 'scn' command"); + return; + } + state->setFillPattern(NULL); + for (i = 0; i < numArgs && i < gfxColorMaxComps; ++i) { + if (args[i].isNum()) { + color.c[i] = dblToCol(args[i].getNum()); + } + } + state->setFillColor(&color); + out->updateFillColor(state); + } +} + +void Gfx::opSetStrokeColorN(Object args[], int numArgs) { + GfxColor color; + GfxPattern *pattern; + int i; + + if (state->getIgnoreColorOps()) { + error(errSyntaxWarning, getPos(), "Ignoring color setting" + " in uncolored Type 3 char or tiling pattern"); + return; + } + if (state->getStrokeColorSpace()->getMode() == csPattern) { + if (numArgs == 0 || !args[numArgs-1].isName()) { + error(errSyntaxError, getPos(), + "Invalid arguments in 'SCN' command"); + return; + } + if (numArgs > 1) { + if (!((GfxPatternColorSpace *)state->getStrokeColorSpace()) + ->getUnder() || + numArgs - 1 != ((GfxPatternColorSpace *)state->getStrokeColorSpace()) + ->getUnder()->getNComps()) { + error(errSyntaxError, getPos(), + "Incorrect number of arguments in 'SCN' command"); + return; + } + for (i = 0; i < numArgs - 1 && i < gfxColorMaxComps; ++i) { + if (args[i].isNum()) { + color.c[i] = dblToCol(args[i].getNum()); + } + } + state->setStrokeColor(&color); + out->updateStrokeColor(state); + } + if ((pattern = res->lookupPattern(args[numArgs-1].getName() + ))) { + state->setStrokePattern(pattern); + } + + } else { + if (numArgs != state->getStrokeColorSpace()->getNComps()) { + error(errSyntaxError, getPos(), + "Incorrect number of arguments in 'SCN' command"); + return; + } + state->setStrokePattern(NULL); + for (i = 0; i < numArgs && i < gfxColorMaxComps; ++i) { + if (args[i].isNum()) { + color.c[i] = dblToCol(args[i].getNum()); + } + } + state->setStrokeColor(&color); + out->updateStrokeColor(state); + } +} + +//------------------------------------------------------------------------ +// path segment operators +//------------------------------------------------------------------------ + +void Gfx::opMoveTo(Object args[], int numArgs) { + state->moveTo(args[0].getNum(), args[1].getNum()); +} + +void Gfx::opLineTo(Object args[], int numArgs) { + if (!state->isCurPt()) { + error(errSyntaxError, getPos(), "No current point in lineto"); + return; + } + state->lineTo(args[0].getNum(), args[1].getNum()); +} + +void Gfx::opCurveTo(Object args[], int numArgs) { + double x1, y1, x2, y2, x3, y3; + + if (!state->isCurPt()) { + error(errSyntaxError, getPos(), "No current point in curveto"); + return; + } + x1 = args[0].getNum(); + y1 = args[1].getNum(); + x2 = args[2].getNum(); + y2 = args[3].getNum(); + x3 = args[4].getNum(); + y3 = args[5].getNum(); + state->curveTo(x1, y1, x2, y2, x3, y3); +} + +void Gfx::opCurveTo1(Object args[], int numArgs) { + double x1, y1, x2, y2, x3, y3; + + if (!state->isCurPt()) { + error(errSyntaxError, getPos(), "No current point in curveto1"); + return; + } + x1 = state->getCurX(); + y1 = state->getCurY(); + x2 = args[0].getNum(); + y2 = args[1].getNum(); + x3 = args[2].getNum(); + y3 = args[3].getNum(); + state->curveTo(x1, y1, x2, y2, x3, y3); +} + +void Gfx::opCurveTo2(Object args[], int numArgs) { + double x1, y1, x2, y2, x3, y3; + + if (!state->isCurPt()) { + error(errSyntaxError, getPos(), "No current point in curveto2"); + return; + } + x1 = args[0].getNum(); + y1 = args[1].getNum(); + x2 = args[2].getNum(); + y2 = args[3].getNum(); + x3 = x2; + y3 = y2; + state->curveTo(x1, y1, x2, y2, x3, y3); +} + +void Gfx::opRectangle(Object args[], int numArgs) { + double x, y, w, h; + + x = args[0].getNum(); + y = args[1].getNum(); + w = args[2].getNum(); + h = args[3].getNum(); + state->moveTo(x, y); + state->lineTo(x + w, y); + state->lineTo(x + w, y + h); + state->lineTo(x, y + h); + state->closePath(); +} + +void Gfx::opClosePath(Object args[], int numArgs) { + if (!state->isCurPt()) { + error(errSyntaxError, getPos(), "No current point in closepath"); + return; + } + state->closePath(); +} + +//------------------------------------------------------------------------ +// path painting operators +//------------------------------------------------------------------------ + +void Gfx::opEndPath(Object args[], int numArgs) { + doEndPath(); +} + +void Gfx::opStroke(Object args[], int numArgs) { + if (!state->isCurPt()) { + //error(errSyntaxError, getPos(), "No path in stroke"); + return; + } + if (state->isPath()) { + if (ocState) { + if (state->getStrokeColorSpace()->getMode() == csPattern) { + doPatternStroke(); + } else { + out->stroke(state); + } + } + } + doEndPath(); +} + +void Gfx::opCloseStroke(Object args[], int numArgs) { + if (!state->isCurPt()) { + //error(errSyntaxError, getPos(), "No path in closepath/stroke"); + return; + } + if (state->isPath()) { + state->closePath(); + if (ocState) { + if (state->getStrokeColorSpace()->getMode() == csPattern) { + doPatternStroke(); + } else { + out->stroke(state); + } + } + } + doEndPath(); +} + +void Gfx::opFill(Object args[], int numArgs) { + if (!state->isCurPt()) { + //error(errSyntaxError, getPos(), "No path in fill"); + return; + } + if (state->isPath()) { + if (ocState) { + if (state->getFillColorSpace()->getMode() == csPattern) { + doPatternFill(gFalse); + } else { + out->fill(state); + } + } + } + doEndPath(); +} + +void Gfx::opEOFill(Object args[], int numArgs) { + if (!state->isCurPt()) { + //error(errSyntaxError, getPos(), "No path in eofill"); + return; + } + if (state->isPath()) { + if (ocState) { + if (state->getFillColorSpace()->getMode() == csPattern) { + doPatternFill(gTrue); + } else { + out->eoFill(state); + } + } + } + doEndPath(); +} + +void Gfx::opFillStroke(Object args[], int numArgs) { + if (!state->isCurPt()) { + //error(errSyntaxError, getPos(), "No path in fill/stroke"); + return; + } + if (state->isPath()) { + if (ocState) { + if (state->getFillColorSpace()->getMode() == csPattern) { + doPatternFill(gFalse); + } else { + out->fill(state); + } + if (state->getStrokeColorSpace()->getMode() == csPattern) { + doPatternStroke(); + } else { + out->stroke(state); + } + } + } + doEndPath(); +} + +void Gfx::opCloseFillStroke(Object args[], int numArgs) { + if (!state->isCurPt()) { + //error(errSyntaxError, getPos(), "No path in closepath/fill/stroke"); + return; + } + if (state->isPath()) { + state->closePath(); + if (ocState) { + if (state->getFillColorSpace()->getMode() == csPattern) { + doPatternFill(gFalse); + } else { + out->fill(state); + } + if (state->getStrokeColorSpace()->getMode() == csPattern) { + doPatternStroke(); + } else { + out->stroke(state); + } + } + } + doEndPath(); +} + +void Gfx::opEOFillStroke(Object args[], int numArgs) { + if (!state->isCurPt()) { + //error(errSyntaxError, getPos(), "No path in eofill/stroke"); + return; + } + if (state->isPath()) { + if (ocState) { + if (state->getFillColorSpace()->getMode() == csPattern) { + doPatternFill(gTrue); + } else { + out->eoFill(state); + } + if (state->getStrokeColorSpace()->getMode() == csPattern) { + doPatternStroke(); + } else { + out->stroke(state); + } + } + } + doEndPath(); +} + +void Gfx::opCloseEOFillStroke(Object args[], int numArgs) { + if (!state->isCurPt()) { + //error(errSyntaxError, getPos(), "No path in closepath/eofill/stroke"); + return; + } + if (state->isPath()) { + state->closePath(); + if (ocState) { + if (state->getFillColorSpace()->getMode() == csPattern) { + doPatternFill(gTrue); + } else { + out->eoFill(state); + } + if (state->getStrokeColorSpace()->getMode() == csPattern) { + doPatternStroke(); + } else { + out->stroke(state); + } + } + } + doEndPath(); +} + +void Gfx::doPatternFill(GBool eoFill) { + 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, eoFill, gFalse); + break; + case 2: + doShadingPatternFill((GfxShadingPattern *)pattern, gFalse, eoFill, gFalse); + break; + default: + error(errSyntaxError, getPos(), "Unknown pattern type ({0:d}) in fill", + pattern->getType()); + break; + } +} + +void Gfx::doPatternStroke() { + 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->getStrokePattern())) { + return; + } + switch (pattern->getType()) { + case 1: + 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, gFalse, gFalse, gTrue); + break; + default: + 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, GBool interpolate) { + saveState(); + + out->setSoftMaskFromImageMask(state, ref, str, + width, height, invert, inlineImg, interpolate); + + state->clearPath(); + state->moveTo(0, 0); + state->lineTo(1, 0); + state->lineTo(1, 1); + state->lineTo(0, 1); + state->closePath(); + doPatternFill(gTrue); + state->clearPath(); + + restoreState(); +} + +void Gfx::doTilingPatternFill(GfxTilingPattern *tPat, + GBool stroke, GBool eoFill, GBool text) { + GfxPatternColorSpace *patCS; + GfxColorSpace *cs; + GfxColor color; + GfxState *savedState; + double xMin, yMin, xMax, yMax, x, y, x1, y1, t; + double cxMin, cyMin, cxMax, cyMax; + int xi0, yi0, xi1, yi1, xi, yi; + double *ctm, *btm, *ptm; + double bbox[4], m[6], ictm[6], m1[6], imb[6]; + double det; + double xstep, ystep; + int abortCheckCounter, i; + + // get color space + patCS = (GfxPatternColorSpace *)(stroke ? state->getStrokeColorSpace() + : state->getFillColorSpace()); + + // construct a (pattern space) -> (current space) transform matrix + ctm = state->getCTM(); + btm = baseMatrix; + ptm = tPat->getMatrix(); + // iCTM = invert CTM + det = ctm[0] * ctm[3] - ctm[1] * ctm[2]; + if (fabs(det) <= 1e-10) { + error(errSyntaxError, getPos(), "Singular matrix in tiling pattern fill"); + return; + } + det = 1 / det; + ictm[0] = ctm[3] * det; + ictm[1] = -ctm[1] * det; + ictm[2] = -ctm[2] * det; + 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; + // m1 = PTM * BTM = PTM * base transform matrix + m1[0] = ptm[0] * btm[0] + ptm[1] * btm[2]; + m1[1] = ptm[0] * btm[1] + ptm[1] * btm[3]; + m1[2] = ptm[2] * btm[0] + ptm[3] * btm[2]; + m1[3] = ptm[2] * btm[1] + ptm[3] * btm[3]; + m1[4] = ptm[4] * btm[0] + ptm[5] * btm[2] + btm[4]; + m1[5] = ptm[4] * btm[1] + ptm[5] * btm[3] + btm[5]; + // m = m1 * iCTM = (PTM * BTM) * (iCTM) + m[0] = m1[0] * ictm[0] + m1[1] * ictm[2]; + m[1] = m1[0] * ictm[1] + m1[1] * ictm[3]; + m[2] = m1[2] * ictm[0] + m1[3] * ictm[2]; + m[3] = m1[2] * ictm[1] + m1[3] * ictm[3]; + m[4] = m1[4] * ictm[0] + m1[5] * ictm[2] + ictm[4]; + m[5] = m1[4] * ictm[1] + m1[5] * ictm[3] + ictm[5]; + + // construct a (device space) -> (pattern space) transform matrix + det = m1[0] * m1[3] - m1[1] * m1[2]; + if (fabs(det) <= 1e-10) { + error(errSyntaxError, getPos(), "Singular matrix in tiling pattern fill"); + return; + } + det = 1 / det; + imb[0] = m1[3] * det; + imb[1] = -m1[1] * det; + imb[2] = -m1[2] * det; + imb[3] = m1[0] * det; + imb[4] = (m1[2] * m1[5] - m1[3] * m1[4]) * det; + imb[5] = (m1[1] * m1[4] - m1[0] * m1[5]) * det; + + // save current graphics state + 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); + state->setFillOverprint(gFalse); + state->setStrokeOverprint(gFalse); + state->setOverprintMode(0); + if (tPat->getPaintType() == 2 && (cs = patCS->getUnder())) { + state->setFillColorSpace(cs->copy()); + out->updateFillColorSpace(state); + state->setStrokeColorSpace(cs->copy()); + out->updateStrokeColorSpace(state); + if (stroke) { + state->setFillColor(state->getStrokeColor()); + } else { + state->setStrokeColor(state->getFillColor()); + } + out->updateFillColor(state); + out->updateStrokeColor(state); + state->setIgnoreColorOps(gTrue); + } else { + state->setFillColorSpace(GfxColorSpace::create(csDeviceGray)); + out->updateFillColorSpace(state); + state->getFillColorSpace()->getDefaultColor(&color); + state->setFillColor(&color); + out->updateFillColor(state); + state->setStrokeColorSpace(GfxColorSpace::create(csDeviceGray)); + out->updateStrokeColorSpace(state); + state->getStrokeColorSpace()->getDefaultColor(&color); + state->setStrokeColor(&color); + out->updateStrokeColor(state); + } + if (!stroke) { + state->setLineWidth(0); + out->updateLineWidth(state); + state->setLineDash(NULL, 0, 0); + out->updateLineDash(state); + } + + // clip to current path + if (stroke) { + state->clipToStrokePath(); + out->clipToStrokePath(state); + } else if (!text) { + state->clip(); + if (eoFill) { + out->eoClip(state); + } else { + out->clip(state); + } + } + state->clearPath(); + + // get the clip region, check for empty + state->getClipBBox(&cxMin, &cyMin, &cxMax, &cyMax); + if (cxMin > cxMax || cyMin > cyMax) { + goto err; + } + + // transform clip region bbox to pattern space + xMin = xMax = cxMin * imb[0] + cyMin * imb[2] + imb[4]; + yMin = yMax = cxMin * imb[1] + cyMin * imb[3] + imb[5]; + x1 = cxMin * imb[0] + cyMax * imb[2] + imb[4]; + y1 = cxMin * imb[1] + cyMax * imb[3] + imb[5]; + if (x1 < xMin) { + xMin = x1; + } else if (x1 > xMax) { + xMax = x1; + } + if (y1 < yMin) { + yMin = y1; + } else if (y1 > yMax) { + yMax = y1; + } + x1 = cxMax * imb[0] + cyMin * imb[2] + imb[4]; + y1 = cxMax * imb[1] + cyMin * imb[3] + imb[5]; + if (x1 < xMin) { + xMin = x1; + } else if (x1 > xMax) { + xMax = x1; + } + if (y1 < yMin) { + yMin = y1; + } else if (y1 > yMax) { + yMax = y1; + } + x1 = cxMax * imb[0] + cyMax * imb[2] + imb[4]; + y1 = cxMax * imb[1] + cyMax * imb[3] + imb[5]; + if (x1 < xMin) { + xMin = x1; + } else if (x1 > xMax) { + xMax = x1; + } + if (y1 < yMin) { + yMin = y1; + } else if (y1 > yMax) { + yMax = y1; + } + + // draw the pattern + //~ this should treat negative steps differently -- start at right/top + //~ edge instead of left/bottom (?) + bbox[0] = tPat->getBBox()[0]; + bbox[1] = tPat->getBBox()[1]; + bbox[2] = tPat->getBBox()[2]; + bbox[3] = tPat->getBBox()[3]; + if (bbox[0] > bbox[2]) { + t = bbox[0]; bbox[0] = bbox[2]; bbox[2] = t; + } + if (bbox[1] > bbox[3]) { + t = bbox[1]; bbox[1] = bbox[3]; bbox[3] = t; + } + xstep = fabs(tPat->getXStep()); + ystep = fabs(tPat->getYStep()); + xi0 = (int)ceil((xMin - bbox[2]) / xstep); + xi1 = (int)floor((xMax - bbox[0]) / xstep) + 1; + yi0 = (int)ceil((yMin - bbox[3]) / ystep); + yi1 = (int)floor((yMax - bbox[1]) / ystep) + 1; + for (i = 0; i < 4; ++i) { + m1[i] = m[i]; + } + if (out->useTilingPatternFill()) { + m1[4] = m[4]; + m1[5] = m[5]; + out->tilingPatternFill(state, this, tPat->getContentStreamRef(), + tPat->getPaintType(), tPat->getTilingType(), + tPat->getResDict(), + m1, bbox, + xi0, yi0, xi1, yi1, xstep, ystep); + } else { + abortCheckCounter = 0; + for (yi = yi0; yi < yi1; ++yi) { + for (xi = xi0; xi < xi1; ++xi) { + if (abortCheckCbk) { + ++abortCheckCounter; + if (abortCheckCounter > 100) { + if ((*abortCheckCbk)(abortCheckCbkData)) { + goto err; + } + abortCheckCounter = 0; + } + } + x = xi * xstep; + y = yi * ystep; + m1[4] = x * m[0] + y * m[2] + m[4]; + m1[5] = x * m[1] + y * m[3] + m[5]; + drawForm(tPat->getContentStreamRef(), tPat->getResDict(), + m1, bbox); + } + } + } + + // restore graphics state + err: + restoreStateStack(savedState); +} + +void Gfx::doShadingPatternFill(GfxShadingPattern *sPat, + GBool stroke, GBool eoFill, GBool text) { + GfxShading *shading; + GfxState *savedState; + double *ctm, *btm, *ptm; + double m[6], ictm[6], m1[6]; + double xMin, yMin, xMax, yMax; + double det; + + shading = sPat->getShading(); + + // save current graphics state + savedState = saveStateStack(); + + // clip to current path + if (stroke) { + state->clipToStrokePath(); + out->clipToStrokePath(state); + state->setFillOverprint(state->getStrokeOverprint()); + } else if (!text) { + state->clip(); + if (eoFill) { + out->eoClip(state); + } else { + out->clip(state); + } + } + state->clearPath(); + + // construct a (pattern space) -> (current space) transform matrix + ctm = state->getCTM(); + btm = baseMatrix; + ptm = sPat->getMatrix(); + // iCTM = invert CTM + det = ctm[0] * ctm[3] - ctm[1] * ctm[2]; + if (fabs(det) <= 1e-10) { + error(errSyntaxError, getPos(), "Singular matrix in shading pattern fill"); + restoreStateStack(savedState); + return; + } + det = 1 / det; + 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; + // m1 = PTM * BTM = PTM * base transform matrix + m1[0] = ptm[0] * btm[0] + ptm[1] * btm[2]; + m1[1] = ptm[0] * btm[1] + ptm[1] * btm[3]; + m1[2] = ptm[2] * btm[0] + ptm[3] * btm[2]; + m1[3] = ptm[2] * btm[1] + ptm[3] * btm[3]; + m1[4] = ptm[4] * btm[0] + ptm[5] * btm[2] + btm[4]; + m1[5] = ptm[4] * btm[1] + ptm[5] * btm[3] + btm[5]; + // m = m1 * iCTM = (PTM * BTM) * (iCTM) + m[0] = m1[0] * ictm[0] + m1[1] * ictm[2]; + m[1] = m1[0] * ictm[1] + m1[1] * ictm[3]; + m[2] = m1[2] * ictm[0] + m1[3] * ictm[2]; + m[3] = m1[2] * ictm[1] + m1[3] * ictm[3]; + m[4] = m1[4] * ictm[0] + m1[5] * ictm[2] + ictm[4]; + m[5] = m1[4] * ictm[1] + m1[5] * ictm[3] + ictm[5]; + + // set the new matrix + 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]); + + // 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(); + } + + // perform the fill + doShFill(shading); + + // restore graphics state + restoreStateStack(savedState); +} + +void Gfx::opShFill(Object args[], int numArgs) { + GfxShading *shading; + GfxState *savedState; + double xMin, yMin, xMax, yMax; + + if (state->getIgnoreColorOps()) { + error(errSyntaxWarning, getPos(), "Ignoring shaded fill" + " in uncolored Type 3 char or tiling pattern"); + return; + } + + if (!out->needNonText()) { + return; + } + + if (!ocState) { + return; + } + + if (!(shading = res->lookupShading(args[0].getName() + ))) { + return; + } + + // save current graphics state + savedState = saveStateStack(); + + // 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); + + // perform the fill + doShFill(shading); + + // restore graphics state + restoreStateStack(savedState); + + delete shading; +} + +void Gfx::doShFill(GfxShading *shading) { + if (out->shadedFill(state, shading)) { + return; + } + + // do shading type-specific operations + switch (shading->getType()) { + case 1: + doFunctionShFill((GfxFunctionShading *)shading); + break; + case 2: + doAxialShFill((GfxAxialShading *)shading); + break; + case 3: + doRadialShFill((GfxRadialShading *)shading); + break; + case 4: + case 5: + doGouraudTriangleShFill((GfxGouraudTriangleShading *)shading); + break; + case 6: + case 7: + doPatchMeshShFill((GfxPatchMeshShading *)shading); + break; + } +} + +void Gfx::doFunctionShFill(GfxFunctionShading *shading) { + double x0, y0, x1, y1; + GfxColor colors[4]; + + shading->getDomain(&x0, &y0, &x1, &y1); + shading->getColor(x0, y0, &colors[0]); + shading->getColor(x0, y1, &colors[1]); + shading->getColor(x1, y0, &colors[2]); + shading->getColor(x1, y1, &colors[3]); + doFunctionShFill1(shading, x0, y0, x1, y1, colors, 0); +} + +void Gfx::doFunctionShFill1(GfxFunctionShading *shading, + double x0, double y0, + double x1, double y1, + GfxColor *colors, int depth) { + GfxColor fillColor; + GfxColor color0M, color1M, colorM0, colorM1, colorMM; + GfxColor colors2[4]; + double *matrix; + double xM, yM; + int nComps, i, j; + + nComps = shading->getColorSpace()->getNComps(); + matrix = shading->getMatrix(); + + // compare the four corner colors + for (i = 0; i < 4; ++i) { + for (j = 0; j < nComps; ++j) { + if (abs(colors[i].c[j] - colors[(i+1)&3].c[j]) > functionColorDelta) { + break; + } + } + if (j < nComps) { + break; + } + } + + // center of the rectangle + xM = 0.5 * (x0 + x1); + yM = 0.5 * (y0 + y1); + + // the four corner colors are close (or we hit the recursive limit) + // -- fill the rectangle; but require at least one subdivision + // (depth==0) to avoid problems when the four outer corners of the + // shaded region are the same color + if ((i == 4 && depth > 0) || depth == functionMaxDepth) { + + // use the center color + shading->getColor(xM, yM, &fillColor); + state->setFillColor(&fillColor); + out->updateFillColor(state); + + // fill the rectangle + state->moveTo(x0 * matrix[0] + y0 * matrix[2] + matrix[4], + x0 * matrix[1] + y0 * matrix[3] + matrix[5]); + state->lineTo(x1 * matrix[0] + y0 * matrix[2] + matrix[4], + x1 * matrix[1] + y0 * matrix[3] + matrix[5]); + state->lineTo(x1 * matrix[0] + y1 * matrix[2] + matrix[4], + x1 * matrix[1] + y1 * matrix[3] + matrix[5]); + state->lineTo(x0 * matrix[0] + y1 * matrix[2] + matrix[4], + x0 * matrix[1] + y1 * matrix[3] + matrix[5]); + state->closePath(); + out->fill(state); + state->clearPath(); + + // the four corner colors are not close enough -- subdivide the + // rectangle + } else { + + // colors[0] colorM0 colors[2] + // (x0,y0) (xM,y0) (x1,y0) + // +----------+----------+ + // | | | + // | UL | UR | + // color0M | colorMM | color1M + // (x0,yM) +----------+----------+ (x1,yM) + // | (xM,yM) | + // | LL | LR | + // | | | + // +----------+----------+ + // colors[1] colorM1 colors[3] + // (x0,y1) (xM,y1) (x1,y1) + + shading->getColor(x0, yM, &color0M); + shading->getColor(x1, yM, &color1M); + shading->getColor(xM, y0, &colorM0); + shading->getColor(xM, y1, &colorM1); + shading->getColor(xM, yM, &colorMM); + + // upper-left sub-rectangle + colors2[0] = colors[0]; + colors2[1] = color0M; + colors2[2] = colorM0; + colors2[3] = colorMM; + doFunctionShFill1(shading, x0, y0, xM, yM, colors2, depth + 1); + + // lower-left sub-rectangle + colors2[0] = color0M; + colors2[1] = colors[1]; + colors2[2] = colorMM; + colors2[3] = colorM1; + doFunctionShFill1(shading, x0, yM, xM, y1, colors2, depth + 1); + + // upper-right sub-rectangle + colors2[0] = colorM0; + colors2[1] = colorMM; + colors2[2] = colors[2]; + colors2[3] = color1M; + doFunctionShFill1(shading, xM, y0, x1, yM, colors2, depth + 1); + + // lower-right sub-rectangle + colors2[0] = colorMM; + colors2[1] = colorM1; + colors2[2] = color1M; + colors2[3] = colors[3]; + doFunctionShFill1(shading, xM, yM, x1, y1, colors2, depth + 1); + } +} + +void Gfx::doAxialShFill(GfxAxialShading *shading) { + double xMin, yMin, xMax, yMax; + double x0, y0, x1, y1; + double dx, dy, mul; + GBool dxdyZero, horiz; + double tMin, tMax, tMinExt, tMaxExt, t, tx, ty; + double sMin, sMax, tmp; + double ux0, uy0, ux1, uy1, vx0, vy0, vx1, vy1; + double t0, t1, tt; + GfxColor colors[axialSplits]; + int abortCheckCounter, nComps, i, j, k; + + // get the clip region bbox + state->getUserClipBBox(&xMin, &yMin, &xMax, &yMax); + + // compute min and max t values, based on the four corners of the + // clip region bbox + shading->getCoords(&x0, &y0, &x1, &y1); + dx = x1 - x0; + dy = y1 - y0; + dxdyZero = fabs(dx) < 0.0001 && fabs(dy) < 0.0001; + horiz = fabs(dy) < fabs(dx); + if (dxdyZero) { + tMinExt = tMaxExt = 0; + tMin = tMax = 0; + } else { + mul = 1 / (dx * dx + dy * dy); + tMinExt = tMaxExt = ((xMin - x0) * dx + (yMin - y0) * dy) * mul; + t = ((xMin - x0) * dx + (yMax - y0) * dy) * mul; + if (t < tMinExt) { + tMinExt = t; + } else if (t > tMaxExt) { + tMaxExt = t; + } + t = ((xMax - x0) * dx + (yMin - y0) * dy) * mul; + if (t < tMinExt) { + tMinExt = t; + } else if (t > tMaxExt) { + tMaxExt = t; + } + t = ((xMax - x0) * dx + (yMax - y0) * dy) * mul; + if (t < tMinExt) { + tMinExt = t; + } else if (t > tMaxExt) { + tMaxExt = t; + } + if ((tMin = tMinExt) < 0) { + tMin = 0; + } + if (!shading->getExtend0()) { + tMinExt = tMin; + } + if ((tMax = tMaxExt) > 1) { + tMax = 1; + } + if (!shading->getExtend1()) { + tMaxExt = tMax; + } + } + + // get the function domain + t0 = shading->getDomain0(); + t1 = shading->getDomain1(); + + // Traverse the t axis and do the shading. + // + // For each point (tx, ty) on the t axis, consider a line through + // that point perpendicular to the t axis: + // + // x(s) = tx + s * -dy --> s = (x - tx) / -dy + // 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). For -1 < |dy/dx| < 1, look at the + // intersection with yMin, yMax: + // + // s0 = (yMin - ty) / dx + // s1 = (yMax - ty) / dx + // + // else look at the intersection with xMin, xMax: + // + // s0 = (xMin - tx) / -dy + // s1 = (xMax - tx) / -dy + // + // Each filled polygon is bounded by two of these line segments + // perpdendicular to the t axis. + // + // The t axis is bisected into smaller regions until the color + // difference across a region is small enough, and then the region + // is painted with a single color. + + // compute the coordinates of the point on the t axis at t = tMin; + // then compute the intersection of the perpendicular line with the + // bounding box + tx = x0 + tMin * dx; + ty = y0 + tMin * dy; + if (dxdyZero) { + sMin = sMax = 0; + } else { + 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; + } + } + ux0 = tx - sMin * dy; + uy0 = ty + sMin * dx; + vx0 = tx - sMax * dy; + vy0 = ty + sMax * dx; + + // fill the extension at t0 + if (shading->getExtend0() && tMinExt < tMin) { + + // compute the color at t0 + shading->getColor(t0, &colors[0]); + + // compute the coordinates of the point on the t axis at t = + // tMinExt; then compute the intersection of the perpendicular + // line with the bounding box + tx = x0 + tMinExt * dx; + ty = y0 + tMinExt * dy; + if (dxdyZero) { + sMin = sMax = 0; + } else { + 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; + } + } + ux1 = tx - sMin * dy; + uy1 = ty + sMin * dx; + vx1 = tx - sMax * dy; + vy1 = ty + sMax * dx; + + // set the color + state->setFillColor(&colors[0]); + out->updateFillColor(state); + + // fill the region + state->moveTo(ux1, uy1); + state->lineTo(vx1, vy1); + state->lineTo(vx0, vy0); + state->lineTo(ux0, uy0); + state->closePath(); + out->fill(state); + state->clearPath(); + } + + // traverse the t axis, splitting [tMin, tMax] into axialSplits regions + + // compute the color in the center of each region + for (i = 0; i < axialSplits; ++i) { + t = tMin + (tMax - tMin) * (i + 0.5) / axialSplits; + tt = t0 + (t1 - t0) * t; + shading->getColor(tt, &colors[i]); + } + + // each iteration draws one or more regions, starting at i -- + // if the colors are similar, it will combine regions i, i+1, ... + nComps = shading->getColorSpace()->getNComps(); + abortCheckCounter = 0; + i = 0; + while (i < axialSplits) { + + if (abortCheckCbk) { + ++abortCheckCounter; + if (abortCheckCounter > 100) { + if ((*abortCheckCbk)(abortCheckCbkData)) { + break; + } + abortCheckCounter = 0; + } + } + + // check for similar colors + for (j = i + 1; j < axialSplits; ++j) { + for (k = 0; k < nComps; ++k) { + if (abs(colors[j].c[k] - colors[i].c[k]) > axialColorDelta) { + break; + } + } + if (k < nComps) { + break; + } + } + + // compute the coordinates of the point on the t axis; then + // compute the intersection of the perpendicular line with the + // bounding box + t = tMin + (tMax - tMin) * (double)j / axialSplits; + tx = x0 + t * dx; + ty = y0 + t * dy; + if (dxdyZero) { + sMin = sMax = 0; + } else { + 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; + } + } + ux1 = tx - sMin * dy; + uy1 = ty + sMin * dx; + vx1 = tx - sMax * dy; + vy1 = ty + sMax * dx; + + // set the color + state->setFillColor(&colors[i]); + out->updateFillColor(state); + + // fill the region + state->moveTo(ux0, uy0); + state->lineTo(vx0, vy0); + state->lineTo(vx1, vy1); + state->lineTo(ux1, uy1); + state->closePath(); + out->fill(state); + state->clearPath(); + + // set up for next region + ux0 = ux1; + uy0 = uy1; + vx0 = vx1; + vy0 = vy1; + + i = j; + } + + // fill the extension at t1 + if (shading->getExtend1() && tMaxExt > tMax) { + + // compute the color at t1 + shading->getColor(t1, &colors[0]); + + // compute the coordinates of the point on the t axis at t = + // tMaxExt; then compute the intersection of the perpendicular + // line with the bounding box + tx = x0 + tMaxExt * dx; + ty = y0 + tMaxExt * dy; + if (dxdyZero) { + sMin = sMax = 0; + } else { + 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; + } + } + ux1 = tx - sMin * dy; + uy1 = ty + sMin * dx; + vx1 = tx - sMax * dy; + vy1 = ty + sMax * dx; + + // set the color + state->setFillColor(&colors[0]); + out->updateFillColor(state); + + // fill the region + state->moveTo(ux0, uy0); + state->lineTo(vx0, vy0); + state->lineTo(vx1, vy1); + state->lineTo(ux1, uy1); + state->closePath(); + out->fill(state); + state->clearPath(); + } +} + +#if defined(__GNUC__) && !defined(__clang__) +// this function makes a lot of sin()/cos() calls, which are slow +// with glibc 2.16 and newer on x86; accuracy isn't terribly +// important here, so tell gcc to use the fast version +#pragma GCC optimize ("fast-math") +#endif + +void Gfx::doRadialShFill(GfxRadialShading *shading) { + double xMin, yMin, xMax, yMax; + double x0, y0, r0, x1, y1, r1, t0, t1; + int nComps; + GfxColor colorA, colorB; + double xa, ya, xb, yb, ra, rb; + double ta, tb, sa, sb; + double sMin, sMax, h; + double sLeft, sRight, sTop, sBottom, sZero, sDiag; + GBool haveSLeft, haveSRight, haveSTop, haveSBottom, haveSZero; + GBool haveSMin, haveSMax; + GBool enclosed; + double *ctm; + double theta, alpha, angle, t; + int abortCheckCounter, ia, ib, k, n; + + // get the shading info + shading->getCoords(&x0, &y0, &r0, &x1, &y1, &r1); + t0 = shading->getDomain0(); + t1 = shading->getDomain1(); + nComps = shading->getColorSpace()->getNComps(); + + // Compute the point at which r(s) = 0; check for the enclosed + // circles case; and compute the angles for the tangent lines. + h = sqrt((x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0)); + if (h == 0) { + enclosed = gTrue; + theta = 0; // make gcc happy + } else if (r1 - r0 == 0) { + enclosed = gFalse; + theta = 0; + } else if (fabs(r1 - r0) >= h - 0.0001) { + enclosed = gTrue; + theta = 0; // make gcc happy + } else { + enclosed = gFalse; + theta = asin((r1 - r0) / h); + } + if (enclosed) { + alpha = 0; + } else { + alpha = atan2(y1 - y0, x1 - x0); + } + + // compute the (possibly extended) s range + state->getUserClipBBox(&xMin, &yMin, &xMax, &yMax); + if (enclosed) { + sMin = 0; + sMax = 1; + } else { + // 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; + } + // 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; + } + } + + // compute the number of steps into which circles must be divided to + // achieve a curve flatness of 0.1 pixel in device space for the + // largest circle (note that "device space" is 72 dpi when generating + // PostScript, hence the relatively small 0.1 pixel accuracy) + ctm = state->getCTM(); + t = fabs(ctm[0]); + if (fabs(ctm[1]) > t) { + t = fabs(ctm[1]); + } + if (fabs(ctm[2]) > t) { + t = fabs(ctm[2]); + } + if (fabs(ctm[3]) > t) { + t = fabs(ctm[3]); + } + if (r0 > r1) { + t *= r0; + } else { + t *= r1; + } + if (t < 1) { + n = 3; + } else { + n = (int)(M_PI / acos(1 - 0.1 / t)); + if (n < 3) { + n = 3; + } else if (n > 200) { + n = 200; + } + } + + // setup for the start circle + ia = 0; + sa = sMin; + ta = t0 + sa * (t1 - t0); + xa = x0 + sa * (x1 - x0); + ya = y0 + sa * (y1 - y0); + ra = r0 + sa * (r1 - r0); + if (ta < t0) { + shading->getColor(t0, &colorA); + } else if (ta > t1) { + shading->getColor(t1, &colorA); + } else { + shading->getColor(ta, &colorA); + } + + // fill the circles + abortCheckCounter = 0; + while (ia < radialMaxSplits) { + + if (abortCheckCbk) { + ++abortCheckCounter; + if (abortCheckCounter > 100) { + if ((*abortCheckCbk)(abortCheckCbkData)) { + break; + } + abortCheckCounter = 0; + } + } + + // go as far along the t axis (toward t1) as we can, such that the + // color difference is within the tolerance (radialColorDelta) -- + // this uses bisection (between the current value, t, and t1), + // limited to radialMaxSplits points along the t axis; require at + // least one split to avoid problems when the innermost and + // outermost colors are the same + ib = radialMaxSplits; + sb = sMax; + tb = t0 + sb * (t1 - t0); + if (tb < t0) { + shading->getColor(t0, &colorB); + } else if (tb > t1) { + shading->getColor(t1, &colorB); + } else { + shading->getColor(tb, &colorB); + } + while (ib - ia > 1) { + for (k = 0; k < nComps; ++k) { + if (abs(colorB.c[k] - colorA.c[k]) > radialColorDelta) { + break; + } + } + if (k == nComps && ib < radialMaxSplits) { + break; + } + ib = (ia + ib) / 2; + sb = sMin + ((double)ib / (double)radialMaxSplits) * (sMax - sMin); + tb = t0 + sb * (t1 - t0); + if (tb < t0) { + shading->getColor(t0, &colorB); + } else if (tb > t1) { + shading->getColor(t1, &colorB); + } else { + shading->getColor(tb, &colorB); + } + } + + // compute center and radius of the circle + xb = x0 + sb * (x1 - x0); + yb = y0 + sb * (y1 - y0); + rb = r0 + sb * (r1 - r0); + + // use the average of the colors at the two circles + for (k = 0; k < nComps; ++k) { + colorA.c[k] = (colorA.c[k] + colorB.c[k]) / 2; + } + state->setFillColor(&colorA); + out->updateFillColor(state); + + if (enclosed) { + + // construct path for first circle (counterclockwise) + state->moveTo(xa + ra, ya); + for (k = 1; k < n; ++k) { + angle = ((double)k / (double)n) * 2 * M_PI; + state->lineTo(xa + ra * cos(angle), ya + ra * sin(angle)); + } + state->closePath(); + + // construct and append path for second circle (clockwise) + state->moveTo(xb + rb, yb); + for (k = 1; k < n; ++k) { + angle = -((double)k / (double)n) * 2 * M_PI; + state->lineTo(xb + rb * cos(angle), yb + rb * sin(angle)); + } + state->closePath(); + + } else { + + // construct the first subpath (clockwise) + state->moveTo(xa + ra * cos(alpha + theta + 0.5 * M_PI), + ya + ra * sin(alpha + theta + 0.5 * M_PI)); + for (k = 0; k < n; ++k) { + angle = alpha + theta + 0.5 * M_PI + - ((double)k / (double)n) * (2 * theta + M_PI); + state->lineTo(xb + rb * cos(angle), yb + rb * sin(angle)); + } + for (k = 0; k < n; ++k) { + angle = alpha - theta - 0.5 * M_PI + + ((double)k / (double)n) * (2 * theta - M_PI); + state->lineTo(xa + ra * cos(angle), ya + ra * sin(angle)); + } + state->closePath(); + + // construct the second subpath (counterclockwise) + state->moveTo(xa + ra * cos(alpha + theta + 0.5 * M_PI), + ya + ra * sin(alpha + theta + 0.5 * M_PI)); + for (k = 0; k < n; ++k) { + angle = alpha + theta + 0.5 * M_PI + + ((double)k / (double)n) * (-2 * theta + M_PI); + state->lineTo(xb + rb * cos(angle), yb + rb * sin(angle)); + } + for (k = 0; k < n; ++k) { + angle = alpha - theta - 0.5 * M_PI + + ((double)k / (double)n) * (2 * theta + M_PI); + state->lineTo(xa + ra * cos(angle), ya + ra * sin(angle)); + } + state->closePath(); + } + + // fill the path + out->fill(state); + state->clearPath(); + + // step to the next value of t + ia = ib; + sa = sb; + ta = tb; + xa = xb; + ya = yb; + ra = rb; + colorA = colorB; + } + + if (enclosed) { + // extend the smaller circle + if ((shading->getExtend0() && r0 <= r1) || + (shading->getExtend1() && r1 < r0)) { + if (r0 <= r1) { + ta = t0; + ra = r0; + xa = x0; + ya = y0; + } else { + ta = t1; + ra = r1; + xa = x1; + ya = y1; + } + shading->getColor(ta, &colorA); + state->setFillColor(&colorA); + out->updateFillColor(state); + state->moveTo(xa + ra, ya); + for (k = 1; k < n; ++k) { + angle = ((double)k / (double)n) * 2 * M_PI; + state->lineTo(xa + ra * cos(angle), ya + ra * sin(angle)); + } + state->closePath(); + out->fill(state); + state->clearPath(); + } + + // extend the larger circle + if ((shading->getExtend0() && r0 > r1) || + (shading->getExtend1() && r1 >= r0)) { + if (r0 > r1) { + ta = t0; + ra = r0; + xa = x0; + ya = y0; + } else { + ta = t1; + ra = r1; + xa = x1; + ya = y1; + } + shading->getColor(ta, &colorA); + state->setFillColor(&colorA); + out->updateFillColor(state); + state->moveTo(xMin, yMin); + state->lineTo(xMin, yMax); + state->lineTo(xMax, yMax); + state->lineTo(xMax, yMin); + state->closePath(); + state->moveTo(xa + ra, ya); + for (k = 1; k < n; ++k) { + angle = ((double)k / (double)n) * 2 * M_PI; + state->lineTo(xa + ra * cos(angle), ya + ra * sin(angle)); + } + state->closePath(); + out->fill(state); + state->clearPath(); + } + } +} + +#if defined(__GNUC__) && !defined(__clang__) +#pragma GCC reset_options +#endif + +void Gfx::doGouraudTriangleShFill(GfxGouraudTriangleShading *shading) { + double x0, y0, x1, y1, x2, y2; + double color0[gfxColorMaxComps]; + double color1[gfxColorMaxComps]; + double color2[gfxColorMaxComps]; + int abortCheckCounter, i; + + abortCheckCounter = 0; + for (i = 0; i < shading->getNTriangles(); ++i) { + if (abortCheckCbk) { + ++abortCheckCounter; + if (abortCheckCounter > 25) { + if ((*abortCheckCbk)(abortCheckCbkData)) { + break; + } + abortCheckCounter = 0; + } + } + shading->getTriangle(i, &x0, &y0, color0, + &x1, &y1, color1, + &x2, &y2, color2); + gouraudFillTriangle(x0, y0, color0, x1, y1, color1, x2, y2, color2, + shading, 0); + } +} + +void Gfx::gouraudFillTriangle(double x0, double y0, double *color0, + double x1, double y1, double *color1, + double x2, double y2, double *color2, + GfxGouraudTriangleShading *shading, int depth) { + double dx0, dy0, dx1, dy1, dx2, dy2; + double x01, y01, x12, y12, x20, y20; + double color01[gfxColorMaxComps]; + double color12[gfxColorMaxComps]; + double color20[gfxColorMaxComps]; + GfxColor c0, c1, c2; + int nComps, i; + + // recursion ends when: + // (1) color difference is smaller than gouraudColorDelta; or + // (2) triangles are smaller than 0.5 pixel (note that "device + // space" is 72dpi when generating PostScript); or + // (3) max recursion depth (gouraudMaxDepth) is hit. + nComps = shading->getColorSpace()->getNComps(); + shading->getColor(color0, &c0); + shading->getColor(color1, &c1); + shading->getColor(color2, &c2); + for (i = 0; i < nComps; ++i) { + if (abs(c0.c[i] - c1.c[i]) > gouraudColorDelta || + abs(c1.c[i] - c2.c[i]) > gouraudColorDelta) { + break; + } + } + state->transformDelta(x1 - x0, y1 - y0, &dx0, &dy0); + state->transformDelta(x2 - x1, y2 - y1, &dx1, &dy1); + state->transformDelta(x0 - x2, y0 - y2, &dx2, &dy2); + if (i == nComps || + depth == gouraudMaxDepth || + (fabs(dx0) < 0.5 && fabs(dy0) < 0.5 && + fabs(dx1) < 0.5 && fabs(dy1) < 0.5 && + fabs(dx2) < 0.5 && fabs(dy2) < 0.5)) { + state->setFillColor(&c0); + out->updateFillColor(state); + state->moveTo(x0, y0); + state->lineTo(x1, y1); + state->lineTo(x2, y2); + state->closePath(); + out->fill(state); + state->clearPath(); + } else { + x01 = 0.5 * (x0 + x1); + y01 = 0.5 * (y0 + y1); + x12 = 0.5 * (x1 + x2); + y12 = 0.5 * (y1 + y2); + x20 = 0.5 * (x2 + x0); + y20 = 0.5 * (y2 + y0); + for (i = 0; i < shading->getNComps(); ++i) { + color01[i] = 0.5 * (color0[i] + color1[i]); + color12[i] = 0.5 * (color1[i] + color2[i]); + color20[i] = 0.5 * (color2[i] + color0[i]); + } + gouraudFillTriangle(x0, y0, color0, x01, y01, color01, + x20, y20, color20, shading, depth + 1); + gouraudFillTriangle(x01, y01, color01, x1, y1, color1, + x12, y12, color12, shading, depth + 1); + gouraudFillTriangle(x01, y01, color01, x12, y12, color12, + x20, y20, color20, shading, depth + 1); + gouraudFillTriangle(x20, y20, color20, x12, y12, color12, + x2, y2, color2, shading, depth + 1); + } +} + +void Gfx::doPatchMeshShFill(GfxPatchMeshShading *shading) { + int start, abortCheckCounter, i; + + if (shading->getNPatches() > 128) { + start = 3; + } else if (shading->getNPatches() > 64) { + start = 2; + } else if (shading->getNPatches() > 16) { + start = 1; + } else { + start = 0; + } + abortCheckCounter = 0; + for (i = 0; i < shading->getNPatches(); ++i) { + if (abortCheckCbk) { + ++abortCheckCounter; + if (abortCheckCounter > 25) { + if ((*abortCheckCbk)(abortCheckCbkData)) { + break; + } + abortCheckCounter = 0; + } + } + fillPatch(shading->getPatch(i), shading, start); + } +} + +void Gfx::fillPatch(GfxPatch *patch, GfxPatchMeshShading *shading, int depth) { + GfxPatch patch00, patch01, patch10, patch11; + GfxColor c00, c01, c10, c11; + double xx[4][8], yy[4][8]; + double x, y, xMin, yMin, xMax, yMax, xxm, yym; + int nComps, i, j; + GBool stop; + + shading->getColor(patch->color[0][0], &c00); + stop = gFalse; + + // stop subdivision at max depth + if (depth == patchMaxDepth) { + stop = gTrue; + } + + // stop subdivision if colors are close enough + if (!stop) { + nComps = shading->getColorSpace()->getNComps(); + shading->getColor(patch->color[0][1], &c01); + shading->getColor(patch->color[1][0], &c10); + shading->getColor(patch->color[1][1], &c11); + for (i = 0; i < nComps; ++i) { + if (abs(c00.c[i] - c01.c[i]) > patchColorDelta || + abs(c01.c[i] - c11.c[i]) > patchColorDelta || + abs(c11.c[i] - c10.c[i]) > patchColorDelta || + abs(c10.c[i] - c00.c[i]) > patchColorDelta) { + break; + } + } + if (i == nComps) { + stop = gTrue; + } + } + + // stop subdivision if patch is small enough + if (!stop) { + xMin = yMin = xMax = yMax = 0; + for (j = 0; j < 4; ++j) { + for (i = 0; i < 4; ++i) { + state->transformDelta(patch->x[i][j], patch->y[i][j], &x, &y); + if (i == 0 && j == 0) { + xMin = xMax = x; + yMin = yMax = y; + } else { + if (x < xMin) { + xMin = x; + } else if (x > xMax) { + xMax = x; + } + if (y < yMin) { + yMin = y; + } else if (y > yMax) { + yMax = y; + } + } + } + } + if (xMax - xMin < 1 && yMax - yMin < 1) { + stop = gTrue; + } + } + + // draw the patch + if (stop) { + state->setFillColor(&c00); + out->updateFillColor(state); + state->moveTo(patch->x[0][0], patch->y[0][0]); + state->curveTo(patch->x[0][1], patch->y[0][1], + patch->x[0][2], patch->y[0][2], + patch->x[0][3], patch->y[0][3]); + state->curveTo(patch->x[1][3], patch->y[1][3], + patch->x[2][3], patch->y[2][3], + patch->x[3][3], patch->y[3][3]); + state->curveTo(patch->x[3][2], patch->y[3][2], + patch->x[3][1], patch->y[3][1], + patch->x[3][0], patch->y[3][0]); + state->curveTo(patch->x[2][0], patch->y[2][0], + patch->x[1][0], patch->y[1][0], + patch->x[0][0], patch->y[0][0]); + state->closePath(); + out->fill(state); + state->clearPath(); + + // subdivide the patch + } else { + for (i = 0; i < 4; ++i) { + xx[i][0] = patch->x[i][0]; + yy[i][0] = patch->y[i][0]; + xx[i][1] = 0.5 * (patch->x[i][0] + patch->x[i][1]); + yy[i][1] = 0.5 * (patch->y[i][0] + patch->y[i][1]); + xxm = 0.5 * (patch->x[i][1] + patch->x[i][2]); + yym = 0.5 * (patch->y[i][1] + patch->y[i][2]); + xx[i][6] = 0.5 * (patch->x[i][2] + patch->x[i][3]); + yy[i][6] = 0.5 * (patch->y[i][2] + patch->y[i][3]); + xx[i][2] = 0.5 * (xx[i][1] + xxm); + yy[i][2] = 0.5 * (yy[i][1] + yym); + xx[i][5] = 0.5 * (xxm + xx[i][6]); + yy[i][5] = 0.5 * (yym + yy[i][6]); + xx[i][3] = xx[i][4] = 0.5 * (xx[i][2] + xx[i][5]); + yy[i][3] = yy[i][4] = 0.5 * (yy[i][2] + yy[i][5]); + xx[i][7] = patch->x[i][3]; + yy[i][7] = patch->y[i][3]; + } + for (i = 0; i < 4; ++i) { + patch00.x[0][i] = xx[0][i]; + patch00.y[0][i] = yy[0][i]; + patch00.x[1][i] = 0.5 * (xx[0][i] + xx[1][i]); + patch00.y[1][i] = 0.5 * (yy[0][i] + yy[1][i]); + xxm = 0.5 * (xx[1][i] + xx[2][i]); + yym = 0.5 * (yy[1][i] + yy[2][i]); + patch10.x[2][i] = 0.5 * (xx[2][i] + xx[3][i]); + patch10.y[2][i] = 0.5 * (yy[2][i] + yy[3][i]); + patch00.x[2][i] = 0.5 * (patch00.x[1][i] + xxm); + patch00.y[2][i] = 0.5 * (patch00.y[1][i] + yym); + patch10.x[1][i] = 0.5 * (xxm + patch10.x[2][i]); + patch10.y[1][i] = 0.5 * (yym + patch10.y[2][i]); + patch00.x[3][i] = 0.5 * (patch00.x[2][i] + patch10.x[1][i]); + patch00.y[3][i] = 0.5 * (patch00.y[2][i] + patch10.y[1][i]); + patch10.x[0][i] = patch00.x[3][i]; + patch10.y[0][i] = patch00.y[3][i]; + patch10.x[3][i] = xx[3][i]; + patch10.y[3][i] = yy[3][i]; + } + for (i = 4; i < 8; ++i) { + patch01.x[0][i-4] = xx[0][i]; + patch01.y[0][i-4] = yy[0][i]; + patch01.x[1][i-4] = 0.5 * (xx[0][i] + xx[1][i]); + patch01.y[1][i-4] = 0.5 * (yy[0][i] + yy[1][i]); + xxm = 0.5 * (xx[1][i] + xx[2][i]); + yym = 0.5 * (yy[1][i] + yy[2][i]); + patch11.x[2][i-4] = 0.5 * (xx[2][i] + xx[3][i]); + patch11.y[2][i-4] = 0.5 * (yy[2][i] + yy[3][i]); + patch01.x[2][i-4] = 0.5 * (patch01.x[1][i-4] + xxm); + patch01.y[2][i-4] = 0.5 * (patch01.y[1][i-4] + yym); + patch11.x[1][i-4] = 0.5 * (xxm + patch11.x[2][i-4]); + patch11.y[1][i-4] = 0.5 * (yym + patch11.y[2][i-4]); + patch01.x[3][i-4] = 0.5 * (patch01.x[2][i-4] + patch11.x[1][i-4]); + patch01.y[3][i-4] = 0.5 * (patch01.y[2][i-4] + patch11.y[1][i-4]); + patch11.x[0][i-4] = patch01.x[3][i-4]; + patch11.y[0][i-4] = patch01.y[3][i-4]; + patch11.x[3][i-4] = xx[3][i]; + patch11.y[3][i-4] = yy[3][i]; + } + for (i = 0; i < shading->getNComps(); ++i) { + patch00.color[0][0][i] = patch->color[0][0][i]; + patch00.color[0][1][i] = 0.5 * (patch->color[0][0][i] + + patch->color[0][1][i]); + patch01.color[0][0][i] = patch00.color[0][1][i]; + patch01.color[0][1][i] = patch->color[0][1][i]; + patch01.color[1][1][i] = 0.5 * (patch->color[0][1][i] + + patch->color[1][1][i]); + patch11.color[0][1][i] = patch01.color[1][1][i]; + patch11.color[1][1][i] = patch->color[1][1][i]; + patch11.color[1][0][i] = 0.5 * (patch->color[1][1][i] + + patch->color[1][0][i]); + patch10.color[1][1][i] = patch11.color[1][0][i]; + patch10.color[1][0][i] = patch->color[1][0][i]; + patch10.color[0][0][i] = 0.5 * (patch->color[1][0][i] + + patch->color[0][0][i]); + patch00.color[1][0][i] = patch10.color[0][0][i]; + patch00.color[1][1][i] = 0.5 * (patch00.color[1][0][i] + + patch01.color[1][1][i]); + patch01.color[1][0][i] = patch00.color[1][1][i]; + patch11.color[0][0][i] = patch00.color[1][1][i]; + patch10.color[0][1][i] = patch00.color[1][1][i]; + } + fillPatch(&patch00, shading, depth + 1); + fillPatch(&patch10, shading, depth + 1); + fillPatch(&patch01, shading, depth + 1); + fillPatch(&patch11, shading, depth + 1); + } +} + +void Gfx::doEndPath() { + if (state->isCurPt() && clip != clipNone) { + state->clip(); + if (clip == clipNormal) { + out->clip(state); + } else { + out->eoClip(state); + } + } + clip = clipNone; + state->clearPath(); +} + +//------------------------------------------------------------------------ +// path clipping operators +//------------------------------------------------------------------------ + +void Gfx::opClip(Object args[], int numArgs) { + clip = clipNormal; +} + +void Gfx::opEOClip(Object args[], int numArgs) { + clip = clipEO; +} + +//------------------------------------------------------------------------ +// text object operators +//------------------------------------------------------------------------ + +void Gfx::opBeginText(Object args[], int numArgs) { + state->setTextMat(1, 0, 0, 1, 0, 0); + state->textMoveTo(0, 0); + out->updateTextMat(state); + out->updateTextPos(state); + fontChanged = gTrue; +} + +void Gfx::opEndText(Object args[], int numArgs) { + out->endTextObject(state); +} + +//------------------------------------------------------------------------ +// text state operators +//------------------------------------------------------------------------ + +void Gfx::opSetCharSpacing(Object args[], int numArgs) { + state->setCharSpace(args[0].getNum()); + out->updateCharSpace(state); +} + +void Gfx::opSetFont(Object args[], int numArgs) { + doSetFont(res->lookupFont(args[0].getName()), args[1].getNum()); +} + +void Gfx::doSetFont(GfxFont *font, double size) { + if (!font) { + if (!defaultFont) { + defaultFont = GfxFont::makeDefaultFont(xref); + } + font = defaultFont; + } + if (printCommands) { + printf(" font: tag=%s name='%s' %g\n", + font->getTag()->getCString(), + font->getName() ? font->getName()->getCString() : "???", + size); + fflush(stdout); + } + state->setFont(font, size); + fontChanged = gTrue; +} + +void Gfx::opSetTextLeading(Object args[], int numArgs) { + state->setLeading(args[0].getNum()); +} + +void Gfx::opSetTextRender(Object args[], int numArgs) { + state->setRender(args[0].getInt()); + out->updateRender(state); +} + +void Gfx::opSetTextRise(Object args[], int numArgs) { + state->setRise(args[0].getNum()); + out->updateRise(state); +} + +void Gfx::opSetWordSpacing(Object args[], int numArgs) { + state->setWordSpace(args[0].getNum()); + out->updateWordSpace(state); +} + +void Gfx::opSetHorizScaling(Object args[], int numArgs) { + state->setHorizScaling(args[0].getNum()); + out->updateHorizScaling(state); + fontChanged = gTrue; +} + +//------------------------------------------------------------------------ +// text positioning operators +//------------------------------------------------------------------------ + +void Gfx::opTextMove(Object args[], int numArgs) { + double tx, ty; + + tx = state->getLineX() + args[0].getNum(); + ty = state->getLineY() + args[1].getNum(); + state->textMoveTo(tx, ty); + out->updateTextPos(state); +} + +void Gfx::opTextMoveSet(Object args[], int numArgs) { + double tx, ty; + + tx = state->getLineX() + args[0].getNum(); + ty = args[1].getNum(); + state->setLeading(-ty); + ty += state->getLineY(); + state->textMoveTo(tx, ty); + out->updateTextPos(state); +} + +void Gfx::opSetTextMatrix(Object args[], int numArgs) { + state->setTextMat(args[0].getNum(), args[1].getNum(), + args[2].getNum(), args[3].getNum(), + args[4].getNum(), args[5].getNum()); + state->textMoveTo(0, 0); + out->updateTextMat(state); + out->updateTextPos(state); + fontChanged = gTrue; +} + +void Gfx::opTextNextLine(Object args[], int numArgs) { + double tx, ty; + + tx = state->getLineX(); + ty = state->getLineY() - state->getLeading(); + state->textMoveTo(tx, ty); + out->updateTextPos(state); +} + +//------------------------------------------------------------------------ +// text string operators +//------------------------------------------------------------------------ + +void Gfx::opShowText(Object args[], int numArgs) { + if (!state->getFont()) { + error(errSyntaxError, getPos(), "No font in show"); + return; + } + if (fontChanged) { + out->updateFont(state); + fontChanged = gFalse; + } + 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(errSyntaxError, getPos(), "No font in move/show"); + return; + } + if (fontChanged) { + out->updateFont(state); + fontChanged = gFalse; + } + tx = state->getLineX(); + ty = state->getLineY() - state->getLeading(); + state->textMoveTo(tx, ty); + out->updateTextPos(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(errSyntaxError, getPos(), "No font in move/set/show"); + return; + } + if (fontChanged) { + out->updateFont(state); + fontChanged = gFalse; + } + state->setWordSpace(args[0].getNum()); + state->setCharSpace(args[1].getNum()); + tx = state->getLineX(); + ty = state->getLineY() - state->getLeading(); + state->textMoveTo(tx, ty); + out->updateWordSpace(state); + out->updateCharSpace(state); + out->updateTextPos(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) { + Array *a; + Object obj; + int wMode; + int i; + + if (!state->getFont()) { + error(errSyntaxError, getPos(), "No font in show/space"); + return; + } + if (fontChanged) { + out->updateFont(state); + fontChanged = gFalse; + } + 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 { + error(errSyntaxError, 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(); + } + } +} + +void Gfx::doShowText(GString *s) { + GfxFont *font; + int wMode; + double riseX, riseY; + CharCode code; + Unicode u[8]; + 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 charProcRef, charProc; + Dict *resDict; + Parser *oldParser; + GfxState *savedState; + char *p; + int render; + GBool patternFill; + int len, n, uLen, nChars, nSpaces, i; + + font = state->getFont(); + wMode = font->getWMode(); + + if (globalParams->isDroppedFont(font->getName() + ? font->getName()->getCString() : "")) { + doIncCharCount(s); + return; + } + + if (out->useDrawChar()) { + 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(); + for (i = 0; i < 6; ++i) { + oldCTM[i] = mat[i]; + } + mat = state->getTextMat(); + newCTM[0] = mat[0] * oldCTM[0] + mat[1] * oldCTM[2]; + newCTM[1] = mat[0] * oldCTM[1] + mat[1] * oldCTM[3]; + newCTM[2] = mat[2] * oldCTM[0] + mat[3] * oldCTM[2]; + newCTM[3] = mat[2] * oldCTM[1] + mat[3] * oldCTM[3]; + mat = font->getFontMatrix(); + newCTM[0] = mat[0] * newCTM[0] + mat[1] * newCTM[2]; + newCTM[1] = mat[0] * newCTM[1] + mat[1] * newCTM[3]; + newCTM[2] = mat[2] * newCTM[0] + mat[3] * newCTM[2]; + newCTM[3] = mat[2] * newCTM[1] + mat[3] * newCTM[3]; + newCTM[0] *= state->getFontSize(); + newCTM[1] *= state->getFontSize(); + newCTM[2] *= state->getFontSize(); + newCTM[3] *= state->getFontSize(); + newCTM[0] *= state->getHorizScaling(); + newCTM[1] *= state->getHorizScaling(); + curX = state->getCurX(); + curY = state->getCurY(); + oldParser = parser; + p = s->getCString(); + len = s->getLength(); + while (len > 0) { + n = font->getNextChar(p, len, &code, + u, (int)(sizeof(u) / sizeof(Unicode)), &uLen, + &dx, &dy, &originX, &originY); + dx = dx * state->getFontSize() + state->getCharSpace(); + if (n == 1 && *p == ' ') { + dx += state->getWordSpace(); + } + dx *= state->getHorizScaling(); + dy *= state->getFontSize(); + state->textTransformDelta(dx, dy, &tdx, &tdy); + state->transform(curX + riseX, curY + riseY, &x, &y); + 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); + state->transformDelta(dx, dy, &ddx, &ddy); +#if 0 + // The PDF spec says: "the graphics state shall be inherited + // from the environment of the text-showing operator that caused + // the [Type 3] glyph description to be invoked". However, + // Acrobat apparently copies the fill color to the stroke color. + // It looks like Ghostscript does the same. (This is only + // relevant for uncached Type 3 glyphs.) Uncomment this block + // to make Xpdf mimic Adobe (in violation of the PDF spec). + state->setStrokeColorSpace(state->getFillColorSpace()->copy()); + out->updateStrokeColorSpace(state); + state->setStrokeColor(state->getFillColor()); + out->updateStrokeColor(state); +#endif + if (!out->beginType3Char(state, curX + riseX, curY + riseY, ddx, ddy, + code, u, uLen)) { + ((Gfx8BitFont *)font)->getCharProcNF(code, &charProcRef); + charProcRef.fetch(xref, &charProc); + if ((resDict = ((Gfx8BitFont *)font)->getResources())) { + pushResources(resDict); + } + if (charProc.isStream()) { + display(&charProcRef, gFalse); + } else { + error(errSyntaxError, getPos(), + "Missing or bad Type3 CharProc entry"); + } + out->endType3Char(state); + if (resDict) { + popResources(); + } + charProc.free(); + charProcRef.free(); + } + restoreStateStack(savedState); + curX += tdx; + curY += tdy; + state->moveTo(curX, curY); + p += n; + len -= n; + } + parser = oldParser; + + } else if (out->useDrawChar()) { + p = s->getCString(); + len = s->getLength(); + while (len > 0) { + n = font->getNextChar(p, len, &code, + u, (int)(sizeof(u) / sizeof(Unicode)), &uLen, + &dx, &dy, &originX, &originY); + if (wMode) { + dx *= state->getFontSize(); + dy = dy * state->getFontSize() + state->getCharSpace(); + if (n == 1 && *p == ' ') { + dy += state->getWordSpace(); + } + } else { + dx = dx * state->getFontSize() + state->getCharSpace(); + if (n == 1 && *p == ' ') { + dx += state->getWordSpace(); + } + dx *= state->getHorizScaling(); + dy *= state->getFontSize(); + } + state->textTransformDelta(dx, dy, &tdx, &tdy); + originX *= state->getFontSize(); + originY *= state->getFontSize(); + state->textTransformDelta(originX, originY, &tOriginX, &tOriginY); + out->drawChar(state, state->getCurX() + riseX, state->getCurY() + riseY, + tdx, tdy, tOriginX, tOriginY, code, n, u, uLen); + state->shift(tdx, tdy); + p += n; + len -= n; + } + + } else { + dx = dy = 0; + p = s->getCString(); + len = s->getLength(); + nChars = nSpaces = 0; + while (len > 0) { + n = font->getNextChar(p, len, &code, + u, (int)(sizeof(u) / sizeof(Unicode)), &uLen, + &dx2, &dy2, &originX, &originY); + dx += dx2; + dy += dy2; + if (n == 1 && *p == ' ') { + ++nSpaces; + } + ++nChars; + p += n; + len -= n; + } + if (wMode) { + dx *= state->getFontSize(); + dy = dy * state->getFontSize() + + nChars * state->getCharSpace() + + nSpaces * state->getWordSpace(); + } else { + dx = dx * state->getFontSize() + + nChars * state->getCharSpace() + + nSpaces * state->getWordSpace(); + dx *= state->getHorizScaling(); + dy *= state->getFontSize(); + } + state->textTransformDelta(dx, dy, &tdx, &tdy); + out->drawString(state, s); + state->shift(tdx, tdy); + } + + if (out->useDrawChar()) { + 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); + } + + opCounter += 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 +//------------------------------------------------------------------------ + +void Gfx::opXObject(Object args[], int numArgs) { + char *name; + Object xObj, refObj, obj2, obj3; + GBool ocSaved, oc; +#if OPI_SUPPORT + Object opiDict; +#endif + + if (!ocState && !out->needCharCount()) { + return; + } + name = args[0].getName(); + // NB: we get both the reference and the object here, to make sure + // they refer to the same object. There's a problematic corner + // case: if the resource dict contains an entry for [name] with a + // reference to a nonexistent object ("/name 99999 0 R", where + // object 99999 doesn't exist), and a parent resource dict contains + // a valid entry with the same name, then lookupXObjectNF() will + // return "99999 0 R", but lookupXObject() will return the valid + // entry. This causes problems for doImage() and doForm(). + if (!res->lookupXObjectNF(name, &refObj)) { + return; + } + if (!refObj.fetch(xref, &xObj)) { + refObj.free(); + return; + } + if (!xObj.isStream()) { + error(errSyntaxError, getPos(), "XObject '{0:s}' is wrong type", name); + xObj.free(); + refObj.free(); + return; + } + + // check for optional content key + ocSaved = ocState; + xObj.streamGetDict()->lookupNF("OC", &obj2); + if (doc->getOptionalContent()->evalOCObject(&obj2, &oc)) { + ocState &= oc; + } + obj2.free(); + +#if USE_EXCEPTIONS + try { +#endif +#if OPI_SUPPORT + xObj.streamGetDict()->lookup("OPI", &opiDict); + if (opiDict.isDict()) { + out->opiBegin(state, opiDict.getDict()); + } +#endif + xObj.streamGetDict()->lookup("Subtype", &obj2); + if (obj2.isName("Image")) { + if (out->needNonText()) { + doImage(&refObj, xObj.getStream(), gFalse); + } + } else if (obj2.isName("Form")) { + if (out->useDrawForm() && refObj.isRef()) { + if (ocState) { + out->drawForm(refObj.getRef()); + } + } else { + doForm(&refObj, &xObj); + } + } else if (obj2.isName("PS")) { + if (ocState) { + xObj.streamGetDict()->lookup("Level1", &obj3); + out->psXObject(xObj.getStream(), + obj3.isStream() ? obj3.getStream() : (Stream *)NULL); + } + } else if (obj2.isName()) { + error(errSyntaxError, getPos(), + "Unknown XObject subtype '{0:s}'", obj2.getName()); + } else { + error(errSyntaxError, getPos(), + "XObject subtype is missing or wrong type"); + } + obj2.free(); +#if OPI_SUPPORT + if (opiDict.isDict()) { + out->opiEnd(state, opiDict.getDict()); + } + opiDict.free(); +#endif +#if USE_EXCEPTIONS + } catch (GMemException e) { + xObj.free(); + refObj.free(); + throw; + } +#endif + + ocState = ocSaved; + + xObj.free(); + refObj.free(); +} + +GBool Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) { + Dict *dict, *maskDict; + int width, height; + int bits, maskBits; + StreamColorSpaceMode csMode; + GBool mask, invert; + GfxColorSpace *colorSpace, *maskColorSpace; + GfxImageColorMap *colorMap, *maskColorMap; + Object maskObj, smaskObj, maskRef; + GBool haveColorKeyMask, haveExplicitMask, haveSoftMask, haveMatte; + int maskColors[2*gfxColorMaxComps]; + int maskWidth, maskHeight; + GBool maskInvert; + Stream *maskStr; + double matte[gfxColorMaxComps]; + GBool interpolate; + GfxRenderingIntent riSaved; + Object obj1, obj2; + int i, n; + + // check for optional content + if (!ocState && !inlineImg) { + return gTrue; + } + + // images can have arbitrarily high compression ratios, but the + // data size is inherently limited + str->disableDecompressionBombChecking(); + + // get info from the stream + bits = 0; + csMode = streamCSNone; + str->getImageParams(&bits, &csMode); + + // get stream dict + dict = str->getDict(); + + // save the current rendering intent + riSaved = state->getRenderingIntent(); + + // get size + dict->lookup("Width", &obj1); + if (obj1.isNull()) { + obj1.free(); + dict->lookup("W", &obj1); + } + 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()) { + goto err2; + } + height = obj1.getInt(); + obj1.free(); + if (height <= 0) { + goto err1; + } + + // image or mask? + dict->lookup("ImageMask", &obj1); + if (obj1.isNull()) { + obj1.free(); + dict->lookup("IM", &obj1); + } + mask = gFalse; + if (obj1.isBool()) + mask = obj1.getBool(); + else if (!obj1.isNull()) + goto err2; + obj1.free(); + + // bit depth + if (bits == 0) { + dict->lookup("BitsPerComponent", &obj1); + if (obj1.isNull()) { + obj1.free(); + dict->lookup("BPC", &obj1); + } + if (obj1.isInt()) { + bits = obj1.getInt(); + if (bits < 1 || bits > 16) { + goto err2; + } + } else if (mask) { + bits = 1; + } else { + goto err2; + } + obj1.free(); + } + + // interpolate flag + dict->lookup("Interpolate", &obj1); + if (obj1.isNull()) { + obj1.free(); + dict->lookup("I", &obj1); + } + interpolate = obj1.isBool() && obj1.getBool(); + obj1.free(); + + // display a mask + if (mask) { + + // check for inverted mask + if (bits != 1) + goto err1; + invert = gFalse; + dict->lookup("Decode", &obj1); + if (obj1.isNull()) { + obj1.free(); + dict->lookup("D", &obj1); + } + if (obj1.isArray()) { + obj1.arrayGet(0, &obj2); + 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->disableDecompressionBombChecking(); + str->reset(); + n = height * ((width + 7) / 8); + for (i = 0; i < n; ++i) { + str->getChar(); + } + str->close(); + + // draw it + } else { + if (state->getFillColorSpace()->getMode() == csPattern) { + doPatternImageMask(ref, str, width, height, invert, inlineImg, + interpolate); + } else { + out->drawImageMask(state, ref, str, width, height, invert, inlineImg, + interpolate); + } + } + + } else { + + // rendering intent + if (dict->lookup("Intent", &obj1)->isName()) { + opSetRenderingIntent(&obj1, 1); + } + obj1.free(); + + // get color space and color map + dict->lookup("ColorSpace", &obj1); + if (obj1.isNull()) { + obj1.free(); + dict->lookup("CS", &obj1); + } + if (obj1.isName()) { + res->lookupColorSpace(obj1.getName(), &obj2); + if (!obj2.isNull()) { + obj1.free(); + obj1 = obj2; + } else { + obj2.free(); + } + } + if (!obj1.isNull()) { + colorSpace = GfxColorSpace::parse(&obj1 + ); + } else if (csMode == streamCSDeviceGray) { + colorSpace = GfxColorSpace::create(csDeviceGray); + } else if (csMode == streamCSDeviceRGB) { + colorSpace = GfxColorSpace::create(csDeviceRGB); + } else if (csMode == streamCSDeviceCMYK) { + colorSpace = GfxColorSpace::create(csDeviceCMYK); + } else { + colorSpace = NULL; + } + obj1.free(); + if (!colorSpace) { + goto err1; + } + if (colorSpace->getMode() == csPattern) { + error(errSyntaxError, getPos(), "Image with a Pattern color space"); + delete colorSpace; + goto err1; + } + dict->lookup("Decode", &obj1); + if (obj1.isNull()) { + obj1.free(); + dict->lookup("D", &obj1); + } + colorMap = new GfxImageColorMap(bits, &obj1, colorSpace); + obj1.free(); + if (!colorMap->isOk()) { + delete colorMap; + goto err1; + } + + // get the mask + haveColorKeyMask = haveExplicitMask = haveSoftMask = haveMatte = gFalse; + maskStr = NULL; // make gcc happy + maskWidth = maskHeight = 0; // make gcc happy + maskInvert = gFalse; // make gcc happy + maskColorMap = NULL; // make gcc happy + dict->lookup("Mask", &maskObj); + dict->lookup("SMask", &smaskObj); + if (smaskObj.isStream()) { + // soft mask + if (inlineImg) { + delete colorMap; + maskObj.free(); + smaskObj.free(); + goto err1; + } + maskStr = smaskObj.getStream(); + maskStr->disableDecompressionBombChecking(); + maskDict = smaskObj.streamGetDict(); + maskDict->lookup("Width", &obj1); + if (obj1.isNull()) { + obj1.free(); + maskDict->lookup("W", &obj1); + } + if (!obj1.isInt()) { + delete colorMap; + maskObj.free(); + smaskObj.free(); + goto err2; + } + maskWidth = obj1.getInt(); + obj1.free(); + maskDict->lookup("Height", &obj1); + if (obj1.isNull()) { + obj1.free(); + maskDict->lookup("H", &obj1); + } + if (!obj1.isInt()) { + delete colorMap; + maskObj.free(); + smaskObj.free(); + goto err2; + } + maskHeight = obj1.getInt(); + obj1.free(); + if (maskWidth <= 0 || maskHeight <= 0) { + delete colorMap; + maskObj.free(); + smaskObj.free(); + goto err1; + } + maskDict->lookup("BitsPerComponent", &obj1); + if (obj1.isNull()) { + obj1.free(); + maskDict->lookup("BPC", &obj1); + } + if (!obj1.isInt()) { + delete colorMap; + maskObj.free(); + smaskObj.free(); + goto err2; + } + maskBits = obj1.getInt(); + obj1.free(); + if (maskBits < 1 || maskBits > 16) { + delete colorMap; + maskObj.free(); + smaskObj.free(); + goto err1; + } + maskDict->lookup("ColorSpace", &obj1); + if (obj1.isNull()) { + obj1.free(); + maskDict->lookup("CS", &obj1); + } + if (obj1.isName()) { + res->lookupColorSpace(obj1.getName(), &obj2); + if (!obj2.isNull()) { + obj1.free(); + obj1 = obj2; + } else { + obj2.free(); + } + } + if (!obj1.isName("DeviceGray")) { + delete colorMap; + maskObj.free(); + smaskObj.free(); + goto err2; + } + maskColorSpace = new GfxDeviceGrayColorSpace(); + obj1.free(); + maskDict->lookup("Decode", &obj1); + if (obj1.isNull()) { + obj1.free(); + maskDict->lookup("D", &obj1); + } + maskColorMap = new GfxImageColorMap(maskBits, &obj1, maskColorSpace); + obj1.free(); + if (!maskColorMap->isOk()) { + delete maskColorMap; + delete colorMap; + maskObj.free(); + smaskObj.free(); + goto err1; + } + if (maskDict->lookup("Matte", &obj1)->isArray()) { + if (obj1.arrayGetLength() == colorSpace->getNComps()) { + for (i = 0; i < obj1.arrayGetLength(); ++i) { + if (obj1.arrayGet(i, &obj2)->isNum()) { + matte[i] = obj2.getNum(); + } else { + error(errSyntaxError, getPos(), + "Invalid Matte entry in soft mask"); + matte[i] = 0; + } + obj2.free(); + } + haveMatte = gTrue; + } else { + error(errSyntaxError, getPos(), "Invalid Matte entry in soft mask"); + } + } + obj1.free(); + haveSoftMask = gTrue; + } else if (maskObj.isArray()) { + // color key mask + haveColorKeyMask = gTrue; + for (i = 0; + 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; + } + } + } else if (maskObj.isStream()) { + // explicit mask + if (inlineImg) { + delete colorMap; + maskObj.free(); + smaskObj.free(); + goto err1; + } + maskStr = maskObj.getStream(); + maskStr->disableDecompressionBombChecking(); + maskDict = maskObj.streamGetDict(); + maskDict->lookup("Width", &obj1); + if (obj1.isNull()) { + obj1.free(); + maskDict->lookup("W", &obj1); + } + if (!obj1.isInt()) { + delete colorMap; + maskObj.free(); + smaskObj.free(); + goto err2; + } + maskWidth = obj1.getInt(); + obj1.free(); + maskDict->lookup("Height", &obj1); + if (obj1.isNull()) { + obj1.free(); + maskDict->lookup("H", &obj1); + } + if (!obj1.isInt()) { + delete colorMap; + maskObj.free(); + smaskObj.free(); + goto err2; + } + maskHeight = obj1.getInt(); + obj1.free(); + if (maskWidth <= 0 || maskHeight <= 0) { + delete colorMap; + maskObj.free(); + smaskObj.free(); + goto err2; + } + maskDict->lookup("ImageMask", &obj1); + if (obj1.isNull()) { + obj1.free(); + maskDict->lookup("IM", &obj1); + } + if (!obj1.isBool() || !obj1.getBool()) { + delete colorMap; + maskObj.free(); + smaskObj.free(); + goto err2; + } + obj1.free(); + maskInvert = gFalse; + maskDict->lookup("Decode", &obj1); + if (obj1.isNull()) { + obj1.free(); + maskDict->lookup("D", &obj1); + } + if (obj1.isArray()) { + obj1.arrayGet(0, &obj2); + maskInvert = obj2.isNum() && obj2.getNum() == 1; + obj2.free(); + } else if (!obj1.isNull()) { + delete colorMap; + maskObj.free(); + smaskObj.free(); + goto err2; + } + obj1.free(); + haveExplicitMask = gTrue; + } + + // if drawing is disabled, skip over inline image data + if (state->getIgnoreColorOps() || !ocState) { + if (state->getIgnoreColorOps()) { + error(errSyntaxWarning, getPos(), "Ignoring image" + " in uncolored Type 3 char or tiling pattern"); + } + if (inlineImg) { + str->disableDecompressionBombChecking(); + str->reset(); + n = height * ((width * colorMap->getNumPixelComps() * + colorMap->getBits() + 7) / 8); + str->discardChars(n); + str->close(); + } + + // draw it + } else { + if (haveSoftMask) { + dict->lookupNF("SMask", &maskRef); + out->drawSoftMaskedImage(state, ref, str, width, height, colorMap, + &maskRef, maskStr, maskWidth, maskHeight, + maskColorMap, + haveMatte ? matte : (double *)NULL, + interpolate); + maskRef.free(); + delete maskColorMap; + } else if (haveExplicitMask) { + dict->lookupNF("Mask", &maskRef); + out->drawMaskedImage(state, ref, str, width, height, colorMap, + &maskRef, maskStr, maskWidth, maskHeight, + maskInvert, interpolate); + maskRef.free(); + } else { + out->drawImage(state, ref, str, width, height, colorMap, + haveColorKeyMask ? maskColors : (int *)NULL, inlineImg, + interpolate); + } + } + + delete colorMap; + maskObj.free(); + smaskObj.free(); + } + + // restore rendering intent + if (state->getRenderingIntent() != riSaved) { + state->setRenderingIntent(riSaved); + out->updateRenderingIntent(state); + } + + if ((i = width * height) > 1000) { + i = 1000; + } + opCounter += i; + + return gTrue; + + err2: + obj1.free(); + err1: + error(errSyntaxError, getPos(), "Bad image parameters"); + + // restore rendering intent + if (state->getRenderingIntent() != riSaved) { + state->setRenderingIntent(riSaved); + out->updateRenderingIntent(state); + } + + return gFalse; +} + +void Gfx::doForm(Object *strRef, Object *str) { + Dict *dict; + GBool transpGroup, isolated, knockout; + Object matrixObj, bboxObj; + double m[6], bbox[4]; + Object resObj; + Dict *resDict; + Object obj1, obj2, obj3; + int i; + + // check for excessive recursion + if (formDepth > 100) { + return; + } + + // check for optional content + if (!ocState && !out->needCharCount()) { + return; + } + + // get stream dict + dict = str->streamGetDict(); + + // check form type + dict->lookup("FormType", &obj1); + if (!(obj1.isNull() || (obj1.isInt() && obj1.getInt() == 1))) { + error(errSyntaxError, getPos(), "Unknown form type"); + } + obj1.free(); + + // get bounding box + dict->lookup("BBox", &bboxObj); + if (!(bboxObj.isArray() && bboxObj.arrayGetLength() == 4)) { + bboxObj.free(); + error(errSyntaxError, getPos(), "Bad form bounding box"); + return; + } + for (i = 0; i < 4; ++i) { + bboxObj.arrayGet(i, &obj1); + if (!obj1.isNum()) { + bboxObj.free(); + error(errSyntaxError, getPos(), "Bad form bounding box"); + return; + } + bbox[i] = obj1.getNum(); + obj1.free(); + } + bboxObj.free(); + + // get matrix + dict->lookup("Matrix", &matrixObj); + if (matrixObj.isArray() && matrixObj.arrayGetLength() == 6) { + for (i = 0; i < 6; ++i) { + matrixObj.arrayGet(i, &obj1); + if (obj1.isNum()) { + m[i] = obj1.getNum(); + } else { + m[i] = 0; + } + obj1.free(); + } + } else { + m[0] = 1; m[1] = 0; + m[2] = 0; m[3] = 1; + m[4] = 0; m[5] = 0; + } + matrixObj.free(); + + // get resources + dict->lookup("Resources", &resObj); + resDict = resObj.isDict() ? resObj.getDict() : (Dict *)NULL; + + // check for a transparency group + transpGroup = isolated = knockout = gFalse; + if (dict->lookup("Group", &obj1)->isDict()) { + if (obj1.dictLookup("S", &obj2)->isName("Transparency")) { + transpGroup = gTrue; + if (obj1.dictLookup("I", &obj3)->isBool()) { + isolated = obj3.getBool(); + } + obj3.free(); + if (obj1.dictLookup("K", &obj3)->isBool()) { + knockout = obj3.getBool(); + } + obj3.free(); + } + obj2.free(); + } + obj1.free(); + + // draw it + ++formDepth; + drawForm(strRef, resDict, m, bbox, transpGroup, gFalse, isolated, knockout); + --formDepth; + + resObj.free(); +} + +void Gfx::drawForm(Object *strRef, Dict *resDict, + double *matrix, double *bbox, + GBool transpGroup, GBool softMask, + GBool isolated, GBool knockout, + GBool alpha, Function *transferFunc, + Object *backdropColorObj) { + Parser *oldParser; + GfxState *savedState; + GfxColorSpace *blendingColorSpace; + GfxColor backdropColor; + Object strObj, groupAttrsObj, csObj, obj1; + double oldBaseMatrix[6]; + int i; + + // push new resources on stack + pushResources(resDict); + + // save current graphics state + saveState(); + + // kill any pre-existing path + state->clearPath(); + + // save current parser + oldParser = parser; + + // set form transformation matrix + state->concatCTM(matrix[0], matrix[1], matrix[2], + matrix[3], matrix[4], matrix[5]); + out->updateCTM(state, matrix[0], matrix[1], matrix[2], + matrix[3], matrix[4], matrix[5]); + + // set form bounding box + state->moveTo(bbox[0], bbox[1]); + state->lineTo(bbox[2], bbox[1]); + state->lineTo(bbox[2], bbox[3]); + state->lineTo(bbox[0], bbox[3]); + state->closePath(); + state->clip(); + out->clip(state); + state->clearPath(); + + blendingColorSpace = NULL; + if (softMask || transpGroup) { + // get the blending color space + // NB: this must be done AFTER pushing the resource dictionary, + // so that any Default*** color spaces are available + strRef->fetch(xref, &strObj); + if (strObj.streamGetDict()->lookup("Group", &groupAttrsObj)->isDict()) { + if (!groupAttrsObj.dictLookup("CS", &csObj)->isNull()) { + blendingColorSpace = GfxColorSpace::parse(&csObj + ); + } + csObj.free(); + } + groupAttrsObj.free(); + strObj.free(); + + if (!out->beginTransparencyGroup(state, bbox, blendingColorSpace, + isolated, knockout, softMask)) { + transpGroup = gFalse; + } + + if (softMask || transpGroup) { + traceBegin(oldBaseMatrix, softMask ? "begin soft mask" : "begin t-group"); + if (state->getBlendMode() != gfxBlendNormal) { + state->setBlendMode(gfxBlendNormal); + out->updateBlendMode(state); + } + if (state->getFillOpacity() != 1) { + state->setFillOpacity(1); + out->updateFillOpacity(state); + } + if (state->getStrokeOpacity() != 1) { + state->setStrokeOpacity(1); + out->updateStrokeOpacity(state); + } + out->clearSoftMask(state); + } + } + + // set new base matrix + for (i = 0; i < 6; ++i) { + oldBaseMatrix[i] = baseMatrix[i]; + baseMatrix[i] = state->getCTM()[i]; + } + + // save the state stack -- this handles the case where the form + // contents have unbalanced q/Q operators + savedState = saveStateStack(); + + // draw the form + display(strRef, gFalse); + + restoreStateStack(savedState); + + if (softMask || transpGroup) { + out->endTransparencyGroup(state); + } + + // restore base matrix + for (i = 0; i < 6; ++i) { + baseMatrix[i] = oldBaseMatrix[i]; + } + + // restore parser + parser = oldParser; + + // restore graphics state + restoreState(); + + // pop resource stack + popResources(); + + if (softMask) { + for (i = 0; i < gfxColorMaxComps; ++i) { + backdropColor.c[i] = 0; + } + if (backdropColorObj->isArray()) { + for (i = 0; + i < backdropColorObj->arrayGetLength() && i < gfxColorMaxComps; + ++i) { + backdropColorObj->arrayGet(i, &obj1); + if (obj1.isNum()) { + backdropColor.c[i] = dblToCol(obj1.getNum()); + } + obj1.free(); + } + } else if (blendingColorSpace) { + blendingColorSpace->getDefaultColor(&backdropColor); + } + //~ else: need to get the parent or default color space (?) + out->setSoftMask(state, bbox, alpha, transferFunc, &backdropColor); + traceEnd(oldBaseMatrix, "end soft mask"); + } else if (transpGroup) { + out->paintTransparencyGroup(state, bbox); + traceEnd(oldBaseMatrix, "end t-group"); + } + + if (blendingColorSpace) { + delete blendingColorSpace; + } + + return; +} + +void Gfx::takeContentStreamStack(Gfx *oldGfx) { + contentStreamStack->append(oldGfx->contentStreamStack); +} + +void Gfx::endOfPage() { + while (state->hasSaves()) { + restoreState(); + } + while (markedContentStack->getLength() > 0) { + opEndMarkedContent(NULL, 0); + } +} + +//------------------------------------------------------------------------ +// in-line image operators +//------------------------------------------------------------------------ + +void Gfx::opBeginImage(Object args[], int numArgs) { + Stream *str; + GBool haveLength; + int c1, c2, c3; + + // 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(&haveLength); + + // display the image + if (str) { + if (!doImage(NULL, str, gTrue)) { + delete str; + + // if we have the stream length, skip to end-of-stream and then + // skip 'EI' in the original stream + } else if (haveLength) { + while ((c1 = str->getChar()) != EOF) ; + delete str; + str = parser->getStream(); + c1 = str->getChar(); + c2 = str->getChar(); + c3 = str->lookChar(); + while (!(c1 == 'E' && c2 == 'I' && Lexer::isSpace(c3)) && c3 != EOF) { + c1 = c2; + c2 = str->getChar(); + c3 = str->lookChar(); + } + + // else, look for the 'EI' tag and skip it + } else { + c1 = str->getUndecodedStream()->getChar(); + c2 = str->getUndecodedStream()->getChar(); + c3 = str->getUndecodedStream()->lookChar(); + while (!(c1 == 'E' && c2 == 'I' && Lexer::isSpace(c3)) && c3 != EOF) { + c1 = c2; + c2 = str->getUndecodedStream()->getChar(); + c3 = str->getUndecodedStream()->lookChar(); + } + delete str; + } + } +} + +Stream *Gfx::buildImageStream(GBool *haveLength) { + Object dict; + Object obj, lengthObj; + char *key; + int length; + Stream *str; + + // build dictionary + dict.initDict(xref); + getContentObj(&obj); + while (!obj.isCmd("ID") && !obj.isEOF()) { + if (!obj.isName()) { + error(errSyntaxError, getPos(), + "Inline image dictionary key must be a name object"); + obj.free(); + } else { + key = copyString(obj.getName()); + obj.free(); + getContentObj(&obj); + if (obj.isEOF()) { + gfree(key); + break; + } + if (obj.isError()) { + gfree(key); + obj.free(); + } else { + dict.dictAdd(key, &obj); + } + } + getContentObj(&obj); + } + if (obj.isEOF()) { + error(errSyntaxError, getPos(), "End of file in inline image"); + obj.free(); + dict.free(); + return NULL; + } + obj.free(); + + // check for length field + length = 0; + *haveLength = gFalse; + if (!dict.dictLookup("Length", &lengthObj)->isInt()) { + lengthObj.free(); + dict.dictLookup("L", &lengthObj); + } + if (lengthObj.isInt()) { + length = lengthObj.getInt(); + *haveLength = gTrue; + } + lengthObj.free(); + + // make stream + if (!(str = parser->getStream())) { + error(errSyntaxError, getPos(), "Invalid inline image data"); + dict.free(); + return NULL; + } + str = new EmbedStream(str, &dict, *haveLength, (GFileOffset)length); + str = str->addFilters(&dict); + + return str; +} + +void Gfx::opImageData(Object args[], int numArgs) { + error(errInternal, getPos(), "Got 'ID' operator"); +} + +void Gfx::opEndImage(Object args[], int numArgs) { + error(errInternal, getPos(), "Got 'EI' operator"); +} + +//------------------------------------------------------------------------ +// type 3 font operators +//------------------------------------------------------------------------ + +void Gfx::opSetCharWidth(Object args[], int numArgs) { + out->type3D0(state, args[0].getNum(), args[1].getNum()); +} + +void Gfx::opSetCacheDevice(Object args[], int numArgs) { + state->setIgnoreColorOps(gTrue); + out->type3D1(state, args[0].getNum(), args[1].getNum(), + args[2].getNum(), args[3].getNum(), + args[4].getNum(), args[5].getNum()); +} + +//------------------------------------------------------------------------ +// compatibility operators +//------------------------------------------------------------------------ + +void Gfx::opBeginIgnoreUndef(Object args[], int numArgs) { + ++ignoreUndef; +} + +void Gfx::opEndIgnoreUndef(Object args[], int numArgs) { + if (ignoreUndef > 0) + --ignoreUndef; +} + +//------------------------------------------------------------------------ +// marked content operators +//------------------------------------------------------------------------ + +void Gfx::opBeginMarkedContent(Object args[], int numArgs) { + GfxMarkedContent *mc; + Object obj; + GBool ocStateNew; + TextString *s; + GfxMarkedContentKind mcKind; + + if (printCommands) { + printf(" marked content: %s ", args[0].getName()); + 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 = new TextString(obj.getString()); + out->beginActualText(state, s->getUnicode(), s->getLength()); + delete s; + 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[1].print(stdout); + printf("\n"); + fflush(stdout); + } +} + +//------------------------------------------------------------------------ +// misc +//------------------------------------------------------------------------ + +void Gfx::drawAnnot(Object *strRef, AnnotBorderStyle *borderStyle, + double xMin, double yMin, double xMax, double yMax) { + Dict *dict, *resDict; + Object str, matrixObj, bboxObj, resObj, obj1; + double formXMin, formYMin, formXMax, formYMax; + double x, y, sx, sy, tx, ty; + double m[6], bbox[4]; + double *borderColor; + GfxColor color; + double *dash, *dash2; + int dashLength; + int i; + + // this function assumes that we are in the default user space, + // i.e., baseMatrix = ctm + + // 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) + strRef->fetch(xref, &str); + if (str.isStream()) { + + // get stream dict + dict = str.streamGetDict(); + + // get the form bounding box + dict->lookup("BBox", &bboxObj); + if (!bboxObj.isArray() || bboxObj.arrayGetLength() != 4) { + error(errSyntaxError, getPos(), "Bad form bounding box"); + bboxObj.free(); + str.free(); + return; + } + for (i = 0; i < 4; ++i) { + bboxObj.arrayGet(i, &obj1); + if (obj1.isNum()) { + bbox[i] = obj1.getNum(); + } else { + bbox[i] = 0; + } + obj1.free(); + } + bboxObj.free(); + + // get the form matrix + dict->lookup("Matrix", &matrixObj); + if (matrixObj.isArray()) { + for (i = 0; i < 6; ++i) { + matrixObj.arrayGet(i, &obj1); + m[i] = obj1.getNum(); + obj1.free(); + } + } else { + m[0] = 1; m[1] = 0; + m[2] = 0; m[3] = 1; + m[4] = 0; m[5] = 0; + } + matrixObj.free(); + + // 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 (y < formYMin) { + formYMin = y; + } else if (y > formYMax) { + formYMax = y; + } + + // 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 = (xMax - xMin) / (formXMax - formXMin); + } + if (formYMin == formYMax) { + // this shouldn't happen + sy = 1; + } else { + 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[1] *= sy; + m[2] *= sx; + m[3] *= sy; + m[4] = m[4] * sx + tx; + m[5] = m[5] * sy + ty; + + // get the resources + dict->lookup("Resources", &resObj); + resDict = resObj.isDict() ? resObj.getDict() : (Dict *)NULL; + + // draw it + drawForm(strRef, resDict, m, bbox); + + resObj.free(); + } + str.free(); + + // draw the border + if (borderStyle && borderStyle->getWidth() > 0 && + borderStyle->getNumColorComps() > 0) { + borderColor = borderStyle->getColor(); + switch (borderStyle->getNumColorComps()) { + case 1: + if (state->getStrokeColorSpace()->getMode() != csDeviceGray) { + state->setStrokePattern(NULL); + state->setStrokeColorSpace(GfxColorSpace::create(csDeviceGray)); + out->updateStrokeColorSpace(state); + } + break; + case 3: + if (state->getStrokeColorSpace()->getMode() != csDeviceRGB) { + state->setStrokePattern(NULL); + state->setStrokeColorSpace(GfxColorSpace::create(csDeviceRGB)); + out->updateStrokeColorSpace(state); + } + break; + case 4: + if (state->getStrokeColorSpace()->getMode() != csDeviceCMYK) { + state->setStrokePattern(NULL); + state->setStrokeColorSpace(GfxColorSpace::create(csDeviceCMYK)); + out->updateStrokeColorSpace(state); + } + break; + } + color.c[0] = dblToCol(borderColor[0]); + color.c[1] = dblToCol(borderColor[1]); + color.c[2] = dblToCol(borderColor[2]); + color.c[3] = dblToCol(borderColor[3]); + state->setStrokeColor(&color); + out->updateStrokeColor(state); + state->setLineWidth(borderStyle->getWidth()); + out->updateLineWidth(state); + borderStyle->getDash(&dash, &dashLength); + if (borderStyle->getType() == annotBorderDashed && dashLength > 0) { + dash2 = (double *)gmallocn(dashLength, sizeof(double)); + 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(xMin, yMin); + state->lineTo(xMax, yMin); + if (borderStyle->getType() != annotBorderUnderlined) { + state->lineTo(xMax, yMax); + state->lineTo(xMin, yMax); + state->closePath(); + } + out->stroke(state); + } +} + +void Gfx::saveState() { + out->saveState(state); + state = state->save(); +} + +void Gfx::restoreState() { + state = state->restore(); + 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); +} + +void Gfx::popResources() { + GfxResources *resPtr; + + resPtr = res->getNext(); + delete res; + res = resPtr; +} diff --git a/xpdf/Gfx.h b/xpdf/Gfx.h new file mode 100644 index 0000000..14d7a60 --- /dev/null +++ b/xpdf/Gfx.h @@ -0,0 +1,363 @@ +//======================================================================== +// +// Gfx.h +// +// Copyright 1996-2016 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef GFX_H +#define GFX_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "gtypes.h" +#include "gfile.h" +#include "GfxState.h" + +class GString; +class GList; +class PDFDoc; +class XRef; +class Array; +class Stream; +class Parser; +class Dict; +class Function; +class OutputDev; +class GfxFontDict; +class GfxFont; +class Gfx; +class PDFRectangle; +class AnnotBorderStyle; + +//------------------------------------------------------------------------ + +enum GfxClipType { + clipNone, + clipNormal, + clipEO +}; + +enum TchkType { + tchkBool, // boolean + tchkInt, // integer + tchkNum, // number (integer or real) + tchkString, // string + tchkName, // name + tchkArray, // array + tchkProps, // properties (dictionary or name) + tchkSCN, // scn/SCN args (number of name) + tchkNone // used to avoid empty initializer lists +}; + +#define maxArgs 33 + +struct Operator { + char name[4]; + int numArgs; + TchkType tchk[maxArgs]; + void (Gfx::*func)(Object args[], int numArgs); +}; + +//------------------------------------------------------------------------ + +class GfxResources { +public: + + GfxResources(XRef *xref, Dict *resDict, GfxResources *nextA); + ~GfxResources(); + + GfxFont *lookupFont(char *name); + GfxFont *lookupFontByRef(Ref ref); + GBool lookupXObject(const char *name, Object *obj); + GBool lookupXObjectNF(const char *name, Object *obj); + void lookupColorSpace(const char *name, Object *obj, GBool inherit = gTrue); + GfxPattern *lookupPattern(const char *name + ); + GfxShading *lookupShading(const char *name + ); + GBool lookupGState(const char *name, Object *obj); + GBool lookupPropertiesNF(const char *name, Object *obj); + + GfxResources *getNext() { return next; } + +private: + + GBool valid; + GfxFontDict *fonts; + Object xObjDict; + Object colorSpaceDict; + 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 +//------------------------------------------------------------------------ + +class Gfx { +public: + + // Constructor for regular output. + 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(PDFDoc *docA, OutputDev *outA, Dict *resDict, + PDFRectangle *box, PDFRectangle *cropBox, + GBool (*abortCheckCbkA)(void *data) = NULL, + void *abortCheckCbkDataA = NULL); + + ~Gfx(); + + // Interpret a stream or array of streams. should be a + // reference wherever possible (for loop-checking). + void display(Object *objRef, GBool topLevel = gTrue); + + // Display an annotation, given its appearance (a Form XObject), + // border style, and bounding box (in default user space). + void drawAnnot(Object *strRef, AnnotBorderStyle *borderStyle, + double xMin, double yMin, double xMax, double yMax); + + // Save graphics state. + void saveState(); + + // Restore graphics state. + void restoreState(); + + // Get the current graphics state object. + GfxState *getState() { return state; } + + void drawForm(Object *strRef, Dict *resDict, double *matrix, double *bbox, + GBool transpGroup = gFalse, GBool softMask = gFalse, + GBool isolated = gFalse, GBool knockout = gFalse, + GBool alpha = gFalse, Function *transferFunc = NULL, + Object *backdropColorObj = NULL); + + // Take all of the content stream stack entries from . This + // is useful when creating a new Gfx object to handle a pattern, + // etc., where it's useful to check for loops that span both Gfx + // objects. This function should be called immediately after the + // Gfx constructor, i.e., before processing any content streams with + // the new Gfx object. + void takeContentStreamStack(Gfx *oldGfx); + + // Clear the state stack and the marked content stack. + void endOfPage(); + +private: + + PDFDoc *doc; + XRef *xref; // the xref table for this PDF file + OutputDev *out; // output device + GBool subPage; // is this a sub-page object? + GBool printCommands; // print the drawing commands (for debugging) + GfxResources *res; // resource stack + GfxFont *defaultFont; // font substituted for undefined fonts + int opCounter; // operation counter (used to decide when + // to check for an abort) + + GfxState *state; // current graphics state + GBool fontChanged; // set if font or text matrix has changed + GfxClipType clip; // do a clip? + int ignoreUndef; // current BX/EX nesting level + double baseMatrix[6]; // default matrix for most recent + // page/form/pattern + int formDepth; + 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) + GList *contentStreamStack; // stack of open content streams, used + // for loop-checking + + GBool // callback to check for an abort + (*abortCheckCbk)(void *data); + void *abortCheckCbkData; + + static Operator opTab[]; // table of operators + + GBool checkForContentStreamLoop(Object *ref); + void go(GBool topLevel); + void getContentObj(Object *obj); + GBool execOp(Object *cmd, Object args[], int numArgs); + Operator *findOp(char *name); + GBool checkArg(Object *arg, TchkType type); + GFileOffset getPos(); + + // graphics state operators + void opSave(Object args[], int numArgs); + void opRestore(Object args[], int numArgs); + void opConcat(Object args[], int numArgs); + void opSetDash(Object args[], int numArgs); + void opSetFlat(Object args[], int numArgs); + void opSetLineJoin(Object args[], int numArgs); + void opSetLineCap(Object args[], int numArgs); + void opSetMiterLimit(Object args[], int numArgs); + void opSetLineWidth(Object args[], int numArgs); + void opSetExtGState(Object args[], int numArgs); + void doSoftMask(Object *str, Object *strRef, GBool alpha, + GBool isolated, GBool knockout, + Function *transferFunc, Object *backdropColorObj); + void opSetRenderingIntent(Object args[], int numArgs); + GfxRenderingIntent parseRenderingIntent(const char *name); + + // color operators + void opSetFillGray(Object args[], int numArgs); + void opSetStrokeGray(Object args[], int numArgs); + void opSetFillCMYKColor(Object args[], int numArgs); + void opSetStrokeCMYKColor(Object args[], int numArgs); + void opSetFillRGBColor(Object args[], int numArgs); + void opSetStrokeRGBColor(Object args[], int numArgs); + void opSetFillColorSpace(Object args[], int numArgs); + void opSetStrokeColorSpace(Object args[], int numArgs); + void opSetFillColor(Object args[], int numArgs); + void opSetStrokeColor(Object args[], int numArgs); + void opSetFillColorN(Object args[], int numArgs); + void opSetStrokeColorN(Object args[], int numArgs); + + // path segment operators + void opMoveTo(Object args[], int numArgs); + void opLineTo(Object args[], int numArgs); + void opCurveTo(Object args[], int numArgs); + void opCurveTo1(Object args[], int numArgs); + void opCurveTo2(Object args[], int numArgs); + void opRectangle(Object args[], int numArgs); + void opClosePath(Object args[], int numArgs); + + // path painting operators + void opEndPath(Object args[], int numArgs); + void opStroke(Object args[], int numArgs); + void opCloseStroke(Object args[], int numArgs); + void opFill(Object args[], int numArgs); + void opEOFill(Object args[], int numArgs); + void opFillStroke(Object args[], int numArgs); + void opCloseFillStroke(Object args[], int numArgs); + void opEOFillStroke(Object args[], int numArgs); + 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, GBool interpolate); + void doTilingPatternFill(GfxTilingPattern *tPat, + GBool stroke, GBool eoFill, GBool text); + void doShadingPatternFill(GfxShadingPattern *sPat, + GBool stroke, GBool eoFill, GBool text); + void opShFill(Object args[], int numArgs); + void doShFill(GfxShading *shading); + void doFunctionShFill(GfxFunctionShading *shading); + void doFunctionShFill1(GfxFunctionShading *shading, + double x0, double y0, + double x1, double y1, + GfxColor *colors, int depth); + void doAxialShFill(GfxAxialShading *shading); + void doRadialShFill(GfxRadialShading *shading); + void doGouraudTriangleShFill(GfxGouraudTriangleShading *shading); + void gouraudFillTriangle(double x0, double y0, double *color0, + double x1, double y1, double *color1, + double x2, double y2, double *color2, + GfxGouraudTriangleShading *shading, int depth); + void doPatchMeshShFill(GfxPatchMeshShading *shading); + void fillPatch(GfxPatch *patch, GfxPatchMeshShading *shading, int depth); + void doEndPath(); + + // path clipping operators + void opClip(Object args[], int numArgs); + void opEOClip(Object args[], int numArgs); + + // text object operators + void opBeginText(Object args[], int numArgs); + void opEndText(Object args[], int numArgs); + + // text state operators + void opSetCharSpacing(Object args[], int numArgs); + void opSetFont(Object args[], int numArgs); + void doSetFont(GfxFont *font, double size); + void opSetTextLeading(Object args[], int numArgs); + void opSetTextRender(Object args[], int numArgs); + void opSetTextRise(Object args[], int numArgs); + void opSetWordSpacing(Object args[], int numArgs); + void opSetHorizScaling(Object args[], int numArgs); + + // text positioning operators + void opTextMove(Object args[], int numArgs); + void opTextMoveSet(Object args[], int numArgs); + void opSetTextMatrix(Object args[], int numArgs); + void opTextNextLine(Object args[], int numArgs); + + // text string operators + void opShowText(Object args[], int numArgs); + void opMoveShowText(Object args[], int numArgs); + 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); + GBool doImage(Object *ref, Stream *str, GBool inlineImg); + void doForm(Object *strRef, Object *str); + + // in-line image operators + void opBeginImage(Object args[], int numArgs); + Stream *buildImageStream(GBool *haveLength); + void opImageData(Object args[], int numArgs); + void opEndImage(Object args[], int numArgs); + + // type 3 font operators + void opSetCharWidth(Object args[], int numArgs); + void opSetCacheDevice(Object args[], int numArgs); + + // compatibility operators + void opBeginIgnoreUndef(Object args[], int numArgs); + void opEndIgnoreUndef(Object args[], int numArgs); + + // marked content operators + void opBeginMarkedContent(Object args[], int numArgs); + void opEndMarkedContent(Object args[], int numArgs); + void opMarkPoint(Object args[], int numArgs); + + GfxState *saveStateStack(); + void restoreStateStack(GfxState *oldState); + void pushResources(Dict *resDict); + void popResources(); +}; + +#endif diff --git a/xpdf/GfxFont.cc b/xpdf/GfxFont.cc new file mode 100644 index 0000000..30e8bd1 --- /dev/null +++ b/xpdf/GfxFont.cc @@ -0,0 +1,2415 @@ +//======================================================================== +// +// GfxFont.cc +// +// Copyright 1996-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include +#include +#include +#include +#include +#include "gmem.h" +#include "gmempp.h" +#include "GList.h" +#include "GHash.h" +#include "Error.h" +#include "Object.h" +#include "Dict.h" +#include "GlobalParams.h" +#include "CMap.h" +#include "CharCodeToUnicode.h" +#include "FontEncodingTables.h" +#include "BuiltinFontTables.h" +#include "FoFiIdentifier.h" +#include "FoFiType1.h" +#include "FoFiType1C.h" +#include "FoFiTrueType.h" +#include "GfxFont.h" + +//------------------------------------------------------------------------ + +struct Base14FontMapEntry { + const char *altName; + const char *base14Name; +}; + +static Base14FontMapEntry base14FontMap[] = { + { "Arial", "Helvetica" }, + { "Arial,Bold", "Helvetica-Bold" }, + { "Arial,BoldItalic", "Helvetica-BoldOblique" }, + { "Arial,Italic", "Helvetica-Oblique" }, + { "Arial-Bold", "Helvetica-Bold" }, + { "Arial-BoldItalic", "Helvetica-BoldOblique" }, + { "Arial-BoldItalicMT", "Helvetica-BoldOblique" }, + { "Arial-BoldMT", "Helvetica-Bold" }, + { "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" }, + { "CourierNew,Italic", "Courier-Oblique" }, + { "CourierNew-Bold", "Courier-Bold" }, + { "CourierNew-BoldItalic", "Courier-BoldOblique" }, + { "CourierNew-Italic", "Courier-Oblique" }, + { "CourierNewPS-BoldItalicMT", "Courier-BoldOblique" }, + { "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" }, + { "TimesNewRoman,Italic", "Times-Italic" }, + { "TimesNewRoman-Bold", "Times-Bold" }, + { "TimesNewRoman-BoldItalic", "Times-BoldItalic" }, + { "TimesNewRoman-Italic", "Times-Italic" }, + { "TimesNewRomanPS", "Times-Roman" }, + { "TimesNewRomanPS-Bold", "Times-Bold" }, + { "TimesNewRomanPS-BoldItalic", "Times-BoldItalic" }, + { "TimesNewRomanPS-BoldItalicMT", "Times-BoldItalic" }, + { "TimesNewRomanPS-BoldMT", "Times-Bold" }, + { "TimesNewRomanPS-Italic", "Times-Italic" }, + { "TimesNewRomanPS-ItalicMT", "Times-Italic" }, + { "TimesNewRomanPSMT", "Times-Roman" }, + { "TimesNewRomanPSMT,Bold", "Times-Bold" }, + { "TimesNewRomanPSMT,BoldItalic", "Times-BoldItalic" }, + { "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; + oblique = 0; + encoding = NULL; + substIdx = -1; +} + +GfxFontLoc::~GfxFontLoc() { + if (path) { + delete path; + } + if (encoding) { + delete encoding; + } +} + +//------------------------------------------------------------------------ +// GfxFont +//------------------------------------------------------------------------ + +GfxFont *GfxFont::makeFont(XRef *xref, const char *tagA, + Ref idA, Dict *fontDict) { + GString *nameA; + Ref embFontIDA; + GfxFontType typeA; + GfxFont *font; + Object obj1; + + // get base font name + nameA = NULL; + fontDict->lookup("BaseFont", &obj1); + if (obj1.isName()) { + nameA = new GString(obj1.getName()); + } else if (obj1.isString()) { + nameA = obj1.getString()->copy(); + } + obj1.free(); + + // get embedded font ID and font type + typeA = getFontType(xref, fontDict, &embFontIDA); + + // create the font object + font = NULL; + if (typeA < fontCIDType0) { + font = new Gfx8BitFont(xref, tagA, idA, nameA, typeA, embFontIDA, + fontDict); + } else { + font = new GfxCIDFont(xref, tagA, idA, nameA, typeA, embFontIDA, + fontDict); + } + + return font; +} + +GfxFont *GfxFont::makeDefaultFont(XRef *xref) { + Object type, subtype, baseFont; + type.initName("Font"); + subtype.initName("Type1"); + baseFont.initName("Helvetica"); + Object fontDict; + fontDict.initDict(xref); + fontDict.dictAdd(copyString("Type"), &type); + fontDict.dictAdd(copyString("Subtype"), &subtype); + fontDict.dictAdd(copyString("BaseFont"), &baseFont); + + Ref r; + r.gen = 100000; + r.num = GfxFontDict::hashFontObject(&fontDict); + + GfxFont *font = makeFont(xref, "undef", r, fontDict.getDict()); + fontDict.free(); + + return font; +} + +GfxFont::GfxFont(const char *tagA, Ref idA, GString *nameA, + GfxFontType typeA, Ref embFontIDA) { + ok = gFalse; + tag = new GString(tagA); + id = idA; + name = nameA; + type = typeA; + embFontID = embFontIDA; + embFontName = NULL; + hasToUnicode = gFalse; +} + +GfxFont::~GfxFont() { + delete tag; + if (name) { + delete name; + } + if (embFontName) { + delete embFontName; + } +} + +// 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) { + Object obj1, obj2, obj3, obj4; + double t, t2; + int i; + + // assume Times-Roman by default (for substitution purposes) + flags = fontSerif; + + if (fontDict->lookup("FontDescriptor", &obj1)->isDict()) { + + // get flags + if (obj1.dictLookup("Flags", &obj2)->isInt()) { + flags = obj2.getInt(); + } + obj2.free(); + + // get name + obj1.dictLookup("FontName", &obj2); + if (obj2.isName()) { + embFontName = new GString(obj2.getName()); + } + obj2.free(); + + // look for MissingWidth + obj1.dictLookup("MissingWidth", &obj2); + if (obj2.isNum()) { + missingWidth = obj2.getNum(); + } + obj2.free(); + + // get Ascent + // (CapHeight is a little more reliable - so use it if present) + obj1.dictLookup("Ascent", &obj2); + obj1.dictLookup("CapHeight", &obj3); + if (obj2.isNum() || obj3.isNum()) { + if (obj2.isNum()) { + t = 0.001 * obj2.getNum(); + // some broken font descriptors specify a negative ascent + if (t < 0) { + t = -t; + } + } else { + t = 0; + } + if (obj3.isNum()) { + t2 = 0.001 * obj3.getNum(); + // some broken font descriptors specify a negative ascent + if (t2 < 0) { + t2 = -t2; + } + } else { + t2 = 0; + } + if (t != 0 && t < 1.9) { + declaredAscent = t; + } + // if both Ascent and CapHeight are set, use the smaller one + // (because the most common problem is that Ascent is too large) + if (t2 != 0 && (t == 0 || t2 < t)) { + t = t2; + } + // some broken font descriptors set ascent and descent to 0; + // others set it to ridiculous values (e.g., 32768) + if (t != 0 && t < 1.9) { + ascent = t; + } + } + obj2.free(); + obj3.free(); + + // get Descent + 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 && t > -1.9) { + descent = t; + } + } + obj2.free(); + + // font FontBBox + if (obj1.dictLookup("FontBBox", &obj2)->isArray()) { + for (i = 0; i < 4 && i < obj2.arrayGetLength(); ++i) { + if (obj2.arrayGet(i, &obj3)->isNum()) { + fontBBox[i] = 0.001 * obj3.getNum(); + } + obj3.free(); + } + } + obj2.free(); + + } + obj1.free(); +} + +CharCodeToUnicode *GfxFont::readToUnicodeCMap(Dict *fontDict, int nBits, + CharCodeToUnicode *ctu) { + GString *buf; + Object obj1; + char buf2[4096]; + int n; + + if (!fontDict->lookup("ToUnicode", &obj1)->isStream()) { + obj1.free(); + return NULL; + } + buf = new GString(); + obj1.streamReset(); + while ((n = obj1.streamGetBlock(buf2, sizeof(buf2))) > 0) { + buf->append(buf2, n); + } + obj1.streamClose(); + obj1.free(); + if (ctu) { + ctu->mergeCMap(buf, nBits); + } else { + ctu = CharCodeToUnicode::parseCMap(buf, nBits); + } + delete buf; + hasToUnicode = gTrue; + return ctu; +} + +GfxFontLoc *GfxFont::locateFont(XRef *xref, GBool ps) { + GfxFontLoc *fontLoc; + SysFontType sysFontType; + FoFiIdentifierType fft; + GString *path, *base14Name, *substName; + PSFontParam16 *psFont16; + Object refObj, embFontObj; + int substIdx, fontNum; + double oblique; + GBool embed; + + 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 && name && !isCIDFont() && globalParams->getPSFontPassthrough()) { + fontLoc = new GfxFontLoc(); + fontLoc->locType = gfxFontLocResident; + fontLoc->fontType = fontType1; + fontLoc->path = name->copy(); + return fontLoc; + } + + //----- external font file (fontFile, fontDir) + if (name && (path = globalParams->findFontFile(name))) { + if ((fontLoc = getExternalFont(path, 0, 0, isCIDFont()))) { + return fontLoc; + } + } + + //----- PS resident Base-14 font + if (ps && !isCIDFont() && ((Gfx8BitFont *)this)->base14) { + fontLoc = new GfxFontLoc(); + fontLoc->locType = gfxFontLocResident; + fontLoc->fontType = fontType1; + fontLoc->path = new GString(((Gfx8BitFont *)this)->base14->base14Name); + return fontLoc; + } + + //----- external font file for Base-14 font + if (!ps && !isCIDFont() && ((Gfx8BitFont *)this)->base14) { + base14Name = new GString(((Gfx8BitFont *)this)->base14->base14Name); + path = globalParams->findBase14FontFile(base14Name, &fontNum, &oblique); + delete base14Name; + if (path && (fontLoc = getExternalFont(path, fontNum, oblique, gFalse))) { + return fontLoc; + } + } + + //----- system font + if (name && (path = globalParams->findSystemFontFile(name, &sysFontType, + &fontNum))) { + fontLoc = new GfxFontLoc(); + fontLoc->locType = gfxFontLocExternal; + fontLoc->path = path; + fontLoc->fontNum = fontNum; + if (isCIDFont()) { + if (sysFontType == sysFontTTF || sysFontType == sysFontTTC) { + fontLoc->fontType = fontCIDType2; + return fontLoc; + } else if (sysFontType == sysFontOTF) { + fft = FoFiIdentifier::identifyFile(fontLoc->path->getCString()); + if (fft == fofiIdOpenTypeCFFCID) { + fontLoc->fontType = fontCIDType0COT; + return fontLoc; + } else if (fft == fofiIdTrueType) { + fontLoc->fontType = fontCIDType2; + return fontLoc; + } + } + } else { + if (sysFontType == sysFontTTF || sysFontType == sysFontTTC) { + fontLoc->fontType = fontTrueType; + return fontLoc; + } else if (sysFontType == sysFontPFA || sysFontType == sysFontPFB) { + fontLoc->fontType = fontType1; + return fontLoc; + } else if (sysFontType == sysFontOTF) { + fft = FoFiIdentifier::identifyFile(fontLoc->path->getCString()); + if (fft == fofiIdOpenTypeCFF8Bit) { + fontLoc->fontType = fontType1COT; + return fontLoc; + } else if (fft == fofiIdTrueType) { + fontLoc->fontType = fontTrueTypeOT; + return fontLoc; + } + } + } + delete fontLoc; + } + + if (!isCIDFont()) { + + //----- 8-bit PS resident font + if (ps) { + if (name && (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->findBase14FontFile(substName, &fontNum, &oblique); + delete substName; + if (path) { + if ((fontLoc = getExternalFont(path, fontNum, oblique, 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 && name && ((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, 0, 0, gTrue))) { + error(errSyntaxWarning, -1, "Substituting font '{0:t}' for '{1:t}'", + fontLoc->path, name); + return fontLoc; + } + } + + // failed to find a substitute font + return NULL; +} + +GfxFontLoc *GfxFont::locateBase14Font(GString *base14Name) { + GString *path; + int fontNum; + double oblique; + + path = globalParams->findBase14FontFile(base14Name, &fontNum, &oblique); + if (!path) { + return NULL; + } + return getExternalFont(path, fontNum, oblique, gFalse); +} + +GfxFontLoc *GfxFont::getExternalFont(GString *path, int fontNum, + double oblique, 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 fofiIdDfont: + fontType = cid ? fontCIDType2 : fontTrueType; + break; + case fofiIdUnknown: + case fofiIdError: + default: + fontType = fontUnknownType; + break; + } + if (fontType == fontUnknownType || + (cid ? (fontType < fontCIDType0) + : (fontType >= fontCIDType0))) { + delete path; + return NULL; + } + fontLoc = new GfxFontLoc(); + fontLoc->locType = gfxFontLocExternal; + fontLoc->fontType = fontType; + fontLoc->path = path; + fontLoc->fontNum = fontNum; + fontLoc->oblique = oblique; + return fontLoc; +} + +char *GfxFont::readEmbFontFile(XRef *xref, int *len) { + char *buf; + Object obj1, obj2; + Stream *str; + int size, n; + + obj1.initRef(embFontID.num, embFontID.gen); + obj1.fetch(xref, &obj2); + if (!obj2.isStream()) { + error(errSyntaxError, -1, "Embedded font file is not a stream"); + obj2.free(); + obj1.free(); + embFontID.num = -1; + return NULL; + } + str = obj2.getStream(); + + size = 4096; + buf = (char *)gmalloc(size); + *len = 0; + str->reset(); + do { + if (*len > size - 4096) { + if (size > INT_MAX / 2) { + error(errSyntaxError, -1, "Embedded font file is too large"); + break; + } + size *= 2; + buf = (char *)grealloc(buf, size); + } + n = str->getBlock(buf + *len, 4096); + *len += n; + } while (n == 4096); + str->close(); + + obj2.free(); + obj1.free(); + + return buf; +} + +//------------------------------------------------------------------------ +// Gfx8BitFont +//------------------------------------------------------------------------ + +Gfx8BitFont::Gfx8BitFont(XRef *xref, const char *tagA, Ref idA, GString *nameA, + GfxFontType typeA, Ref embFontIDA, Dict *fontDict): + GfxFont(tagA, idA, nameA, typeA, embFontIDA) +{ + GString *name2; + BuiltinFont *builtinFont; + const char **baseEnc; + char *buf; + int len; + FoFiType1 *ffT1; + FoFiType1C *ffT1C; + int code, code2; + char *charName; + GBool missing, hex; + Unicode toUnicode[256]; + CharCodeToUnicode *utu, *ctu2; + Unicode uBuf[8]; + double mul; + int firstChar, lastChar; + Gushort w; + Object obj1, obj2, obj3; + int n, i, a, b, m; + + ctu = NULL; + + // do font name substitution for various aliases of the Base 14 font + // names + base14 = NULL; + if (name) { + name2 = name->copy(); + i = 0; + while (i < name2->getLength()) { + if (name2->getChar(i) == ' ') { + name2->del(i); + } else { + ++i; + } + } + a = 0; + b = sizeof(base14FontMap) / sizeof(Base14FontMapEntry); + // invariant: base14FontMap[a].altName <= name2 < base14FontMap[b].altName + while (b - a > 1) { + m = (a + b) / 2; + if (name2->cmp(base14FontMap[m].altName) >= 0) { + a = m; + } else { + b = m; + } + } + if (!name2->cmp(base14FontMap[a].altName)) { + base14 = &base14FontMap[a]; + } + delete name2; + } + + // is it a built-in font? + builtinFont = NULL; + if (base14) { + for (i = 0; i < nBuiltinFonts; ++i) { + if (!strcmp(base14->base14Name, builtinFonts[i].name)) { + builtinFont = &builtinFonts[i]; + break; + } + } + } + + // default ascent/descent values + if (builtinFont) { + missingWidth = builtinFont->missingWidth; + ascent = 0.001 * builtinFont->ascent; + descent = 0.001 * builtinFont->descent; + declaredAscent = ascent; + fontBBox[0] = 0.001 * builtinFont->bbox[0]; + fontBBox[1] = 0.001 * builtinFont->bbox[1]; + fontBBox[2] = 0.001 * builtinFont->bbox[2]; + fontBBox[3] = 0.001 * builtinFont->bbox[3]; + } else { + missingWidth = 0; + ascent = 0.75; + descent = -0.25; + declaredAscent = ascent; + fontBBox[0] = fontBBox[1] = fontBBox[2] = fontBBox[3] = 0; + } + + // get info from font descriptor + readFontDescriptor(xref, fontDict); + + // for Base-14 fonts (even if embedded), don't trust the + // ascent/descent/bbox values from the font descriptor + if (builtinFont) { + ascent = 0.001 * builtinFont->ascent; + descent = 0.001 * builtinFont->descent; + declaredAscent = ascent; + fontBBox[0] = 0.001 * builtinFont->bbox[0]; + fontBBox[1] = 0.001 * builtinFont->bbox[1]; + fontBBox[2] = 0.001 * builtinFont->bbox[2]; + fontBBox[3] = 0.001 * builtinFont->bbox[3]; + } + + // get font matrix + fontMat[0] = fontMat[3] = 1; + fontMat[1] = fontMat[2] = fontMat[4] = fontMat[5] = 0; + if (fontDict->lookup("FontMatrix", &obj1)->isArray()) { + for (i = 0; i < 6 && i < obj1.arrayGetLength(); ++i) { + if (obj1.arrayGet(i, &obj2)->isNum()) { + fontMat[i] = obj2.getNum(); + } + obj2.free(); + } + } + obj1.free(); + + // get Type 3 bounding box, font definition, and resources + if (type == fontType3) { + if (fontDict->lookup("FontBBox", &obj1)->isArray()) { + for (i = 0; i < 4 && i < obj1.arrayGetLength(); ++i) { + if (obj1.arrayGet(i, &obj2)->isNum()) { + fontBBox[i] = obj2.getNum(); + } + obj2.free(); + } + } + obj1.free(); + if (!fontDict->lookup("CharProcs", &charProcs)->isDict()) { + error(errSyntaxError, -1, + "Missing or invalid CharProcs dictionary in Type 3 font"); + charProcs.free(); + } + if (!fontDict->lookup("Resources", &resources)->isDict()) { + resources.free(); + } + } + + //----- build the font encoding ----- + + // Encodings start with a base encoding, which can come from + // (in order of priority): + // 1. FontDict.Encoding or FontDict.Encoding.BaseEncoding + // - MacRoman / MacExpert / WinAnsi / Standard + // 2. embedded or external font file + // 3. default: + // - builtin --> builtin encoding + // - TrueType --> WinAnsiEncoding + // - others --> StandardEncoding + // and then add a list of differences (if any) from + // FontDict.Encoding.Differences. + + // check FontDict for base encoding + hasEncoding = gFalse; + usesMacRomanEnc = gFalse; + baseEnc = NULL; + baseEncFromFontFile = gFalse; + fontDict->lookup("Encoding", &obj1); + if (obj1.isDict()) { + obj1.dictLookup("BaseEncoding", &obj2); + if (obj2.isName("MacRomanEncoding")) { + hasEncoding = gTrue; + usesMacRomanEnc = gTrue; + baseEnc = macRomanEncoding; + } else if (obj2.isName("MacExpertEncoding")) { + hasEncoding = gTrue; + baseEnc = macExpertEncoding; + } else if (obj2.isName("WinAnsiEncoding")) { + hasEncoding = gTrue; + baseEnc = winAnsiEncoding; + } + obj2.free(); + } else if (obj1.isName("MacRomanEncoding")) { + hasEncoding = gTrue; + usesMacRomanEnc = gTrue; + baseEnc = macRomanEncoding; + } else if (obj1.isName("MacExpertEncoding")) { + hasEncoding = gTrue; + baseEnc = macExpertEncoding; + } else if (obj1.isName("WinAnsiEncoding")) { + hasEncoding = gTrue; + baseEnc = winAnsiEncoding; + } + + // 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 && 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; + } + } + gfree(buf); + } + } 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; + } + } + gfree(buf); + } + } + + // get default base encoding + if (!baseEnc) { + if (builtinFont && embFontID.num < 0) { + baseEnc = builtinFont->defaultBaseEnc; + hasEncoding = gTrue; + } else if (type == fontTrueType) { + baseEnc = winAnsiEncoding; + } else { + baseEnc = standardEncoding; + } + } + + // copy the base encoding + for (i = 0; i < 256; ++i) { + enc[i] = (char *)baseEnc[i]; + if ((encFree[i] = (char)baseEncFromFontFile) && enc[i]) { + enc[i] = copyString(baseEnc[i]); + } + } + + // some Type 1C font files have empty encodings, which can break the + // 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 && embFontID.num >= 0 && baseEncFromFontFile) { + for (i = 0; i < 256; ++i) { + if (!enc[i] && standardEncoding[i]) { + enc[i] = (char *)standardEncoding[i]; + encFree[i] = gFalse; + } + } + } + + // merge differences into encoding + if (obj1.isDict()) { + obj1.dictLookup("Differences", &obj2); + if (obj2.isArray()) { + hasEncoding = gTrue; + code = 0; + for (i = 0; i < obj2.arrayGetLength(); ++i) { + obj2.arrayGet(i, &obj3); + if (obj3.isInt()) { + code = obj3.getInt(); + } else if (obj3.isName()) { + if (code >= 0 && code < 256) { + if (encFree[code]) { + gfree(enc[code]); + } + enc[code] = copyString(obj3.getName()); + encFree[code] = gTrue; + } + ++code; + } else { + error(errSyntaxError, -1, + "Wrong type in font encoding resource differences ({0:s})", + obj3.getTypeName()); + } + obj3.free(); + } + } + obj2.free(); + } + obj1.free(); + if (ffT1) { + delete ffT1; + } + if (ffT1C) { + delete ffT1C; + } + + //----- build the mapping to Unicode ----- + + // pass 1: use the name-to-Unicode mapping table + missing = hex = gFalse; + for (code = 0; code < 256; ++code) { + if ((charName = enc[code])) { + if (!(toUnicode[code] = globalParams->mapNameToUnicode(charName)) && + strcmp(charName, ".notdef")) { + // if it wasn't in the name-to-Unicode table, check for a + // name that looks like 'Axx' or 'xx', where 'A' is any letter + // and 'xx' is two hex digits + if ((strlen(charName) == 3 && + isalpha(charName[0] & 0xff) && + isxdigit(charName[1] & 0xff) && isxdigit(charName[2] & 0xff) && + ((charName[1] >= 'a' && charName[1] <= 'f') || + (charName[1] >= 'A' && charName[1] <= 'F') || + (charName[2] >= 'a' && charName[2] <= 'f') || + (charName[2] >= 'A' && charName[2] <= 'F'))) || + (strlen(charName) == 2 && + isxdigit(charName[0] & 0xff) && isxdigit(charName[1] & 0xff) && + ((charName[0] >= 'a' && charName[0] <= 'f') || + (charName[0] >= 'A' && charName[0] <= 'F') || + (charName[1] >= 'a' && charName[1] <= 'f') || + (charName[1] >= 'A' && charName[1] <= 'F')))) { + hex = gTrue; + } + missing = gTrue; + } + } else { + toUnicode[code] = 0; + } + } + + // pass 2: try to fill in the missing chars, looking for names of + // 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 + usedNumericHeuristic = gFalse; + if (missing && globalParams->getMapNumericCharNames()) { + for (code = 0; code < 256; ++code) { + if ((charName = enc[code]) && !toUnicode[code] && + strcmp(charName, ".notdef")) { + n = (int)strlen(charName); + code2 = -1; + if (hex && n == 3 && isalpha(charName[0] & 0xff) && + isxdigit(charName[1] & 0xff) && isxdigit(charName[2] & 0xff)) { + sscanf(charName+1, "%x", &code2); + } else if (hex && n == 2 && + isxdigit(charName[0] & 0xff) && + isxdigit(charName[1] & 0xff)) { + sscanf(charName, "%x", &code2); + } else if (!hex && n >= 2 && n <= 4 && + isdigit(charName[0] & 0xff) && isdigit(charName[1] & 0xff)) { + code2 = atoi(charName); + } else if (n >= 3 && n <= 5 && + isdigit(charName[1] & 0xff) && isdigit(charName[2] & 0xff)) { + code2 = atoi(charName+1); + } else if (n >= 4 && n <= 6 && + isdigit(charName[2] & 0xff) && isdigit(charName[3] & 0xff)) { + code2 = atoi(charName+2); + } else if (n >= 7 && charName[0] == 'u' && charName[1] == 'n' && + charName[2] == 'i' && + isxdigit(charName[3] & 0xff) && + isxdigit(charName[4] & 0xff) && + isxdigit(charName[5] & 0xff) && + isxdigit(charName[6] & 0xff)) { + sscanf(charName + 3, "%x", &code2); + } + if (code2 >= 0 && code2 <= 0xffff) { + toUnicode[code] = (Unicode)code2; + usedNumericHeuristic = gTrue; + } + } + } + + // if the 'mapUnknownCharNames' flag is set, do a simple pass-through + // mapping for unknown character names + } else if (missing && globalParams->getMapUnknownCharNames()) { + for (code = 0; code < 256; ++code) { + if (!toUnicode[code]) { + toUnicode[code] = code; + } + } + } + + // construct the char code -> Unicode mapping object + ctu = CharCodeToUnicode::make8BitToUnicode(toUnicode); + + // merge in a ToUnicode CMap, if there is one -- this overwrites + // existing entries in ctu, i.e., the ToUnicode CMap takes + // precedence, but the other encoding info is allowed to fill in any + // holes + readToUnicodeCMap(fontDict, 8, ctu); + + // look for a Unicode-to-Unicode mapping + if (name && (utu = globalParams->getUnicodeToUnicode(name))) { + for (i = 0; i < 256; ++i) { + toUnicode[i] = 0; + } + ctu2 = CharCodeToUnicode::make8BitToUnicode(toUnicode); + for (i = 0; i < 256; ++i) { + n = ctu->mapToUnicode((CharCode)i, uBuf, 8); + if (n >= 1) { + n = utu->mapToUnicode((CharCode)uBuf[0], uBuf, 8); + if (n >= 1) { + ctu2->setMapping((CharCode)i, uBuf, n); + } + } + } + utu->decRefCnt(); + delete ctu; + ctu = ctu2; + } + + //----- get the character widths ----- + + // initialize all widths + for (code = 0; code < 256; ++code) { + widths[code] = missingWidth * 0.001; + } + + // use widths from font dict, if present + fontDict->lookup("FirstChar", &obj1); + firstChar = obj1.isInt() ? obj1.getInt() : 0; + obj1.free(); + if (firstChar < 0 || firstChar > 255) { + firstChar = 0; + } + fontDict->lookup("LastChar", &obj1); + lastChar = obj1.isInt() ? obj1.getInt() : 255; + obj1.free(); + if (lastChar < 0 || lastChar > 255) { + lastChar = 255; + } + mul = (type == fontType3) ? fontMat[0] : 0.001; + fontDict->lookup("Widths", &obj1); + if (obj1.isArray()) { + flags |= fontFixedWidth; + if (obj1.arrayGetLength() < lastChar - firstChar + 1) { + lastChar = firstChar + obj1.arrayGetLength() - 1; + } + for (code = firstChar; code <= lastChar; ++code) { + obj1.arrayGet(code - firstChar, &obj2); + if (obj2.isNum()) { + widths[code] = obj2.getNum() * mul; + if (fabs(widths[code] - widths[firstChar]) > 0.00001) { + flags &= ~fontFixedWidth; + } + } + obj2.free(); + } + + // use widths from built-in font + } else if (builtinFont) { + // this is a kludge for broken PDF files that encode char 32 + // as .notdef + if (builtinFont->widths->getWidth("space", &w)) { + widths[32] = 0.001 * w; + } + for (code = 0; code < 256; ++code) { + if (enc[code] && builtinFont->widths->getWidth(enc[code], &w)) { + widths[code] = 0.001 * w; + } + } + + // couldn't find widths -- use defaults + } else { + // this is technically an error -- the Widths entry is required + // for all but the Base-14 fonts -- but certain PDF generators + // apparently don't include widths for Arial and TimesNewRoman + if (isFixedWidth()) { + i = 0; + } else if (isSerif()) { + i = 8; + } else { + i = 4; + } + if (isBold()) { + i += 2; + } + if (isItalic()) { + i += 1; + } + builtinFont = builtinFontSubst[i]; + // this is a kludge for broken PDF files that encode char 32 + // as .notdef + if (builtinFont->widths->getWidth("space", &w)) { + widths[32] = 0.001 * w; + } + for (code = 0; code < 256; ++code) { + if (enc[code] && builtinFont->widths->getWidth(enc[code], &w)) { + widths[code] = 0.001 * w; + } + } + } + obj1.free(); + + ok = gTrue; +} + +Gfx8BitFont::~Gfx8BitFont() { + int i; + + for (i = 0; i < 256; ++i) { + if (encFree[i] && enc[i]) { + gfree(enc[i]); + } + } + ctu->decRefCnt(); + if (charProcs.isDict()) { + charProcs.free(); + } + if (resources.isDict()) { + resources.free(); + } +} + +int Gfx8BitFont::getNextChar(char *s, int len, CharCode *code, + Unicode *u, int uSize, int *uLen, + double *dx, double *dy, double *ox, double *oy) { + CharCode c; + + *code = c = (CharCode)(*s & 0xff); + *uLen = ctu->mapToUnicode(c, u, uSize); + *dx = widths[c]; + *dy = *ox = *oy = 0; + return 1; +} + +CharCodeToUnicode *Gfx8BitFont::getToUnicode() { + ctu->incRefCnt(); + return ctu; +} + +int *Gfx8BitFont::getCodeToGIDMap(FoFiTrueType *ff) { + int *map; + int cmapPlatform, cmapEncoding; + int unicodeCmap, macRomanCmap, msSymbolCmap, cmap; + GBool nonsymbolic, useMacRoman, useUnicode; + char *charName; + Unicode u; + int code, i, n; + + map = (int *)gmallocn(256, sizeof(int)); + for (i = 0; i < 256; ++i) { + map[i] = 0; + } + + // This is based on the cmap/encoding selection algorithm in the PDF + // 2.0 spec, but with some differences to match up with Adobe's + // behavior. + unicodeCmap = macRomanCmap = msSymbolCmap = -1; + for (i = 0; i < ff->getNumCmaps(); ++i) { + cmapPlatform = ff->getCmapPlatform(i); + cmapEncoding = ff->getCmapEncoding(i); + if ((cmapPlatform == 3 && cmapEncoding == 1) || + (cmapPlatform == 0 && cmapEncoding <= 4)) { + unicodeCmap = i; + } else if (cmapPlatform == 1 && cmapEncoding == 0) { + macRomanCmap = i; + } else if (cmapPlatform == 3 && cmapEncoding == 0) { + msSymbolCmap = i; + } + } + useMacRoman = gFalse; + useUnicode = gFalse; + nonsymbolic = !(flags & fontSymbolic); + if (usesMacRomanEnc && macRomanCmap >= 0) { + cmap = macRomanCmap; + useMacRoman = gTrue; + } else if (embFontID.num < 0 && hasEncoding && unicodeCmap >= 0) { + cmap = unicodeCmap; + useUnicode = gTrue; + } else if (nonsymbolic && unicodeCmap >= 0) { + cmap = unicodeCmap; + useUnicode = gTrue; + } else if (nonsymbolic && macRomanCmap >= 0) { + cmap = macRomanCmap; + useMacRoman = gTrue; + } else if (msSymbolCmap >= 0) { + cmap = msSymbolCmap; + } else if (unicodeCmap >= 0) { + cmap = unicodeCmap; + } else if (macRomanCmap >= 0) { + cmap = macRomanCmap; + } else { + cmap = 0; + } + + // reverse map the char names through MacRomanEncoding, then map the + // char codes through the cmap; fall back on Unicode if that doesn't + // work + if (useMacRoman) { + for (i = 0; i < 256; ++i) { + if ((charName = enc[i])) { + if ((code = globalParams->getMacRomanCharCode(charName))) { + map[i] = ff->mapCodeToGID(cmap, code); + } else if (unicodeCmap >= 0 && + (u = globalParams->mapNameToUnicode(charName))) { + map[i] = ff->mapCodeToGID(unicodeCmap, u); + } + } else if (unicodeCmap >= 0 && + (n = ctu->mapToUnicode((CharCode)i, &u, 1))) { + map[i] = ff->mapCodeToGID(cmap, u); + } else { + map[i] = -1; + } + } + + // map Unicode through the cmap + } else if (useUnicode) { + for (i = 0; i < 256; ++i) { + if (((charName = enc[i]) && + (u = globalParams->mapNameToUnicode(charName))) || + (n = ctu->mapToUnicode((CharCode)i, &u, 1))) { + map[i] = ff->mapCodeToGID(cmap, u); + } else { + map[i] = -1; + } + } + + // map the char codes through the cmap, possibly with an offset of + // 0xf000 + } else { + for (i = 0; i < 256; ++i) { + if (!(map[i] = ff->mapCodeToGID(cmap, i))) { + map[i] = ff->mapCodeToGID(cmap, 0xf000 + i); + } + } + } + + // try the TrueType 'post' table to handle any unmapped characters + for (i = 0; i < 256; ++i) { + if (map[i] <= 0 && (charName = enc[i])) { + map[i] = ff->mapNameToGID(charName); + } + } + + return map; +} + +int *Gfx8BitFont::getCodeToGIDMap(FoFiType1C *ff) { + int *map; + GHash *nameToGID; + int i, gid; + + map = (int *)gmallocn(256, sizeof(int)); + for (i = 0; i < 256; ++i) { + map[i] = 0; + } + + nameToGID = ff->getNameToGIDMap(); + for (i = 0; i < 256; ++i) { + if (!enc[i]) { + continue; + } + gid = nameToGID->lookupInt(enc[i]); + if (gid < 0 || gid >= 65536) { + continue; + } + map[i] = gid; + } + + delete nameToGID; + + return map; +} + +Dict *Gfx8BitFont::getCharProcs() { + return charProcs.isDict() ? charProcs.getDict() : (Dict *)NULL; +} + +Object *Gfx8BitFont::getCharProc(int code, Object *proc) { + if (enc[code] && charProcs.isDict()) { + charProcs.dictLookup(enc[code], proc); + } else { + proc->initNull(); + } + return proc; +} + +Object *Gfx8BitFont::getCharProcNF(int code, Object *proc) { + if (enc[code] && charProcs.isDict()) { + charProcs.dictLookupNF(enc[code], proc); + } else { + proc->initNull(); + } + return proc; +} + +Dict *Gfx8BitFont::getResources() { + return resources.isDict() ? resources.getDict() : (Dict *)NULL; +} + +GBool Gfx8BitFont::problematicForUnicode() { + GString *nameLC; + GBool symbolic; + + // potential inputs: + // - font is embedded (GfxFont.embFontID.num >= 0) + // - font name (GfxFont.name) + // - font type (GfxFont.type) + // - Base-14 font (Gfx8BitFont.base14 != NULL) + // - symbolic (GfxFont.flags & fontSymbolic) + // - has Encoding array (Gfx8BitFont.hasEncoding) + // - extracted base encoding from embedded font file + // (Gfx8BitFont.baseEncFromFontFile) + // - has a ToUnicode map (GfxFont.hasToUnicode) + // - used the numeric glyph name heuristic + // (Gfx8BitFont.usedNumericHeuristic) + + if (name) { + nameLC = name->copy(); + nameLC->lowerCase(); + symbolic = strstr(nameLC->getCString(), "dingbat") || + strstr(nameLC->getCString(), "wingding") || + strstr(nameLC->getCString(), "commpi"); + delete nameLC; + if (symbolic) { + return gFalse; + } + } + + if (embFontID.num >= 0) { + switch (type) { + case fontType1: + case fontType1C: + case fontType1COT: + return !hasToUnicode && (!hasEncoding || usedNumericHeuristic); + + case fontType3: + return !hasToUnicode && !hasEncoding; + + case fontTrueType: + case fontTrueTypeOT: + return !hasToUnicode && !hasEncoding; + + default: + return !hasToUnicode; + } + + } else { + // NB: type will be fontTypeUnknown if the PDF specifies an + // invalid font type -- which is ok, if we have a ToUnicode map or + // an encoding + return !hasToUnicode && !hasEncoding; + } +} + +//------------------------------------------------------------------------ +// GfxCIDFont +//------------------------------------------------------------------------ + +GfxCIDFont::GfxCIDFont(XRef *xref, const char *tagA, Ref idA, GString *nameA, + GfxFontType typeA, Ref embFontIDA, Dict *fontDict): + GfxFont(tagA, idA, nameA, typeA, embFontIDA) +{ + Dict *desFontDict; + Object desFontDictObj; + Object obj1, obj2, obj3, obj4, obj5, obj6; + CharCodeToUnicode *utu; + CharCode c; + Unicode uBuf[8]; + int c1, c2; + int excepsSize, i, j, k, n; + + missingWidth = 0; + ascent = 0.95; + descent = -0.35; + declaredAscent = ascent; + 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; + widths.exceps = NULL; + widths.nExceps = 0; + widths.excepsV = NULL; + widths.nExcepsV = 0; + cidToGID = NULL; + cidToGIDLen = 0; + + // get the descendant 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(errSyntaxError, -1, "Bad descendant font in Type 0 font"); + goto err2; + } + obj1.free(); + desFontDict = desFontDictObj.getDict(); + + // get info from font descriptor + readFontDescriptor(xref, desFontDict); + + //----- encoding info ----- + + // char collection + if (!desFontDict->lookup("CIDSystemInfo", &obj1)->isDict()) { + 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(errSyntaxError, -1, + "Invalid CIDSystemInfo dictionary in Type 0 descendant font"); + goto err3; + } + collection = obj2.getString()->copy()->append('-')->append(obj3.getString()); + obj3.free(); + obj2.free(); + obj1.free(); + + // encoding (i.e., CMap) + if (fontDict->lookup("Encoding", &obj1)->isNull()) { + error(errSyntaxError, -1, "Missing Encoding entry in Type 0 font"); + goto err2; + } + if (!(cMap = CMap::parse(NULL, collection, &obj1))) { + goto err2; + } + + // check for fonts that use the Identity-H encoding (cmap), and the + // Adobe-Identity character collection + identityEnc = obj1.isName("Identity-H") && + !collection->cmp("Adobe-Identity"); + + obj1.free(); + + // CIDToGIDMap + // (the PDF 1.7 spec only allows these for TrueType fonts, but + // Acrobat apparently also allows them for OpenType CFF fonts -- and + // the PDF 2.0 spec has removed the prohibition) + hasIdentityCIDToGID = gFalse; + desFontDict->lookup("CIDToGIDMap", &obj1); + if (obj1.isStream()) { + cidToGIDLen = 0; + i = 64; + cidToGID = (int *)gmallocn(i, sizeof(int)); + obj1.streamReset(); + while ((c1 = obj1.streamGetChar()) != EOF && + (c2 = obj1.streamGetChar()) != EOF) { + if (cidToGIDLen == i) { + i *= 2; + cidToGID = (int *)greallocn(cidToGID, i, sizeof(int)); + } + cidToGID[cidToGIDLen++] = (c1 << 8) + c2; + } + obj1.streamClose(); + identityEnc = gFalse; + } else if (obj1.isName("Identity")) { + hasIdentityCIDToGID = gTrue; + } else if (!obj1.isNull()) { + error(errSyntaxError, -1, "Invalid CIDToGIDMap entry in CID font"); + } + obj1.free(); + + // look for a ToUnicode CMap + hasKnownCollection = gFalse; + if (globalParams->getUseTrueTypeUnicodeMapping()) { + readTrueTypeUnicodeMapping(xref); + } + if (!ctu) { + ctu = readToUnicodeCMap(fontDict, 16, NULL); + } + if (!ctu) { + 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))) { + hasKnownCollection = gTrue; + + } else { + error(errSyntaxError, -1, + "Unknown character collection '{0:t}'", collection); + + // fall back to an identity mapping + ctu = CharCodeToUnicode::makeIdentityMapping(); + } + } + + // look for a Unicode-to-Unicode mapping + if (name && (utu = globalParams->getUnicodeToUnicode(name))) { + if (ctu) { + if (ctu->isIdentity()) { + ctu->decRefCnt(); + ctu = utu; + } else { + for (c = 0; c < ctu->getLength(); ++c) { + n = ctu->mapToUnicode(c, uBuf, 8); + if (n >= 1) { + n = utu->mapToUnicode((CharCode)uBuf[0], uBuf, 8); + if (n >= 1) { + ctu->setMapping(c, uBuf, n); + } + } + } + utu->decRefCnt(); + } + } else { + ctu = utu; + } + } + + //----- character metrics ----- + + // default char width + if (desFontDict->lookup("DW", &obj1)->isNum()) { + widths.defWidth = obj1.getNum() * 0.001; + } + obj1.free(); + + // char width exceptions + if (desFontDict->lookup("W", &obj1)->isArray()) { + excepsSize = 0; + i = 0; + while (i + 1 < obj1.arrayGetLength()) { + obj1.arrayGet(i, &obj2); + obj1.arrayGet(i + 1, &obj3); + if (obj2.isInt() && obj3.isInt() && i + 2 < obj1.arrayGetLength()) { + if (obj1.arrayGet(i + 2, &obj4)->isNum()) { + if (widths.nExceps == excepsSize) { + excepsSize += 16; + widths.exceps = (GfxFontCIDWidthExcep *) + greallocn(widths.exceps, + excepsSize, sizeof(GfxFontCIDWidthExcep)); + } + widths.exceps[widths.nExceps].first = obj2.getInt(); + widths.exceps[widths.nExceps].last = obj3.getInt(); + widths.exceps[widths.nExceps].width = obj4.getNum() * 0.001; + ++widths.nExceps; + } else { + error(errSyntaxError, -1, "Bad widths array in Type 0 font"); + } + obj4.free(); + i += 3; + } else if (obj2.isInt() && obj3.isArray()) { + if (widths.nExceps + obj3.arrayGetLength() > excepsSize) { + excepsSize = (widths.nExceps + obj3.arrayGetLength() + 15) & ~15; + widths.exceps = (GfxFontCIDWidthExcep *) + greallocn(widths.exceps, + excepsSize, sizeof(GfxFontCIDWidthExcep)); + } + j = obj2.getInt(); + for (k = 0; k < obj3.arrayGetLength(); ++k) { + if (obj3.arrayGet(k, &obj4)->isNum()) { + widths.exceps[widths.nExceps].first = j; + widths.exceps[widths.nExceps].last = j; + widths.exceps[widths.nExceps].width = obj4.getNum() * 0.001; + ++j; + ++widths.nExceps; + } else { + error(errSyntaxError, -1, "Bad widths array in Type 0 font"); + } + obj4.free(); + } + i += 2; + } else { + error(errSyntaxError, -1, "Bad widths array in Type 0 font"); + ++i; + } + obj3.free(); + obj2.free(); + } + } + obj1.free(); + + // default metrics for vertical font + if (desFontDict->lookup("DW2", &obj1)->isArray() && + obj1.arrayGetLength() == 2) { + if (obj1.arrayGet(0, &obj2)->isNum()) { + widths.defVY = obj2.getNum() * 0.001; + } + obj2.free(); + if (obj1.arrayGet(1, &obj2)->isNum()) { + widths.defHeight = obj2.getNum() * 0.001; + } + obj2.free(); + } + obj1.free(); + + // char metric exceptions for vertical font + if (desFontDict->lookup("W2", &obj1)->isArray()) { + excepsSize = 0; + i = 0; + while (i + 1 < obj1.arrayGetLength()) { + obj1.arrayGet(i, &obj2); + obj1.arrayGet(i+ 1, &obj3); + if (obj2.isInt() && obj3.isInt() && i + 4 < obj1.arrayGetLength()) { + if (obj1.arrayGet(i + 2, &obj4)->isNum() && + obj1.arrayGet(i + 3, &obj5)->isNum() && + obj1.arrayGet(i + 4, &obj6)->isNum()) { + if (widths.nExcepsV == excepsSize) { + excepsSize += 16; + widths.excepsV = (GfxFontCIDWidthExcepV *) + greallocn(widths.excepsV, + excepsSize, sizeof(GfxFontCIDWidthExcepV)); + } + widths.excepsV[widths.nExcepsV].first = obj2.getInt(); + widths.excepsV[widths.nExcepsV].last = obj3.getInt(); + 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; + ++widths.nExcepsV; + } else { + error(errSyntaxError, -1, "Bad widths (W2) array in Type 0 font"); + } + obj6.free(); + obj5.free(); + obj4.free(); + i += 5; + } else if (obj2.isInt() && obj3.isArray()) { + if (widths.nExcepsV + obj3.arrayGetLength() / 3 > excepsSize) { + excepsSize = + (widths.nExcepsV + obj3.arrayGetLength() / 3 + 15) & ~15; + widths.excepsV = (GfxFontCIDWidthExcepV *) + greallocn(widths.excepsV, + excepsSize, sizeof(GfxFontCIDWidthExcepV)); + } + j = obj2.getInt(); + for (k = 0; k + 2 < obj3.arrayGetLength(); k += 3) { + if (obj3.arrayGet(k, &obj4)->isNum() && + obj3.arrayGet(k+1, &obj5)->isNum() && + obj3.arrayGet(k+2, &obj6)->isNum()) { + 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(errSyntaxError, -1, "Bad widths (W2) array in Type 0 font"); + } + obj6.free(); + obj5.free(); + obj4.free(); + } + i += 2; + } else { + error(errSyntaxError, -1, "Bad widths (W2) array in Type 0 font"); + ++i; + } + obj3.free(); + obj2.free(); + } + } + obj1.free(); + + desFontDictObj.free(); + ok = gTrue; + return; + + err3: + obj3.free(); + obj2.free(); + err2: + obj1.free(); + desFontDictObj.free(); + err1: + error(errSyntaxError, -1, "Failed to parse font object for '{0:t}'", name); +} + +GfxCIDFont::~GfxCIDFont() { + if (collection) { + delete collection; + } + if (cMap) { + cMap->decRefCnt(); + } + if (ctu) { + ctu->decRefCnt(); + } + gfree(widths.exceps); + gfree(widths.excepsV); + if (cidToGID) { + gfree(cidToGID); + } +} + +// Construct a code-to-Unicode mapping, based on the TrueType Unicode +// cmap (if present). Constructs ctu if succesful; leaves ctu = null +// otherwise. Always leaves ctu = null for non-TrueType fonts. +void GfxCIDFont::readTrueTypeUnicodeMapping(XRef *xref) { + char *buf; + FoFiTrueType *ff; + Unicode *gidToUnicode, *codeToUnicode; + Unicode u; + int bufLen, cmapPlatform, cmapEncoding, unicodeCmap; + int nGlyphs, nMappings, gid, i; + + // must be an embedded TrueType font, with an unknown char collection + if ((type != fontCIDType2 && type == fontCIDType2OT) || + embFontID.num < 0 || + hasKnownCollection) { + goto err0; + } + + // read the embedded font and construct a FoFiTrueType + if (!(buf = readEmbFontFile(xref, &bufLen))) { + goto err0; + } + if (!(ff = FoFiTrueType::make(buf, bufLen, 0))) { + goto err1; + } + + // find the TrueType Unicode cmap + unicodeCmap = -1; + for (i = 0; i < ff->getNumCmaps(); ++i) { + cmapPlatform = ff->getCmapPlatform(i); + cmapEncoding = ff->getCmapEncoding(i); + if ((cmapPlatform == 3 && cmapEncoding == 1) || + (cmapPlatform == 0 && cmapEncoding <= 4)) { + unicodeCmap = i; + break; + } + } + if (unicodeCmap < 0) { + goto err2; + } + + // construct reverse GID-to-Unicode map + nGlyphs = ff->getNumGlyphs(); + gidToUnicode = (Unicode *)gmallocn(nGlyphs, sizeof(Unicode)); + memset(gidToUnicode, 0, nGlyphs * sizeof(Unicode)); + nMappings = 0; + for (u = 1; u <= 0xffff; ++u) { + gid = ff->mapCodeToGID(unicodeCmap, (int)u); + if (gid > 0 && gid < nGlyphs) { + gidToUnicode[gid] = u; + ++nMappings; + } + } + // bail out if the Unicode cmap was completely empty + if (nMappings == 0) { + goto err3; + } + + // construct code-to-Unicode map + codeToUnicode = (Unicode *)gmallocn(65536, sizeof(Unicode)); + memset(codeToUnicode, 0, 65536 * sizeof(Unicode)); + for (i = 0; i <= 0xffff; ++i) { + // we've already checked for an identity encoding, so CID = i + if (cidToGID && i < cidToGIDLen) { + gid = cidToGID[i]; + } else { + gid = i; + } + if (gid < nGlyphs && gidToUnicode[gid] > 0) { + codeToUnicode[i] = gidToUnicode[gid]; + } + } + ctu = CharCodeToUnicode::make16BitToUnicode(codeToUnicode); + + gfree(codeToUnicode); + err3: + gfree(gidToUnicode); + err2: + delete ff; + err1: + gfree(buf); + err0: + return; +} + +int GfxCIDFont::getNextChar(char *s, int len, CharCode *code, + Unicode *u, int uSize, int *uLen, + double *dx, double *dy, double *ox, double *oy) { + CID cid; + CharCode c; + int n; + + if (!cMap) { + *code = 0; + *uLen = 0; + *dx = *dy = 0; + return 1; + } + + *code = (CharCode)(cid = cMap->getCID(s, len, &c, &n)); + if (ctu) { + *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) { + getHorizontalMetrics(cid, dx); + *dy = *ox = *oy = 0; + + // vertical + } else { + getVerticalMetrics(cid, dy, ox, oy); + *dx = 0; + } + + return n; +} + +// NB: Section 9.7.4.3 in the PDF 2.0 spec says that, in the case of +// duplicate entries in the metrics, the first entry should be used. +// This means we need to leave the metrics in the original order and +// perform a linear search. (Or use a more complex data structure.) +void GfxCIDFont::getHorizontalMetrics(CID cid, double *w) { + int i; + for (i = 0; i < widths.nExceps; ++i) { + if (widths.exceps[i].first <= cid && cid <= widths.exceps[i].last) { + *w = widths.exceps[i].width; + return; + } + } + *w = widths.defWidth; +} + +// NB: Section 9.7.4.3 in the PDF 2.0 spec says that, in the case of +// duplicate entries in the metrics, the first entry should be used. +// This means we need to leave the metrics in the original order and +// perform a linear search. (Or use a more complex data structure.) +void GfxCIDFont::getVerticalMetrics(CID cid, double *h, + double *vx, double *vy) { + int i; + for (i = 0; i < widths.nExcepsV; ++i) { + if (widths.excepsV[i].first <= cid && cid <= widths.excepsV[i].last) { + *h = widths.excepsV[i].height; + *vx = widths.excepsV[i].vx; + *vy = widths.excepsV[i].vy; + return; + } + } + *h = widths.defHeight; + getHorizontalMetrics(cid, vx); + *vx /= 2; + *vy = widths.defVY; +} + +int GfxCIDFont::getWMode() { + return cMap ? cMap->getWMode() : 0; +} + +CharCodeToUnicode *GfxCIDFont::getToUnicode() { + if (ctu) { + ctu->incRefCnt(); + } + return ctu; +} + +GString *GfxCIDFont::getCollection() { + return cMap ? cMap->getCollection() : (GString *)NULL; +} + +double GfxCIDFont::getWidth(CID cid) { + double w; + + getHorizontalMetrics(cid, &w); + return w; +} + +GBool GfxCIDFont::problematicForUnicode() { + GString *nameLC; + GBool symbolic; + + // potential inputs: + // - font is embedded (GfxFont.embFontID.num >= 0) + // - font name (GfxFont.name) + // - font type (GfxFont.type) + // - symbolic (GfxFont.flags & fontSymbolic) + // - has a ToUnicode map (GfxFont.hasToUnicode) + // - collection is Adobe-Identity or Adobe-UCS + // (GfxCIDFont.collection - compare string) + // - collection is known AdobeCJK (GfxCIDFont.hasKnownCollection) + // - has non-Identity CIDToGIDMap (GfxCIDFont.cidToGID != NULL) + // - has Identity CIDToGIDMap (GfxCIDFont.hasIdentityCIDToGID) + + if (name) { + nameLC = name->copy(); + nameLC->lowerCase(); + symbolic = strstr(nameLC->getCString(), "dingbat") || + strstr(nameLC->getCString(), "wingding") || + strstr(nameLC->getCString(), "commpi"); + delete nameLC; + if (symbolic) { + return gFalse; + } + } + + if (embFontID.num >= 0) { + switch (type) { + case fontCIDType0: + case fontCIDType0C: + case fontCIDType0COT: + return !hasToUnicode && !hasKnownCollection; + + case fontCIDType2: + case fontCIDType2OT: + return !hasToUnicode && !hasKnownCollection; + + default: + return !hasToUnicode; + } + + } else { + return !hasToUnicode; + } +} + +//------------------------------------------------------------------------ +// GfxFontDict +//------------------------------------------------------------------------ + +GfxFontDict::GfxFontDict(XRef *xref, Ref *fontDictRef, Dict *fontDict) { + GfxFont *font; + char *tag; + Object obj1, obj2; + Ref r; + int i; + + fonts = new GHash(gTrue); + uniqueFonts = new GList(); + for (i = 0; i < fontDict->getLength(); ++i) { + tag = fontDict->getKey(i); + fontDict->getValNF(i, &obj1); + obj1.fetch(xref, &obj2); + if (!obj2.isDict()) { + error(errSyntaxError, -1, "font resource is not a dictionary"); + } else if (obj1.isRef() && (font = lookupByRef(obj1.getRef()))) { + fonts->add(new GString(tag), font); + } else { + if (obj1.isRef()) { + r = obj1.getRef(); + } else if (fontDictRef) { + // legal generation numbers are five digits, so we use a + // 6-digit number here + r.gen = 100000 + fontDictRef->num; + r.num = i; + } else { + // no indirect reference for this font, or for the containing + // font dict, so hash the font and use that + r.gen = 100000; + r.num = hashFontObject(&obj2); + } + if ((font = GfxFont::makeFont(xref, tag, r, obj2.getDict()))) { + if (!font->isOk()) { + delete font; + } else { + uniqueFonts->append(font); + fonts->add(new GString(tag), font); + } + } + } + obj1.free(); + obj2.free(); + } +} + +GfxFontDict::~GfxFontDict() { + deleteGList(uniqueFonts, GfxFont); + delete fonts; +} + +GfxFont *GfxFontDict::lookup(char *tag) { + return (GfxFont *)fonts->lookup(tag); +} + +GfxFont *GfxFontDict::lookupByRef(Ref ref) { + GfxFont *font; + int i; + + for (i = 0; i < uniqueFonts->getLength(); ++i) { + font = (GfxFont *)uniqueFonts->get(i); + if (font->getID()->num == ref.num && + font->getID()->gen == ref.gen) { + return font; + } + } + return NULL; +} + +int GfxFontDict::getNumFonts() { + return uniqueFonts->getLength(); +} + +GfxFont *GfxFontDict::getFont(int i) { + return (GfxFont *)uniqueFonts->get(i); +} + +// FNV-1a hash +class FNVHash { +public: + + FNVHash() { + h = 2166136261U; + } + + void hash(char c) { + h ^= c & 0xff; + h *= 16777619; + } + + void hash(char *p, int n) { + int i; + for (i = 0; i < n; ++i) { + hash(p[i]); + } + } + + int get31() { + return (h ^ (h >> 31)) & 0x7fffffff; + } + +private: + + Guint h; +}; + +int GfxFontDict::hashFontObject(Object *obj) { + FNVHash h; + + hashFontObject1(obj, &h); + return h.get31(); +} + +void GfxFontDict::hashFontObject1(Object *obj, FNVHash *h) { + Object obj2; + GString *s; + char *p; + double r; + int n, i; + + switch (obj->getType()) { + case objBool: + h->hash('b'); + h->hash(obj->getBool() ? 1 : 0); + break; + case objInt: + h->hash('i'); + n = obj->getInt(); + h->hash((char *)&n, sizeof(int)); + break; + case objReal: + h->hash('r'); + r = obj->getReal(); + h->hash((char *)&r, sizeof(double)); + break; + case objString: + h->hash('s'); + s = obj->getString(); + h->hash(s->getCString(), s->getLength()); + break; + case objName: + h->hash('n'); + p = obj->getName(); + h->hash(p, (int)strlen(p)); + break; + case objNull: + h->hash('z'); + break; + case objArray: + h->hash('a'); + n = obj->arrayGetLength(); + h->hash((char *)&n, sizeof(int)); + for (i = 0; i < n; ++i) { + obj->arrayGetNF(i, &obj2); + hashFontObject1(&obj2, h); + obj2.free(); + } + break; + case objDict: + h->hash('d'); + n = obj->dictGetLength(); + h->hash((char *)&n, sizeof(int)); + for (i = 0; i < n; ++i) { + p = obj->dictGetKey(i); + h->hash(p, (int)strlen(p)); + obj->dictGetValNF(i, &obj2); + hashFontObject1(&obj2, h); + obj2.free(); + } + break; + case objStream: + // this should never happen - streams must be indirect refs + break; + case objRef: + h->hash('f'); + n = obj->getRefNum(); + h->hash((char *)&n, sizeof(int)); + n = obj->getRefGen(); + h->hash((char *)&n, sizeof(int)); + break; + default: + h->hash('u'); + break; + } +} diff --git a/xpdf/GfxFont.h b/xpdf/GfxFont.h new file mode 100644 index 0000000..e752ded --- /dev/null +++ b/xpdf/GfxFont.h @@ -0,0 +1,417 @@ +//======================================================================== +// +// GfxFont.h +// +// Copyright 1996-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef GFXFONT_H +#define GFXFONT_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "gtypes.h" +#include "GString.h" +#include "Object.h" +#include "CharTypes.h" + +class GList; +class GHash; +class Dict; +class CMap; +class CharCodeToUnicode; +class FoFiTrueType; +class FoFiType1C; +struct GfxFontCIDWidths; +struct Base14FontMapEntry; +class FNVHash; + +//------------------------------------------------------------------------ +// GfxFontType +//------------------------------------------------------------------------ + +enum GfxFontType { + //----- Gfx8BitFont + fontUnknownType, + fontType1, + fontType1C, + fontType1COT, + fontType3, + fontTrueType, + fontTrueTypeOT, + //----- GfxCIDFont + fontCIDType0, + fontCIDType0C, + fontCIDType0COT, + fontCIDType2, + fontCIDType2OT +}; + +//------------------------------------------------------------------------ +// GfxFontCIDWidths +//------------------------------------------------------------------------ + +struct GfxFontCIDWidthExcep { + CID first; // this record applies to + CID last; // CIDs .. + double width; // char width +}; + +struct GfxFontCIDWidthExcepV { + CID first; // this record applies to + CID last; // CIDs .. + double height; // char height + double vx, vy; // origin position +}; + +struct GfxFontCIDWidths { + double defWidth; // default char width + double defHeight; // default char height + double defVY; // default origin position + GfxFontCIDWidthExcep *exceps; // exceptions + int nExceps; // number of valid entries in exceps + GfxFontCIDWidthExcepV * // exceptions for vertical font + excepsV; + int nExcepsV; // number of valid entries in excepsV +}; + +//------------------------------------------------------------------------ +// 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 and Mac dfonts + // (if locType == gfxFontLocExternal) + double oblique; // sheer factor to oblique this font + // (used when substituting a plain + // font for an oblique font) + GString *encoding; // PS font encoding, only for 16-bit fonts + // (if locType == gfxFontLocResident) + int wMode; // writing mode, only for 16-bit fonts + // (if locType == gfxFontLocResident) + int substIdx; // substitute font index + // (if locType == gfxFontLocExternal, + // and a Base-14 substitution was made) +}; + +//------------------------------------------------------------------------ +// GfxFont +//------------------------------------------------------------------------ + +#define fontFixedWidth (1 << 0) +#define fontSerif (1 << 1) +#define fontSymbolic (1 << 2) +#define fontItalic (1 << 6) +#define fontBold (1 << 18) + +class GfxFont { +public: + + // Build a GfxFont object. + static GfxFont *makeFont(XRef *xref, const char *tagA, + Ref idA, Dict *fontDict); + + // Create a simple default font, to substitute for an undefined font + // object. + static GfxFont *makeDefaultFont(XRef *xref); + + GfxFont(const char *tagA, Ref idA, GString *nameA, + GfxFontType typeA, Ref embFontIDA); + + virtual ~GfxFont(); + + GBool isOk() { return ok; } + + // Get font tag. + GString *getTag() { return tag; } + + // Get font dictionary ID. + Ref *getID() { return &id; } + + // Does this font match the tag? + GBool matches(char *tagA) { return !tag->cmp(tagA); } + + // Get the original font name (ignornig any munging that might have + // been done to map to a canonical Base-14 font name). + GString *getName() { return name; } + + // Get font type. + GfxFontType getType() { return type; } + virtual GBool isCIDFont() { return gFalse; } + + // Get embedded font ID, i.e., a ref for the font file stream. + // Returns false if there is no embedded font. + GBool getEmbeddedFontID(Ref *embID) + { *embID = embFontID; return embFontID.num >= 0; } + + // Get the PostScript font name for the embedded font. Returns + // NULL if there is no embedded font. + GString *getEmbeddedFontName() { return embFontName; } + + // Get font descriptor flags. + int getFlags() { return flags; } + GBool isFixedWidth() { return flags & fontFixedWidth; } + GBool isSerif() { return flags & fontSerif; } + GBool isSymbolic() { return flags & fontSymbolic; } + GBool isItalic() { return flags & fontItalic; } + GBool isBold() { return flags & fontBold; } + + // Return the font matrix. + double *getFontMatrix() { return fontMat; } + + // Return the font bounding box. + double *getFontBBox() { return fontBBox; } + + // Return the ascent and descent values. + double getAscent() { return ascent; } + double getDescent() { return descent; } + double getDeclaredAscent() { return declaredAscent; } + + // Return the writing mode (0=horizontal, 1=vertical). + virtual int getWMode() { return 0; } + + // Locate the font file for this font. If 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 of bytes, returning the + // char , its Unicode mapping , its displacement vector + // (, ), and its origin offset vector (, ). + // is the number of entries available in , and is set to + // the number actually used. Returns the number of bytes used by + // the char code. + virtual int getNextChar(char *s, int len, CharCode *code, + Unicode *u, int uSize, int *uLen, + double *dx, double *dy, double *ox, double *oy) = 0; + + // Returns true if this font is likely to be problematic when + // converting text to Unicode. + virtual GBool problematicForUnicode() = 0; + +protected: + + static GfxFontType getFontType(XRef *xref, Dict *fontDict, Ref *embID); + void readFontDescriptor(XRef *xref, Dict *fontDict); + CharCodeToUnicode *readToUnicodeCMap(Dict *fontDict, int nBits, + CharCodeToUnicode *ctu); + static GfxFontLoc *getExternalFont(GString *path, int fontNum, + double oblique, GBool cid); + + GString *tag; // PDF font tag + Ref id; // reference (used as unique ID) + GString *name; // 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 + 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 + double declaredAscent; // ascent value, before munging + GBool hasToUnicode; // true if the font has a ToUnicode map + GBool ok; +}; + +//------------------------------------------------------------------------ +// Gfx8BitFont +//------------------------------------------------------------------------ + +class Gfx8BitFont: public GfxFont { +public: + + Gfx8BitFont(XRef *xref, const char *tagA, Ref idA, GString *nameA, + GfxFontType typeA, Ref embFontIDA, Dict *fontDict); + + virtual ~Gfx8BitFont(); + + virtual int getNextChar(char *s, int len, CharCode *code, + Unicode *u, int uSize, int *uLen, + double *dx, double *dy, double *ox, double *oy); + + // Return the encoding. + char **getEncoding() { return enc; } + + // Return the Unicode map. + CharCodeToUnicode *getToUnicode(); + + // Return the character name associated with . + char *getCharName(int code) { return enc[code]; } + + // Returns true if the PDF font specified an encoding. + GBool getHasEncoding() { return hasEncoding; } + + // Returns true if the PDF font specified MacRomanEncoding. + GBool getUsesMacRomanEnc() { return usesMacRomanEnc; } + + // Get width of a character. + double getWidth(Guchar c) { return widths[c]; } + + // Return a char code-to-GID mapping for the provided font file. + // (This is only useful for TrueType fonts.) + int *getCodeToGIDMap(FoFiTrueType *ff); + + // Return a char code-to-GID mapping for the provided font file. + // (This is only useful for Type1C fonts.) + int *getCodeToGIDMap(FoFiType1C *ff); + + // Return the Type 3 CharProc dictionary, or NULL if none. + Dict *getCharProcs(); + + // Return the Type 3 CharProc for the character associated with . + Object *getCharProc(int code, Object *proc); + Object *getCharProcNF(int code, Object *proc); + + // Return the Type 3 Resources dictionary, or NULL if none. + Dict *getResources(); + + virtual GBool problematicForUnicode(); + +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 + CharCodeToUnicode *ctu; // char code --> Unicode + GBool hasEncoding; + GBool usesMacRomanEnc; + GBool baseEncFromFontFile; + GBool usedNumericHeuristic; + double widths[256]; // character widths + Object charProcs; // Type 3 CharProcs dictionary + Object resources; // Type 3 Resources dictionary + + friend class GfxFont; +}; + +//------------------------------------------------------------------------ +// GfxCIDFont +//------------------------------------------------------------------------ + +class GfxCIDFont: public GfxFont { +public: + + GfxCIDFont(XRef *xref, const char *tagA, Ref idA, GString *nameA, + GfxFontType typeA, Ref embFontIDA, Dict *fontDict); + + virtual ~GfxCIDFont(); + + virtual GBool isCIDFont() { return gTrue; } + + virtual int getNextChar(char *s, int len, CharCode *code, + Unicode *u, int uSize, int *uLen, + double *dx, double *dy, double *ox, double *oy); + + // Return the writing mode (0=horizontal, 1=vertical). + virtual int getWMode(); + + // Return the Unicode map. + CharCodeToUnicode *getToUnicode(); + + // Get the collection name (-). + GString *getCollection(); + + // Return the horizontal width for . + double getWidth(CID cid); + + // Return the CID-to-GID mapping table. These should only be called + // if type is fontCIDType2. + int *getCIDToGID() { return cidToGID; } + int getCIDToGIDLen() { return cidToGIDLen; } + + // Returns true if this font uses the Identity-H encoding (cmap), + // and the Adobe-Identity character collection, and does not have a + // CIDToGIDMap. When this is true for a CID TrueType font, Adobe + // appears to treat char codes as raw GIDs. + GBool usesIdentityEncoding() { return identityEnc; } + + virtual GBool problematicForUnicode(); + +private: + + void readTrueTypeUnicodeMapping(XRef *xref); + void getHorizontalMetrics(CID cid, double *w); + void getVerticalMetrics(CID cid, double *h, + double *vx, double *vy); + + GString *collection; // collection name + CMap *cMap; // char code --> CID + 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 + int *cidToGID; // CID --> GID mapping (for embedded + // TrueType fonts) + int cidToGIDLen; + GBool hasKnownCollection; + GBool hasIdentityCIDToGID; + GBool identityEnc; +}; + +//------------------------------------------------------------------------ +// GfxFontDict +//------------------------------------------------------------------------ + +class GfxFontDict { +public: + + // Build the font dictionary, given the PDF font dictionary. + GfxFontDict(XRef *xref, Ref *fontDictRef, Dict *fontDict); + + // Destructor. + ~GfxFontDict(); + + // Get the specified font. + GfxFont *lookup(char *tag); + GfxFont *lookupByRef(Ref ref); + + // Iterative access. + int getNumFonts(); + GfxFont *getFont(int i); + +private: + + friend class GfxFont; + + static int hashFontObject(Object *obj); + static void hashFontObject1(Object *obj, FNVHash *h); + + GHash *fonts; // hash table of fonts -- this may + // include duplicates, i.e., when + // two tags map to the same font + GList *uniqueFonts; // list of all unique font objects (no dups) +}; + +#endif diff --git a/xpdf/GfxState.cc b/xpdf/GfxState.cc new file mode 100644 index 0000000..43503aa --- /dev/null +++ b/xpdf/GfxState.cc @@ -0,0 +1,4918 @@ +//======================================================================== +// +// GfxState.cc +// +// Copyright 1996-2016 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include +#include +#include "gmem.h" +#include "gmempp.h" +#include "Error.h" +#include "GlobalParams.h" +#include "Object.h" +#include "Array.h" +#include "Page.h" +#include "XRef.h" +#include "GfxState.h" + +//------------------------------------------------------------------------ + +// 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; +} + +static inline double clip01(double x) { + return (x < 0) ? 0 : (x > 1) ? 1 : x; +} + +//------------------------------------------------------------------------ + +struct GfxBlendModeInfo { + const char *name; + GfxBlendMode mode; +}; + +static GfxBlendModeInfo gfxBlendModeNames[] = { + { "Normal", gfxBlendNormal }, + { "Compatible", gfxBlendNormal }, + { "Multiply", gfxBlendMultiply }, + { "Screen", gfxBlendScreen }, + { "Overlay", gfxBlendOverlay }, + { "Darken", gfxBlendDarken }, + { "Lighten", gfxBlendLighten }, + { "ColorDodge", gfxBlendColorDodge }, + { "ColorBurn", gfxBlendColorBurn }, + { "HardLight", gfxBlendHardLight }, + { "SoftLight", gfxBlendSoftLight }, + { "Difference", gfxBlendDifference }, + { "Exclusion", gfxBlendExclusion }, + { "Hue", gfxBlendHue }, + { "Saturation", gfxBlendSaturation }, + { "Color", gfxBlendColor }, + { "Luminosity", gfxBlendLuminosity } +}; + +#define nGfxBlendModeNames \ + ((int)((sizeof(gfxBlendModeNames) / sizeof(GfxBlendModeInfo)))) + +//------------------------------------------------------------------------ + +// NB: This must match the GfxColorSpaceMode enum defined in +// GfxState.h +static const char *gfxColorSpaceModeNames[] = { + "DeviceGray", + "CalGray", + "DeviceRGB", + "CalRGB", + "DeviceCMYK", + "Lab", + "ICCBased", + "Indexed", + "Separation", + "DeviceN", + "Pattern" +}; + +#define nGfxColorSpaceModes ((sizeof(gfxColorSpaceModeNames) / sizeof(char *))) + + + + +//------------------------------------------------------------------------ +// GfxColorSpace +//------------------------------------------------------------------------ + +GfxColorSpace::GfxColorSpace() { + overprintMask = 0x0f; + defaultColorSpace = gFalse; +} + +GfxColorSpace::~GfxColorSpace() { +} + +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")) { + cs = GfxColorSpace::create(csDeviceGray); + } else if (csObj->isName("DeviceRGB") || csObj->isName("RGB")) { + cs = GfxColorSpace::create(csDeviceRGB); + } else if (csObj->isName("DeviceCMYK") || csObj->isName("CMYK")) { + cs = GfxColorSpace::create(csDeviceCMYK); + } else if (csObj->isName("Pattern")) { + cs = new GfxPatternColorSpace(NULL); + } else { + error(errSyntaxError, -1, "Bad color space '{0:s}'", csObj->getName()); + } + } else if (csObj->isArray() && csObj->arrayGetLength() > 0) { + csObj->arrayGet(0, &obj1); + if (obj1.isName("DeviceGray") || obj1.isName("G")) { + cs = GfxColorSpace::create(csDeviceGray); + } else if (obj1.isName("DeviceRGB") || obj1.isName("RGB")) { + cs = GfxColorSpace::create(csDeviceRGB); + } else if (obj1.isName("DeviceCMYK") || obj1.isName("CMYK")) { + cs = GfxColorSpace::create(csDeviceCMYK); + } else if (obj1.isName("CalGray")) { + cs = GfxCalGrayColorSpace::parse(csObj->getArray(), recursion); + } else if (obj1.isName("CalRGB")) { + cs = GfxCalRGBColorSpace::parse(csObj->getArray(), recursion); + } else if (obj1.isName("Lab")) { + cs = GfxLabColorSpace::parse(csObj->getArray(), recursion); + } else if (obj1.isName("ICCBased")) { + cs = GfxICCBasedColorSpace::parse(csObj->getArray(), + recursion); + } else if (obj1.isName("Indexed") || obj1.isName("I")) { + cs = GfxIndexedColorSpace::parse(csObj->getArray(), + recursion); + } else if (obj1.isName("Separation")) { + cs = GfxSeparationColorSpace::parse(csObj->getArray(), + recursion); + } else if (obj1.isName("DeviceN")) { + cs = GfxDeviceNColorSpace::parse(csObj->getArray(), + recursion); + } else if (obj1.isName("Pattern")) { + cs = GfxPatternColorSpace::parse(csObj->getArray(), + recursion); + } else { + error(errSyntaxError, -1, "Bad color space"); + } + obj1.free(); + } else { + error(errSyntaxError, -1, "Bad color space - expected name or array"); + } + return cs; +} + +GfxColorSpace *GfxColorSpace::create(GfxColorSpaceMode mode) { + GfxColorSpace *cs; + + cs = NULL; + if (mode == csDeviceGray) { + cs = new GfxDeviceGrayColorSpace(); + } else if (mode == csDeviceRGB) { + cs = new GfxDeviceRGBColorSpace(); + } else if (mode == csDeviceCMYK) { + cs = new GfxDeviceCMYKColorSpace(); + } + return cs; +} + +void GfxColorSpace::getDefaultRanges(double *decodeLow, double *decodeRange, + int maxImgPixel) { + int i; + + for (i = 0; i < getNComps(); ++i) { + decodeLow[i] = 0; + decodeRange[i] = 1; + } +} + +int GfxColorSpace::getNumColorSpaceModes() { + return nGfxColorSpaceModes; +} + +const char *GfxColorSpace::getColorSpaceModeName(int idx) { + return gfxColorSpaceModeNames[idx]; +} + +//------------------------------------------------------------------------ +// GfxDeviceGrayColorSpace +//------------------------------------------------------------------------ + +GfxDeviceGrayColorSpace::GfxDeviceGrayColorSpace() { +} + +GfxDeviceGrayColorSpace::~GfxDeviceGrayColorSpace() { +} + +GfxColorSpace *GfxDeviceGrayColorSpace::copy() { + GfxDeviceGrayColorSpace *cs; + + cs = new GfxDeviceGrayColorSpace(); + return cs; +} + + +void GfxDeviceGrayColorSpace::getGray(GfxColor *color, GfxGray *gray, + GfxRenderingIntent ri) { + *gray = clip01(color->c[0]); +} + +void GfxDeviceGrayColorSpace::getRGB(GfxColor *color, GfxRGB *rgb, + GfxRenderingIntent ri) { + rgb->r = rgb->g = rgb->b = clip01(color->c[0]); +} + +void GfxDeviceGrayColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk, + GfxRenderingIntent ri) { + cmyk->c = cmyk->m = cmyk->y = 0; + cmyk->k = clip01(gfxColorComp1 - color->c[0]); +} + + + +void GfxDeviceGrayColorSpace::getDefaultColor(GfxColor *color) { + color->c[0] = 0; +} + +//------------------------------------------------------------------------ +// GfxCalGrayColorSpace +//------------------------------------------------------------------------ + +GfxCalGrayColorSpace::GfxCalGrayColorSpace() { + whiteX = whiteY = whiteZ = 1; + blackX = blackY = blackZ = 0; + gamma = 1; +} + +GfxCalGrayColorSpace::~GfxCalGrayColorSpace() { +} + +GfxColorSpace *GfxCalGrayColorSpace::copy() { + GfxCalGrayColorSpace *cs; + + cs = new GfxCalGrayColorSpace(); + cs->whiteX = whiteX; + cs->whiteY = whiteY; + cs->whiteZ = whiteZ; + cs->blackX = blackX; + cs->blackY = blackY; + cs->blackZ = blackZ; + cs->gamma = gamma; + return cs; +} + + +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(errSyntaxError, -1, "Bad CalGray color space"); + obj1.free(); + return NULL; + } + cs = new GfxCalGrayColorSpace(); + if (obj1.dictLookup("WhitePoint", &obj2)->isArray() && + obj2.arrayGetLength() == 3) { + obj2.arrayGet(0, &obj3); + cs->whiteX = obj3.getNum(); + obj3.free(); + obj2.arrayGet(1, &obj3); + cs->whiteY = obj3.getNum(); + obj3.free(); + obj2.arrayGet(2, &obj3); + cs->whiteZ = obj3.getNum(); + obj3.free(); + } + obj2.free(); + if (obj1.dictLookup("BlackPoint", &obj2)->isArray() && + obj2.arrayGetLength() == 3) { + obj2.arrayGet(0, &obj3); + cs->blackX = obj3.getNum(); + obj3.free(); + obj2.arrayGet(1, &obj3); + cs->blackY = obj3.getNum(); + obj3.free(); + obj2.arrayGet(2, &obj3); + cs->blackZ = obj3.getNum(); + obj3.free(); + } + obj2.free(); + if (obj1.dictLookup("Gamma", &obj2)->isNum()) { + cs->gamma = obj2.getNum(); + } + obj2.free(); + obj1.free(); + return cs; +} + +void GfxCalGrayColorSpace::getGray(GfxColor *color, GfxGray *gray, + GfxRenderingIntent ri) { + *gray = clip01(color->c[0]); +} + +void GfxCalGrayColorSpace::getRGB(GfxColor *color, GfxRGB *rgb, + GfxRenderingIntent ri) { + rgb->r = rgb->g = rgb->b = clip01(color->c[0]); +} + +void GfxCalGrayColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk, + GfxRenderingIntent ri) { + cmyk->c = cmyk->m = cmyk->y = 0; + cmyk->k = clip01(gfxColorComp1 - color->c[0]); +} + + + +void GfxCalGrayColorSpace::getDefaultColor(GfxColor *color) { + color->c[0] = 0; +} + +//------------------------------------------------------------------------ +// GfxDeviceRGBColorSpace +//------------------------------------------------------------------------ + +GfxDeviceRGBColorSpace::GfxDeviceRGBColorSpace() { +} + +GfxDeviceRGBColorSpace::~GfxDeviceRGBColorSpace() { +} + +GfxColorSpace *GfxDeviceRGBColorSpace::copy() { + GfxDeviceRGBColorSpace *cs; + + cs = new GfxDeviceRGBColorSpace(); + return cs; +} + + +void GfxDeviceRGBColorSpace::getGray(GfxColor *color, GfxGray *gray, + GfxRenderingIntent ri) { + *gray = clip01((GfxColorComp)(0.3 * color->c[0] + + 0.59 * color->c[1] + + 0.11 * color->c[2] + 0.5)); +} + +void GfxDeviceRGBColorSpace::getRGB(GfxColor *color, GfxRGB *rgb, + GfxRenderingIntent ri) { + rgb->r = clip01(color->c[0]); + rgb->g = clip01(color->c[1]); + rgb->b = clip01(color->c[2]); +} + +void GfxDeviceRGBColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk, + GfxRenderingIntent ri) { + GfxColorComp c, m, y, k; + + c = clip01(gfxColorComp1 - color->c[0]); + m = clip01(gfxColorComp1 - color->c[1]); + y = clip01(gfxColorComp1 - color->c[2]); + k = c; + if (m < k) { + k = m; + } + if (y < k) { + k = y; + } + cmyk->c = c - k; + cmyk->m = m - k; + cmyk->y = y - k; + cmyk->k = k; +} + + + +void GfxDeviceRGBColorSpace::getDefaultColor(GfxColor *color) { + color->c[0] = 0; + color->c[1] = 0; + color->c[2] = 0; +} + +//------------------------------------------------------------------------ +// GfxCalRGBColorSpace +//------------------------------------------------------------------------ + +GfxCalRGBColorSpace::GfxCalRGBColorSpace() { + whiteX = whiteY = whiteZ = 1; + blackX = blackY = blackZ = 0; + gammaR = gammaG = gammaB = 1; + mat[0] = 1; mat[1] = 0; mat[2] = 0; + mat[3] = 0; mat[4] = 1; mat[5] = 0; + mat[6] = 0; mat[7] = 0; mat[8] = 1; +} + +GfxCalRGBColorSpace::~GfxCalRGBColorSpace() { +} + +GfxColorSpace *GfxCalRGBColorSpace::copy() { + GfxCalRGBColorSpace *cs; + int i; + + cs = new GfxCalRGBColorSpace(); + cs->whiteX = whiteX; + cs->whiteY = whiteY; + cs->whiteZ = whiteZ; + cs->blackX = blackX; + cs->blackY = blackY; + cs->blackZ = blackZ; + cs->gammaR = gammaR; + cs->gammaG = gammaG; + cs->gammaB = gammaB; + for (i = 0; i < 9; ++i) { + cs->mat[i] = mat[i]; + } + return cs; +} + +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(errSyntaxError, -1, "Bad CalRGB color space"); + obj1.free(); + return NULL; + } + cs = new GfxCalRGBColorSpace(); + if (obj1.dictLookup("WhitePoint", &obj2)->isArray() && + obj2.arrayGetLength() == 3) { + obj2.arrayGet(0, &obj3); + cs->whiteX = obj3.getNum(); + obj3.free(); + obj2.arrayGet(1, &obj3); + cs->whiteY = obj3.getNum(); + obj3.free(); + obj2.arrayGet(2, &obj3); + cs->whiteZ = obj3.getNum(); + obj3.free(); + } + obj2.free(); + if (obj1.dictLookup("BlackPoint", &obj2)->isArray() && + obj2.arrayGetLength() == 3) { + obj2.arrayGet(0, &obj3); + cs->blackX = obj3.getNum(); + obj3.free(); + obj2.arrayGet(1, &obj3); + cs->blackY = obj3.getNum(); + obj3.free(); + obj2.arrayGet(2, &obj3); + cs->blackZ = obj3.getNum(); + obj3.free(); + } + obj2.free(); + if (obj1.dictLookup("Gamma", &obj2)->isArray() && + obj2.arrayGetLength() == 3) { + obj2.arrayGet(0, &obj3); + cs->gammaR = obj3.getNum(); + obj3.free(); + obj2.arrayGet(1, &obj3); + cs->gammaG = obj3.getNum(); + obj3.free(); + obj2.arrayGet(2, &obj3); + cs->gammaB = obj3.getNum(); + obj3.free(); + } + obj2.free(); + if (obj1.dictLookup("Matrix", &obj2)->isArray() && + obj2.arrayGetLength() == 9) { + for (i = 0; i < 9; ++i) { + obj2.arrayGet(i, &obj3); + cs->mat[i] = obj3.getNum(); + obj3.free(); + } + } + obj2.free(); + obj1.free(); + return cs; +} + + +void GfxCalRGBColorSpace::getGray(GfxColor *color, GfxGray *gray, + GfxRenderingIntent ri) { + *gray = clip01((GfxColorComp)(0.299 * color->c[0] + + 0.587 * color->c[1] + + 0.114 * color->c[2] + 0.5)); +} + +void GfxCalRGBColorSpace::getRGB(GfxColor *color, GfxRGB *rgb, + GfxRenderingIntent ri) { + rgb->r = clip01(color->c[0]); + rgb->g = clip01(color->c[1]); + rgb->b = clip01(color->c[2]); +} + +void GfxCalRGBColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk, + GfxRenderingIntent ri) { + GfxColorComp c, m, y, k; + + c = clip01(gfxColorComp1 - color->c[0]); + m = clip01(gfxColorComp1 - color->c[1]); + y = clip01(gfxColorComp1 - color->c[2]); + k = c; + if (m < k) { + k = m; + } + if (y < k) { + k = y; + } + cmyk->c = c - k; + cmyk->m = m - k; + cmyk->y = y - k; + cmyk->k = k; +} + + + +void GfxCalRGBColorSpace::getDefaultColor(GfxColor *color) { + color->c[0] = 0; + color->c[1] = 0; + color->c[2] = 0; +} + +//------------------------------------------------------------------------ +// GfxDeviceCMYKColorSpace +//------------------------------------------------------------------------ + +GfxDeviceCMYKColorSpace::GfxDeviceCMYKColorSpace() { +} + +GfxDeviceCMYKColorSpace::~GfxDeviceCMYKColorSpace() { +} + +GfxColorSpace *GfxDeviceCMYKColorSpace::copy() { + GfxDeviceCMYKColorSpace *cs; + + cs = new GfxDeviceCMYKColorSpace(); + return cs; +} + + +void GfxDeviceCMYKColorSpace::getGray(GfxColor *color, GfxGray *gray, + GfxRenderingIntent ri) { + *gray = clip01((GfxColorComp)(gfxColorComp1 - color->c[3] + - 0.3 * color->c[0] + - 0.59 * color->c[1] + - 0.11 * color->c[2] + 0.5)); +} + +void GfxDeviceCMYKColorSpace::getRGB(GfxColor *color, GfxRGB *rgb, + GfxRenderingIntent ri) { + double c, m, y, k, c1, m1, y1, k1, r, g, b, x; + + c = colToDbl(color->c[0]); + m = colToDbl(color->c[1]); + y = colToDbl(color->c[2]); + k = colToDbl(color->c[3]); + c1 = 1 - c; + m1 = 1 - m; + y1 = 1 - y; + k1 = 1 - k; + // this is a matrix multiplication, unrolled for performance + // C M Y K + x = c1 * m1 * y1 * k1; // 0 0 0 0 + r = g = b = x; + x = c1 * m1 * y1 * k; // 0 0 0 1 + r += 0.1373 * x; + g += 0.1216 * x; + b += 0.1255 * x; + x = c1 * m1 * y * k1; // 0 0 1 0 + r += x; + g += 0.9490 * x; + x = c1 * m1 * y * k; // 0 0 1 1 + r += 0.1098 * x; + g += 0.1020 * x; + x = c1 * m * y1 * k1; // 0 1 0 0 + r += 0.9255 * x; + b += 0.5490 * x; + x = c1 * m * y1 * k; // 0 1 0 1 + r += 0.1412 * x; + x = c1 * m * y * k1; // 0 1 1 0 + r += 0.9294 * x; + g += 0.1098 * x; + b += 0.1412 * x; + x = c1 * m * y * k; // 0 1 1 1 + r += 0.1333 * x; + x = c * m1 * y1 * k1; // 1 0 0 0 + g += 0.6784 * x; + b += 0.9373 * x; + x = c * m1 * y1 * k; // 1 0 0 1 + g += 0.0588 * x; + b += 0.1412 * x; + x = c * m1 * y * k1; // 1 0 1 0 + g += 0.6510 * x; + b += 0.3137 * x; + x = c * m1 * y * k; // 1 0 1 1 + g += 0.0745 * x; + x = c * m * y1 * k1; // 1 1 0 0 + r += 0.1804 * x; + g += 0.1922 * x; + b += 0.5725 * x; + x = c * m * y1 * k; // 1 1 0 1 + b += 0.0078 * x; + x = c * m * y * k1; // 1 1 1 0 + r += 0.2118 * x; + g += 0.2119 * x; + b += 0.2235 * x; + rgb->r = clip01(dblToCol(r)); + rgb->g = clip01(dblToCol(g)); + rgb->b = clip01(dblToCol(b)); +} + +void GfxDeviceCMYKColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk, + GfxRenderingIntent ri) { + cmyk->c = clip01(color->c[0]); + cmyk->m = clip01(color->c[1]); + cmyk->y = clip01(color->c[2]); + cmyk->k = clip01(color->c[3]); +} + + + +void GfxDeviceCMYKColorSpace::getDefaultColor(GfxColor *color) { + color->c[0] = 0; + color->c[1] = 0; + color->c[2] = 0; + color->c[3] = gfxColorComp1; +} + + +//------------------------------------------------------------------------ +// GfxLabColorSpace +//------------------------------------------------------------------------ + +// This is the inverse of MatrixLMN in Example 4.10 from the PostScript +// Language Reference, Third Edition. +static double xyzrgb[3][3] = { + { 3.240449, -1.537136, -0.498531 }, + { -0.969265, 1.876011, 0.041556 }, + { 0.055643, -0.204026, 1.057229 } +}; + +GfxLabColorSpace::GfxLabColorSpace() { + whiteX = whiteY = whiteZ = 1; + blackX = blackY = blackZ = 0; + aMin = bMin = -100; + aMax = bMax = 100; +} + +GfxLabColorSpace::~GfxLabColorSpace() { +} + +GfxColorSpace *GfxLabColorSpace::copy() { + GfxLabColorSpace *cs; + + cs = new GfxLabColorSpace(); + cs->whiteX = whiteX; + cs->whiteY = whiteY; + cs->whiteZ = whiteZ; + cs->blackX = blackX; + cs->blackY = blackY; + cs->blackZ = blackZ; + cs->aMin = aMin; + cs->aMax = aMax; + cs->bMin = bMin; + cs->bMax = bMax; + cs->kr = kr; + cs->kg = kg; + cs->kb = kb; + return cs; +} + +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(errSyntaxError, -1, "Bad Lab color space"); + obj1.free(); + return NULL; + } + cs = new GfxLabColorSpace(); + if (obj1.dictLookup("WhitePoint", &obj2)->isArray() && + obj2.arrayGetLength() == 3) { + obj2.arrayGet(0, &obj3); + cs->whiteX = obj3.getNum(); + obj3.free(); + obj2.arrayGet(1, &obj3); + cs->whiteY = obj3.getNum(); + obj3.free(); + obj2.arrayGet(2, &obj3); + cs->whiteZ = obj3.getNum(); + obj3.free(); + } + obj2.free(); + if (obj1.dictLookup("BlackPoint", &obj2)->isArray() && + obj2.arrayGetLength() == 3) { + obj2.arrayGet(0, &obj3); + cs->blackX = obj3.getNum(); + obj3.free(); + obj2.arrayGet(1, &obj3); + cs->blackY = obj3.getNum(); + obj3.free(); + obj2.arrayGet(2, &obj3); + cs->blackZ = obj3.getNum(); + obj3.free(); + } + obj2.free(); + if (obj1.dictLookup("Range", &obj2)->isArray() && + obj2.arrayGetLength() == 4) { + obj2.arrayGet(0, &obj3); + cs->aMin = obj3.getNum(); + obj3.free(); + obj2.arrayGet(1, &obj3); + cs->aMax = obj3.getNum(); + obj3.free(); + obj2.arrayGet(2, &obj3); + cs->bMin = obj3.getNum(); + obj3.free(); + obj2.arrayGet(3, &obj3); + cs->bMax = obj3.getNum(); + obj3.free(); + } + obj2.free(); + obj1.free(); + + cs->kr = 1 / (xyzrgb[0][0] * cs->whiteX + + xyzrgb[0][1] * cs->whiteY + + xyzrgb[0][2] * cs->whiteZ); + cs->kg = 1 / (xyzrgb[1][0] * cs->whiteX + + xyzrgb[1][1] * cs->whiteY + + xyzrgb[1][2] * cs->whiteZ); + cs->kb = 1 / (xyzrgb[2][0] * cs->whiteX + + xyzrgb[2][1] * cs->whiteY + + xyzrgb[2][2] * cs->whiteZ); + + return cs; +} + + +void GfxLabColorSpace::getGray(GfxColor *color, GfxGray *gray, + GfxRenderingIntent ri) { + GfxRGB rgb; + + getRGB(color, &rgb, ri); + *gray = clip01((GfxColorComp)(0.299 * rgb.r + + 0.587 * rgb.g + + 0.114 * rgb.b + 0.5)); +} + +void GfxLabColorSpace::getRGB(GfxColor *color, GfxRGB *rgb, + GfxRenderingIntent ri) { + double X, Y, Z; + double t1, t2; + double r, g, b; + + + // convert L*a*b* to CIE 1931 XYZ color space + t1 = (colToDbl(color->c[0]) + 16) / 116; + t2 = t1 + colToDbl(color->c[1]) / 500; + if (t2 >= (6.0 / 29.0)) { + X = t2 * t2 * t2; + } else { + X = (108.0 / 841.0) * (t2 - (4.0 / 29.0)); + } + X *= whiteX; + if (t1 >= (6.0 / 29.0)) { + Y = t1 * t1 * t1; + } else { + Y = (108.0 / 841.0) * (t1 - (4.0 / 29.0)); + } + Y *= whiteY; + t2 = t1 - colToDbl(color->c[2]) / 200; + if (t2 >= (6.0 / 29.0)) { + Z = t2 * t2 * t2; + } else { + Z = (108.0 / 841.0) * (t2 - (4.0 / 29.0)); + } + Z *= whiteZ; + + // convert XYZ to RGB, including gamut mapping and gamma correction + r = xyzrgb[0][0] * X + xyzrgb[0][1] * Y + xyzrgb[0][2] * Z; + g = xyzrgb[1][0] * X + xyzrgb[1][1] * Y + xyzrgb[1][2] * Z; + b = xyzrgb[2][0] * X + xyzrgb[2][1] * Y + xyzrgb[2][2] * Z; + rgb->r = dblToCol(pow(clip01(r * kr), 0.5)); + rgb->g = dblToCol(pow(clip01(g * kg), 0.5)); + rgb->b = dblToCol(pow(clip01(b * kb), 0.5)); +} + +void GfxLabColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk, + GfxRenderingIntent ri) { + GfxRGB rgb; + GfxColorComp c, m, y, k; + + + getRGB(color, &rgb, ri); + c = clip01(gfxColorComp1 - rgb.r); + m = clip01(gfxColorComp1 - rgb.g); + y = clip01(gfxColorComp1 - rgb.b); + k = c; + if (m < k) { + k = m; + } + if (y < k) { + k = y; + } + cmyk->c = c - k; + cmyk->m = m - k; + cmyk->y = y - k; + cmyk->k = k; +} + + + +void GfxLabColorSpace::getDefaultColor(GfxColor *color) { + color->c[0] = 0; + if (aMin > 0) { + color->c[1] = dblToCol(aMin); + } else if (aMax < 0) { + color->c[1] = dblToCol(aMax); + } else { + color->c[1] = 0; + } + if (bMin > 0) { + color->c[2] = dblToCol(bMin); + } else if (bMax < 0) { + color->c[2] = dblToCol(bMax); + } else { + color->c[2] = 0; + } +} + +void GfxLabColorSpace::getDefaultRanges(double *decodeLow, double *decodeRange, + int maxImgPixel) { + decodeLow[0] = 0; + decodeRange[0] = 100; + decodeLow[1] = aMin; + decodeRange[1] = aMax - aMin; + decodeLow[2] = bMin; + decodeRange[2] = bMax - bMin; +} + +//------------------------------------------------------------------------ +// GfxICCBasedColorSpace +//------------------------------------------------------------------------ + +GfxICCBasedColorSpace::GfxICCBasedColorSpace(int nCompsA, GfxColorSpace *altA, + Ref *iccProfileStreamA) { + nComps = nCompsA; + alt = altA; + iccProfileStream = *iccProfileStreamA; + rangeMin[0] = rangeMin[1] = rangeMin[2] = rangeMin[3] = 0; + rangeMax[0] = rangeMax[1] = rangeMax[2] = rangeMax[3] = 1; +} + +GfxICCBasedColorSpace::~GfxICCBasedColorSpace() { + delete alt; +} + +GfxColorSpace *GfxICCBasedColorSpace::copy() { + GfxICCBasedColorSpace *cs; + int i; + + cs = new GfxICCBasedColorSpace(nComps, alt->copy(), &iccProfileStream); + for (i = 0; i < 4; ++i) { + cs->rangeMin[i] = rangeMin[i]; + cs->rangeMax[i] = rangeMax[i]; + } + return cs; +} + +GfxColorSpace *GfxICCBasedColorSpace::parse(Array *arr, + int recursion) { + GfxICCBasedColorSpace *cs; + Ref iccProfileStreamA; + int nCompsA; + GfxColorSpace *altA; + Dict *dict; + 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(); + } else { + iccProfileStreamA.num = 0; + iccProfileStreamA.gen = 0; + } + obj1.free(); + arr->get(1, &obj1); + if (!obj1.isStream()) { + error(errSyntaxError, -1, "Bad ICCBased color space (stream)"); + obj1.free(); + return NULL; + } + dict = obj1.streamGetDict(); + if (!dict->lookup("N", &obj2)->isInt()) { + error(errSyntaxError, -1, "Bad ICCBased color space (N)"); + obj2.free(); + obj1.free(); + return NULL; + } + nCompsA = obj2.getInt(); + obj2.free(); + 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, + recursion + 1))) { + switch (nCompsA) { + case 1: + altA = GfxColorSpace::create(csDeviceGray); + break; + case 3: + altA = GfxColorSpace::create(csDeviceRGB); + break; + case 4: + altA = GfxColorSpace::create(csDeviceCMYK); + break; + default: + error(errSyntaxError, -1, "Bad ICCBased color space - invalid N"); + obj2.free(); + obj1.free(); + return NULL; + } + } + obj2.free(); + cs = new GfxICCBasedColorSpace(nCompsA, altA, &iccProfileStreamA); + if (dict->lookup("Range", &obj2)->isArray() && + obj2.arrayGetLength() == 2 * nCompsA) { + for (i = 0; i < nCompsA; ++i) { + obj2.arrayGet(2*i, &obj3); + cs->rangeMin[i] = obj3.getNum(); + obj3.free(); + obj2.arrayGet(2*i+1, &obj3); + cs->rangeMax[i] = obj3.getNum(); + obj3.free(); + } + } + obj2.free(); + obj1.free(); + return cs; +} + + +void GfxICCBasedColorSpace::getGray(GfxColor *color, GfxGray *gray, + GfxRenderingIntent ri) { + alt->getGray(color, gray, ri); +} + +void GfxICCBasedColorSpace::getRGB(GfxColor *color, GfxRGB *rgb, + GfxRenderingIntent ri) { + alt->getRGB(color, rgb, ri); +} + +void GfxICCBasedColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk, + GfxRenderingIntent ri) { + alt->getCMYK(color, cmyk, ri); +} + + + +void GfxICCBasedColorSpace::getDefaultColor(GfxColor *color) { + int i; + + for (i = 0; i < nComps; ++i) { + if (rangeMin[i] > 0) { + color->c[i] = dblToCol(rangeMin[i]); + } else if (rangeMax[i] < 0) { + color->c[i] = dblToCol(rangeMax[i]); + } else { + color->c[i] = 0; + } + } +} + +void GfxICCBasedColorSpace::getDefaultRanges(double *decodeLow, + double *decodeRange, + int maxImgPixel) { + alt->getDefaultRanges(decodeLow, decodeRange, maxImgPixel); + +#if 0 + // this is nominally correct, but some PDF files don't set the + // correct ranges in the ICCBased dict + int i; + + for (i = 0; i < nComps; ++i) { + decodeLow[i] = rangeMin[i]; + decodeRange[i] = rangeMax[i] - rangeMin[i]; + } +#endif +} + + +//------------------------------------------------------------------------ +// GfxIndexedColorSpace +//------------------------------------------------------------------------ + +GfxIndexedColorSpace::GfxIndexedColorSpace(GfxColorSpace *baseA, + int indexHighA) { + base = baseA; + indexHigh = indexHighA; + lookup = (Guchar *)gmallocn((indexHigh + 1) * base->getNComps(), + sizeof(Guchar)); + overprintMask = base->getOverprintMask(); +} + +GfxIndexedColorSpace::~GfxIndexedColorSpace() { + delete base; + gfree(lookup); +} + +GfxColorSpace *GfxIndexedColorSpace::copy() { + GfxIndexedColorSpace *cs; + + cs = new GfxIndexedColorSpace(base->copy(), indexHigh); + memcpy(cs->lookup, lookup, + (indexHigh + 1) * base->getNComps() * sizeof(Guchar)); + return cs; +} + +GfxColorSpace *GfxIndexedColorSpace::parse(Array *arr, + int recursion) { + GfxIndexedColorSpace *cs; + GfxColorSpace *baseA; + int indexHighA; + Object obj1; + int x; + char *s; + int n, i, j; + + if (arr->getLength() != 4) { + error(errSyntaxError, -1, "Bad Indexed color space"); + goto err1; + } + arr->get(1, &obj1); + 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(errSyntaxError, -1, "Bad Indexed color space (hival)"); + delete baseA; + goto err2; + } + indexHighA = obj1.getInt(); + if (indexHighA < 0 || indexHighA > 255) { + // the PDF spec requires indexHigh to be in [0,255] -- allowing + // 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(errSyntaxError, -1, + "Bad Indexed color space (invalid indexHigh value)"); + delete baseA; + goto err2; + } + obj1.free(); + cs = new GfxIndexedColorSpace(baseA, indexHighA); + arr->get(3, &obj1); + n = baseA->getNComps(); + if (obj1.isStream()) { + obj1.streamReset(); + for (i = 0; i <= indexHighA; ++i) { + for (j = 0; j < n; ++j) { + if ((x = obj1.streamGetChar()) == EOF) { + error(errSyntaxError, -1, + "Bad Indexed color space (lookup table stream too short)"); + cs->indexHigh = indexHighA = i - 1; + if (cs->indexHigh < 0) { + goto err3; + } + } + cs->lookup[i*n + j] = (Guchar)x; + } + } + obj1.streamClose(); + } else if (obj1.isString()) { + if (obj1.getString()->getLength() < (indexHighA + 1) * n) { + error(errSyntaxError, -1, + "Bad Indexed color space (lookup table string too short)"); + cs->indexHigh = indexHighA = obj1.getString()->getLength() / n - 1; + if (cs->indexHigh < 0) { + goto err3; + } + } + s = obj1.getString()->getCString(); + for (i = 0; i <= indexHighA; ++i) { + for (j = 0; j < n; ++j) { + cs->lookup[i*n + j] = (Guchar)*s++; + } + } + } else { + error(errSyntaxError, -1, "Bad Indexed color space (lookup table)"); + goto err3; + } + obj1.free(); + return cs; + + err3: + delete cs; + err2: + obj1.free(); + err1: + return NULL; +} + + +GfxColor *GfxIndexedColorSpace::mapColorToBase(GfxColor *color, + GfxColor *baseColor) { + Guchar *p; + double low[gfxColorMaxComps], range[gfxColorMaxComps]; + int n, i, k; + + n = base->getNComps(); + base->getDefaultRanges(low, range, indexHigh); + k = (int)(colToDbl(color->c[0]) + 0.5); + if (k < 0) { + k = 0; + } else if (k > indexHigh) { + k = indexHigh; + } + p = &lookup[k * n]; + for (i = 0; i < n; ++i) { + baseColor->c[i] = dblToCol(low[i] + (p[i] / 255.0) * range[i]); + } + return baseColor; +} + +void GfxIndexedColorSpace::getGray(GfxColor *color, GfxGray *gray, + GfxRenderingIntent ri) { + GfxColor color2; + + base->getGray(mapColorToBase(color, &color2), gray, ri); +} + +void GfxIndexedColorSpace::getRGB(GfxColor *color, GfxRGB *rgb, + GfxRenderingIntent ri) { + GfxColor color2; + + base->getRGB(mapColorToBase(color, &color2), rgb, ri); +} + +void GfxIndexedColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk, + GfxRenderingIntent ri) { + GfxColor color2; + + base->getCMYK(mapColorToBase(color, &color2), cmyk, ri); +} + + + +void GfxIndexedColorSpace::getDefaultColor(GfxColor *color) { + color->c[0] = 0; +} + +void GfxIndexedColorSpace::getDefaultRanges(double *decodeLow, + double *decodeRange, + int maxImgPixel) { + decodeLow[0] = 0; + decodeRange[0] = maxImgPixel; +} + +//------------------------------------------------------------------------ +// GfxSeparationColorSpace +//------------------------------------------------------------------------ + +GfxSeparationColorSpace::GfxSeparationColorSpace(GString *nameA, + GfxColorSpace *altA, + Function *funcA) { + name = 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() { + delete name; + delete alt; + delete func; +} + +GfxColorSpace *GfxSeparationColorSpace::copy() { + GfxSeparationColorSpace *cs; + + cs = new GfxSeparationColorSpace(name->copy(), alt->copy(), func->copy(), + nonMarking, overprintMask); + return cs; +} + +GfxColorSpace *GfxSeparationColorSpace::parse(Array *arr, + int recursion) { + GfxSeparationColorSpace *cs; + GString *nameA; + GfxColorSpace *altA; + Function *funcA; + Object obj1, obj2; + + if (arr->getLength() != 4) { + error(errSyntaxError, -1, "Bad Separation color space"); + goto err1; + } + if (!arr->get(1, &obj1)->isName()) { + error(errSyntaxError, -1, "Bad Separation color space (name)"); + goto err2; + } + nameA = new GString(obj1.getName()); + obj1.free(); + arr->get(2, &obj1); + // some PDF generators use an ICC profile stream here; Adobe + // apparently looks at the /Alternate entry in the stream dictionary + if (obj1.isStream() && + !obj1.streamGetDict()->lookup("Alternate", &obj2)->isNull()) { + obj1.free(); + obj1 = obj2; + } + if (!(altA = GfxColorSpace::parse(&obj1, + recursion + 1))) { + error(errSyntaxError, -1, + "Bad Separation color space (alternate color space)"); + goto err3; + } + obj1.free(); + arr->get(3, &obj1); + if (!(funcA = Function::parse(&obj1, 1, altA->getNComps()))) { + goto err4; + } + obj1.free(); + cs = new GfxSeparationColorSpace(nameA, altA, funcA); + return cs; + + err4: + delete altA; + err3: + delete nameA; + err2: + obj1.free(); + err1: + return NULL; +} + + +void GfxSeparationColorSpace::getGray(GfxColor *color, GfxGray *gray, + GfxRenderingIntent ri) { + double x; + double c[gfxColorMaxComps]; + GfxColor color2; + int i; + + x = colToDbl(color->c[0]); + func->transform(&x, c); + for (i = 0; i < alt->getNComps(); ++i) { + color2.c[i] = dblToCol(c[i]); + } + alt->getGray(&color2, gray, ri); +} + +void GfxSeparationColorSpace::getRGB(GfxColor *color, GfxRGB *rgb, + GfxRenderingIntent ri) { + double x; + double c[gfxColorMaxComps]; + GfxColor color2; + int i; + + x = colToDbl(color->c[0]); + func->transform(&x, c); + for (i = 0; i < alt->getNComps(); ++i) { + color2.c[i] = dblToCol(c[i]); + } + alt->getRGB(&color2, rgb, ri); +} + +void GfxSeparationColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk, + GfxRenderingIntent ri) { + double x; + double c[gfxColorMaxComps]; + GfxColor color2; + int i; + + x = colToDbl(color->c[0]); + func->transform(&x, c); + for (i = 0; i < alt->getNComps(); ++i) { + color2.c[i] = dblToCol(c[i]); + } + alt->getCMYK(&color2, cmyk, ri); +} + + + +void GfxSeparationColorSpace::getDefaultColor(GfxColor *color) { + color->c[0] = gfxColorComp1; +} + +//------------------------------------------------------------------------ +// GfxDeviceNColorSpace +//------------------------------------------------------------------------ + +GfxDeviceNColorSpace::GfxDeviceNColorSpace(int nCompsA, + GString **namesA, + GfxColorSpace *altA, + Function *funcA, + Object *attrsA) { + int i; + + nComps = nCompsA; + alt = altA; + func = funcA; + attrsA->copy(&attrs); + 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, + Object *attrsA, + GBool nonMarkingA, + Guint overprintMaskA) { + int i; + + nComps = nCompsA; + alt = altA; + func = funcA; + attrsA->copy(&attrs); + nonMarking = nonMarkingA; + overprintMask = overprintMaskA; + for (i = 0; i < nComps; ++i) { + names[i] = namesA[i]->copy(); + } +} + +GfxDeviceNColorSpace::~GfxDeviceNColorSpace() { + int i; + + for (i = 0; i < nComps; ++i) { + delete names[i]; + } + delete alt; + delete func; + attrs.free(); +} + +GfxColorSpace *GfxDeviceNColorSpace::copy() { + GfxDeviceNColorSpace *cs; + + cs = new GfxDeviceNColorSpace(nComps, names, alt->copy(), func->copy(), + &attrs, nonMarking, overprintMask); + return cs; +} + +GfxColorSpace *GfxDeviceNColorSpace::parse(Array *arr, + int recursion) { + GfxDeviceNColorSpace *cs; + int nCompsA; + GString *namesA[gfxColorMaxComps]; + GfxColorSpace *altA; + Function *funcA; + Object attrsA, obj1, obj2; + int i; + + if (arr->getLength() != 4 && arr->getLength() != 5) { + error(errSyntaxError, -1, "Bad DeviceN color space"); + goto err1; + } + if (!arr->get(1, &obj1)->isArray()) { + error(errSyntaxError, -1, "Bad DeviceN color space (names)"); + goto err2; + } + nCompsA = obj1.arrayGetLength(); + if (nCompsA > gfxColorMaxComps) { + 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(errSyntaxError, -1, "Bad DeviceN color space (names)"); + obj2.free(); + goto err2; + } + namesA[i] = new GString(obj2.getName()); + obj2.free(); + } + obj1.free(); + arr->get(2, &obj1); + // some PDF generators use an ICC profile stream here; Adobe + // apparently looks at the /Alternate entry in the stream dictionary + if (obj1.isStream() && + !obj1.streamGetDict()->lookup("Alternate", &obj2)->isNull()) { + obj1.free(); + obj1 = obj2; + } + if (!(altA = GfxColorSpace::parse(&obj1, + recursion + 1))) { + error(errSyntaxError, -1, + "Bad DeviceN color space (alternate color space)"); + goto err3; + } + obj1.free(); + arr->get(3, &obj1); + if (!(funcA = Function::parse(&obj1, nCompsA, altA->getNComps()))) { + goto err4; + } + obj1.free(); + if (arr->getLength() == 5) { + arr->get(4, &attrsA); + } else { + attrsA.initNull(); + } + cs = new GfxDeviceNColorSpace(nCompsA, namesA, altA, funcA, &attrsA); + attrsA.free(); + return cs; + + err4: + delete altA; + err3: + for (i = 0; i < nCompsA; ++i) { + delete namesA[i]; + } + err2: + obj1.free(); + err1: + return NULL; +} + + +void GfxDeviceNColorSpace::getGray(GfxColor *color, GfxGray *gray, + GfxRenderingIntent ri) { + double x[gfxColorMaxComps], c[gfxColorMaxComps]; + GfxColor color2; + int i; + + for (i = 0; i < nComps; ++i) { + x[i] = colToDbl(color->c[i]); + } + func->transform(x, c); + for (i = 0; i < alt->getNComps(); ++i) { + color2.c[i] = dblToCol(c[i]); + } + alt->getGray(&color2, gray, ri); +} + +void GfxDeviceNColorSpace::getRGB(GfxColor *color, GfxRGB *rgb, + GfxRenderingIntent ri) { + double x[gfxColorMaxComps], c[gfxColorMaxComps]; + GfxColor color2; + int i; + + for (i = 0; i < nComps; ++i) { + x[i] = colToDbl(color->c[i]); + } + func->transform(x, c); + for (i = 0; i < alt->getNComps(); ++i) { + color2.c[i] = dblToCol(c[i]); + } + alt->getRGB(&color2, rgb, ri); +} + +void GfxDeviceNColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk, + GfxRenderingIntent ri) { + double x[gfxColorMaxComps], c[gfxColorMaxComps]; + GfxColor color2; + int i; + + for (i = 0; i < nComps; ++i) { + x[i] = colToDbl(color->c[i]); + } + func->transform(x, c); + for (i = 0; i < alt->getNComps(); ++i) { + color2.c[i] = dblToCol(c[i]); + } + alt->getCMYK(&color2, cmyk, ri); +} + + + +void GfxDeviceNColorSpace::getDefaultColor(GfxColor *color) { + int i; + + for (i = 0; i < nComps; ++i) { + color->c[i] = gfxColorComp1; + } +} + +//------------------------------------------------------------------------ +// GfxPatternColorSpace +//------------------------------------------------------------------------ + +GfxPatternColorSpace::GfxPatternColorSpace(GfxColorSpace *underA) { + under = underA; +} + +GfxPatternColorSpace::~GfxPatternColorSpace() { + if (under) { + delete under; + } +} + +GfxColorSpace *GfxPatternColorSpace::copy() { + GfxPatternColorSpace *cs; + + cs = new GfxPatternColorSpace(under ? under->copy() : + (GfxColorSpace *)NULL); + return cs; +} + +GfxColorSpace *GfxPatternColorSpace::parse(Array *arr, + int recursion) { + GfxPatternColorSpace *cs; + GfxColorSpace *underA; + Object obj1; + + if (arr->getLength() != 1 && arr->getLength() != 2) { + error(errSyntaxError, -1, "Bad Pattern color space"); + return NULL; + } + underA = NULL; + if (arr->getLength() == 2) { + arr->get(1, &obj1); + if (!(underA = GfxColorSpace::parse(&obj1, + recursion + 1))) { + error(errSyntaxError, -1, + "Bad Pattern color space (underlying color space)"); + obj1.free(); + return NULL; + } + obj1.free(); + } + cs = new GfxPatternColorSpace(underA); + return cs; +} + + +void GfxPatternColorSpace::getGray(GfxColor *color, GfxGray *gray, + GfxRenderingIntent ri) { + *gray = 0; +} + +void GfxPatternColorSpace::getRGB(GfxColor *color, GfxRGB *rgb, + GfxRenderingIntent ri) { + rgb->r = rgb->g = rgb->b = 0; +} + +void GfxPatternColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk, + GfxRenderingIntent ri) { + cmyk->c = cmyk->m = cmyk->y = 0; + cmyk->k = 1; +} + + + +void GfxPatternColorSpace::getDefaultColor(GfxColor *color) { + // not used +} + +//------------------------------------------------------------------------ +// Pattern +//------------------------------------------------------------------------ + +GfxPattern::GfxPattern(int typeA) { + type = typeA; +} + +GfxPattern::~GfxPattern() { +} + +GfxPattern *GfxPattern::parse(Object *objRef, Object *obj + ) { + GfxPattern *pattern; + Object typeObj; + + if (obj->isDict()) { + obj->dictLookup("PatternType", &typeObj); + } else if (obj->isStream()) { + obj->streamGetDict()->lookup("PatternType", &typeObj); + } else { + return NULL; + } + pattern = NULL; + if (typeObj.isInt() && typeObj.getInt() == 1) { + pattern = GfxTilingPattern::parse(objRef, obj); + } else if (typeObj.isInt() && typeObj.getInt() == 2) { + pattern = GfxShadingPattern::parse(obj + ); + } + typeObj.free(); + return pattern; +} + +//------------------------------------------------------------------------ +// GfxTilingPattern +//------------------------------------------------------------------------ + +GfxTilingPattern *GfxTilingPattern::parse(Object *patObjRef, Object *patObj) { + GfxTilingPattern *pat; + Dict *dict; + int paintTypeA, tilingTypeA; + double bboxA[4], matrixA[6]; + double xStepA, yStepA; + Object resDictA; + Object obj1, obj2; + int i; + + if (!patObj->isStream()) { + return NULL; + } + dict = patObj->streamGetDict(); + + if (dict->lookup("PaintType", &obj1)->isInt()) { + paintTypeA = obj1.getInt(); + } else { + paintTypeA = 1; + error(errSyntaxWarning, -1, "Invalid or missing PaintType in pattern"); + } + obj1.free(); + if (dict->lookup("TilingType", &obj1)->isInt()) { + tilingTypeA = obj1.getInt(); + } else { + tilingTypeA = 1; + error(errSyntaxWarning, -1, "Invalid or missing TilingType in pattern"); + } + obj1.free(); + bboxA[0] = bboxA[1] = 0; + bboxA[2] = bboxA[3] = 1; + if (dict->lookup("BBox", &obj1)->isArray() && + obj1.arrayGetLength() == 4) { + for (i = 0; i < 4; ++i) { + if (obj1.arrayGet(i, &obj2)->isNum()) { + bboxA[i] = obj2.getNum(); + } + obj2.free(); + } + } else { + error(errSyntaxError, -1, "Invalid or missing BBox in pattern"); + } + obj1.free(); + if (dict->lookup("XStep", &obj1)->isNum()) { + xStepA = obj1.getNum(); + } else { + xStepA = 1; + error(errSyntaxError, -1, "Invalid or missing XStep in pattern"); + } + obj1.free(); + if (dict->lookup("YStep", &obj1)->isNum()) { + yStepA = obj1.getNum(); + } else { + yStepA = 1; + error(errSyntaxError, -1, "Invalid or missing YStep in pattern"); + } + obj1.free(); + if (!dict->lookup("Resources", &resDictA)->isDict()) { + resDictA.free(); + resDictA.initNull(); + error(errSyntaxError, -1, "Invalid or missing Resources in pattern"); + } + matrixA[0] = 1; matrixA[1] = 0; + matrixA[2] = 0; matrixA[3] = 1; + matrixA[4] = 0; matrixA[5] = 0; + if (dict->lookup("Matrix", &obj1)->isArray() && + obj1.arrayGetLength() == 6) { + for (i = 0; i < 6; ++i) { + if (obj1.arrayGet(i, &obj2)->isNum()) { + matrixA[i] = obj2.getNum(); + } + obj2.free(); + } + } + obj1.free(); + + pat = new GfxTilingPattern(paintTypeA, tilingTypeA, bboxA, xStepA, yStepA, + &resDictA, matrixA, patObjRef); + resDictA.free(); + return pat; +} + +GfxTilingPattern::GfxTilingPattern(int paintTypeA, int tilingTypeA, + double *bboxA, double xStepA, double yStepA, + Object *resDictA, double *matrixA, + Object *contentStreamRefA): + GfxPattern(1) +{ + int i; + + paintType = paintTypeA; + tilingType = tilingTypeA; + for (i = 0; i < 4; ++i) { + bbox[i] = bboxA[i]; + } + xStep = xStepA; + yStep = yStepA; + resDictA->copy(&resDict); + for (i = 0; i < 6; ++i) { + matrix[i] = matrixA[i]; + } + contentStreamRefA->copy(&contentStreamRef); +} + +GfxTilingPattern::~GfxTilingPattern() { + resDict.free(); + contentStreamRef.free(); +} + +GfxPattern *GfxTilingPattern::copy() { + return new GfxTilingPattern(paintType, tilingType, bbox, xStep, yStep, + &resDict, matrix, &contentStreamRef); +} + +//------------------------------------------------------------------------ +// GfxShadingPattern +//------------------------------------------------------------------------ + +GfxShadingPattern *GfxShadingPattern::parse(Object *patObj + ) { + Dict *dict; + GfxShading *shadingA; + double matrixA[6]; + Object obj1, obj2; + int i; + + if (!patObj->isDict()) { + return NULL; + } + dict = patObj->getDict(); + + dict->lookup("Shading", &obj1); + shadingA = GfxShading::parse(&obj1 + ); + obj1.free(); + if (!shadingA) { + return NULL; + } + + matrixA[0] = 1; matrixA[1] = 0; + matrixA[2] = 0; matrixA[3] = 1; + matrixA[4] = 0; matrixA[5] = 0; + if (dict->lookup("Matrix", &obj1)->isArray() && + obj1.arrayGetLength() == 6) { + for (i = 0; i < 6; ++i) { + if (obj1.arrayGet(i, &obj2)->isNum()) { + matrixA[i] = obj2.getNum(); + } + obj2.free(); + } + } + obj1.free(); + + return new GfxShadingPattern(shadingA, matrixA); +} + +GfxShadingPattern::GfxShadingPattern(GfxShading *shadingA, double *matrixA): + GfxPattern(2) +{ + int i; + + shading = shadingA; + for (i = 0; i < 6; ++i) { + matrix[i] = matrixA[i]; + } +} + +GfxShadingPattern::~GfxShadingPattern() { + delete shading; +} + +GfxPattern *GfxShadingPattern::copy() { + return new GfxShadingPattern(shading->copy(), matrix); +} + +//------------------------------------------------------------------------ +// GfxShading +//------------------------------------------------------------------------ + +GfxShading::GfxShading(int typeA) { + type = typeA; + colorSpace = NULL; +} + +GfxShading::GfxShading(GfxShading *shading) { + int i; + + type = shading->type; + colorSpace = shading->colorSpace->copy(); + for (i = 0; i < gfxColorMaxComps; ++i) { + background.c[i] = shading->background.c[i]; + } + hasBackground = shading->hasBackground; + xMin = shading->xMin; + yMin = shading->yMin; + xMax = shading->xMax; + yMax = shading->yMax; + hasBBox = shading->hasBBox; +} + +GfxShading::~GfxShading() { + if (colorSpace) { + delete colorSpace; + } +} + +GfxShading *GfxShading::parse(Object *obj + ) { + GfxShading *shading; + Dict *dict; + int typeA; + Object obj1; + + if (obj->isDict()) { + dict = obj->getDict(); + } else if (obj->isStream()) { + dict = obj->streamGetDict(); + } else { + return NULL; + } + + if (!dict->lookup("ShadingType", &obj1)->isInt()) { + error(errSyntaxError, -1, "Invalid ShadingType in shading dictionary"); + obj1.free(); + return NULL; + } + typeA = obj1.getInt(); + obj1.free(); + + switch (typeA) { + case 1: + shading = GfxFunctionShading::parse(dict + ); + break; + case 2: + shading = GfxAxialShading::parse(dict + ); + break; + case 3: + shading = GfxRadialShading::parse(dict + ); + break; + case 4: + if (obj->isStream()) { + shading = GfxGouraudTriangleShading::parse(4, dict, obj->getStream() + ); + } else { + error(errSyntaxError, -1, "Invalid Type 4 shading object"); + goto err1; + } + break; + case 5: + if (obj->isStream()) { + shading = GfxGouraudTriangleShading::parse(5, dict, obj->getStream() + ); + } else { + error(errSyntaxError, -1, "Invalid Type 5 shading object"); + goto err1; + } + break; + case 6: + if (obj->isStream()) { + shading = GfxPatchMeshShading::parse(6, dict, obj->getStream() + ); + } else { + error(errSyntaxError, -1, "Invalid Type 6 shading object"); + goto err1; + } + break; + case 7: + if (obj->isStream()) { + shading = GfxPatchMeshShading::parse(7, dict, obj->getStream() + ); + } else { + error(errSyntaxError, -1, "Invalid Type 7 shading object"); + goto err1; + } + break; + default: + error(errSyntaxError, -1, "Unknown shading type {0:d}", typeA); + goto err1; + } + + return shading; + + err1: + return NULL; +} + +GBool GfxShading::init(Dict *dict + ) { + Object obj1, obj2; + int i; + + dict->lookup("ColorSpace", &obj1); + if (!(colorSpace = GfxColorSpace::parse(&obj1 + ))) { + error(errSyntaxError, -1, "Bad color space in shading dictionary"); + obj1.free(); + return gFalse; + } + obj1.free(); + + for (i = 0; i < gfxColorMaxComps; ++i) { + background.c[i] = 0; + } + hasBackground = gFalse; + if (dict->lookup("Background", &obj1)->isArray()) { + if (obj1.arrayGetLength() == colorSpace->getNComps()) { + hasBackground = gTrue; + for (i = 0; i < colorSpace->getNComps(); ++i) { + background.c[i] = dblToCol(obj1.arrayGet(i, &obj2)->getNum()); + obj2.free(); + } + } else { + error(errSyntaxError, -1, "Bad Background in shading dictionary"); + } + } + obj1.free(); + + xMin = yMin = xMax = yMax = 0; + hasBBox = gFalse; + if (dict->lookup("BBox", &obj1)->isArray()) { + if (obj1.arrayGetLength() == 4) { + hasBBox = gTrue; + xMin = obj1.arrayGet(0, &obj2)->getNum(); + obj2.free(); + yMin = obj1.arrayGet(1, &obj2)->getNum(); + obj2.free(); + xMax = obj1.arrayGet(2, &obj2)->getNum(); + obj2.free(); + yMax = obj1.arrayGet(3, &obj2)->getNum(); + obj2.free(); + } else { + error(errSyntaxError, -1, "Bad BBox in shading dictionary"); + } + } + obj1.free(); + + return gTrue; +} + +//------------------------------------------------------------------------ +// GfxFunctionShading +//------------------------------------------------------------------------ + +GfxFunctionShading::GfxFunctionShading(double x0A, double y0A, + double x1A, double y1A, + double *matrixA, + Function **funcsA, int nFuncsA): + GfxShading(1) +{ + int i; + + x0 = x0A; + y0 = y0A; + x1 = x1A; + y1 = y1A; + for (i = 0; i < 6; ++i) { + matrix[i] = matrixA[i]; + } + nFuncs = nFuncsA; + for (i = 0; i < nFuncs; ++i) { + funcs[i] = funcsA[i]; + } +} + +GfxFunctionShading::GfxFunctionShading(GfxFunctionShading *shading): + GfxShading(shading) +{ + int i; + + x0 = shading->x0; + y0 = shading->y0; + x1 = shading->x1; + y1 = shading->y1; + for (i = 0; i < 6; ++i) { + matrix[i] = shading->matrix[i]; + } + nFuncs = shading->nFuncs; + for (i = 0; i < nFuncs; ++i) { + funcs[i] = shading->funcs[i]->copy(); + } +} + +GfxFunctionShading::~GfxFunctionShading() { + int i; + + for (i = 0; i < nFuncs; ++i) { + delete funcs[i]; + } +} + +GfxFunctionShading *GfxFunctionShading::parse(Dict *dict + ) { + GfxFunctionShading *shading; + double x0A, y0A, x1A, y1A; + double matrixA[6]; + Function *funcsA[gfxColorMaxComps]; + int nFuncsA; + Object obj1, obj2; + GBool ok; + int i; + + x0A = y0A = 0; + x1A = y1A = 1; + if (dict->lookup("Domain", &obj1)->isArray() && + obj1.arrayGetLength() == 4) { + x0A = obj1.arrayGet(0, &obj2)->getNum(); + obj2.free(); + x1A = obj1.arrayGet(1, &obj2)->getNum(); + obj2.free(); + y0A = obj1.arrayGet(2, &obj2)->getNum(); + obj2.free(); + y1A = obj1.arrayGet(3, &obj2)->getNum(); + obj2.free(); + } + obj1.free(); + + matrixA[0] = 1; matrixA[1] = 0; + matrixA[2] = 0; matrixA[3] = 1; + matrixA[4] = 0; matrixA[5] = 0; + if (dict->lookup("Matrix", &obj1)->isArray() && + obj1.arrayGetLength() == 6) { + matrixA[0] = obj1.arrayGet(0, &obj2)->getNum(); + obj2.free(); + matrixA[1] = obj1.arrayGet(1, &obj2)->getNum(); + obj2.free(); + matrixA[2] = obj1.arrayGet(2, &obj2)->getNum(); + obj2.free(); + matrixA[3] = obj1.arrayGet(3, &obj2)->getNum(); + obj2.free(); + matrixA[4] = obj1.arrayGet(4, &obj2)->getNum(); + obj2.free(); + matrixA[5] = obj1.arrayGet(5, &obj2)->getNum(); + obj2.free(); + } + obj1.free(); + + dict->lookup("Function", &obj1); + if (obj1.isArray()) { + nFuncsA = obj1.arrayGetLength(); + if (nFuncsA > gfxColorMaxComps) { + error(errSyntaxError, -1, + "Invalid Function array in shading dictionary"); + goto err1; + } + for (i = 0; i < nFuncsA; ++i) { + obj1.arrayGet(i, &obj2); + if (!(funcsA[i] = Function::parse(&obj2, 2, 1))) { + goto err2; + } + obj2.free(); + } + } else { + nFuncsA = 1; + if (!(funcsA[0] = Function::parse(&obj1, 2, -1))) { + goto err1; + } + } + obj1.free(); + + shading = new GfxFunctionShading(x0A, y0A, x1A, y1A, matrixA, + funcsA, nFuncsA); + if (!shading->init(dict + )) { + delete shading; + return NULL; + } + + ok = gFalse; + if (shading->nFuncs == 1) { + ok = shading->funcs[0]->getOutputSize() + == shading->getColorSpace()->getNComps(); + } else if (shading->nFuncs == shading->getColorSpace()->getNComps()) { + ok = gTrue; + for (i = 0; i < shading->nFuncs; ++i) { + ok = ok && shading->funcs[i]->getOutputSize() == 1; + } + } + if (!ok) { + error(errSyntaxError, -1, "Invalid function in shading dictionary"); + delete shading; + return NULL; + } + + return shading; + + err2: + obj2.free(); + err1: + obj1.free(); + return NULL; +} + +GfxShading *GfxFunctionShading::copy() { + return new GfxFunctionShading(this); +} + +void GfxFunctionShading::getColor(double x, double y, GfxColor *color) { + double in[2], out[gfxColorMaxComps]; + int i; + + // NB: there can be one function with n outputs or n functions with + // one output each (where n = number of color components) + for (i = 0; i < gfxColorMaxComps; ++i) { + out[i] = 0; + } + in[0] = x; + in[1] = y; + for (i = 0; i < nFuncs; ++i) { + funcs[i]->transform(in, &out[i]); + } + for (i = 0; i < gfxColorMaxComps; ++i) { + color->c[i] = dblToCol(out[i]); + } +} + +//------------------------------------------------------------------------ +// GfxAxialShading +//------------------------------------------------------------------------ + +GfxAxialShading::GfxAxialShading(double x0A, double y0A, + double x1A, double y1A, + double t0A, double t1A, + Function **funcsA, int nFuncsA, + GBool extend0A, GBool extend1A): + GfxShading(2) +{ + int i; + + x0 = x0A; + y0 = y0A; + x1 = x1A; + y1 = y1A; + t0 = t0A; + t1 = t1A; + nFuncs = nFuncsA; + for (i = 0; i < nFuncs; ++i) { + funcs[i] = funcsA[i]; + } + extend0 = extend0A; + extend1 = extend1A; +} + +GfxAxialShading::GfxAxialShading(GfxAxialShading *shading): + GfxShading(shading) +{ + int i; + + x0 = shading->x0; + y0 = shading->y0; + x1 = shading->x1; + y1 = shading->y1; + t0 = shading->t0; + t1 = shading->t1; + nFuncs = shading->nFuncs; + for (i = 0; i < nFuncs; ++i) { + funcs[i] = shading->funcs[i]->copy(); + } + extend0 = shading->extend0; + extend1 = shading->extend1; +} + +GfxAxialShading::~GfxAxialShading() { + int i; + + for (i = 0; i < nFuncs; ++i) { + delete funcs[i]; + } +} + +GfxAxialShading *GfxAxialShading::parse(Dict *dict + ) { + GfxAxialShading *shading; + double x0A, y0A, x1A, y1A; + double t0A, t1A; + Function *funcsA[gfxColorMaxComps]; + int nFuncsA; + GBool extend0A, extend1A, ok; + Object obj1, obj2; + int i; + + x0A = y0A = x1A = y1A = 0; + if (dict->lookup("Coords", &obj1)->isArray() && + obj1.arrayGetLength() == 4) { + x0A = obj1.arrayGet(0, &obj2)->getNum(); + obj2.free(); + y0A = obj1.arrayGet(1, &obj2)->getNum(); + obj2.free(); + x1A = obj1.arrayGet(2, &obj2)->getNum(); + obj2.free(); + y1A = obj1.arrayGet(3, &obj2)->getNum(); + obj2.free(); + } else { + error(errSyntaxError, -1, + "Missing or invalid Coords in shading dictionary"); + obj1.free(); + goto err1; + } + obj1.free(); + + t0A = 0; + t1A = 1; + if (dict->lookup("Domain", &obj1)->isArray() && + obj1.arrayGetLength() == 2) { + t0A = obj1.arrayGet(0, &obj2)->getNum(); + obj2.free(); + t1A = obj1.arrayGet(1, &obj2)->getNum(); + obj2.free(); + } + obj1.free(); + + dict->lookup("Function", &obj1); + if (obj1.isArray()) { + nFuncsA = obj1.arrayGetLength(); + if (nFuncsA > gfxColorMaxComps) { + error(errSyntaxError, -1, + "Invalid Function array in shading dictionary"); + goto err1; + } + for (i = 0; i < nFuncsA; ++i) { + obj1.arrayGet(i, &obj2); + if (!(funcsA[i] = Function::parse(&obj2, 1, 1))) { + obj1.free(); + obj2.free(); + goto err1; + } + obj2.free(); + } + } else { + nFuncsA = 1; + if (!(funcsA[0] = Function::parse(&obj1, 1, -1))) { + obj1.free(); + goto err1; + } + } + obj1.free(); + + extend0A = extend1A = gFalse; + if (dict->lookup("Extend", &obj1)->isArray() && + obj1.arrayGetLength() == 2) { + extend0A = obj1.arrayGet(0, &obj2)->getBool(); + obj2.free(); + extend1A = obj1.arrayGet(1, &obj2)->getBool(); + obj2.free(); + } + obj1.free(); + + shading = new GfxAxialShading(x0A, y0A, x1A, y1A, t0A, t1A, + funcsA, nFuncsA, extend0A, extend1A); + if (!shading->init(dict + )) { + delete shading; + return NULL; + } + + ok = gFalse; + if (shading->nFuncs == 1) { + ok = shading->funcs[0]->getOutputSize() + == shading->getColorSpace()->getNComps(); + } else if (shading->nFuncs == shading->getColorSpace()->getNComps()) { + ok = gTrue; + for (i = 0; i < shading->nFuncs; ++i) { + ok = ok && shading->funcs[i]->getOutputSize() == 1; + } + } + if (!ok) { + error(errSyntaxError, -1, "Invalid function in shading dictionary"); + delete shading; + return NULL; + } + + return shading; + + err1: + return NULL; +} + +GfxShading *GfxAxialShading::copy() { + return new GfxAxialShading(this); +} + +void GfxAxialShading::getColor(double t, GfxColor *color) { + double out[gfxColorMaxComps]; + int i; + + // NB: there can be one function with n outputs or n functions with + // one output each (where n = number of color components) + for (i = 0; i < gfxColorMaxComps; ++i) { + out[i] = 0; + } + for (i = 0; i < nFuncs; ++i) { + funcs[i]->transform(&t, &out[i]); + } + for (i = 0; i < gfxColorMaxComps; ++i) { + color->c[i] = dblToCol(out[i]); + } +} + +//------------------------------------------------------------------------ +// GfxRadialShading +//------------------------------------------------------------------------ + +GfxRadialShading::GfxRadialShading(double x0A, double y0A, double r0A, + double x1A, double y1A, double r1A, + double t0A, double t1A, + Function **funcsA, int nFuncsA, + GBool extend0A, GBool extend1A): + GfxShading(3) +{ + int i; + + x0 = x0A; + y0 = y0A; + r0 = r0A; + x1 = x1A; + y1 = y1A; + r1 = r1A; + t0 = t0A; + t1 = t1A; + nFuncs = nFuncsA; + for (i = 0; i < nFuncs; ++i) { + funcs[i] = funcsA[i]; + } + extend0 = extend0A; + extend1 = extend1A; +} + +GfxRadialShading::GfxRadialShading(GfxRadialShading *shading): + GfxShading(shading) +{ + int i; + + x0 = shading->x0; + y0 = shading->y0; + r0 = shading->r0; + x1 = shading->x1; + y1 = shading->y1; + r1 = shading->r1; + t0 = shading->t0; + t1 = shading->t1; + nFuncs = shading->nFuncs; + for (i = 0; i < nFuncs; ++i) { + funcs[i] = shading->funcs[i]->copy(); + } + extend0 = shading->extend0; + extend1 = shading->extend1; +} + +GfxRadialShading::~GfxRadialShading() { + int i; + + for (i = 0; i < nFuncs; ++i) { + delete funcs[i]; + } +} + +GfxRadialShading *GfxRadialShading::parse(Dict *dict + ) { + GfxRadialShading *shading; + double x0A, y0A, r0A, x1A, y1A, r1A; + double t0A, t1A; + Function *funcsA[gfxColorMaxComps]; + int nFuncsA; + GBool extend0A, extend1A, ok; + Object obj1, obj2; + int i; + + x0A = y0A = r0A = x1A = y1A = r1A = 0; + if (dict->lookup("Coords", &obj1)->isArray() && + obj1.arrayGetLength() == 6) { + x0A = obj1.arrayGet(0, &obj2)->getNum(); + obj2.free(); + y0A = obj1.arrayGet(1, &obj2)->getNum(); + obj2.free(); + r0A = obj1.arrayGet(2, &obj2)->getNum(); + obj2.free(); + x1A = obj1.arrayGet(3, &obj2)->getNum(); + obj2.free(); + y1A = obj1.arrayGet(4, &obj2)->getNum(); + obj2.free(); + r1A = obj1.arrayGet(5, &obj2)->getNum(); + obj2.free(); + } else { + error(errSyntaxError, -1, + "Missing or invalid Coords in shading dictionary"); + goto err1; + } + obj1.free(); + + t0A = 0; + t1A = 1; + if (dict->lookup("Domain", &obj1)->isArray() && + obj1.arrayGetLength() == 2) { + t0A = obj1.arrayGet(0, &obj2)->getNum(); + obj2.free(); + t1A = obj1.arrayGet(1, &obj2)->getNum(); + obj2.free(); + } + obj1.free(); + + dict->lookup("Function", &obj1); + if (obj1.isArray()) { + nFuncsA = obj1.arrayGetLength(); + if (nFuncsA > gfxColorMaxComps) { + error(errSyntaxError, -1, + "Invalid Function array in shading dictionary"); + goto err1; + } + for (i = 0; i < nFuncsA; ++i) { + obj1.arrayGet(i, &obj2); + if (!(funcsA[i] = Function::parse(&obj2, 1, 1))) { + obj1.free(); + obj2.free(); + goto err1; + } + obj2.free(); + } + } else { + nFuncsA = 1; + if (!(funcsA[0] = Function::parse(&obj1, 1, -1))) { + obj1.free(); + goto err1; + } + } + obj1.free(); + + extend0A = extend1A = gFalse; + if (dict->lookup("Extend", &obj1)->isArray() && + obj1.arrayGetLength() == 2) { + extend0A = obj1.arrayGet(0, &obj2)->getBool(); + obj2.free(); + extend1A = obj1.arrayGet(1, &obj2)->getBool(); + obj2.free(); + } + obj1.free(); + + shading = new GfxRadialShading(x0A, y0A, r0A, x1A, y1A, r1A, t0A, t1A, + funcsA, nFuncsA, extend0A, extend1A); + if (!shading->init(dict + )) { + delete shading; + return NULL; + } + + ok = gFalse; + if (shading->nFuncs == 1) { + ok = shading->funcs[0]->getOutputSize() + == shading->getColorSpace()->getNComps(); + } else if (shading->nFuncs == shading->getColorSpace()->getNComps()) { + ok = gTrue; + for (i = 0; i < shading->nFuncs; ++i) { + ok = ok && shading->funcs[i]->getOutputSize() == 1; + } + } + if (!ok) { + error(errSyntaxError, -1, "Invalid function in shading dictionary"); + delete shading; + return NULL; + } + + return shading; + + err1: + return NULL; +} + +GfxShading *GfxRadialShading::copy() { + return new GfxRadialShading(this); +} + +void GfxRadialShading::getColor(double t, GfxColor *color) { + double out[gfxColorMaxComps]; + int i; + + // NB: there can be one function with n outputs or n functions with + // one output each (where n = number of color components) + for (i = 0; i < gfxColorMaxComps; ++i) { + out[i] = 0; + } + for (i = 0; i < nFuncs; ++i) { + funcs[i]->transform(&t, &out[i]); + } + for (i = 0; i < gfxColorMaxComps; ++i) { + color->c[i] = dblToCol(out[i]); + } +} + +//------------------------------------------------------------------------ +// GfxShadingBitBuf +//------------------------------------------------------------------------ + +class GfxShadingBitBuf { +public: + + GfxShadingBitBuf(Stream *strA); + ~GfxShadingBitBuf(); + GBool getBits(int n, Guint *val); + void flushBits(); + +private: + + Stream *str; + int bitBuf; + int nBits; +}; + +GfxShadingBitBuf::GfxShadingBitBuf(Stream *strA) { + str = strA; + str->reset(); + bitBuf = 0; + nBits = 0; +} + +GfxShadingBitBuf::~GfxShadingBitBuf() { + str->close(); +} + +GBool GfxShadingBitBuf::getBits(int n, Guint *val) { + int x; + + if (nBits >= n) { + x = (bitBuf >> (nBits - n)) & ((1 << n) - 1); + nBits -= n; + } else { + x = 0; + if (nBits > 0) { + x = bitBuf & ((1 << nBits) - 1); + n -= nBits; + nBits = 0; + } + while (n > 0) { + if ((bitBuf = str->getChar()) == EOF) { + nBits = 0; + return gFalse; + } + if (n >= 8) { + x = (x << 8) | bitBuf; + n -= 8; + } else { + x = (x << n) | (bitBuf >> (8 - n)); + nBits = 8 - n; + n = 0; + } + } + } + *val = x; + return gTrue; +} + +void GfxShadingBitBuf::flushBits() { + bitBuf = 0; + nBits = 0; +} + +//------------------------------------------------------------------------ +// GfxGouraudTriangleShading +//------------------------------------------------------------------------ + +GfxGouraudTriangleShading::GfxGouraudTriangleShading( + int typeA, + GfxGouraudVertex *verticesA, int nVerticesA, + int (*trianglesA)[3], int nTrianglesA, + int nCompsA, Function **funcsA, int nFuncsA): + GfxShading(typeA) +{ + int i; + + vertices = verticesA; + nVertices = nVerticesA; + triangles = trianglesA; + nTriangles = nTrianglesA; + nComps = nCompsA; + nFuncs = nFuncsA; + for (i = 0; i < nFuncs; ++i) { + funcs[i] = funcsA[i]; + } +} + +GfxGouraudTriangleShading::GfxGouraudTriangleShading( + GfxGouraudTriangleShading *shading): + GfxShading(shading) +{ + int i; + + nVertices = shading->nVertices; + vertices = (GfxGouraudVertex *)gmallocn(nVertices, sizeof(GfxGouraudVertex)); + memcpy(vertices, shading->vertices, nVertices * sizeof(GfxGouraudVertex)); + nTriangles = shading->nTriangles; + triangles = (int (*)[3])gmallocn(nTriangles * 3, sizeof(int)); + memcpy(triangles, shading->triangles, nTriangles * 3 * sizeof(int)); + nComps = shading->nComps; + nFuncs = shading->nFuncs; + for (i = 0; i < nFuncs; ++i) { + funcs[i] = shading->funcs[i]->copy(); + } +} + +GfxGouraudTriangleShading::~GfxGouraudTriangleShading() { + int i; + + gfree(vertices); + gfree(triangles); + for (i = 0; i < nFuncs; ++i) { + delete funcs[i]; + } +} + +GfxGouraudTriangleShading *GfxGouraudTriangleShading::parse( + int typeA, Dict *dict, Stream *str + ) { + GfxGouraudTriangleShading *shading; + Function *funcsA[gfxColorMaxComps]; + int nFuncsA; + int coordBits, compBits, flagBits, vertsPerRow, nRows; + double xMin, xMax, yMin, yMax; + double cMin[gfxColorMaxComps], cMax[gfxColorMaxComps]; + double xMul, yMul; + double cMul[gfxColorMaxComps]; + GfxGouraudVertex *verticesA; + int (*trianglesA)[3]; + int nCompsA, nVerticesA, nTrianglesA, vertSize, triSize; + Guint x, y, flag; + Guint c[gfxColorMaxComps]; + GfxShadingBitBuf *bitBuf; + Object obj1, obj2; + GBool ok; + int i, j, k, state; + + if (dict->lookup("BitsPerCoordinate", &obj1)->isInt()) { + coordBits = obj1.getInt(); + } else { + error(errSyntaxError, -1, + "Missing or invalid BitsPerCoordinate in shading dictionary"); + goto err2; + } + if (coordBits <= 0 || coordBits > 32) { + error(errSyntaxError, -1, + "Invalid BitsPerCoordinate in shading dictionary"); + goto err2; + } + obj1.free(); + if (dict->lookup("BitsPerComponent", &obj1)->isInt()) { + compBits = obj1.getInt(); + } else { + error(errSyntaxError, -1, + "Missing or invalid BitsPerComponent in shading dictionary"); + goto err2; + } + if (compBits <= 0 || compBits > 16) { + error(errSyntaxError, -1, + "Invalid BitsPerComponent in shading dictionary"); + goto err2; + } + obj1.free(); + flagBits = vertsPerRow = 0; // make gcc happy + if (typeA == 4) { + if (dict->lookup("BitsPerFlag", &obj1)->isInt()) { + flagBits = obj1.getInt(); + } else { + error(errSyntaxError, -1, + "Missing or invalid BitsPerFlag in shading dictionary"); + goto err2; + } + if (flagBits < 2 || flagBits > 8) { + error(errSyntaxError, -1, "Invalid BitsPerFlag in shading dictionary"); + goto err2; + } + obj1.free(); + } else { + if (dict->lookup("VerticesPerRow", &obj1)->isInt()) { + vertsPerRow = obj1.getInt(); + } else { + error(errSyntaxError, -1, + "Missing or invalid VerticesPerRow in shading dictionary"); + goto err2; + } + obj1.free(); + if (vertsPerRow < 2) { + error(errSyntaxError, -1, + "Invalid VerticesPerRow in shading dictionary"); + goto err2; + } + } + if (dict->lookup("Decode", &obj1)->isArray() && + obj1.arrayGetLength() >= 6) { + xMin = obj1.arrayGet(0, &obj2)->getNum(); + obj2.free(); + xMax = obj1.arrayGet(1, &obj2)->getNum(); + obj2.free(); + xMul = (xMax - xMin) / (pow(2.0, coordBits) - 1); + yMin = obj1.arrayGet(2, &obj2)->getNum(); + obj2.free(); + yMax = obj1.arrayGet(3, &obj2)->getNum(); + obj2.free(); + yMul = (yMax - yMin) / (pow(2.0, coordBits) - 1); + for (i = 0; 5 + 2*i < obj1.arrayGetLength() && i < gfxColorMaxComps; ++i) { + cMin[i] = obj1.arrayGet(4 + 2*i, &obj2)->getNum(); + obj2.free(); + cMax[i] = obj1.arrayGet(5 + 2*i, &obj2)->getNum(); + obj2.free(); + cMul[i] = (cMax[i] - cMin[i]) / (double)((1 << compBits) - 1); + } + nCompsA = i; + } else { + error(errSyntaxError, -1, + "Missing or invalid Decode array in shading dictionary"); + goto err2; + } + obj1.free(); + + if (!dict->lookup("Function", &obj1)->isNull()) { + if (obj1.isArray()) { + nFuncsA = obj1.arrayGetLength(); + if (nFuncsA > gfxColorMaxComps) { + error(errSyntaxError, -1, + "Invalid Function array in shading dictionary"); + goto err1; + } + for (i = 0; i < nFuncsA; ++i) { + obj1.arrayGet(i, &obj2); + if (!(funcsA[i] = Function::parse(&obj2, 1, 1))) { + obj1.free(); + obj2.free(); + goto err1; + } + obj2.free(); + } + } else { + nFuncsA = 1; + if (!(funcsA[0] = Function::parse(&obj1, 1, -1))) { + obj1.free(); + goto err1; + } + } + } else { + nFuncsA = 0; + } + obj1.free(); + + nVerticesA = nTrianglesA = 0; + verticesA = NULL; + trianglesA = NULL; + vertSize = triSize = 0; + state = 0; + flag = 0; // make gcc happy + bitBuf = new GfxShadingBitBuf(str); + while (1) { + if (typeA == 4) { + if (!bitBuf->getBits(flagBits, &flag)) { + break; + } + } + if (!bitBuf->getBits(coordBits, &x) || + !bitBuf->getBits(coordBits, &y)) { + break; + } + for (i = 0; i < nCompsA; ++i) { + if (!bitBuf->getBits(compBits, &c[i])) { + break; + } + } + if (i < nCompsA) { + break; + } + if (nVerticesA == vertSize) { + vertSize = (vertSize == 0) ? 16 : 2 * vertSize; + verticesA = (GfxGouraudVertex *) + greallocn(verticesA, vertSize, sizeof(GfxGouraudVertex)); + } + verticesA[nVerticesA].x = xMin + xMul * (double)x; + verticesA[nVerticesA].y = yMin + yMul * (double)y; + for (i = 0; i < nCompsA; ++i) { + verticesA[nVerticesA].color[i] = cMin[i] + cMul[i] * (double)c[i]; + } + ++nVerticesA; + bitBuf->flushBits(); + if (typeA == 4) { + if (state == 0 || state == 1) { + ++state; + } else if (state == 2 || flag > 0) { + if (nTrianglesA == triSize) { + triSize = (triSize == 0) ? 16 : 2 * triSize; + trianglesA = (int (*)[3]) + greallocn(trianglesA, triSize * 3, sizeof(int)); + } + if (state == 2) { + trianglesA[nTrianglesA][0] = nVerticesA - 3; + trianglesA[nTrianglesA][1] = nVerticesA - 2; + trianglesA[nTrianglesA][2] = nVerticesA - 1; + ++state; + } else if (flag == 1) { + trianglesA[nTrianglesA][0] = trianglesA[nTrianglesA - 1][1]; + trianglesA[nTrianglesA][1] = trianglesA[nTrianglesA - 1][2]; + trianglesA[nTrianglesA][2] = nVerticesA - 1; + } else { // flag == 2 + trianglesA[nTrianglesA][0] = trianglesA[nTrianglesA - 1][0]; + trianglesA[nTrianglesA][1] = trianglesA[nTrianglesA - 1][2]; + trianglesA[nTrianglesA][2] = nVerticesA - 1; + } + ++nTrianglesA; + } else { // state == 3 && flag == 0 + state = 1; + } + } + } + delete bitBuf; + if (typeA == 5) { + nRows = nVerticesA / vertsPerRow; + nTrianglesA = (nRows - 1) * 2 * (vertsPerRow - 1); + trianglesA = (int (*)[3])gmallocn(nTrianglesA * 3, sizeof(int)); + k = 0; + for (i = 0; i < nRows - 1; ++i) { + for (j = 0; j < vertsPerRow - 1; ++j) { + trianglesA[k][0] = i * vertsPerRow + j; + trianglesA[k][1] = i * vertsPerRow + j+1; + trianglesA[k][2] = (i+1) * vertsPerRow + j; + ++k; + trianglesA[k][0] = i * vertsPerRow + j+1; + trianglesA[k][1] = (i+1) * vertsPerRow + j; + trianglesA[k][2] = (i+1) * vertsPerRow + j+1; + ++k; + } + } + } + + shading = new GfxGouraudTriangleShading(typeA, verticesA, nVerticesA, + trianglesA, nTrianglesA, + nCompsA, funcsA, nFuncsA); + if (!shading->init(dict + )) { + delete shading; + return NULL; + } + + ok = gFalse; + if (shading->nFuncs == 0) { + ok = shading->nComps == shading->getColorSpace()->getNComps(); + } else if (shading->nFuncs == 1) { + ok = shading->funcs[0]->getOutputSize() + == shading->getColorSpace()->getNComps(); + } else if (shading->nFuncs == shading->getColorSpace()->getNComps()) { + ok = gTrue; + for (i = 0; i < shading->nFuncs; ++i) { + ok = ok && shading->funcs[i]->getOutputSize() == 1; + } + } + if (!ok) { + error(errSyntaxError, -1, "Invalid function in shading dictionary"); + delete shading; + return NULL; + } + + return shading; + + err2: + obj1.free(); + err1: + return NULL; +} + +GfxShading *GfxGouraudTriangleShading::copy() { + return new GfxGouraudTriangleShading(this); +} + +void GfxGouraudTriangleShading::getTriangle( + int i, + double *x0, double *y0, double *color0, + double *x1, double *y1, double *color1, + double *x2, double *y2, double *color2) { + int v, j; + + v = triangles[i][0]; + *x0 = vertices[v].x; + *y0 = vertices[v].y; + for (j = 0; j < nComps; ++j) { + color0[j] = vertices[v].color[j]; + } + v = triangles[i][1]; + *x1 = vertices[v].x; + *y1 = vertices[v].y; + for (j = 0; j < nComps; ++j) { + color1[j] = vertices[v].color[j]; + } + v = triangles[i][2]; + *x2 = vertices[v].x; + *y2 = vertices[v].y; + for (j = 0; j < nComps; ++j) { + color2[j] = vertices[v].color[j]; + } +} + +void GfxGouraudTriangleShading::getBBox(double *xMin, double *yMin, + double *xMax, double *yMax) { + double xxMin = 0; + double yyMin = 0; + double xxMax = 0; + double yyMax = 0; + if (nVertices > 0) { + xxMin = xxMax = vertices[0].x; + yyMin = yyMax = vertices[0].y; + } + for (int i = 1; i < nVertices; ++i) { + if (vertices[i].x < xxMin) { + xxMin = vertices[i].x; + } else if (vertices[i].x > xxMax) { + xxMax = vertices[i].x; + } + if (vertices[i].y < yyMin) { + yyMin = vertices[i].y; + } else if (vertices[i].y > yyMax) { + yyMax = vertices[i].y; + } + } + *xMin = xxMin; + *yMin = yyMin; + *xMax = xxMax; + *yMax = yyMax; +} + +void GfxGouraudTriangleShading::getColor(double *in, GfxColor *out) { + double c[gfxColorMaxComps]; + int i; + + if (nFuncs > 0) { + for (i = 0; i < nFuncs; ++i) { + funcs[i]->transform(in, &c[i]); + } + for (i = 0; i < colorSpace->getNComps(); ++i) { + out->c[i] = dblToCol(c[i]); + } + } else { + for (i = 0; i < nComps; ++i) { + out->c[i] = dblToCol(in[i]); + } + } +} + +//------------------------------------------------------------------------ +// GfxPatchMeshShading +//------------------------------------------------------------------------ + +GfxPatchMeshShading::GfxPatchMeshShading(int typeA, + GfxPatch *patchesA, int nPatchesA, + int nCompsA, + Function **funcsA, int nFuncsA): + GfxShading(typeA) +{ + int i; + + patches = patchesA; + nPatches = nPatchesA; + nComps = nCompsA; + nFuncs = nFuncsA; + for (i = 0; i < nFuncs; ++i) { + funcs[i] = funcsA[i]; + } +} + +GfxPatchMeshShading::GfxPatchMeshShading(GfxPatchMeshShading *shading): + GfxShading(shading) +{ + int i; + + nPatches = shading->nPatches; + patches = (GfxPatch *)gmallocn(nPatches, sizeof(GfxPatch)); + memcpy(patches, shading->patches, nPatches * sizeof(GfxPatch)); + nComps = shading->nComps; + nFuncs = shading->nFuncs; + for (i = 0; i < nFuncs; ++i) { + funcs[i] = shading->funcs[i]->copy(); + } +} + +GfxPatchMeshShading::~GfxPatchMeshShading() { + int i; + + gfree(patches); + for (i = 0; i < nFuncs; ++i) { + delete funcs[i]; + } +} + +GfxPatchMeshShading *GfxPatchMeshShading::parse(int typeA, Dict *dict, + Stream *str + ) { + GfxPatchMeshShading *shading; + Function *funcsA[gfxColorMaxComps]; + int nFuncsA; + int coordBits, compBits, flagBits; + double xMin, xMax, yMin, yMax; + double cMin[gfxColorMaxComps], cMax[gfxColorMaxComps]; + double xMul, yMul; + double cMul[gfxColorMaxComps]; + GfxPatch *patchesA, *p; + int nCompsA, nPatchesA, patchesSize, nPts, nColors; + Guint flag; + double x[16], y[16]; + Guint xi, yi; + double c[4][gfxColorMaxComps]; + Guint ci; + GfxShadingBitBuf *bitBuf; + Object obj1, obj2; + GBool ok; + int i, j; + + nPatchesA = 0; + patchesA = NULL; + patchesSize = 0; + + if (dict->lookup("BitsPerCoordinate", &obj1)->isInt()) { + coordBits = obj1.getInt(); + } else { + error(errSyntaxError, -1, + "Missing or invalid BitsPerCoordinate in shading dictionary"); + goto err2; + } + if (coordBits <= 0 || coordBits > 32) { + error(errSyntaxError, -1, + "Invalid BitsPerCoordinate in shading dictionary"); + goto err2; + } + obj1.free(); + if (dict->lookup("BitsPerComponent", &obj1)->isInt()) { + compBits = obj1.getInt(); + } else { + error(errSyntaxError, -1, + "Missing or invalid BitsPerComponent in shading dictionary"); + goto err2; + } + if (compBits <= 0 || compBits > 16) { + error(errSyntaxError, -1, + "Invalid BitsPerComponent in shading dictionary"); + goto err2; + } + obj1.free(); + if (dict->lookup("BitsPerFlag", &obj1)->isInt()) { + flagBits = obj1.getInt(); + } else { + error(errSyntaxError, -1, + "Missing or invalid BitsPerFlag in shading dictionary"); + goto err2; + } + if (flagBits < 2 || flagBits > 8) { + error(errSyntaxError, -1, "Invalid BitsPerFlag in shading dictionary"); + goto err2; + } + obj1.free(); + if (dict->lookup("Decode", &obj1)->isArray() && + obj1.arrayGetLength() >= 6) { + xMin = obj1.arrayGet(0, &obj2)->getNum(); + obj2.free(); + xMax = obj1.arrayGet(1, &obj2)->getNum(); + obj2.free(); + xMul = (xMax - xMin) / (pow(2.0, coordBits) - 1); + yMin = obj1.arrayGet(2, &obj2)->getNum(); + obj2.free(); + yMax = obj1.arrayGet(3, &obj2)->getNum(); + obj2.free(); + yMul = (yMax - yMin) / (pow(2.0, coordBits) - 1); + for (i = 0; 5 + 2*i < obj1.arrayGetLength() && i < gfxColorMaxComps; ++i) { + cMin[i] = obj1.arrayGet(4 + 2*i, &obj2)->getNum(); + obj2.free(); + cMax[i] = obj1.arrayGet(5 + 2*i, &obj2)->getNum(); + obj2.free(); + cMul[i] = (cMax[i] - cMin[i]) / (double)((1 << compBits) - 1); + } + nCompsA = i; + } else { + error(errSyntaxError, -1, + "Missing or invalid Decode array in shading dictionary"); + goto err2; + } + obj1.free(); + + if (!dict->lookup("Function", &obj1)->isNull()) { + if (obj1.isArray()) { + nFuncsA = obj1.arrayGetLength(); + if (nFuncsA > gfxColorMaxComps) { + error(errSyntaxError, -1, + "Invalid Function array in shading dictionary"); + goto err1; + } + for (i = 0; i < nFuncsA; ++i) { + obj1.arrayGet(i, &obj2); + if (!(funcsA[i] = Function::parse(&obj2, 1, 1))) { + obj1.free(); + obj2.free(); + goto err1; + } + obj2.free(); + } + } else { + nFuncsA = 1; + if (!(funcsA[0] = Function::parse(&obj1, 1, -1))) { + obj1.free(); + goto err1; + } + } + } else { + nFuncsA = 0; + } + obj1.free(); + + bitBuf = new GfxShadingBitBuf(str); + while (1) { + if (!bitBuf->getBits(flagBits, &flag)) { + break; + } + flag &= 3; + if (flag != 0 && nPatchesA == 0) { + error(errSyntaxError, -1, "Invalid patch in patch mesh shading"); + delete bitBuf; + goto err1; + } + if (typeA == 6) { + switch (flag) { + case 0: nPts = 12; nColors = 4; break; + case 1: + case 2: + case 3: + default: nPts = 8; nColors = 2; break; + } + } else { + switch (flag) { + case 0: nPts = 16; nColors = 4; break; + case 1: + case 2: + case 3: + default: nPts = 12; nColors = 2; break; + } + } + for (i = 0; i < nPts; ++i) { + if (!bitBuf->getBits(coordBits, &xi) || + !bitBuf->getBits(coordBits, &yi)) { + break; + } + x[i] = xMin + xMul * (double)xi; + y[i] = yMin + yMul * (double)yi; + } + if (i < nPts) { + break; + } + for (i = 0; i < nColors; ++i) { + for (j = 0; j < nCompsA; ++j) { + if (!bitBuf->getBits(compBits, &ci)) { + break; + } + c[i][j] = cMin[j] + cMul[j] * (double)ci; + } + if (j < nCompsA) { + break; + } + } + if (i < nColors) { + break; + } + if (nPatchesA == patchesSize) { + patchesSize = (patchesSize == 0) ? 16 : 2 * patchesSize; + patchesA = (GfxPatch *)greallocn(patchesA, + patchesSize, sizeof(GfxPatch)); + } + p = &patchesA[nPatchesA]; + if (typeA == 6) { + switch (flag) { + case 0: + p->x[0][0] = x[0]; + p->y[0][0] = y[0]; + p->x[0][1] = x[1]; + p->y[0][1] = y[1]; + p->x[0][2] = x[2]; + p->y[0][2] = y[2]; + p->x[0][3] = x[3]; + p->y[0][3] = y[3]; + p->x[1][3] = x[4]; + p->y[1][3] = y[4]; + p->x[2][3] = x[5]; + p->y[2][3] = y[5]; + p->x[3][3] = x[6]; + p->y[3][3] = y[6]; + p->x[3][2] = x[7]; + p->y[3][2] = y[7]; + p->x[3][1] = x[8]; + p->y[3][1] = y[8]; + p->x[3][0] = x[9]; + p->y[3][0] = y[9]; + p->x[2][0] = x[10]; + p->y[2][0] = y[10]; + p->x[1][0] = x[11]; + p->y[1][0] = y[11]; + for (j = 0; j < nCompsA; ++j) { + p->color[0][0][j] = c[0][j]; + p->color[0][1][j] = c[1][j]; + p->color[1][1][j] = c[2][j]; + p->color[1][0][j] = c[3][j]; + } + break; + case 1: + p->x[0][0] = patchesA[nPatchesA-1].x[0][3]; + p->y[0][0] = patchesA[nPatchesA-1].y[0][3]; + p->x[0][1] = patchesA[nPatchesA-1].x[1][3]; + p->y[0][1] = patchesA[nPatchesA-1].y[1][3]; + p->x[0][2] = patchesA[nPatchesA-1].x[2][3]; + p->y[0][2] = patchesA[nPatchesA-1].y[2][3]; + p->x[0][3] = patchesA[nPatchesA-1].x[3][3]; + p->y[0][3] = patchesA[nPatchesA-1].y[3][3]; + p->x[1][3] = x[0]; + p->y[1][3] = y[0]; + p->x[2][3] = x[1]; + p->y[2][3] = y[1]; + p->x[3][3] = x[2]; + p->y[3][3] = y[2]; + p->x[3][2] = x[3]; + p->y[3][2] = y[3]; + p->x[3][1] = x[4]; + p->y[3][1] = y[4]; + p->x[3][0] = x[5]; + p->y[3][0] = y[5]; + p->x[2][0] = x[6]; + p->y[2][0] = y[6]; + p->x[1][0] = x[7]; + p->y[1][0] = y[7]; + for (j = 0; j < nCompsA; ++j) { + p->color[0][0][j] = patchesA[nPatchesA-1].color[0][1][j]; + p->color[0][1][j] = patchesA[nPatchesA-1].color[1][1][j]; + p->color[1][1][j] = c[0][j]; + p->color[1][0][j] = c[1][j]; + } + break; + case 2: + p->x[0][0] = patchesA[nPatchesA-1].x[3][3]; + p->y[0][0] = patchesA[nPatchesA-1].y[3][3]; + p->x[0][1] = patchesA[nPatchesA-1].x[3][2]; + p->y[0][1] = patchesA[nPatchesA-1].y[3][2]; + p->x[0][2] = patchesA[nPatchesA-1].x[3][1]; + p->y[0][2] = patchesA[nPatchesA-1].y[3][1]; + p->x[0][3] = patchesA[nPatchesA-1].x[3][0]; + p->y[0][3] = patchesA[nPatchesA-1].y[3][0]; + p->x[1][3] = x[0]; + p->y[1][3] = y[0]; + p->x[2][3] = x[1]; + p->y[2][3] = y[1]; + p->x[3][3] = x[2]; + p->y[3][3] = y[2]; + p->x[3][2] = x[3]; + p->y[3][2] = y[3]; + p->x[3][1] = x[4]; + p->y[3][1] = y[4]; + p->x[3][0] = x[5]; + p->y[3][0] = y[5]; + p->x[2][0] = x[6]; + p->y[2][0] = y[6]; + p->x[1][0] = x[7]; + p->y[1][0] = y[7]; + for (j = 0; j < nCompsA; ++j) { + p->color[0][0][j] = patchesA[nPatchesA-1].color[1][1][j]; + p->color[0][1][j] = patchesA[nPatchesA-1].color[1][0][j]; + p->color[1][1][j] = c[0][j]; + p->color[1][0][j] = c[1][j]; + } + break; + case 3: + p->x[0][0] = patchesA[nPatchesA-1].x[3][0]; + p->y[0][0] = patchesA[nPatchesA-1].y[3][0]; + p->x[0][1] = patchesA[nPatchesA-1].x[2][0]; + p->y[0][1] = patchesA[nPatchesA-1].y[2][0]; + p->x[0][2] = patchesA[nPatchesA-1].x[1][0]; + p->y[0][2] = patchesA[nPatchesA-1].y[1][0]; + p->x[0][3] = patchesA[nPatchesA-1].x[0][0]; + p->y[0][3] = patchesA[nPatchesA-1].y[0][0]; + p->x[1][3] = x[0]; + p->y[1][3] = y[0]; + p->x[2][3] = x[1]; + p->y[2][3] = y[1]; + p->x[3][3] = x[2]; + p->y[3][3] = y[2]; + p->x[3][2] = x[3]; + p->y[3][2] = y[3]; + p->x[3][1] = x[4]; + p->y[3][1] = y[4]; + p->x[3][0] = x[5]; + p->y[3][0] = y[5]; + p->x[2][0] = x[6]; + p->y[2][0] = y[6]; + p->x[1][0] = x[7]; + p->y[1][0] = y[7]; + for (j = 0; j < nCompsA; ++j) { + p->color[0][0][j] = patchesA[nPatchesA-1].color[1][0][j]; + p->color[0][1][j] = patchesA[nPatchesA-1].color[0][0][j]; + p->color[1][1][j] = c[0][j]; + p->color[1][0][j] = c[1][j]; + } + break; + } + } else { + switch (flag) { + case 0: + p->x[0][0] = x[0]; + p->y[0][0] = y[0]; + p->x[0][1] = x[1]; + p->y[0][1] = y[1]; + p->x[0][2] = x[2]; + p->y[0][2] = y[2]; + p->x[0][3] = x[3]; + p->y[0][3] = y[3]; + p->x[1][3] = x[4]; + p->y[1][3] = y[4]; + p->x[2][3] = x[5]; + p->y[2][3] = y[5]; + p->x[3][3] = x[6]; + p->y[3][3] = y[6]; + p->x[3][2] = x[7]; + p->y[3][2] = y[7]; + p->x[3][1] = x[8]; + p->y[3][1] = y[8]; + p->x[3][0] = x[9]; + p->y[3][0] = y[9]; + p->x[2][0] = x[10]; + p->y[2][0] = y[10]; + p->x[1][0] = x[11]; + p->y[1][0] = y[11]; + p->x[1][1] = x[12]; + p->y[1][1] = y[12]; + p->x[1][2] = x[13]; + p->y[1][2] = y[13]; + p->x[2][2] = x[14]; + p->y[2][2] = y[14]; + p->x[2][1] = x[15]; + p->y[2][1] = y[15]; + for (j = 0; j < nCompsA; ++j) { + p->color[0][0][j] = c[0][j]; + p->color[0][1][j] = c[1][j]; + p->color[1][1][j] = c[2][j]; + p->color[1][0][j] = c[3][j]; + } + break; + case 1: + p->x[0][0] = patchesA[nPatchesA-1].x[0][3]; + p->y[0][0] = patchesA[nPatchesA-1].y[0][3]; + p->x[0][1] = patchesA[nPatchesA-1].x[1][3]; + p->y[0][1] = patchesA[nPatchesA-1].y[1][3]; + p->x[0][2] = patchesA[nPatchesA-1].x[2][3]; + p->y[0][2] = patchesA[nPatchesA-1].y[2][3]; + p->x[0][3] = patchesA[nPatchesA-1].x[3][3]; + p->y[0][3] = patchesA[nPatchesA-1].y[3][3]; + p->x[1][3] = x[0]; + p->y[1][3] = y[0]; + p->x[2][3] = x[1]; + p->y[2][3] = y[1]; + p->x[3][3] = x[2]; + p->y[3][3] = y[2]; + p->x[3][2] = x[3]; + p->y[3][2] = y[3]; + p->x[3][1] = x[4]; + p->y[3][1] = y[4]; + p->x[3][0] = x[5]; + p->y[3][0] = y[5]; + p->x[2][0] = x[6]; + p->y[2][0] = y[6]; + p->x[1][0] = x[7]; + p->y[1][0] = y[7]; + p->x[1][1] = x[8]; + p->y[1][1] = y[8]; + p->x[1][2] = x[9]; + p->y[1][2] = y[9]; + p->x[2][2] = x[10]; + p->y[2][2] = y[10]; + p->x[2][1] = x[11]; + p->y[2][1] = y[11]; + for (j = 0; j < nCompsA; ++j) { + p->color[0][0][j] = patchesA[nPatchesA-1].color[0][1][j]; + p->color[0][1][j] = patchesA[nPatchesA-1].color[1][1][j]; + p->color[1][1][j] = c[0][j]; + p->color[1][0][j] = c[1][j]; + } + break; + case 2: + p->x[0][0] = patchesA[nPatchesA-1].x[3][3]; + p->y[0][0] = patchesA[nPatchesA-1].y[3][3]; + p->x[0][1] = patchesA[nPatchesA-1].x[3][2]; + p->y[0][1] = patchesA[nPatchesA-1].y[3][2]; + p->x[0][2] = patchesA[nPatchesA-1].x[3][1]; + p->y[0][2] = patchesA[nPatchesA-1].y[3][1]; + p->x[0][3] = patchesA[nPatchesA-1].x[3][0]; + p->y[0][3] = patchesA[nPatchesA-1].y[3][0]; + p->x[1][3] = x[0]; + p->y[1][3] = y[0]; + p->x[2][3] = x[1]; + p->y[2][3] = y[1]; + p->x[3][3] = x[2]; + p->y[3][3] = y[2]; + p->x[3][2] = x[3]; + p->y[3][2] = y[3]; + p->x[3][1] = x[4]; + p->y[3][1] = y[4]; + p->x[3][0] = x[5]; + p->y[3][0] = y[5]; + p->x[2][0] = x[6]; + p->y[2][0] = y[6]; + p->x[1][0] = x[7]; + p->y[1][0] = y[7]; + p->x[1][1] = x[8]; + p->y[1][1] = y[8]; + p->x[1][2] = x[9]; + p->y[1][2] = y[9]; + p->x[2][2] = x[10]; + p->y[2][2] = y[10]; + p->x[2][1] = x[11]; + p->y[2][1] = y[11]; + for (j = 0; j < nCompsA; ++j) { + p->color[0][0][j] = patchesA[nPatchesA-1].color[1][1][j]; + p->color[0][1][j] = patchesA[nPatchesA-1].color[1][0][j]; + p->color[1][1][j] = c[0][j]; + p->color[1][0][j] = c[1][j]; + } + break; + case 3: + p->x[0][0] = patchesA[nPatchesA-1].x[3][0]; + p->y[0][0] = patchesA[nPatchesA-1].y[3][0]; + p->x[0][1] = patchesA[nPatchesA-1].x[2][0]; + p->y[0][1] = patchesA[nPatchesA-1].y[2][0]; + p->x[0][2] = patchesA[nPatchesA-1].x[1][0]; + p->y[0][2] = patchesA[nPatchesA-1].y[1][0]; + p->x[0][3] = patchesA[nPatchesA-1].x[0][0]; + p->y[0][3] = patchesA[nPatchesA-1].y[0][0]; + p->x[1][3] = x[0]; + p->y[1][3] = y[0]; + p->x[2][3] = x[1]; + p->y[2][3] = y[1]; + p->x[3][3] = x[2]; + p->y[3][3] = y[2]; + p->x[3][2] = x[3]; + p->y[3][2] = y[3]; + p->x[3][1] = x[4]; + p->y[3][1] = y[4]; + p->x[3][0] = x[5]; + p->y[3][0] = y[5]; + p->x[2][0] = x[6]; + p->y[2][0] = y[6]; + p->x[1][0] = x[7]; + p->y[1][0] = y[7]; + p->x[1][1] = x[8]; + p->y[1][1] = y[8]; + p->x[1][2] = x[9]; + p->y[1][2] = y[9]; + p->x[2][2] = x[10]; + p->y[2][2] = y[10]; + p->x[2][1] = x[11]; + p->y[2][1] = y[11]; + for (j = 0; j < nCompsA; ++j) { + p->color[0][0][j] = patchesA[nPatchesA-1].color[1][0][j]; + p->color[0][1][j] = patchesA[nPatchesA-1].color[0][0][j]; + p->color[1][1][j] = c[0][j]; + p->color[1][0][j] = c[1][j]; + } + break; + } + } + ++nPatchesA; + bitBuf->flushBits(); + } + delete bitBuf; + + if (typeA == 6) { + for (i = 0; i < nPatchesA; ++i) { + p = &patchesA[i]; + p->x[1][1] = (-4 * p->x[0][0] + +6 * (p->x[0][1] + p->x[1][0]) + -2 * (p->x[0][3] + p->x[3][0]) + +3 * (p->x[3][1] + p->x[1][3]) + - p->x[3][3]) / 9; + p->y[1][1] = (-4 * p->y[0][0] + +6 * (p->y[0][1] + p->y[1][0]) + -2 * (p->y[0][3] + p->y[3][0]) + +3 * (p->y[3][1] + p->y[1][3]) + - p->y[3][3]) / 9; + p->x[1][2] = (-4 * p->x[0][3] + +6 * (p->x[0][2] + p->x[1][3]) + -2 * (p->x[0][0] + p->x[3][3]) + +3 * (p->x[3][2] + p->x[1][0]) + - p->x[3][0]) / 9; + p->y[1][2] = (-4 * p->y[0][3] + +6 * (p->y[0][2] + p->y[1][3]) + -2 * (p->y[0][0] + p->y[3][3]) + +3 * (p->y[3][2] + p->y[1][0]) + - p->y[3][0]) / 9; + p->x[2][1] = (-4 * p->x[3][0] + +6 * (p->x[3][1] + p->x[2][0]) + -2 * (p->x[3][3] + p->x[0][0]) + +3 * (p->x[0][1] + p->x[2][3]) + - p->x[0][3]) / 9; + p->y[2][1] = (-4 * p->y[3][0] + +6 * (p->y[3][1] + p->y[2][0]) + -2 * (p->y[3][3] + p->y[0][0]) + +3 * (p->y[0][1] + p->y[2][3]) + - p->y[0][3]) / 9; + p->x[2][2] = (-4 * p->x[3][3] + +6 * (p->x[3][2] + p->x[2][3]) + -2 * (p->x[3][0] + p->x[0][3]) + +3 * (p->x[0][2] + p->x[2][0]) + - p->x[0][0]) / 9; + p->y[2][2] = (-4 * p->y[3][3] + +6 * (p->y[3][2] + p->y[2][3]) + -2 * (p->y[3][0] + p->y[0][3]) + +3 * (p->y[0][2] + p->y[2][0]) + - p->y[0][0]) / 9; + } + } + + shading = new GfxPatchMeshShading(typeA, patchesA, nPatchesA, + nCompsA, funcsA, nFuncsA); + if (!shading->init(dict + )) { + delete shading; + return NULL; + } + + ok = gFalse; + if (shading->nFuncs == 0) { + ok = shading->nComps == shading->getColorSpace()->getNComps(); + } else if (shading->nFuncs == 1) { + ok = shading->funcs[0]->getOutputSize() + == shading->getColorSpace()->getNComps(); + } else if (shading->nFuncs == shading->getColorSpace()->getNComps()) { + ok = gTrue; + for (i = 0; i < shading->nFuncs; ++i) { + ok = ok && shading->funcs[i]->getOutputSize() == 1; + } + } + if (!ok) { + error(errSyntaxError, -1, "Invalid function in shading dictionary"); + delete shading; + return NULL; + } + + return shading; + + err2: + obj1.free(); + err1: + if (patchesA) { + gfree(patchesA); + } + return NULL; +} + +GfxShading *GfxPatchMeshShading::copy() { + return new GfxPatchMeshShading(this); +} + +void GfxPatchMeshShading::getBBox(double *xMin, double *yMin, + double *xMax, double *yMax) { + double xxMin = 0; + double yyMin = 0; + double xxMax = 0; + double yyMax = 0; + if (nPatches > 0) { + xxMin = patches[0].x[0][0]; + yyMin = patches[0].y[0][0]; + } + for (int i = 0; i < nPatches; ++i) { + for (int j = 0; j < 4; ++j) { + for (int k = 0; k < 4; ++k) { + if (patches[i].x[j][k] < xxMin) { + xxMin = patches[i].x[j][k]; + } else if (patches[i].x[j][k] > xxMax) { + xxMax = patches[i].x[j][k]; + } + if (patches[i].y[j][k] < yyMin) { + yyMin = patches[i].y[j][k]; + } else if (patches[i].y[j][k] > yyMax) { + yyMax = patches[i].y[j][k]; + } + } + } + } + *xMin = xxMin; + *yMin = yyMin; + *xMax = xxMax; + *yMax = yyMax; +} + +void GfxPatchMeshShading::getColor(double *in, GfxColor *out) { + double c[gfxColorMaxComps]; + int i; + + if (nFuncs > 0) { + for (i = 0; i < nFuncs; ++i) { + funcs[i]->transform(in, &c[i]); + } + for (i = 0; i < colorSpace->getNComps(); ++i) { + out->c[i] = dblToCol(c[i]); + } + } else { + for (i = 0; i < nComps; ++i) { + out->c[i] = dblToCol(in[i]); + } + } +} + +//------------------------------------------------------------------------ +// GfxImageColorMap +//------------------------------------------------------------------------ + +GfxImageColorMap::GfxImageColorMap(int bitsA, Object *decode, + GfxColorSpace *colorSpaceA, + int maxAllowedBits) { + GfxIndexedColorSpace *indexedCS; + GfxSeparationColorSpace *sepCS; + int maxPixel, indexHigh; + Guchar *indexedLookup; + Function *sepFunc; + Object obj; + double defaultLow[gfxColorMaxComps], defaultRange[gfxColorMaxComps]; + double x[gfxColorMaxComps], y[gfxColorMaxComps]; + int i, j, k; + + ok = gTrue; + + // bits per component and color space + bits = bitsA; + if (bits <= maxAllowedBits) { + maxPixel = (1 << bits) - 1; + } else { + maxPixel = (1 << maxAllowedBits) - 1; + } + colorSpace = colorSpaceA; + + // initialize + for (k = 0; k < gfxColorMaxComps; ++k) { + lookup[k] = NULL; + lookup2[k] = NULL; + } + + // get decode map + colorSpace->getDefaultRanges(defaultLow, defaultRange, maxPixel); + if (decode->isNull()) { + nComps = colorSpace->getNComps(); + for (i = 0; i < nComps; ++i) { + decodeLow[i] = defaultLow[i]; + decodeRange[i] = defaultRange[i]; + } + } else if (decode->isArray()) { + nComps = decode->arrayGetLength() / 2; + 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()) { + goto err2; + } + decodeLow[i] = obj.getNum(); + obj.free(); + decode->arrayGet(2*i+1, &obj); + if (!obj.isNum()) { + goto err2; + } + decodeRange[i] = obj.getNum() - decodeLow[i]; + obj.free(); + } + } else { + goto err1; + } + + // 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) { + double t = decodeLow[k] + (i * decodeRange[k]) / maxPixel; + if (t < defaultLow[k]) { + t = defaultLow[k]; + } else if (t > defaultLow[k] + defaultRange[k]) { + t = defaultLow[k] + defaultRange[k]; + } + lookup[k][i] = dblToCol(t); + } + } + + // Optimization: for Indexed and Separation color spaces (which have + // only one component), we pre-compute a second lookup table with + // color values + colorSpace2 = NULL; + nComps2 = 0; + if (colorSpace->getMode() == csIndexed) { + // Note that indexHigh may not be the same as maxPixel -- + // Distiller will remove unused palette entries, resulting in + // indexHigh < maxPixel. + indexedCS = (GfxIndexedColorSpace *)colorSpace; + colorSpace2 = indexedCS->getBase(); + indexHigh = indexedCS->getIndexHigh(); + nComps2 = colorSpace2->getNComps(); + indexedLookup = indexedCS->getLookup(); + colorSpace2->getDefaultRanges(x, y, indexHigh); + for (k = 0; k < nComps2; ++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) { + sepCS = (GfxSeparationColorSpace *)colorSpace; + colorSpace2 = sepCS->getAlt(); + nComps2 = colorSpace2->getNComps(); + sepFunc = sepCS->getFunc(); + for (k = 0; k < nComps2; ++k) { + lookup2[k] = (GfxColorComp *)gmallocn(maxPixel + 1, + sizeof(GfxColorComp)); + } + for (i = 0; i <= maxPixel; ++i) { + double t = decodeLow[0] + (i * decodeRange[0]) / maxPixel; + if (t < defaultLow[0]) { + t = defaultLow[0]; + } else if (t > defaultLow[0] + defaultRange[0]) { + t = defaultLow[0] + defaultRange[0]; + } + x[0] = t; + sepFunc->transform(x, y); + for (k = 0; k < nComps2; ++k) { + lookup2[k][i] = dblToCol(y[k]); + } + } + } + + return; + + err2: + obj.free(); + err1: + ok = gFalse; +} + +GfxImageColorMap::GfxImageColorMap(GfxImageColorMap *colorMap) { + int n, i, k; + + colorSpace = colorMap->colorSpace->copy(); + bits = colorMap->bits; + nComps = colorMap->nComps; + nComps2 = colorMap->nComps2; + colorSpace2 = NULL; + for (k = 0; k < gfxColorMaxComps; ++k) { + lookup[k] = NULL; + lookup2[k] = NULL; + } + if (bits <= 8) { + n = 1 << bits; + } else { + n = 256; + } + for (k = 0; k < nComps; ++k) { + lookup[k] = (GfxColorComp *)gmallocn(n, sizeof(GfxColorComp)); + memcpy(lookup[k], colorMap->lookup[k], n * sizeof(GfxColorComp)); + } + if (colorSpace->getMode() == csIndexed) { + colorSpace2 = ((GfxIndexedColorSpace *)colorSpace)->getBase(); + for (k = 0; k < nComps2; ++k) { + 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) { + lookup2[k] = (GfxColorComp *)gmallocn(n, sizeof(GfxColorComp)); + memcpy(lookup2[k], colorMap->lookup2[k], n * sizeof(GfxColorComp)); + } + } + for (i = 0; i < nComps; ++i) { + decodeLow[i] = colorMap->decodeLow[i]; + decodeRange[i] = colorMap->decodeRange[i]; + } + ok = gTrue; +} + +GfxImageColorMap::~GfxImageColorMap() { + int i; + + delete colorSpace; + for (i = 0; i < gfxColorMaxComps; ++i) { + gfree(lookup[i]); + gfree(lookup2[i]); + } +} + +void GfxImageColorMap::getGray(Guchar *x, GfxGray *gray, + GfxRenderingIntent ri) { + GfxColor color; + int i; + + if (colorSpace2) { + for (i = 0; i < nComps2; ++i) { + color.c[i] = lookup2[i][x[0]]; + } + colorSpace2->getGray(&color, gray, ri); + } else { + for (i = 0; i < nComps; ++i) { + color.c[i] = lookup[i][x[i]]; + } + colorSpace->getGray(&color, gray, ri); + } +} + +void GfxImageColorMap::getRGB(Guchar *x, GfxRGB *rgb, GfxRenderingIntent ri) { + GfxColor color; + int i; + + if (colorSpace2) { + for (i = 0; i < nComps2; ++i) { + color.c[i] = lookup2[i][x[0]]; + } + colorSpace2->getRGB(&color, rgb, ri); + } else { + for (i = 0; i < nComps; ++i) { + color.c[i] = lookup[i][x[i]]; + } + colorSpace->getRGB(&color, rgb, ri); + } +} + +void GfxImageColorMap::getCMYK(Guchar *x, GfxCMYK *cmyk, + GfxRenderingIntent ri) { + GfxColor color; + int i; + + if (colorSpace2) { + for (i = 0; i < nComps2; ++i) { + color.c[i] = lookup2[i][x[0]]; + } + colorSpace2->getCMYK(&color, cmyk, ri); + } else { + for (i = 0; i < nComps; ++i) { + color.c[i] = lookup[i][x[i]]; + } + colorSpace->getCMYK(&color, cmyk, ri); + } +} + + +void GfxImageColorMap::getColor(Guchar *x, GfxColor *color) { + int i; + + for (i = 0; i < nComps; ++i) { + color->c[i] = lookup[i][x[i]]; + } +} + +void GfxImageColorMap::getGrayByteLine(Guchar *in, Guchar *out, int n, + GfxRenderingIntent ri) { + 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, ri); + 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, ri); + out[j] = colToByte(gray); + } + } +} + +void GfxImageColorMap::getRGBByteLine(Guchar *in, Guchar *out, int n, + GfxRenderingIntent ri) { + 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, ri); + 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, ri); + 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, + GfxRenderingIntent ri) { + 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, ri); + 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, ri); + 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 +//------------------------------------------------------------------------ + +GfxSubpath::GfxSubpath(double x1, double y1) { + size = 16; + x = (double *)gmallocn(size, sizeof(double)); + y = (double *)gmallocn(size, sizeof(double)); + curve = (GBool *)gmallocn(size, sizeof(GBool)); + n = 1; + x[0] = x1; + y[0] = y1; + curve[0] = gFalse; + closed = gFalse; +} + +GfxSubpath::~GfxSubpath() { + gfree(x); + gfree(y); + gfree(curve); +} + +// Used for copy(). +GfxSubpath::GfxSubpath(GfxSubpath *subpath) { + size = subpath->size; + n = subpath->n; + x = (double *)gmallocn(size, sizeof(double)); + y = (double *)gmallocn(size, sizeof(double)); + curve = (GBool *)gmallocn(size, sizeof(GBool)); + memcpy(x, subpath->x, n * sizeof(double)); + memcpy(y, subpath->y, n * sizeof(double)); + memcpy(curve, subpath->curve, n * sizeof(GBool)); + closed = subpath->closed; +} + +void GfxSubpath::lineTo(double x1, double y1) { + if (n >= size) { + size *= 2; + x = (double *)greallocn(x, size, sizeof(double)); + y = (double *)greallocn(y, size, sizeof(double)); + curve = (GBool *)greallocn(curve, size, sizeof(GBool)); + } + x[n] = x1; + y[n] = y1; + curve[n] = gFalse; + ++n; +} + +void GfxSubpath::curveTo(double x1, double y1, double x2, double y2, + double x3, double y3) { + if (n+3 > size) { + size *= 2; + x = (double *)greallocn(x, size, sizeof(double)); + y = (double *)greallocn(y, size, sizeof(double)); + curve = (GBool *)greallocn(curve, size, sizeof(GBool)); + } + x[n] = x1; + y[n] = y1; + x[n+1] = x2; + y[n+1] = y2; + x[n+2] = x3; + y[n+2] = y3; + curve[n] = curve[n+1] = gTrue; + curve[n+2] = gFalse; + n += 3; +} + +void GfxSubpath::close() { + if (x[n-1] != x[0] || y[n-1] != y[0]) { + lineTo(x[0], y[0]); + } + closed = gTrue; +} + +void GfxSubpath::offset(double dx, double dy) { + int i; + + for (i = 0; i < n; ++i) { + x[i] += dx; + y[i] += dy; + } +} + +GfxPath::GfxPath() { + justMoved = gFalse; + size = 16; + n = 0; + firstX = firstY = 0; + subpaths = (GfxSubpath **)gmallocn(size, sizeof(GfxSubpath *)); +} + +GfxPath::~GfxPath() { + int i; + + for (i = 0; i < n; ++i) + delete subpaths[i]; + gfree(subpaths); +} + +// Used for copy(). +GfxPath::GfxPath(GBool justMoved1, double firstX1, double firstY1, + GfxSubpath **subpaths1, int n1, int size1) { + int i; + + justMoved = justMoved1; + firstX = firstX1; + firstY = firstY1; + size = size1; + n = n1; + subpaths = (GfxSubpath **)gmallocn(size, sizeof(GfxSubpath *)); + for (i = 0; i < n; ++i) + subpaths[i] = subpaths1[i]->copy(); +} + +double GfxPath::getCurX() { + if (justMoved) { + return firstX; + } else if (n > 0) { + return subpaths[n-1]->getLastX(); + } else { + return 0; + } +} + +double GfxPath::getCurY() { + if (justMoved) { + return firstY; + } else if (n > 0) { + return subpaths[n-1]->getLastY(); + } else { + return 0; + } +} + +void GfxPath::moveTo(double x, double y) { + justMoved = gTrue; + firstX = x; + firstY = y; +} + +void GfxPath::lineTo(double x, double y) { + if (justMoved || (n > 0 && subpaths[n-1]->isClosed())) { + if (n >= size) { + size *= 2; + subpaths = (GfxSubpath **) + greallocn(subpaths, size, sizeof(GfxSubpath *)); + } + if (justMoved) { + subpaths[n] = new GfxSubpath(firstX, firstY); + } else { + subpaths[n] = new GfxSubpath(subpaths[n-1]->getLastX(), + subpaths[n-1]->getLastY()); + } + ++n; + justMoved = gFalse; + } + subpaths[n-1]->lineTo(x, y); +} + +void GfxPath::curveTo(double x1, double y1, double x2, double y2, + double x3, double y3) { + if (justMoved || (n > 0 && subpaths[n-1]->isClosed())) { + if (n >= size) { + size *= 2; + subpaths = (GfxSubpath **) + greallocn(subpaths, size, sizeof(GfxSubpath *)); + } + if (justMoved) { + subpaths[n] = new GfxSubpath(firstX, firstY); + } else { + subpaths[n] = new GfxSubpath(subpaths[n-1]->getLastX(), + subpaths[n-1]->getLastY()); + } + ++n; + justMoved = gFalse; + } + subpaths[n-1]->curveTo(x1, y1, x2, y2, x3, y3); +} + +void GfxPath::close() { + // this is necessary to handle the pathological case of + // moveto/closepath/clip, which defines an empty clipping region + if (justMoved) { + if (n >= size) { + size *= 2; + subpaths = (GfxSubpath **) + greallocn(subpaths, size, sizeof(GfxSubpath *)); + } + subpaths[n] = new GfxSubpath(firstX, firstY); + ++n; + justMoved = gFalse; + } + subpaths[n-1]->close(); +} + +void GfxPath::append(GfxPath *path) { + int i; + + if (n + path->n > size) { + size = n + path->n; + subpaths = (GfxSubpath **) + greallocn(subpaths, size, sizeof(GfxSubpath *)); + } + for (i = 0; i < path->n; ++i) { + subpaths[n++] = path->subpaths[i]->copy(); + } + justMoved = gFalse; +} + +void GfxPath::offset(double dx, double dy) { + int i; + + for (i = 0; i < n; ++i) { + subpaths[i]->offset(dx, dy); + } +} + +//------------------------------------------------------------------------ +// GfxState +//------------------------------------------------------------------------ + +GfxState::GfxState(double hDPIA, double vDPIA, PDFRectangle *pageBox, + int rotateA, GBool upsideDown + ) { + double kx, ky; + + hDPI = hDPIA; + vDPI = vDPIA; + rotate = rotateA; + px1 = pageBox->x1; + py1 = pageBox->y1; + px2 = pageBox->x2; + py2 = pageBox->y2; + kx = hDPI / 72.0; + ky = vDPI / 72.0; + if (rotate == 90) { + ctm[0] = 0; + ctm[1] = upsideDown ? ky : -ky; + ctm[2] = kx; + ctm[3] = 0; + ctm[4] = -kx * py1; + ctm[5] = ky * (upsideDown ? -px1 : px2); + pageWidth = kx * (py2 - py1); + pageHeight = ky * (px2 - px1); + } else if (rotate == 180) { + ctm[0] = -kx; + ctm[1] = 0; + ctm[2] = 0; + ctm[3] = upsideDown ? ky : -ky; + ctm[4] = kx * px2; + ctm[5] = ky * (upsideDown ? -py1 : py2); + pageWidth = kx * (px2 - px1); + pageHeight = ky * (py2 - py1); + } else if (rotate == 270) { + ctm[0] = 0; + ctm[1] = upsideDown ? -ky : ky; + ctm[2] = -kx; + ctm[3] = 0; + ctm[4] = kx * py2; + ctm[5] = ky * (upsideDown ? px2 : -px1); + pageWidth = kx * (py2 - py1); + pageHeight = ky * (px2 - px1); + } else { + ctm[0] = kx; + ctm[1] = 0; + ctm[2] = 0; + ctm[3] = upsideDown ? -ky : ky; + ctm[4] = -kx * px1; + ctm[5] = ky * (upsideDown ? py2 : -py1); + pageWidth = kx * (px2 - px1); + pageHeight = ky * (py2 - py1); + } + + fillColorSpace = GfxColorSpace::create(csDeviceGray); + strokeColorSpace = GfxColorSpace::create(csDeviceGray); + fillColor.c[0] = 0; + strokeColor.c[0] = 0; + fillPattern = NULL; + strokePattern = NULL; + blendMode = gfxBlendNormal; + fillOpacity = 1; + strokeOpacity = 1; + fillOverprint = gFalse; + strokeOverprint = gFalse; + renderingIntent = gfxRenderingIntentRelativeColorimetric; + overprintMode = 0; + transfer[0] = transfer[1] = transfer[2] = transfer[3] = NULL; + + lineWidth = 1; + lineDash = NULL; + lineDashLength = 0; + lineDashStart = 0; + flatness = 1; + lineJoin = 0; + lineCap = 0; + miterLimit = 10; + strokeAdjust = gFalse; + + font = NULL; + fontSize = 0; + textMat[0] = 1; textMat[1] = 0; + textMat[2] = 0; textMat[3] = 1; + textMat[4] = 0; textMat[5] = 0; + charSpace = 0; + wordSpace = 0; + horizScaling = 1; + leading = 0; + rise = 0; + render = 0; + + path = new GfxPath(); + curX = curY = 0; + lineX = lineY = 0; + + clipXMin = 0; + clipYMin = 0; + clipXMax = pageWidth; + clipYMax = pageHeight; + + ignoreColorOps = gFalse; + + saved = NULL; +} + +GfxState::~GfxState() { + int i; + + if (fillColorSpace) { + delete fillColorSpace; + } + if (strokeColorSpace) { + delete strokeColorSpace; + } + if (fillPattern) { + delete fillPattern; + } + if (strokePattern) { + delete strokePattern; + } + for (i = 0; i < 4; ++i) { + if (transfer[i]) { + delete transfer[i]; + } + } + gfree(lineDash); + if (path) { + // this gets set to NULL by restore() + delete path; + } +} + +// Used for copy(); +GfxState::GfxState(GfxState *state, GBool copyPath) { + int i; + + memcpy(this, state, sizeof(GfxState)); + if (fillColorSpace) { + fillColorSpace = state->fillColorSpace->copy(); + } + if (strokeColorSpace) { + strokeColorSpace = state->strokeColorSpace->copy(); + } + if (fillPattern) { + fillPattern = state->fillPattern->copy(); + } + if (strokePattern) { + strokePattern = state->strokePattern->copy(); + } + for (i = 0; i < 4; ++i) { + if (transfer[i]) { + transfer[i] = state->transfer[i]->copy(); + } + } + if (lineDashLength > 0) { + lineDash = (double *)gmallocn(lineDashLength, sizeof(double)); + memcpy(lineDash, state->lineDash, lineDashLength * sizeof(double)); + } + if (copyPath) { + path = state->path->copy(); + } + saved = NULL; +} + +void GfxState::setPath(GfxPath *pathA) { + delete path; + path = pathA; +} + +void GfxState::getUserClipBBox(double *xMin, double *yMin, + double *xMax, double *yMax) { + double ictm[6]; + double xMin1, yMin1, xMax1, yMax1, det, tx, ty; + + // invert the CTM + 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; + + // transform all four corners of the clip bbox; find the min and max + // x and y values + xMin1 = xMax1 = clipXMin * ictm[0] + clipYMin * ictm[2] + ictm[4]; + yMin1 = yMax1 = clipXMin * ictm[1] + clipYMin * ictm[3] + ictm[5]; + tx = clipXMin * ictm[0] + clipYMax * ictm[2] + ictm[4]; + ty = clipXMin * ictm[1] + clipYMax * ictm[3] + ictm[5]; + if (tx < xMin1) { + xMin1 = tx; + } else if (tx > xMax1) { + xMax1 = tx; + } + if (ty < yMin1) { + yMin1 = ty; + } else if (ty > yMax1) { + yMax1 = ty; + } + tx = clipXMax * ictm[0] + clipYMin * ictm[2] + ictm[4]; + ty = clipXMax * ictm[1] + clipYMin * ictm[3] + ictm[5]; + if (tx < xMin1) { + xMin1 = tx; + } else if (tx > xMax1) { + xMax1 = tx; + } + if (ty < yMin1) { + yMin1 = ty; + } else if (ty > yMax1) { + yMax1 = ty; + } + tx = clipXMax * ictm[0] + clipYMax * ictm[2] + ictm[4]; + ty = clipXMax * ictm[1] + clipYMax * ictm[3] + ictm[5]; + if (tx < xMin1) { + xMin1 = tx; + } else if (tx > xMax1) { + xMax1 = tx; + } + if (ty < yMin1) { + yMin1 = ty; + } else if (ty > yMax1) { + yMax1 = ty; + } + + *xMin = xMin1; + *yMin = yMin1; + *xMax = xMax1; + *yMax = yMax1; +} + +double GfxState::transformWidth(double w) { + double x, y; + + x = ctm[0] + ctm[2]; + y = ctm[1] + ctm[3]; + return w * sqrt(0.5 * (x * x + y * y)); +} + +double GfxState::getTransformedFontSize() { + double x1, y1, x2, y2; + + x1 = textMat[2] * fontSize; + y1 = textMat[3] * fontSize; + x2 = ctm[0] * x1 + ctm[2] * y1; + y2 = ctm[1] * x1 + ctm[3] * y1; + return sqrt(x2 * x2 + y2 * y2); +} + +void GfxState::getFontTransMat(double *m11, double *m12, + double *m21, double *m22) { + *m11 = (textMat[0] * ctm[0] + textMat[1] * ctm[2]) * fontSize * horizScaling; + *m12 = (textMat[0] * ctm[1] + textMat[1] * ctm[3]) * fontSize * horizScaling; + *m21 = (textMat[2] * ctm[0] + textMat[3] * ctm[2]) * fontSize; + *m22 = (textMat[2] * ctm[1] + textMat[3] * ctm[3]) * fontSize; +} + +void GfxState::setCTM(double a, double b, double c, + double d, double e, double f) { + int i; + + ctm[0] = a; + ctm[1] = b; + ctm[2] = c; + ctm[3] = d; + ctm[4] = e; + ctm[5] = f; + + // avoid FP exceptions on badly messed up PDF files + for (i = 0; i < 6; ++i) { + if (ctm[i] > 1e10) { + ctm[i] = 1e10; + } else if (ctm[i] < -1e10) { + ctm[i] = -1e10; + } + } +} + +void GfxState::concatCTM(double a, double b, double c, + double d, double e, double f) { + double a1 = ctm[0]; + double b1 = ctm[1]; + double c1 = ctm[2]; + double d1 = ctm[3]; + int i; + + ctm[0] = a * a1 + b * c1; + ctm[1] = a * b1 + b * d1; + ctm[2] = c * a1 + d * c1; + ctm[3] = c * b1 + d * d1; + ctm[4] = e * a1 + f * c1 + ctm[4]; + ctm[5] = e * b1 + f * d1 + ctm[5]; + + // avoid FP exceptions on badly messed up PDF files + for (i = 0; i < 6; ++i) { + if (ctm[i] > 1e10) { + ctm[i] = 1e10; + } else if (ctm[i] < -1e10) { + ctm[i] = -1e10; + } + } +} + +void GfxState::shiftCTM(double tx, double ty) { + ctm[4] += tx; + ctm[5] += ty; + clipXMin += tx; + clipYMin += ty; + clipXMax += tx; + clipYMax += ty; +} + +void GfxState::setFillColorSpace(GfxColorSpace *colorSpace) { + if (fillColorSpace) { + delete fillColorSpace; + } + fillColorSpace = colorSpace; +} + +void GfxState::setStrokeColorSpace(GfxColorSpace *colorSpace) { + if (strokeColorSpace) { + delete strokeColorSpace; + } + strokeColorSpace = colorSpace; +} + +void GfxState::setFillPattern(GfxPattern *pattern) { + if (fillPattern) { + delete fillPattern; + } + fillPattern = pattern; +} + +void GfxState::setStrokePattern(GfxPattern *pattern) { + if (strokePattern) { + delete strokePattern; + } + strokePattern = pattern; +} + +void GfxState::setTransfer(Function **funcs) { + int i; + + for (i = 0; i < 4; ++i) { + if (transfer[i]) { + delete transfer[i]; + } + transfer[i] = funcs[i]; + } +} + +void GfxState::setLineDash(double *dash, int length, double start) { + if (lineDash) + gfree(lineDash); + lineDash = dash; + lineDashLength = length; + lineDashStart = start; +} + +void GfxState::clearPath() { + delete path; + path = new GfxPath(); +} + +void GfxState::clip() { + double xMin, yMin, xMax, yMax, x, y; + GfxSubpath *subpath; + int i, j; + + xMin = xMax = yMin = yMax = 0; // make gcc happy + for (i = 0; i < path->getNumSubpaths(); ++i) { + subpath = path->getSubpath(i); + for (j = 0; j < subpath->getNumPoints(); ++j) { + transform(subpath->getX(j), subpath->getY(j), &x, &y); + if (i == 0 && j == 0) { + xMin = xMax = x; + yMin = yMax = y; + } else { + if (x < xMin) { + xMin = x; + } else if (x > xMax) { + xMax = x; + } + if (y < yMin) { + yMin = y; + } else if (y > yMax) { + yMax = y; + } + } + } + } + if (xMin > clipXMin) { + clipXMin = xMin; + } + if (yMin > clipYMin) { + clipYMin = yMin; + } + if (xMax < clipXMax) { + clipXMax = xMax; + } + if (yMax < clipYMax) { + clipYMax = yMax; + } +} + +void GfxState::clipToStrokePath() { + // We compute the stroke path bbox in user space (line width and + // miter limt are handled in user space), and then transform the + // bbox to device space. This can result in a larger-than-needed + // bbox if the matrix isn't "square", but that's ok. + // + // There are two cases for each point on the path: + // (1) miter join, under miter limit => compute the miter point + // (2) all other joins and caps => use the path point +/- 0.5 * line width + double xMin = 0, yMin = 0, xMax = 0, yMax = 0; + double w = 0.5 * lineWidth; + for (int i = 0; i < path->getNumSubpaths(); ++i) { + GfxSubpath *subpath = path->getSubpath(i); + for (int j = 0; j < subpath->getNumPoints(); ++j) { + double x1 = subpath->getX(j); + double y1 = subpath->getY(j); + if (i == 0 && j == 0) { + xMin = xMax = x1; + yMin = yMax = y1; + } + GBool useMiter = gFalse; + if (lineJoin == 0 && // miter join + ((j > 0 && j < subpath->getNumPoints() - 1) || subpath->isClosed())) { + double x0, y0, x2, y2; + if (j > 0) { + x0 = subpath->getX(j - 1); + y0 = subpath->getY(j - 1); + } else { + x0 = subpath->getLastX(); + y0 = subpath->getLastY(); + } + if (j < subpath->getNumPoints() - 1) { + x2 = subpath->getX(j + 1); + y2 = subpath->getY(j + 1); + } else { + x2 = subpath->getX(0); + y2 = subpath->getY(0); + } + if ((fabs(x1 - x0) > 0.0001 || fabs(y1 - y0) > 0.0001) && + (fabs(x2 - x1) > 0.0001 || fabs(y2 - y1) > 0.0001)) { + double d01 = 1 / sqrt((x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0)); + double ux = (x1 - x0) * d01; + double uy = (y1 - y0) * d01; + double d12 = 1 / sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1)); + double vx = (x2 - x1) * d12; + double vy = (y2 - y1) * d12; + double dot = -ux * vx - uy * vy; + if (dot < 0.9999) { + double miter = sqrt(2 / (1 - dot)); + if (miter <= miterLimit) { + double cross = ux * vy - uy * vx; + double m = sqrt(2 / (1 - dot) - 1); + double ax, ay; + if (cross >= 0) { + ax = x1 + w * uy; + ay = y1 - w * ux; + } else { + ax = x1 - w * uy; + ay = y1 + w * ux; + } + double mx = ax + m * w * ux; + double my = ay + m * w * uy; + if (mx < xMin) { + xMin = mx; + } else if (mx > xMax) { + xMax = mx; + } + if (my < yMin) { + yMin = my; + } else if (my > yMax) { + yMax = my; + } + useMiter = gTrue; + } + } + } + } + if (!useMiter) { + if (x1 - w < xMin) { + xMin = x1 - w; + } + if (x1 + w > xMax) { + xMax = x1 + w; + } + if (y1 - w < yMin) { + yMin = y1 - w; + } + if (y1 + w > yMax) { + yMax = y1 + w; + } + } + } + } + + double xx, yy; + transform(xMin, yMin, &xx, &yy); + if (xx < clipXMin) { + clipXMin = xx; + } else if (xx > clipXMax) { + clipXMax = xx; + } + if (yy < clipYMin) { + clipYMin = yy; + } else if (yy > clipYMax) { + clipYMax = yy; + } + transform(xMin, yMax, &xx, &yy); + if (xx < clipXMin) { + clipXMin = xx; + } else if (xx > clipXMax) { + clipXMax = xx; + } + if (yy < clipYMin) { + clipYMin = yy; + } else if (yy > clipYMax) { + clipYMax = yy; + } + transform(xMax, yMin, &xx, &yy); + if (xx < clipXMin) { + clipXMin = xx; + } else if (xx > clipXMax) { + clipXMax = xx; + } + if (yy < clipYMin) { + clipYMin = yy; + } else if (yy > clipYMax) { + clipYMax = yy; + } + transform(xMax, yMax, &xx, &yy); + if (xx < clipXMin) { + clipXMin = xx; + } else if (xx > clipXMax) { + clipXMax = xx; + } + if (yy < clipYMin) { + clipYMin = yy; + } else if (yy > clipYMax) { + clipYMax = yy; + } +} + +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; + + textTransformDelta(tx, ty, &dx, &dy); + curX += dx; + curY += dy; +} + +void GfxState::shift(double dx, double dy) { + curX += dx; + curY += dy; +} + +GfxState *GfxState::save() { + GfxState *newState; + + newState = copy(); + newState->saved = this; + return newState; +} + +GfxState *GfxState::restore() { + GfxState *oldState; + + if (saved) { + oldState = saved; + + // these attributes aren't saved/restored by the q/Q operators + oldState->path = path; + oldState->curX = curX; + oldState->curY = curY; + oldState->lineX = lineX; + oldState->lineY = lineY; + + path = NULL; + saved = NULL; + delete this; + + } else { + oldState = this; + } + + return oldState; +} + +GBool GfxState::parseBlendMode(Object *obj, GfxBlendMode *mode) { + Object obj2; + int i, j; + + if (obj->isName()) { + for (i = 0; i < nGfxBlendModeNames; ++i) { + if (!strcmp(obj->getName(), gfxBlendModeNames[i].name)) { + *mode = gfxBlendModeNames[i].mode; + return gTrue; + } + } + return gFalse; + } else if (obj->isArray()) { + for (i = 0; i < obj->arrayGetLength(); ++i) { + obj->arrayGet(i, &obj2); + if (!obj2.isName()) { + obj2.free(); + return gFalse; + } + for (j = 0; j < nGfxBlendModeNames; ++j) { + if (!strcmp(obj2.getName(), gfxBlendModeNames[j].name)) { + obj2.free(); + *mode = gfxBlendModeNames[j].mode; + return gTrue; + } + } + obj2.free(); + } + *mode = gfxBlendNormal; + return gTrue; + } else { + return gFalse; + } +} diff --git a/xpdf/GfxState.h b/xpdf/GfxState.h new file mode 100644 index 0000000..60d4852 --- /dev/null +++ b/xpdf/GfxState.h @@ -0,0 +1,1369 @@ +//======================================================================== +// +// GfxState.h +// +// Copyright 1996-2016 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef GFXSTATE_H +#define GFXSTATE_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "gtypes.h" +#include "Object.h" +#include "Function.h" + +class Array; +class GfxFont; +class PDFRectangle; +class GfxDeviceNColorSpace; +class GfxSeparationColorSpace; +class GfxShading; +class GfxState; + +//------------------------------------------------------------------------ +// GfxBlendMode +//------------------------------------------------------------------------ + +enum GfxBlendMode { + gfxBlendNormal, + gfxBlendMultiply, + gfxBlendScreen, + gfxBlendOverlay, + gfxBlendDarken, + gfxBlendLighten, + gfxBlendColorDodge, + gfxBlendColorBurn, + gfxBlendHardLight, + gfxBlendSoftLight, + gfxBlendDifference, + gfxBlendExclusion, + gfxBlendHue, + gfxBlendSaturation, + gfxBlendColor, + gfxBlendLuminosity +}; + +//------------------------------------------------------------------------ +// GfxRenderingIntent +//------------------------------------------------------------------------ + +enum GfxRenderingIntent { + gfxRenderingIntentAbsoluteColorimetric, + gfxRenderingIntentRelativeColorimetric, + gfxRenderingIntentSaturation, + gfxRenderingIntentPerceptual +}; + +#define gfxNumRenderingIntents 4 + +//------------------------------------------------------------------------ +// GfxColorComp +//------------------------------------------------------------------------ + +// 16.16 fixed point color component +typedef int GfxColorComp; + +#define gfxColorComp1 0x10000 + +static inline GfxColorComp dblToCol(double x) { + return (GfxColorComp)(x * gfxColorComp1); +} + +static inline double colToDbl(GfxColorComp x) { + return (double)x / (double)gfxColorComp1; +} + +static inline GfxColorComp byteToCol(Guchar x) { + // (x / 255) << 16 = (0.0000000100000001... * x) << 16 + // = ((x << 8) + (x) + (x >> 8) + ...) + // = (x << 8) + (x) + (x >> 7) + // [for rounding] + return (GfxColorComp)((x << 8) + x + (x >> 7)); +} + +static inline GfxColorComp wordToCol(Gushort x) { + // (x / 65535) << 16 = (0.0000000000000001... * x) << 16 + // = x + (x >> 15) + // [for rounding] + return (GfxColorComp)(x + (x >> 15)); +} + +static inline Guchar colToByte(GfxColorComp x) { + // 255 * x + 0.5 = 256 * x - x + 0.5 + // = [256 * (x << 16) - (x << 16) + (1 << 15)] >> 16 + return (Guchar)(((x << 8) - x + 0x8000) >> 16); +} + +static inline Gushort colToWord(GfxColorComp x) { + // 65535 * x + 0.5 = 65536 * x - x + 0.5 + // = [65536 * (x << 16) - (x << 16) + (1 << 15)] >> 16 + return (Gushort)(((x << 16) - x + 0x8000) >> 16); +} + +//------------------------------------------------------------------------ +// GfxColor +//------------------------------------------------------------------------ + +#define gfxColorMaxComps funcMaxOutputs + +struct GfxColor { + GfxColorComp c[gfxColorMaxComps]; +}; + +//------------------------------------------------------------------------ +// GfxGray +//------------------------------------------------------------------------ + +typedef GfxColorComp GfxGray; + +//------------------------------------------------------------------------ +// GfxRGB +//------------------------------------------------------------------------ + +struct GfxRGB { + GfxColorComp r, g, b; +}; + +//------------------------------------------------------------------------ +// GfxCMYK +//------------------------------------------------------------------------ + +struct GfxCMYK { + GfxColorComp c, m, y, k; +}; + + + + + +//------------------------------------------------------------------------ +// GfxColorSpace +//------------------------------------------------------------------------ + +// NB: The nGfxColorSpaceModes constant and the gfxColorSpaceModeNames +// array defined in GfxState.cc must match this enum. +enum GfxColorSpaceMode { + csDeviceGray, + csCalGray, + csDeviceRGB, + csCalRGB, + csDeviceCMYK, + csLab, + csICCBased, + csIndexed, + csSeparation, + csDeviceN, + csPattern +}; + +class GfxColorSpace { +public: + + GfxColorSpace(); + virtual ~GfxColorSpace(); + virtual GfxColorSpace *copy() = 0; + virtual GfxColorSpaceMode getMode() = 0; + + // Construct a color space. Returns NULL if unsuccessful. + static GfxColorSpace *parse(Object *csObj, + int recursion = 0); + + // Construct a simple color space. The argument can be + // csDeviceGray, csDeviceRGB, or csDeviceCMYK. + static GfxColorSpace *create(GfxColorSpaceMode mode); + + + // Convert to gray, RGB, or CMYK. + virtual void getGray(GfxColor *color, GfxGray *gray, + GfxRenderingIntent ri) = 0; + virtual void getRGB(GfxColor *color, GfxRGB *rgb, + GfxRenderingIntent ri) = 0; + virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk, + GfxRenderingIntent ri) = 0; + + // Return the number of color components. + virtual int getNComps() = 0; + + // Get this color space's default color. + virtual void getDefaultColor(GfxColor *color) = 0; + + // Return the default ranges for each component, assuming an image + // with a max pixel value of . + virtual void getDefaultRanges(double *decodeLow, double *decodeRange, + int maxImgPixel); + + // Returns true if painting operations in this color space never + // mark the page (e.g., the "None" colorant). + virtual GBool isNonMarking() { return gFalse; } + + + // Return the color space's overprint mask. + Guint getOverprintMask() { return overprintMask; } + + // Return true if this color space object is the result of + // substituting a DefaultGray/RGB/CMYK color space for + // DeviceGray/RGB/CMYK. + GBool isDefaultColorSpace() { return defaultColorSpace; } + + // Return the number of color space modes + static int getNumColorSpaceModes(); + + // Return the name of the th color space mode. + static const char *getColorSpaceModeName(int idx); + +protected: + + Guint overprintMask; + GBool defaultColorSpace; +}; + +//------------------------------------------------------------------------ +// GfxDeviceGrayColorSpace +//------------------------------------------------------------------------ + +class GfxDeviceGrayColorSpace: public GfxColorSpace { +public: + + GfxDeviceGrayColorSpace(); + virtual ~GfxDeviceGrayColorSpace(); + virtual GfxColorSpace *copy(); + virtual GfxColorSpaceMode getMode() { return csDeviceGray; } + + virtual void getGray(GfxColor *color, GfxGray *gray, GfxRenderingIntent ri); + virtual void getRGB(GfxColor *color, GfxRGB *rgb, GfxRenderingIntent ri); + virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk, GfxRenderingIntent ri); + + virtual int getNComps() { return 1; } + virtual void getDefaultColor(GfxColor *color); + +private: +}; + +//------------------------------------------------------------------------ +// GfxCalGrayColorSpace +//------------------------------------------------------------------------ + +class GfxCalGrayColorSpace: public GfxColorSpace { +public: + + GfxCalGrayColorSpace(); + virtual ~GfxCalGrayColorSpace(); + virtual GfxColorSpace *copy(); + virtual GfxColorSpaceMode getMode() { return csCalGray; } + + // Construct a CalGray color space. Returns NULL if unsuccessful. + static GfxColorSpace *parse(Array *arr, int recursion); + + virtual void getGray(GfxColor *color, GfxGray *gray, GfxRenderingIntent ri); + virtual void getRGB(GfxColor *color, GfxRGB *rgb, GfxRenderingIntent ri); + virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk, GfxRenderingIntent ri); + + virtual int getNComps() { return 1; } + virtual void getDefaultColor(GfxColor *color); + + // CalGray-specific access. + double getWhiteX() { return whiteX; } + double getWhiteY() { return whiteY; } + double getWhiteZ() { return whiteZ; } + double getBlackX() { return blackX; } + double getBlackY() { return blackY; } + double getBlackZ() { return blackZ; } + double getGamma() { return gamma; } + +private: + + double whiteX, whiteY, whiteZ; // white point + double blackX, blackY, blackZ; // black point + double gamma; // gamma value +}; + +//------------------------------------------------------------------------ +// GfxDeviceRGBColorSpace +//------------------------------------------------------------------------ + +class GfxDeviceRGBColorSpace: public GfxColorSpace { +public: + + GfxDeviceRGBColorSpace(); + virtual ~GfxDeviceRGBColorSpace(); + virtual GfxColorSpace *copy(); + virtual GfxColorSpaceMode getMode() { return csDeviceRGB; } + + virtual void getGray(GfxColor *color, GfxGray *gray, GfxRenderingIntent ri); + virtual void getRGB(GfxColor *color, GfxRGB *rgb, GfxRenderingIntent ri); + virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk, GfxRenderingIntent ri); + + virtual int getNComps() { return 3; } + virtual void getDefaultColor(GfxColor *color); + +private: +}; + +//------------------------------------------------------------------------ +// GfxCalRGBColorSpace +//------------------------------------------------------------------------ + +class GfxCalRGBColorSpace: public GfxColorSpace { +public: + + GfxCalRGBColorSpace(); + virtual ~GfxCalRGBColorSpace(); + virtual GfxColorSpace *copy(); + virtual GfxColorSpaceMode getMode() { return csCalRGB; } + + // Construct a CalRGB color space. Returns NULL if unsuccessful. + static GfxColorSpace *parse(Array *arr, int recursion); + + virtual void getGray(GfxColor *color, GfxGray *gray, GfxRenderingIntent ri); + virtual void getRGB(GfxColor *color, GfxRGB *rgb, GfxRenderingIntent ri); + virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk, GfxRenderingIntent ri); + + virtual int getNComps() { return 3; } + virtual void getDefaultColor(GfxColor *color); + + // CalRGB-specific access. + double getWhiteX() { return whiteX; } + double getWhiteY() { return whiteY; } + double getWhiteZ() { return whiteZ; } + double getBlackX() { return blackX; } + double getBlackY() { return blackY; } + double getBlackZ() { return blackZ; } + double getGammaR() { return gammaR; } + double getGammaG() { return gammaG; } + double getGammaB() { return gammaB; } + double *getMatrix() { return mat; } + +private: + + double whiteX, whiteY, whiteZ; // white point + double blackX, blackY, blackZ; // black point + double gammaR, gammaG, gammaB; // gamma values + double mat[9]; // ABC -> XYZ transform matrix +}; + +//------------------------------------------------------------------------ +// GfxDeviceCMYKColorSpace +//------------------------------------------------------------------------ + +class GfxDeviceCMYKColorSpace: public GfxColorSpace { +public: + + GfxDeviceCMYKColorSpace(); + virtual ~GfxDeviceCMYKColorSpace(); + virtual GfxColorSpace *copy(); + virtual GfxColorSpaceMode getMode() { return csDeviceCMYK; } + + virtual void getGray(GfxColor *color, GfxGray *gray, GfxRenderingIntent ri); + virtual void getRGB(GfxColor *color, GfxRGB *rgb, GfxRenderingIntent ri); + virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk, GfxRenderingIntent ri); + + virtual int getNComps() { return 4; } + virtual void getDefaultColor(GfxColor *color); + + +private: +}; + +//------------------------------------------------------------------------ +// GfxLabColorSpace +//------------------------------------------------------------------------ + +class GfxLabColorSpace: public GfxColorSpace { +public: + + GfxLabColorSpace(); + virtual ~GfxLabColorSpace(); + virtual GfxColorSpace *copy(); + virtual GfxColorSpaceMode getMode() { return csLab; } + + // Construct a Lab color space. Returns NULL if unsuccessful. + static GfxColorSpace *parse(Array *arr, int recursion); + + virtual void getGray(GfxColor *color, GfxGray *gray, GfxRenderingIntent ri); + virtual void getRGB(GfxColor *color, GfxRGB *rgb, GfxRenderingIntent ri); + virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk, GfxRenderingIntent ri); + + virtual int getNComps() { return 3; } + virtual void getDefaultColor(GfxColor *color); + + virtual void getDefaultRanges(double *decodeLow, double *decodeRange, + int maxImgPixel); + + // Lab-specific access. + double getWhiteX() { return whiteX; } + double getWhiteY() { return whiteY; } + double getWhiteZ() { return whiteZ; } + double getBlackX() { return blackX; } + double getBlackY() { return blackY; } + double getBlackZ() { return blackZ; } + double getAMin() { return aMin; } + double getAMax() { return aMax; } + double getBMin() { return bMin; } + double getBMax() { return bMax; } + +private: + + double whiteX, whiteY, whiteZ; // white point + double blackX, blackY, blackZ; // black point + double aMin, aMax, bMin, bMax; // range for the a and b components + double kr, kg, kb; // gamut mapping mulitpliers +}; + +//------------------------------------------------------------------------ +// GfxICCBasedColorSpace +//------------------------------------------------------------------------ + +class GfxICCBasedColorSpace: public GfxColorSpace { +public: + + GfxICCBasedColorSpace(int nCompsA, GfxColorSpace *altA, + Ref *iccProfileStreamA); + virtual ~GfxICCBasedColorSpace(); + virtual GfxColorSpace *copy(); + virtual GfxColorSpaceMode getMode() { return csICCBased; } + + // Construct an ICCBased color space. Returns NULL if unsuccessful. + static GfxColorSpace *parse(Array *arr, + int recursion); + + virtual void getGray(GfxColor *color, GfxGray *gray, GfxRenderingIntent ri); + virtual void getRGB(GfxColor *color, GfxRGB *rgb, GfxRenderingIntent ri); + virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk, GfxRenderingIntent ri); + + virtual int getNComps() { return nComps; } + virtual void getDefaultColor(GfxColor *color); + + virtual void getDefaultRanges(double *decodeLow, double *decodeRange, + int maxImgPixel); + + + // ICCBased-specific access. + GfxColorSpace *getAlt() { return alt; } + Ref getICCProfileStreamRef() { return iccProfileStream; } + +private: + + int nComps; // number of color components (1, 3, or 4) + GfxColorSpace *alt; // alternate color space + double rangeMin[4]; // min values for each component + double rangeMax[4]; // max values for each component + Ref iccProfileStream; // the ICC profile +}; + +//------------------------------------------------------------------------ +// GfxIndexedColorSpace +//------------------------------------------------------------------------ + +class GfxIndexedColorSpace: public GfxColorSpace { +public: + + GfxIndexedColorSpace(GfxColorSpace *baseA, int indexHighA); + virtual ~GfxIndexedColorSpace(); + virtual GfxColorSpace *copy(); + virtual GfxColorSpaceMode getMode() { return csIndexed; } + + // Construct an Indexed color space. Returns NULL if unsuccessful. + static GfxColorSpace *parse(Array *arr, + int recursion); + + virtual void getGray(GfxColor *color, GfxGray *gray, GfxRenderingIntent ri); + virtual void getRGB(GfxColor *color, GfxRGB *rgb, GfxRenderingIntent ri); + virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk, GfxRenderingIntent ri); + + virtual int getNComps() { return 1; } + virtual void getDefaultColor(GfxColor *color); + + virtual void getDefaultRanges(double *decodeLow, double *decodeRange, + int maxImgPixel); + + // Indexed-specific access. + GfxColorSpace *getBase() { return base; } + int getIndexHigh() { return indexHigh; } + Guchar *getLookup() { return lookup; } + GfxColor *mapColorToBase(GfxColor *color, GfxColor *baseColor); + +private: + + GfxColorSpace *base; // base color space + int indexHigh; // max pixel value + Guchar *lookup; // lookup table +}; + +//------------------------------------------------------------------------ +// GfxSeparationColorSpace +//------------------------------------------------------------------------ + +class GfxSeparationColorSpace: public GfxColorSpace { +public: + + GfxSeparationColorSpace(GString *nameA, GfxColorSpace *altA, + Function *funcA); + virtual ~GfxSeparationColorSpace(); + virtual GfxColorSpace *copy(); + virtual GfxColorSpaceMode getMode() { return csSeparation; } + + // Construct a Separation color space. Returns NULL if unsuccessful. + static GfxColorSpace *parse(Array *arr, + int recursion); + + virtual void getGray(GfxColor *color, GfxGray *gray, GfxRenderingIntent ri); + virtual void getRGB(GfxColor *color, GfxRGB *rgb, GfxRenderingIntent ri); + virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk, GfxRenderingIntent ri); + + virtual int getNComps() { return 1; } + virtual void getDefaultColor(GfxColor *color); + + virtual GBool isNonMarking() { return nonMarking; } + + // Separation-specific access. + GString *getName() { return name; } + GfxColorSpace *getAlt() { return alt; } + Function *getFunc() { return func; } + +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) + GBool nonMarking; +}; + +//------------------------------------------------------------------------ +// GfxDeviceNColorSpace +//------------------------------------------------------------------------ + +class GfxDeviceNColorSpace: public GfxColorSpace { +public: + + GfxDeviceNColorSpace(int nCompsA, GString **namesA, + GfxColorSpace *alt, Function *func, + Object *attrsA); + virtual ~GfxDeviceNColorSpace(); + virtual GfxColorSpace *copy(); + virtual GfxColorSpaceMode getMode() { return csDeviceN; } + + // Construct a DeviceN color space. Returns NULL if unsuccessful. + static GfxColorSpace *parse(Array *arr, + int recursion); + + virtual void getGray(GfxColor *color, GfxGray *gray, GfxRenderingIntent ri); + virtual void getRGB(GfxColor *color, GfxRGB *rgb, GfxRenderingIntent ri); + virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk, GfxRenderingIntent ri); + + virtual int getNComps() { return nComps; } + virtual void getDefaultColor(GfxColor *color); + + virtual GBool isNonMarking() { return nonMarking; } + + // DeviceN-specific access. + GString *getColorantName(int i) { return names[i]; } + GfxColorSpace *getAlt() { return alt; } + Function *getTintTransformFunc() { return func; } + Object *getAttrs() { return &attrs; } + +private: + + GfxDeviceNColorSpace(int nCompsA, GString **namesA, + GfxColorSpace *alt, Function *func, + Object *attrsA, + GBool nonMarkingA, Guint overprintMaskA); + + int nComps; // number of components + GString // colorant names + *names[gfxColorMaxComps]; + GfxColorSpace *alt; // alternate color space + Function *func; // tint transform (into alternate color space) + Object attrs; + GBool nonMarking; +}; + +//------------------------------------------------------------------------ +// GfxPatternColorSpace +//------------------------------------------------------------------------ + +class GfxPatternColorSpace: public GfxColorSpace { +public: + + GfxPatternColorSpace(GfxColorSpace *underA); + virtual ~GfxPatternColorSpace(); + virtual GfxColorSpace *copy(); + virtual GfxColorSpaceMode getMode() { return csPattern; } + + // Construct a Pattern color space. Returns NULL if unsuccessful. + static GfxColorSpace *parse(Array *arr, + int recursion); + + virtual void getGray(GfxColor *color, GfxGray *gray, GfxRenderingIntent ri); + virtual void getRGB(GfxColor *color, GfxRGB *rgb, GfxRenderingIntent ri); + virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk, GfxRenderingIntent ri); + + virtual int getNComps() { return 0; } + virtual void getDefaultColor(GfxColor *color); + + // Pattern-specific access. + GfxColorSpace *getUnder() { return under; } + +private: + + GfxColorSpace *under; // underlying color space (for uncolored + // patterns) +}; + +//------------------------------------------------------------------------ +// GfxPattern +//------------------------------------------------------------------------ + +class GfxPattern { +public: + + GfxPattern(int typeA); + virtual ~GfxPattern(); + + static GfxPattern *parse(Object *objRef, Object *obj + ); + + virtual GfxPattern *copy() = 0; + + int getType() { return type; } + +private: + + int type; +}; + +//------------------------------------------------------------------------ +// GfxTilingPattern +//------------------------------------------------------------------------ + +class GfxTilingPattern: public GfxPattern { +public: + + static GfxTilingPattern *parse(Object *patObjRef, Object *patObj); + virtual ~GfxTilingPattern(); + + virtual GfxPattern *copy(); + + int getPaintType() { return paintType; } + int getTilingType() { return tilingType; } + double *getBBox() { return bbox; } + double getXStep() { return xStep; } + double getYStep() { return yStep; } + Dict *getResDict() + { return resDict.isDict() ? resDict.getDict() : (Dict *)NULL; } + double *getMatrix() { return matrix; } + Object *getContentStreamRef() { return &contentStreamRef; } + +private: + + GfxTilingPattern(int paintTypeA, int tilingTypeA, + double *bboxA, double xStepA, double yStepA, + Object *resDictA, double *matrixA, + Object *contentStreamA); + + int paintType; + int tilingType; + double bbox[4]; + double xStep, yStep; + Object resDict; + double matrix[6]; + Object contentStreamRef; +}; + +//------------------------------------------------------------------------ +// GfxShadingPattern +//------------------------------------------------------------------------ + +class GfxShadingPattern: public GfxPattern { +public: + + static GfxShadingPattern *parse(Object *patObj + ); + virtual ~GfxShadingPattern(); + + virtual GfxPattern *copy(); + + GfxShading *getShading() { return shading; } + double *getMatrix() { return matrix; } + +private: + + GfxShadingPattern(GfxShading *shadingA, double *matrixA); + + GfxShading *shading; + double matrix[6]; +}; + +//------------------------------------------------------------------------ +// GfxShading +//------------------------------------------------------------------------ + +class GfxShading { +public: + + GfxShading(int typeA); + GfxShading(GfxShading *shading); + virtual ~GfxShading(); + + static GfxShading *parse(Object *obj + ); + + virtual GfxShading *copy() = 0; + + int getType() { return type; } + GfxColorSpace *getColorSpace() { return colorSpace; } + GfxColor *getBackground() { return &background; } + GBool getHasBackground() { return hasBackground; } + void getBBox(double *xMinA, double *yMinA, double *xMaxA, double *yMaxA) + { *xMinA = xMin; *yMinA = yMin; *xMaxA = xMax; *yMaxA = yMax; } + GBool getHasBBox() { return hasBBox; } + +protected: + + GBool init(Dict *dict + ); + + int type; + GfxColorSpace *colorSpace; + GfxColor background; + GBool hasBackground; + double xMin, yMin, xMax, yMax; + GBool hasBBox; +}; + +//------------------------------------------------------------------------ +// GfxFunctionShading +//------------------------------------------------------------------------ + +class GfxFunctionShading: public GfxShading { +public: + + GfxFunctionShading(double x0A, double y0A, + double x1A, double y1A, + double *matrixA, + Function **funcsA, int nFuncsA); + GfxFunctionShading(GfxFunctionShading *shading); + virtual ~GfxFunctionShading(); + + static GfxFunctionShading *parse(Dict *dict + ); + + virtual GfxShading *copy(); + + void getDomain(double *x0A, double *y0A, double *x1A, double *y1A) + { *x0A = x0; *y0A = y0; *x1A = x1; *y1A = y1; } + double *getMatrix() { return matrix; } + int getNFuncs() { return nFuncs; } + Function *getFunc(int i) { return funcs[i]; } + void getColor(double x, double y, GfxColor *color); + +private: + + double x0, y0, x1, y1; + double matrix[6]; + Function *funcs[gfxColorMaxComps]; + int nFuncs; +}; + +//------------------------------------------------------------------------ +// GfxAxialShading +//------------------------------------------------------------------------ + +class GfxAxialShading: public GfxShading { +public: + + GfxAxialShading(double x0A, double y0A, + double x1A, double y1A, + double t0A, double t1A, + Function **funcsA, int nFuncsA, + GBool extend0A, GBool extend1A); + GfxAxialShading(GfxAxialShading *shading); + virtual ~GfxAxialShading(); + + static GfxAxialShading *parse(Dict *dict + ); + + virtual GfxShading *copy(); + + void getCoords(double *x0A, double *y0A, double *x1A, double *y1A) + { *x0A = x0; *y0A = y0; *x1A = x1; *y1A = y1; } + double getDomain0() { return t0; } + double getDomain1() { return t1; } + GBool getExtend0() { return extend0; } + GBool getExtend1() { return extend1; } + int getNFuncs() { return nFuncs; } + Function *getFunc(int i) { return funcs[i]; } + void getColor(double t, GfxColor *color); + +private: + + double x0, y0, x1, y1; + double t0, t1; + Function *funcs[gfxColorMaxComps]; + int nFuncs; + GBool extend0, extend1; +}; + +//------------------------------------------------------------------------ +// GfxRadialShading +//------------------------------------------------------------------------ + +class GfxRadialShading: public GfxShading { +public: + + GfxRadialShading(double x0A, double y0A, double r0A, + double x1A, double y1A, double r1A, + double t0A, double t1A, + Function **funcsA, int nFuncsA, + GBool extend0A, GBool extend1A); + GfxRadialShading(GfxRadialShading *shading); + virtual ~GfxRadialShading(); + + static GfxRadialShading *parse(Dict *dict + ); + + virtual GfxShading *copy(); + + void getCoords(double *x0A, double *y0A, double *r0A, + double *x1A, double *y1A, double *r1A) + { *x0A = x0; *y0A = y0; *r0A = r0; *x1A = x1; *y1A = y1; *r1A = r1; } + double getDomain0() { return t0; } + double getDomain1() { return t1; } + GBool getExtend0() { return extend0; } + GBool getExtend1() { return extend1; } + int getNFuncs() { return nFuncs; } + Function *getFunc(int i) { return funcs[i]; } + void getColor(double t, GfxColor *color); + +private: + + double x0, y0, r0, x1, y1, r1; + double t0, t1; + Function *funcs[gfxColorMaxComps]; + int nFuncs; + GBool extend0, extend1; +}; + +//------------------------------------------------------------------------ +// GfxGouraudTriangleShading +//------------------------------------------------------------------------ + +struct GfxGouraudVertex { + double x, y; + double color[gfxColorMaxComps]; +}; + +class GfxGouraudTriangleShading: public GfxShading { +public: + + GfxGouraudTriangleShading(int typeA, + GfxGouraudVertex *verticesA, int nVerticesA, + int (*trianglesA)[3], int nTrianglesA, + int nCompsA, Function **funcsA, int nFuncsA); + GfxGouraudTriangleShading(GfxGouraudTriangleShading *shading); + virtual ~GfxGouraudTriangleShading(); + + static GfxGouraudTriangleShading *parse(int typeA, Dict *dict, Stream *str + ); + + virtual GfxShading *copy(); + + int getNComps() { return nComps; } + int getNTriangles() { return nTriangles; } + void getTriangle(int i, double *x0, double *y0, double *color0, + double *x1, double *y1, double *color1, + double *x2, double *y2, double *color2); + void getBBox(double *xMin, double *yMin, double *xMax, double *yMax); + void getColor(double *in, GfxColor *out); + +private: + + GfxGouraudVertex *vertices; + int nVertices; + int (*triangles)[3]; + int nTriangles; + Function *funcs[gfxColorMaxComps]; + int nComps; // number of color components (1 if nFuncs > 0) + int nFuncs; +}; + +//------------------------------------------------------------------------ +// GfxPatchMeshShading +//------------------------------------------------------------------------ + +struct GfxPatch { + double x[4][4]; + double y[4][4]; + double color[2][2][gfxColorMaxComps]; +}; + +class GfxPatchMeshShading: public GfxShading { +public: + + GfxPatchMeshShading(int typeA, GfxPatch *patchesA, int nPatchesA, + int nCompsA, Function **funcsA, int nFuncsA); + GfxPatchMeshShading(GfxPatchMeshShading *shading); + virtual ~GfxPatchMeshShading(); + + static GfxPatchMeshShading *parse(int typeA, Dict *dict, Stream *str + ); + + virtual GfxShading *copy(); + + int getNComps() { return nComps; } + int getNPatches() { return nPatches; } + GfxPatch *getPatch(int i) { return &patches[i]; } + void getBBox(double *xMin, double *yMin, double *xMax, double *yMax); + void getColor(double *in, GfxColor *out); + +private: + + GfxPatch *patches; + int nPatches; + Function *funcs[gfxColorMaxComps]; + int nComps; // number of color components (1 if nFuncs > 0) + int nFuncs; +}; + +//------------------------------------------------------------------------ +// GfxImageColorMap +//------------------------------------------------------------------------ + +class GfxImageColorMap { +public: + + // Constructor. + GfxImageColorMap(int bitsA, Object *decode, GfxColorSpace *colorSpaceA, + int maxAllowedBits = 8); + + // Destructor. + ~GfxImageColorMap(); + + // Return a copy of this color map. + GfxImageColorMap *copy() { return new GfxImageColorMap(this); } + + // Is color map valid? + GBool isOk() { return ok; } + + // Get the color space. + GfxColorSpace *getColorSpace() { return colorSpace; } + + // Get stream decoding info. + int getNumPixelComps() { return nComps; } + int getBits() { return bits; } + + // Get decode table. + double getDecodeLow(int i) { return decodeLow[i]; } + double getDecodeHigh(int i) { return decodeLow[i] + decodeRange[i]; } + + // Convert an image pixel to a color. + void getGray(Guchar *x, GfxGray *gray, GfxRenderingIntent ri); + void getRGB(Guchar *x, GfxRGB *rgb, GfxRenderingIntent ri); + void getCMYK(Guchar *x, GfxCMYK *cmyk, GfxRenderingIntent ri); + void getColor(Guchar *x, GfxColor *color); + + // Convert a line of pixels to 8-bit colors. + void getGrayByteLine(Guchar *in, Guchar *out, int n, GfxRenderingIntent ri); + void getRGBByteLine(Guchar *in, Guchar *out, int n, GfxRenderingIntent ri); + void getCMYKByteLine(Guchar *in, Guchar *out, int n, GfxRenderingIntent ri); + +private: + + GfxImageColorMap(GfxImageColorMap *colorMap); + + GfxColorSpace *colorSpace; // the image color space + int bits; // bits per component + int nComps; // number of components in a pixel + GfxColorSpace *colorSpace2; // secondary color space + 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 + decodeRange[gfxColorMaxComps]; + GBool ok; +}; + +//------------------------------------------------------------------------ +// GfxSubpath and GfxPath +//------------------------------------------------------------------------ + +class GfxSubpath { +public: + + // Constructor. + GfxSubpath(double x1, double y1); + + // Destructor. + ~GfxSubpath(); + + // Copy. + GfxSubpath *copy() { return new GfxSubpath(this); } + + // Get points. + int getNumPoints() { return n; } + double getX(int i) { return x[i]; } + double getY(int i) { return y[i]; } + GBool getCurve(int i) { return curve[i]; } + + // Get last point. + double getLastX() { return x[n-1]; } + double getLastY() { return y[n-1]; } + + // Add a line segment. + void lineTo(double x1, double y1); + + // Add a Bezier curve. + void curveTo(double x1, double y1, double x2, double y2, + double x3, double y3); + + // Close the subpath. + void close(); + GBool isClosed() { return closed; } + + // Add (, ) to each point in the subpath. + void offset(double dx, double dy); + +private: + + double *x, *y; // points + GBool *curve; // curve[i] => point i is a control point + // for a Bezier curve + int n; // number of points + int size; // size of x/y arrays + GBool closed; // set if path is closed + + GfxSubpath(GfxSubpath *subpath); +}; + +class GfxPath { +public: + + // Constructor. + GfxPath(); + + // Destructor. + ~GfxPath(); + + // Copy. + GfxPath *copy() + { return new GfxPath(justMoved, firstX, firstY, subpaths, n, size); } + + // Is there a current point? + GBool isCurPt() { return n > 0 || justMoved; } + + // Is the path non-empty, i.e., is there at least one segment? + GBool isPath() { return n > 0; } + + // Get subpaths. + int getNumSubpaths() { return n; } + GfxSubpath *getSubpath(int i) { return subpaths[i]; } + + // Get last point on last subpath. + double getLastX() { return subpaths[n-1]->getLastX(); } + double getLastY() { return subpaths[n-1]->getLastY(); } + + // Get the current point + double getCurX(); + double getCurY(); + + // Move the current point. + void moveTo(double x, double y); + + // Add a segment to the last subpath. + void lineTo(double x, double y); + + // Add a Bezier curve to the last subpath + void curveTo(double x1, double y1, double x2, double y2, + double x3, double y3); + + // Close the last subpath. + void close(); + + // Append to . + void append(GfxPath *path); + + // Add (, ) to each point in the path. + void offset(double dx, double dy); + +private: + + GBool justMoved; // set if a new subpath was just started + double firstX, firstY; // first point in new subpath + GfxSubpath **subpaths; // subpaths + int n; // number of subpaths + int size; // size of subpaths array + + GfxPath(GBool justMoved1, double firstX1, double firstY1, + GfxSubpath **subpaths1, int n1, int size1); +}; + +//------------------------------------------------------------------------ +// GfxState +//------------------------------------------------------------------------ + +class GfxState { +public: + + // Construct a default GfxState, for a device with resolution + // x , page box , page rotation , and + // coordinate system specified by . + GfxState(double hDPIA, double vDPIA, PDFRectangle *pageBox, + int rotateA, GBool upsideDown + ); + + // Destructor. + ~GfxState(); + + // Copy. + GfxState *copy(GBool copyPath = gFalse) + { return new GfxState(this, copyPath); } + + // Accessors. + double getHDPI() { return hDPI; } + double getVDPI() { return vDPI; } + double *getCTM() { return ctm; } + double getX1() { return px1; } + double getY1() { return py1; } + double getX2() { return px2; } + double getY2() { return py2; } + double getPageWidth() { return pageWidth; } + double getPageHeight() { return pageHeight; } + int getRotate() { return rotate; } + GfxColor *getFillColor() { return &fillColor; } + GfxColor *getStrokeColor() { return &strokeColor; } + void getFillGray(GfxGray *gray) + { fillColorSpace->getGray(&fillColor, gray, renderingIntent); } + void getStrokeGray(GfxGray *gray) + { strokeColorSpace->getGray(&strokeColor, gray, renderingIntent); } + void getFillRGB(GfxRGB *rgb) + { fillColorSpace->getRGB(&fillColor, rgb, renderingIntent); } + void getStrokeRGB(GfxRGB *rgb) + { strokeColorSpace->getRGB(&strokeColor, rgb, renderingIntent); } + void getFillCMYK(GfxCMYK *cmyk) + { fillColorSpace->getCMYK(&fillColor, cmyk, renderingIntent); } + void getStrokeCMYK(GfxCMYK *cmyk) + { strokeColorSpace->getCMYK(&strokeColor, cmyk, renderingIntent); } + GfxColorSpace *getFillColorSpace() { return fillColorSpace; } + GfxColorSpace *getStrokeColorSpace() { return strokeColorSpace; } + GfxPattern *getFillPattern() { return fillPattern; } + GfxPattern *getStrokePattern() { return strokePattern; } + GfxBlendMode getBlendMode() { return blendMode; } + double getFillOpacity() { return fillOpacity; } + double getStrokeOpacity() { return strokeOpacity; } + GBool getFillOverprint() { return fillOverprint; } + GBool getStrokeOverprint() { return strokeOverprint; } + int getOverprintMode() { return overprintMode; } + GfxRenderingIntent getRenderingIntent() { return renderingIntent; } + Function **getTransfer() { return transfer; } + double getLineWidth() { return lineWidth; } + void getLineDash(double **dash, int *length, double *start) + { *dash = lineDash; *length = lineDashLength; *start = lineDashStart; } + double getFlatness() { return flatness; } + int getLineJoin() { return lineJoin; } + int getLineCap() { return lineCap; } + double getMiterLimit() { return miterLimit; } + GBool getStrokeAdjust() { return strokeAdjust; } + GfxFont *getFont() { return font; } + double getFontSize() { return fontSize; } + double *getTextMat() { return textMat; } + double getCharSpace() { return charSpace; } + double getWordSpace() { return wordSpace; } + double getHorizScaling() { return horizScaling; } + double getLeading() { return leading; } + double getRise() { return rise; } + int getRender() { return render; } + GfxPath *getPath() { return path; } + void setPath(GfxPath *pathA); + double getCurX() { return curX; } + double getCurY() { return curY; } + void getClipBBox(double *xMin, double *yMin, double *xMax, double *yMax) + { *xMin = clipXMin; *yMin = clipYMin; *xMax = clipXMax; *yMax = clipYMax; } + void getUserClipBBox(double *xMin, double *yMin, double *xMax, double *yMax); + double getLineX() { return lineX; } + double getLineY() { return lineY; } + GBool getIgnoreColorOps() { return ignoreColorOps; } + + // Is there a current point/path? + GBool isCurPt() { return path->isCurPt(); } + GBool isPath() { return path->isPath(); } + + // Transforms. + void transform(double x1, double y1, double *x2, double *y2) + { *x2 = ctm[0] * x1 + ctm[2] * y1 + ctm[4]; + *y2 = ctm[1] * x1 + ctm[3] * y1 + ctm[5]; } + void transformDelta(double x1, double y1, double *x2, double *y2) + { *x2 = ctm[0] * x1 + ctm[2] * y1; + *y2 = ctm[1] * x1 + ctm[3] * y1; } + void textTransform(double x1, double y1, double *x2, double *y2) + { *x2 = textMat[0] * x1 + textMat[2] * y1 + textMat[4]; + *y2 = textMat[1] * x1 + textMat[3] * y1 + textMat[5]; } + void textTransformDelta(double x1, double y1, double *x2, double *y2) + { *x2 = textMat[0] * x1 + textMat[2] * y1; + *y2 = textMat[1] * x1 + textMat[3] * y1; } + double transformWidth(double w); + double getTransformedLineWidth() + { return transformWidth(lineWidth); } + double getTransformedFontSize(); + void getFontTransMat(double *m11, double *m12, double *m21, double *m22); + + // Change state parameters. + void setCTM(double a, double b, double c, + double d, double e, double f); + void concatCTM(double a, double b, double c, + double d, double e, double f); + void shiftCTM(double tx, double ty); + void setFillColorSpace(GfxColorSpace *colorSpace); + void setStrokeColorSpace(GfxColorSpace *colorSpace); + void setFillColor(GfxColor *color) { fillColor = *color; } + void setStrokeColor(GfxColor *color) { strokeColor = *color; } + void setFillPattern(GfxPattern *pattern); + void setStrokePattern(GfxPattern *pattern); + void setBlendMode(GfxBlendMode mode) { blendMode = mode; } + void setFillOpacity(double opac) { fillOpacity = opac; } + 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 setRenderingIntent(GfxRenderingIntent ri) { renderingIntent = ri; } + void setTransfer(Function **funcs); + void setLineWidth(double width) { lineWidth = width; } + void setLineDash(double *dash, int length, double start); + void setFlatness(double flatness1) { flatness = flatness1; } + void setLineJoin(int lineJoin1) { lineJoin = lineJoin1; } + void setLineCap(int lineCap1) { lineCap = lineCap1; } + void setMiterLimit(double limit) { miterLimit = limit; } + void setStrokeAdjust(GBool sa) { strokeAdjust = sa; } + void setFont(GfxFont *fontA, double fontSizeA) + { font = fontA; fontSize = fontSizeA; } + void setTextMat(double a, double b, double c, + double d, double e, double f) + { textMat[0] = a; textMat[1] = b; textMat[2] = c; + textMat[3] = d; textMat[4] = e; textMat[5] = f; } + void setCharSpace(double space) + { charSpace = space; } + void setWordSpace(double space) + { wordSpace = space; } + void setHorizScaling(double scale) + { horizScaling = 0.01 * scale; } + void setLeading(double leadingA) + { leading = leadingA; } + void setRise(double riseA) + { rise = riseA; } + void setRender(int renderA) + { render = renderA; } + + // Add to path. + void moveTo(double x, double y) + { path->moveTo(curX = x, curY = y); } + void lineTo(double x, double y) + { path->lineTo(curX = x, curY = y); } + void curveTo(double x1, double y1, double x2, double y2, + double x3, double y3) + { path->curveTo(x1, y1, x2, y2, curX = x3, curY = y3); } + void closePath() + { path->close(); curX = path->getLastX(); curY = path->getLastY(); } + void clearPath(); + + // Update clip region. + void clip(); + void clipToStrokePath(); + void clipToRect(double xMin, double yMin, double xMax, double yMax); + void resetDevClipRect(double xMin, double yMin, double xMax, double yMax) + { clipXMin = xMin; clipYMin = yMin; clipXMax = xMax; clipYMax = yMax; } + + // Text position. + void textSetPos(double tx, double ty) { lineX = tx; lineY = ty; } + void textMoveTo(double tx, double ty) + { lineX = tx; lineY = ty; textTransform(tx, ty, &curX, &curY); } + void textShift(double tx, double ty); + void shift(double dx, double dy); + + // Ignore color operators (in cached/uncolored Type 3 chars, and + // uncolored tiling patterns). Cached Type 3 char status. + void setIgnoreColorOps(GBool ignore) { ignoreColorOps = ignore; } + + // Push/pop GfxState on/off stack. + GfxState *save(); + GfxState *restore(); + GBool hasSaves() { return saved != NULL; } + + // Misc + GBool parseBlendMode(Object *obj, GfxBlendMode *mode); + +private: + + double hDPI, vDPI; // resolution + double ctm[6]; // coord transform matrix + double px1, py1, px2, py2; // page corners (user coords) + double pageWidth, pageHeight; // page size (pixels) + int rotate; // page rotation angle + + GfxColorSpace *fillColorSpace; // fill color space + GfxColorSpace *strokeColorSpace; // stroke color space + GfxColor fillColor; // fill color + GfxColor strokeColor; // stroke color + GfxPattern *fillPattern; // fill pattern + GfxPattern *strokePattern; // stroke pattern + GfxBlendMode blendMode; // transparency blend mode + double fillOpacity; // fill opacity + double strokeOpacity; // stroke opacity + GBool fillOverprint; // fill overprint + GBool strokeOverprint; // stroke overprint + int overprintMode; // overprint mode ("OPM") + GfxRenderingIntent renderingIntent; // rendering intent + Function *transfer[4]; // transfer function (entries may be: all + // NULL = identity; last three NULL = + // single function; all four non-NULL = + // R,G,B,gray functions) + + double lineWidth; // line width + double *lineDash; // line dash + int lineDashLength; + double lineDashStart; + double flatness; // curve flatness + int lineJoin; // line join style + int lineCap; // line cap style + double miterLimit; // line miter limit + GBool strokeAdjust; // stroke adjustment + + GfxFont *font; // font + double fontSize; // font size + double textMat[6]; // text matrix + double charSpace; // character spacing + double wordSpace; // word spacing + double horizScaling; // horizontal scaling + double leading; // text leading + double rise; // text rise + int render; // text rendering mode + + GfxPath *path; // array of path elements + double curX, curY; // current point (user coords) + double lineX, lineY; // start of current text line (text coords) + + double clipXMin, clipYMin, // bounding box for clip region + clipXMax, clipYMax; + + GBool ignoreColorOps; // ignore color ops (in cached/uncolored + // Type 3 chars, and uncolored tiling + // patterns) + + GfxState *saved; // next GfxState on stack + + GfxState(GfxState *state, GBool copyPath); +}; + +#endif diff --git a/xpdf/GlobalParams.cc b/xpdf/GlobalParams.cc new file mode 100644 index 0000000..5fd4393 --- /dev/null +++ b/xpdf/GlobalParams.cc @@ -0,0 +1,3858 @@ +//======================================================================== +// +// GlobalParams.cc +// +// Copyright 2001-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include +#include +#include +#include +#ifdef _WIN32 +# include +#endif +#if HAVE_PAPER_H +#include +#endif +#if HAVE_FONTCONFIG +# include +#endif +#include "gmem.h" +#include "gmempp.h" +#include "GString.h" +#include "GList.h" +#include "GHash.h" +#include "gfile.h" +#include "FoFiIdentifier.h" +#include "Error.h" +#include "NameToCharCode.h" +#include "CharCodeToUnicode.h" +#include "UnicodeRemapping.h" +#include "UnicodeMap.h" +#include "CMap.h" +#include "BuiltinFontTables.h" +#include "FontEncodingTables.h" +#include "GlobalParams.h" + +#ifdef _WIN32 +# define strcasecmp stricmp +# define strncasecmp strnicmp +#endif + +#if MULTITHREADED +# define lockGlobalParams gLockMutex(&mutex) +# define lockUnicodeMapCache gLockMutex(&unicodeMapCacheMutex) +# define lockCMapCache gLockMutex(&cMapCacheMutex) +# define unlockGlobalParams gUnlockMutex(&mutex) +# define unlockUnicodeMapCache gUnlockMutex(&unicodeMapCacheMutex) +# define unlockCMapCache gUnlockMutex(&cMapCacheMutex) +#else +# define lockGlobalParams +# define lockUnicodeMapCache +# define lockCMapCache +# define unlockGlobalParams +# define unlockUnicodeMapCache +# define unlockCMapCache +#endif + +#include "NameToUnicodeTable.h" +#include "UnicodeMapTables.h" +#include "UTF8.h" + +//------------------------------------------------------------------------ + +#define cidToUnicodeCacheSize 4 +#define unicodeToUnicodeCacheSize 4 + +//------------------------------------------------------------------------ + +static struct { + const char *name; + const char *t1FileName; + const char *ttFileName; + const char *macFileName; // may be .dfont, .ttf, or .ttc + const char *macFontName; // font name inside .dfont or .ttc + const char *obliqueFont; // name of font to oblique + double obliqueFactor; // oblique sheer factor +} displayFontTab[] = { + {"Courier", "n022003l.pfb", "cour.ttf", "Courier", "Courier", NULL, 0}, + {"Courier-Bold", "n022004l.pfb", "courbd.ttf", "Courier", "Courier Bold", NULL, 0}, + {"Courier-BoldOblique", "n022024l.pfb", "courbi.ttf", "Courier", "Courier Bold Oblique", "Courier-Bold", 0.212557}, + {"Courier-Oblique", "n022023l.pfb", "couri.ttf", "Courier", "Courier Oblique", "Courier", 0.212557}, + {"Helvetica", "n019003l.pfb", "arial.ttf", "Helvetica", "Helvetica", NULL, 0}, + {"Helvetica-Bold", "n019004l.pfb", "arialbd.ttf", "Helvetica", "Helvetica Bold", NULL, 0}, + {"Helvetica-BoldOblique", "n019024l.pfb", "arialbi.ttf", "Helvetica", "Helvetica Bold Oblique", "Helvetica-Bold", 0.212557}, + {"Helvetica-Oblique", "n019023l.pfb", "ariali.ttf", "Helvetica", "Helvetica Oblique", "Helvetica", 0.212557}, + {"Symbol", "s050000l.pfb", NULL, "Symbol", "Symbol", NULL, 0}, + {"Times-Bold", "n021004l.pfb", "timesbd.ttf", "Times", "Times Bold", NULL, 0}, + {"Times-BoldItalic", "n021024l.pfb", "timesbi.ttf", "Times", "Times Bold Italic", NULL, 0}, + {"Times-Italic", "n021023l.pfb", "timesi.ttf", "Times", "Times Italic", NULL, 0}, + {"Times-Roman", "n021003l.pfb", "times.ttf", "Times", "Times Roman", NULL, 0}, + {"ZapfDingbats", "d050000l.pfb", NULL, "ZapfDingbats", "Zapf Dingbats", NULL, 0}, + {NULL} +}; + +#ifdef _WIN32 +static const char *displayFontDirs[] = { + "c:/windows/fonts", + "c:/winnt/fonts", + NULL +}; +#else +static const char *displayFontDirs[] = { + "/usr/share/ghostscript/fonts", + "/usr/local/share/ghostscript/fonts", + "/usr/share/fonts/default/Type1", + "/usr/share/fonts/default/ghostscript", + "/usr/share/fonts/type1/gsfonts", +#if defined(__sun) && defined(__SVR4) + "/usr/sfw/share/ghostscript/fonts", +#endif + NULL +}; +#endif + +#ifdef __APPLE__ +static const char *macSystemFontPath = "/System/Library/Fonts"; +#endif + +struct Base14FontInfo { + Base14FontInfo(GString *fileNameA, int fontNumA, double obliqueA) { + fileName = fileNameA; + fontNum = fontNumA; + oblique = obliqueA; + } + ~Base14FontInfo() { + delete fileName; + } + GString *fileName; + int fontNum; + double oblique; +}; + +//------------------------------------------------------------------------ + +GlobalParams *globalParams = NULL; + +const char *GlobalParams::defaultTextEncoding = "Latin1"; + +//------------------------------------------------------------------------ +// PSFontParam16 +//------------------------------------------------------------------------ + +PSFontParam16::PSFontParam16(GString *nameA, int wModeA, + GString *psFontNameA, GString *encodingA) { + name = nameA; + wMode = wModeA; + psFontName = psFontNameA; + encoding = encodingA; +} + +PSFontParam16::~PSFontParam16() { + delete name; + delete psFontName; + delete encoding; +} + +//------------------------------------------------------------------------ +// SysFontInfo +//------------------------------------------------------------------------ + +class SysFontInfo { +public: + + GString *name; + GString *path; + SysFontType type; + int fontNum; // for TrueType collections + + SysFontInfo(GString *nameA, GString *pathA, SysFontType typeA, int fontNumA); + ~SysFontInfo(); + GString *mungeName1(GString *in); + GString *mungeName2(GString *in); + void mungeName3(GString *name, GBool *bold, GBool *italic); + int match(GString *nameA); +}; + +SysFontInfo::SysFontInfo(GString *nameA, GString *pathA, + SysFontType typeA, int fontNumA) { + name = nameA; + path = pathA; + type = typeA; + fontNum = fontNumA; +} + +SysFontInfo::~SysFontInfo() { + delete name; + delete path; +} + +// Remove space/comma/dash/underscore chars. +// Uppercase the name. +GString *SysFontInfo::mungeName1(GString *in) { + GString *out = new GString(); + for (char *p = in->getCString(); *p; ++p) { + if (*p == ' ' || *p == ',' || *p == '-' || *p == '_') { + // skip + } else if (*p >= 'a' && *p <= 'z') { + out->append((char)(*p & 0xdf)); + } else { + out->append(*p); + } + } + return out; +} + +// Remove trailing encoding tags from the name. +// Split the name into tokens at space/comma/dash/underscore. +// Remove trailing "MT" or "BT" from tokens. +// Remove trailing "PS" and "WGL4" from tokens. +// Uppercase each token. +// Concatenate tokens (dropping the space/comma/dash chars). +GString *SysFontInfo::mungeName2(GString *in) { + GString *out = new GString(); + char *p0 = in->getCString(); + while (*p0) { + if (!strcmp(p0, "Identity-H") || !strcmp(p0, "Identity-V") || + !strcmp(p0, "GB2312") || + !strcmp(p0, "UniGB-UCS2-H") || !strcmp(p0, "UniGB-UCS2-V")) { + break; + } + char *p1; + for (p1 = p0 + 1; + *p1 && *p1 != ' ' && *p1 != ',' && *p1 != '-' && *p1 != '_'; + ++p1) ; + char *p2 = p1; + if (p2 - p0 >= 2 && (p2[-2] == 'B' || p2[-2] == 'M') && p2[-1] == 'T') { + p2 -= 2; + } + if (p2 - p0 >= 2 && p2[-2] == 'P' && p2[-1] == 'S') { + p2 -= 2; + } + if (p2 - p0 >= 4 && + p2[-4] == 'W' && p2[-3] == 'G' && p2[-2] == 'L' && p2[-1] == '4') { + p2 -= 4; + } + for (; p0 < p2; ++p0) { + if (*p0 >= 'a' && *p0 <= 'z') { + out->append((char)(*p0 & 0xdf)); + } else { + out->append(*p0); + } + } + for (p0 = p1; *p0 == ' ' || *p0 == ',' || *p0 == '-' || *p0 == '_'; ++p0) ; + } + return out; +} + +// Remove trailing bold/italic/regular/roman tags from the name. +// (Note: the names have already been uppercased by mungeName1/2.) +void SysFontInfo::mungeName3(GString *name, GBool *bold, GBool *italic) { + *bold = gFalse; + *italic = gFalse; + int n = name->getLength(); + while (1) { + if (n >= 4 && !strcmp(name->getCString() + n - 4, "BOLD")) { + name->del(n - 4, 4); + n -= 4; + *bold = gTrue; + } else if (n >= 6 && !strcmp(name->getCString() + n - 6, "ITALIC")) { + name->del(n - 6, 6); + n -= 6; + *italic = gTrue; + } else if (n >= 7 && !strcmp(name->getCString() + n - 7, "REGULAR")) { + name->del(n - 7, 7); + n -= 7; + } else if (n >= 5 && !strcmp(name->getCString() + n - 5, "ROMAN")) { + name->del(n - 5, 5); + n -= 5; + } else { + break; + } + } +} + +// Returns a score indicating how well this font matches [nameA]. A +// higher score is better. Zero indicates a non-match. +int SysFontInfo::match(GString *nameA) { + // fast fail: check if the first two letters match + if (strncasecmp(name->getCString(), nameA->getCString(), 2)) { + return 0; + } + + GString *pdfName1 = mungeName1(nameA); + GString *sysName1 = mungeName1(name); + if (!pdfName1->cmp(sysName1)) { + delete pdfName1; + delete sysName1; + return 8; + } + + GString *pdfName2 = mungeName2(nameA); + GString *sysName2 = mungeName2(name); + if (!pdfName2->cmp(sysName2)) { + delete pdfName1; + delete sysName1; + delete pdfName2; + delete sysName2; + return 7; + } + + GBool pdfBold1, pdfItalic1, sysBold1, sysItalic1; + mungeName3(pdfName1, &pdfBold1, &pdfItalic1); + mungeName3(sysName1, &sysBold1, &sysItalic1); + int eq1 = !pdfName1->cmp(sysName1); + + GBool pdfBold2, pdfItalic2, sysBold2, sysItalic2; + mungeName3(pdfName2, &pdfBold2, &pdfItalic2); + mungeName3(sysName2, &sysBold2, &sysItalic2); + int eq2 =!pdfName2->cmp(sysName2); + + delete pdfName1; + delete sysName1; + delete pdfName2; + delete sysName2; + + if (eq1 && pdfBold1 == sysBold1 && pdfItalic1 == sysItalic1) { + return 6; + } + if (eq2 && pdfBold2 == sysBold2 && pdfItalic2 == sysItalic2) { + return 5; + } + if (eq1 && pdfItalic1 == sysItalic1) { + return 4; + } + if (eq2 && pdfItalic2 == sysItalic2) { + return 3; + } + if (eq1) { + return 2; + } + if (eq2) { + return 1; + } + + return 0; +} + +//------------------------------------------------------------------------ +// SysFontList +//------------------------------------------------------------------------ + +class SysFontList { +public: + + SysFontList(); + ~SysFontList(); + SysFontInfo *find(GString *name); + +#ifdef _WIN32 + void scanWindowsFonts(char *winFontDir); +#endif + +#if HAVE_FONTCONFIG + void scanFontconfigFonts(); +#endif + +private: + +#ifdef _WIN32 + SysFontInfo *makeWindowsFont(char *name, int fontNum, + char *path); +#endif + + GList *fonts; // [SysFontInfo] +}; + +SysFontList::SysFontList() { + fonts = new GList(); +} + +SysFontList::~SysFontList() { + deleteGList(fonts, SysFontInfo); +} + +SysFontInfo *SysFontList::find(GString *name) { + SysFontInfo *match = NULL; + int score = 0; + for (int i = 0; i < fonts->getLength(); ++i) { + SysFontInfo *fi = (SysFontInfo *)fonts->get(i); + int s = fi->match(name); + if (s > score) { + match = fi; + score = s; + } + } + return match; +} + +#ifdef _WIN32 +void SysFontList::scanWindowsFonts(char *winFontDir) { + OSVERSIONINFO version; + const char *path; + DWORD idx, valNameLen, dataLen, type; + HKEY regKey; + char valName[1024], data[1024]; + int n, fontNum; + char *p0, *p1; + GString *fontPath; + + 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 (RegOpenKeyExA(HKEY_LOCAL_MACHINE, path, 0, + KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS, + ®Key) == ERROR_SUCCESS) { + idx = 0; + while (1) { + valNameLen = sizeof(valName) - 1; + dataLen = sizeof(data) - 1; + if (RegEnumValueA(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 = (int)strlen(data); + if (!strcasecmp(data + n - 4, ".ttf") || + !strcasecmp(data + n - 4, ".ttc") || + !strcasecmp(data + n - 4, ".otf")) { + 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); + } +} + +SysFontInfo *SysFontList::makeWindowsFont(char *name, int fontNum, + char *path) { + int n = (int)strlen(name); + + // remove trailing ' (TrueType)' or ' (OpenType)' + if (n > 11 && (!strncmp(name + n - 11, " (TrueType)", 11) || + !strncmp(name + n - 11, " (OpenType)", 11))) { + n -= 11; + } + + SysFontType type; + if (!strcasecmp(path + strlen(path) - 4, ".ttc")) { + type = sysFontTTC; + } else if (!strcasecmp(path + strlen(path) - 4, ".otf")) { + type = sysFontOTF; + } else { + type = sysFontTTF; + } + + return new SysFontInfo(new GString(name, n), new GString(path), + type, fontNum); +} +#endif // _WIN32 + +#if HAVE_FONTCONFIG +void SysFontList::scanFontconfigFonts() { + FcConfig *cfg; + FcPattern *pattern; + FcObjectSet *objSet; + FcFontSet *fontSet; + char *name, *file; + SysFontType type; + int fontNum, i, n; + + if (!(cfg = FcInitLoadConfigAndFonts())) { + return; + } + + pattern = FcPatternBuild(NULL, + FC_OUTLINE, FcTypeBool, FcTrue, + FC_SCALABLE, FcTypeBool, FcTrue, + NULL); + objSet = FcObjectSetBuild(FC_FULLNAME, FC_FILE, FC_INDEX, NULL); + fontSet = FcFontList(cfg, pattern, objSet); + FcPatternDestroy(pattern); + FcObjectSetDestroy(objSet); + + if (fontSet) { + for (i = 0; i < fontSet->nfont; ++i) { + + //--- font file, font type + if (FcPatternGetString(fontSet->fonts[i], FC_FILE, 0, + (FcChar8 **)&file) + != FcResultMatch) { + continue; + } + n = (int)strlen(file); + if (n > 4 && !strcasecmp(file + n - 4, ".pfa")) { + type = sysFontPFA; + } else if (n > 4 && !strcasecmp(file + n - 4, ".pfb")) { + type = sysFontPFB; + } else if (n > 4 && !strcasecmp(file + n - 4, ".ttf")) { + type = sysFontTTF; + } else if (n > 4 && !strcasecmp(file + n - 4, ".otf")) { + type = sysFontOTF; + } else { + continue; + } + + //--- font number + if (FcPatternGetInteger(fontSet->fonts[i], FC_INDEX, 0, &fontNum) + != FcResultMatch) { + fontNum = 0; + } + + //--- font name + if (FcPatternGetString(fontSet->fonts[i], FC_FULLNAME, 0, + (FcChar8 **)&name) + != FcResultMatch) { + continue; + } + + fonts->append(new SysFontInfo(new GString(name), new GString(file), + type, fontNum)); + } + + FcFontSetDestroy(fontSet); + } + + FcConfigDestroy(cfg); +} +#endif // HAVE_FONTCONFIG + +//------------------------------------------------------------------------ +// KeyBinding +//------------------------------------------------------------------------ + +KeyBinding::KeyBinding(int codeA, int modsA, int contextA, const char *cmd0) { + code = codeA; + mods = modsA; + context = contextA; + cmds = new GList(); + cmds->append(new GString(cmd0)); +} + +KeyBinding::KeyBinding(int codeA, int modsA, int contextA, + const char *cmd0, const char *cmd1) { + code = codeA; + mods = modsA; + context = contextA; + cmds = new GList(); + cmds->append(new GString(cmd0)); + cmds->append(new GString(cmd1)); +} + +KeyBinding::KeyBinding(int codeA, int modsA, int contextA, GList *cmdsA) { + code = codeA; + mods = modsA; + context = contextA; + cmds = cmdsA; +} + +KeyBinding::~KeyBinding() { + deleteGList(cmds, GString); +} + +//------------------------------------------------------------------------ +// PopupMenuCmd +//------------------------------------------------------------------------ + +PopupMenuCmd::PopupMenuCmd(GString *labelA, GList *cmdsA) { + label = labelA; + cmds = cmdsA; +} + +PopupMenuCmd::~PopupMenuCmd() { + delete label; + deleteGList(cmds, GString); +} + +//------------------------------------------------------------------------ +// parsing +//------------------------------------------------------------------------ + +GlobalParams::GlobalParams(const char *cfgFileName) { + UnicodeMap *map; + GString *fileName; + FILE *f; + int i; + +#if MULTITHREADED + gInitMutex(&mutex); + gInitMutex(&unicodeMapCacheMutex); + gInitMutex(&cMapCacheMutex); +#endif + +#ifdef _WIN32 + tlsWin32ErrorInfo = TlsAlloc(); +#endif + + initBuiltinFontTables(); + + // scan the encoding in reverse because we want the lowest-numbered + // index for each char name ('space' is encoded twice) + macRomanReverseMap = new NameToCharCode(); + for (i = 255; i >= 0; --i) { + if (macRomanEncoding[i]) { + macRomanReverseMap->add(macRomanEncoding[i], (CharCode)i); + } + } + +#ifdef _WIN32 + // baseDir will be set by a call to setBaseDir + baseDir = new GString(); +#else + baseDir = appendToPath(getHomeDir(), ".xpdf"); +#endif + configFileVars = new GHash(gTrue); + setDataDirVar(); + nameToUnicode = new NameToCharCode(); + cidToUnicodes = new GHash(gTrue); + unicodeToUnicodes = new GHash(gTrue); + residentUnicodeMaps = new GHash(); + unicodeMaps = new GHash(gTrue); + cMapDirs = new GHash(gTrue); + toUnicodeDirs = new GList(); + unicodeRemapping = new UnicodeRemapping(); + fontFiles = new GHash(gTrue); + fontDirs = new GList(); + ccFontFiles = new GHash(gTrue); + base14SysFonts = new GHash(gTrue); + sysFonts = new SysFontList(); +#if HAVE_PAPER_H + char *paperName; + const struct paper *paperType; + paperinit(); + if ((paperName = systempapername())) { + paperType = paperinfo(paperName); + psPaperWidth = (int)paperpswidth(paperType); + psPaperHeight = (int)paperpsheight(paperType); + } else { + error(errConfig, -1, "No paper information available - using defaults"); + psPaperWidth = defPaperWidth; + psPaperHeight = defPaperHeight; + } + paperdone(); +#else + psPaperWidth = defPaperWidth; + psPaperHeight = defPaperHeight; +#endif + psImageableLLX = psImageableLLY = 0; + psImageableURX = psPaperWidth; + psImageableURY = psPaperHeight; + psCrop = gTrue; + psUseCropBoxAsPage = gFalse; + psExpandSmaller = gFalse; + psShrinkLarger = gTrue; + psCenter = gTrue; + psDuplex = gFalse; + psLevel = psLevel2; + 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; + psLZW = gTrue; + psUncompressPreloadedImages = gFalse; + psMinLineWidth = 0; + psRasterResolution = 300; + psRasterMono = gFalse; + psRasterSliceSize = 20000000; + psAlwaysRasterize = gFalse; + psNeverRasterize = gFalse; + textEncoding = new GString(defaultTextEncoding); +#if defined(_WIN32) + textEOL = eolDOS; +#else + textEOL = eolUnix; +#endif + textPageBreaks = gTrue; + textKeepTinyChars = gTrue; + initialZoom = new GString("125"); + defaultFitZoom = 0; + initialDisplayMode = new GString("continuous"); + initialToolbarState = gTrue; + initialSidebarState = gTrue; + initialSidebarWidth = 0; + initialSelectMode = new GString("linear"); + maxTileWidth = 1500; + maxTileHeight = 1500; + tileCacheSize = 10; + workerThreads = 1; + enableFreeType = gTrue; + disableFreeTypeHinting = gFalse; + antialias = gTrue; + vectorAntialias = gTrue; + imageMaskAntialias = gTrue; + antialiasPrinting = gFalse; + strokeAdjust = strokeAdjustNormal; + screenType = screenUnset; + screenSize = -1; + screenDotRadius = -1; + screenGamma = 1.0; + screenBlackThreshold = 0.0; + screenWhiteThreshold = 1.0; + minLineWidth = 0.0; + enablePathSimplification = gFalse; + drawAnnotations = gTrue; + drawFormFields = gTrue; + enableXFA = gTrue; + overprintPreview = gFalse; + paperColor = new GString("#ffffff"); + matteColor = new GString("#808080"); + fullScreenMatteColor = new GString("#000000"); + selectionColor = new GString("#8080ff"); + reverseVideoInvertImages = gFalse; + launchCommand = NULL; + movieCommand = NULL; + defaultPrinter = NULL; + mapNumericCharNames = gTrue; + mapUnknownCharNames = gFalse; + mapExtTrueTypeFontsViaUnicode = gTrue; + useTrueTypeUnicodeMapping = gFalse; + droppedFonts = new GHash(gTrue); + createDefaultKeyBindings(); + popupMenuCmds = new GList(); + tabStateFile = appendToPath(getHomeDir(), ".xpdf.tab-state"); + savePageNumbers = gTrue; + printCommands = gFalse; + printStatusInfo = gFalse; + errQuiet = gFalse; + debugLogFile = NULL; + + cidToUnicodeCache = new CharCodeToUnicodeCache(cidToUnicodeCacheSize); + unicodeToUnicodeCache = + new CharCodeToUnicodeCache(unicodeToUnicodeCacheSize); + unicodeMapCache = new UnicodeMapCache(); + cMapCache = new CMapCache(); + + // set up the initial nameToUnicode table + for (i = 0; nameToUnicodeTab[i].name; ++i) { + nameToUnicode->add(nameToUnicodeTab[i].name, nameToUnicodeTab[i].u); + } + + // set up the residentUnicodeMaps table + map = new UnicodeMap("Latin1", gFalse, + latin1UnicodeMapRanges, latin1UnicodeMapLen); + residentUnicodeMaps->add(map->getEncodingName(), map); + map = new UnicodeMap("ASCII7", gFalse, + ascii7UnicodeMapRanges, ascii7UnicodeMapLen); + residentUnicodeMaps->add(map->getEncodingName(), map); + map = new UnicodeMap("Symbol", gFalse, + symbolUnicodeMapRanges, symbolUnicodeMapLen); + residentUnicodeMaps->add(map->getEncodingName(), map); + map = new UnicodeMap("ZapfDingbats", gFalse, zapfDingbatsUnicodeMapRanges, + zapfDingbatsUnicodeMapLen); + residentUnicodeMaps->add(map->getEncodingName(), map); + map = new UnicodeMap("UTF-8", gTrue, &mapUTF8); + residentUnicodeMaps->add(map->getEncodingName(), map); + map = new UnicodeMap("UCS-2", gTrue, &mapUCS2); + residentUnicodeMaps->add(map->getEncodingName(), map); + + // look for a user config file, then a system-wide config file + f = NULL; + fileName = NULL; + if (cfgFileName && cfgFileName[0]) { + fileName = new GString(cfgFileName); + if (!(f = fopen(fileName->getCString(), "r"))) { + delete fileName; + } + } + if (!f) { + fileName = appendToPath(getHomeDir(), xpdfUserConfigFile); + if (!(f = fopen(fileName->getCString(), "r"))) { + delete fileName; + } + } + if (!f) { +#ifdef _WIN32 + char buf[512]; + i = GetModuleFileNameA(NULL, buf, sizeof(buf)); + if (i <= 0 || i >= sizeof(buf)) { + // error or path too long for buffer - just use the current dir + buf[0] = '\0'; + } + fileName = grabPath(buf); + appendToPath(fileName, xpdfSysConfigFile); +#else + fileName = new GString(xpdfSysConfigFile); +#endif + if (!(f = fopen(fileName->getCString(), "r"))) { + delete fileName; + } + } + if (f) { + parseFile(fileName, f); + delete fileName; + fclose(f); + } +} + +void GlobalParams::setDataDirVar() { + GString *dir; + +#if defined(XPDFRC_DATADIR) + dir = new GString(XPDFRC_DATADIR); +#elif defined(_WIN32) + wchar_t buf[512]; + DWORD n = GetModuleFileNameW(NULL, buf, sizeof(buf) / sizeof(wchar_t)); + if (n <= 0 || n >= sizeof(buf)) { + // error or path too long for buffer - just use the current dir + buf[0] = L'\0'; + } + GString *path = fileNameToUTF8(buf); + dir = grabPath(path->getCString()); + delete path; + appendToPath(dir, "data"); +#else + //~ may be useful to allow the options of using the install dir + //~ and/or the user's home dir (?) + dir = new GString("./data"); +#endif + + configFileVars->add(new GString("DATADIR"), dir); +} + +void GlobalParams::createDefaultKeyBindings() { + keyBindings = new GList(); + + //----- mouse buttons + keyBindings->append(new KeyBinding(xpdfKeyCodeMousePress1, xpdfKeyModNone, + xpdfKeyContextAny, "startSelection")); + keyBindings->append(new KeyBinding(xpdfKeyCodeMousePress1, xpdfKeyModShift, + xpdfKeyContextAny, + "startExtendedSelection")); + keyBindings->append(new KeyBinding(xpdfKeyCodeMouseRelease1, xpdfKeyModNone, + xpdfKeyContextAny, "endSelection")); + keyBindings->append(new KeyBinding(xpdfKeyCodeMouseRelease1, xpdfKeyModShift, + xpdfKeyContextAny, + "endSelection")); + keyBindings->append(new KeyBinding(xpdfKeyCodeMouseDoubleClick1, + xpdfKeyModNone, xpdfKeyContextAny, + "selectWord")); + keyBindings->append(new KeyBinding(xpdfKeyCodeMouseTripleClick1, + xpdfKeyModNone, xpdfKeyContextAny, + "selectLine")); + keyBindings->append(new KeyBinding(xpdfKeyCodeMouseClick1, xpdfKeyModNone, + xpdfKeyContextAny, "followLinkNoSel")); + keyBindings->append(new KeyBinding(xpdfKeyCodeMouseClick2, xpdfKeyModNone, + xpdfKeyContextOverLink, + "followLinkInNewTab")); + keyBindings->append(new KeyBinding(xpdfKeyCodeMousePress2, xpdfKeyModNone, + xpdfKeyContextAny, "startPan")); + keyBindings->append(new KeyBinding(xpdfKeyCodeMouseRelease2, xpdfKeyModNone, + xpdfKeyContextAny, "endPan")); + keyBindings->append(new KeyBinding(xpdfKeyCodeMousePress3, xpdfKeyModNone, + xpdfKeyContextAny, "postPopupMenu")); + keyBindings->append(new KeyBinding(xpdfKeyCodeMousePress4, xpdfKeyModNone, + xpdfKeyContextAny, + "scrollUpPrevPage(16)")); + keyBindings->append(new KeyBinding(xpdfKeyCodeMousePress5, xpdfKeyModNone, + xpdfKeyContextAny, + "scrollDownNextPage(16)")); + keyBindings->append(new KeyBinding(xpdfKeyCodeMousePress6, xpdfKeyModNone, + xpdfKeyContextAny, "scrollLeft(16)")); + keyBindings->append(new KeyBinding(xpdfKeyCodeMousePress7, xpdfKeyModNone, + xpdfKeyContextAny, "scrollRight(16)")); + keyBindings->append(new KeyBinding(xpdfKeyCodeMousePress4, xpdfKeyModCtrl, + xpdfKeyContextAny, "zoomIn")); + keyBindings->append(new KeyBinding(xpdfKeyCodeMousePress5, xpdfKeyModCtrl, + xpdfKeyContextAny, "zoomOut")); + + //----- control keys + keyBindings->append(new KeyBinding('o', xpdfKeyModCtrl, + xpdfKeyContextAny, "open")); + keyBindings->append(new KeyBinding('r', xpdfKeyModCtrl, + xpdfKeyContextAny, "reload")); + keyBindings->append(new KeyBinding('f', xpdfKeyModCtrl, + xpdfKeyContextAny, "find")); + keyBindings->append(new KeyBinding('g', xpdfKeyModCtrl, + xpdfKeyContextAny, "findNext")); + keyBindings->append(new KeyBinding('c', xpdfKeyModCtrl, + xpdfKeyContextAny, "copy")); + keyBindings->append(new KeyBinding('p', xpdfKeyModCtrl, + xpdfKeyContextAny, "print")); + keyBindings->append(new KeyBinding('0', xpdfKeyModCtrl, + xpdfKeyContextAny, "zoomPercent(125)")); + keyBindings->append(new KeyBinding('+', xpdfKeyModCtrl, + xpdfKeyContextAny, "zoomIn")); + keyBindings->append(new KeyBinding('=', xpdfKeyModCtrl, + xpdfKeyContextAny, "zoomIn")); + keyBindings->append(new KeyBinding('-', xpdfKeyModCtrl, + xpdfKeyContextAny, "zoomOut")); + keyBindings->append(new KeyBinding('s', xpdfKeyModCtrl, + xpdfKeyContextAny, "saveAs")); + keyBindings->append(new KeyBinding('t', xpdfKeyModCtrl, + xpdfKeyContextAny, "newTab")); + keyBindings->append(new KeyBinding('n', xpdfKeyModCtrl, + xpdfKeyContextAny, "newWindow")); + keyBindings->append(new KeyBinding('w', xpdfKeyModCtrl, + xpdfKeyContextAny, "closeTabOrQuit")); + keyBindings->append(new KeyBinding('l', xpdfKeyModCtrl, + xpdfKeyContextAny, + "toggleFullScreenMode")); + keyBindings->append(new KeyBinding('q', xpdfKeyModCtrl, + xpdfKeyContextAny, "quit")); + keyBindings->append(new KeyBinding(xpdfKeyCodeTab, xpdfKeyModCtrl, + xpdfKeyContextAny, "nextTab")); + keyBindings->append(new KeyBinding(xpdfKeyCodeTab, + xpdfKeyModShift | xpdfKeyModCtrl, + xpdfKeyContextAny, "prevTab")); + keyBindings->append(new KeyBinding('?', xpdfKeyModCtrl, + xpdfKeyContextAny, "help")); + + //----- alt keys + keyBindings->append(new KeyBinding(xpdfKeyCodeLeft, xpdfKeyModAlt, + xpdfKeyContextAny, "goBackward")); + keyBindings->append(new KeyBinding(xpdfKeyCodeRight, xpdfKeyModAlt, + xpdfKeyContextAny, "goForward")); + + //----- home/end keys + keyBindings->append(new KeyBinding(xpdfKeyCodeHome, xpdfKeyModCtrl, + xpdfKeyContextAny, "gotoPage(1)")); + keyBindings->append(new KeyBinding(xpdfKeyCodeHome, xpdfKeyModNone, + xpdfKeyContextAny, "scrollToTopLeft")); + keyBindings->append(new KeyBinding(xpdfKeyCodeEnd, xpdfKeyModCtrl, + xpdfKeyContextAny, "gotoLastPage")); + keyBindings->append(new KeyBinding(xpdfKeyCodeEnd, xpdfKeyModNone, + xpdfKeyContextAny, + "scrollToBottomRight")); + + //----- pgup/pgdn keys + keyBindings->append(new KeyBinding(xpdfKeyCodePgUp, xpdfKeyModNone, + xpdfKeyContextAny, "pageUp")); + keyBindings->append(new KeyBinding(xpdfKeyCodePgDn, xpdfKeyModNone, + xpdfKeyContextAny, "pageDown")); + keyBindings->append(new KeyBinding(xpdfKeyCodePgUp, xpdfKeyModCtrl, + xpdfKeyContextAny, "prevPage")); + keyBindings->append(new KeyBinding(xpdfKeyCodePgDn, xpdfKeyModCtrl, + xpdfKeyContextAny, "nextPage")); + keyBindings->append(new KeyBinding(xpdfKeyCodePgUp, xpdfKeyModCtrl, + xpdfKeyContextScrLockOn, + "prevPageNoScroll")); + keyBindings->append(new KeyBinding(xpdfKeyCodePgDn, xpdfKeyModCtrl, + xpdfKeyContextScrLockOn, + "nextPageNoScroll")); + + //----- esc key + keyBindings->append(new KeyBinding(xpdfKeyCodeEsc, xpdfKeyModNone, + xpdfKeyContextFullScreen, + "windowMode")); + + //----- arrow keys + keyBindings->append(new KeyBinding(xpdfKeyCodeLeft, xpdfKeyModNone, + xpdfKeyContextAny, "scrollLeft(16)")); + keyBindings->append(new KeyBinding(xpdfKeyCodeRight, xpdfKeyModNone, + xpdfKeyContextAny, "scrollRight(16)")); + keyBindings->append(new KeyBinding(xpdfKeyCodeUp, xpdfKeyModNone, + xpdfKeyContextAny, "scrollUp(16)")); + keyBindings->append(new KeyBinding(xpdfKeyCodeDown, xpdfKeyModNone, + xpdfKeyContextAny, "scrollDown(16)")); + keyBindings->append(new KeyBinding(xpdfKeyCodeUp, xpdfKeyModCtrl, + xpdfKeyContextAny, "prevPage")); + keyBindings->append(new KeyBinding(xpdfKeyCodeDown, xpdfKeyModCtrl, + xpdfKeyContextAny, "nextPage")); + keyBindings->append(new KeyBinding(xpdfKeyCodeUp, xpdfKeyModCtrl, + xpdfKeyContextScrLockOn, + "prevPageNoScroll")); + keyBindings->append(new KeyBinding(xpdfKeyCodeDown, xpdfKeyModCtrl, + xpdfKeyContextScrLockOn, + "nextPageNoScroll")); + + //----- letter keys + keyBindings->append(new KeyBinding(' ', xpdfKeyModNone, + xpdfKeyContextAny, "pageDown")); + keyBindings->append(new KeyBinding('g', xpdfKeyModNone, + xpdfKeyContextAny, "focusToPageNum")); + keyBindings->append(new KeyBinding('z', xpdfKeyModNone, + xpdfKeyContextAny, "zoomFitPage")); + keyBindings->append(new KeyBinding('w', xpdfKeyModNone, + xpdfKeyContextAny, "zoomFitWidth")); +} + +void GlobalParams::parseFile(GString *fileName, FILE *f) { + int line; + char buf[512]; + + line = 1; + while (getLine(buf, sizeof(buf) - 1, f)) { + parseLine(buf, fileName, line); + ++line; + } +} + +void GlobalParams::parseLine(char *buf, GString *fileName, int line) { + GList *tokens; + GString *cmd, *incFile; + FILE *f2; + + // break the line into tokens + tokens = parseLineTokens(buf, fileName, line); + + // parse the line + if (tokens->getLength() > 0 && + ((GString *)tokens->get(0))->getChar(0) != '#') { + cmd = (GString *)tokens->get(0); + if (!cmd->cmp("include")) { + if (tokens->getLength() == 2) { + incFile = (GString *)tokens->get(1); + if ((f2 = openFile(incFile->getCString(), "r"))) { + parseFile(incFile, f2); + fclose(f2); + } else { + error(errConfig, -1, + "Couldn't find included config file: '{0:t}' ({1:t}:{2:d})", + incFile, fileName, line); + } + } else { + error(errConfig, -1, "Bad 'include' config file command ({0:t}:{1:d})", + fileName, line); + } + } else if (!cmd->cmp("nameToUnicode")) { + parseNameToUnicode(tokens, fileName, line); + } else if (!cmd->cmp("cidToUnicode")) { + parseCIDToUnicode(tokens, fileName, line); + } else if (!cmd->cmp("unicodeToUnicode")) { + parseUnicodeToUnicode(tokens, fileName, line); + } else if (!cmd->cmp("unicodeMap")) { + parseUnicodeMap(tokens, fileName, line); + } else if (!cmd->cmp("cMapDir")) { + parseCMapDir(tokens, fileName, line); + } else if (!cmd->cmp("toUnicodeDir")) { + parseToUnicodeDir(tokens, fileName, line); + } else if (!cmd->cmp("unicodeRemapping")) { + parseUnicodeRemapping(tokens, 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("psPaperSize")) { + parsePSPaperSize(tokens, fileName, line); + } else if (!cmd->cmp("psImageableArea")) { + parsePSImageableArea(tokens, fileName, line); + } else if (!cmd->cmp("psCrop")) { + parseYesNo("psCrop", &psCrop, tokens, fileName, line); + } else if (!cmd->cmp("psUseCropBoxAsPage")) { + parseYesNo("psUseCropBoxAsPage", &psUseCropBoxAsPage, + tokens, fileName, line); + } else if (!cmd->cmp("psExpandSmaller")) { + parseYesNo("psExpandSmaller", &psExpandSmaller, + tokens, fileName, line); + } else if (!cmd->cmp("psShrinkLarger")) { + parseYesNo("psShrinkLarger", &psShrinkLarger, tokens, fileName, line); + } else if (!cmd->cmp("psCenter")) { + parseYesNo("psCenter", &psCenter, tokens, fileName, line); + } else if (!cmd->cmp("psDuplex")) { + parseYesNo("psDuplex", &psDuplex, tokens, fileName, line); + } else if (!cmd->cmp("psLevel")) { + parsePSLevel(tokens, fileName, line); + } else if (!cmd->cmp("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")) { + parseYesNo("psEmbedTrueType", &psEmbedTrueType, + tokens, fileName, line); + } else if (!cmd->cmp("psEmbedCIDPostScriptFonts")) { + parseYesNo("psEmbedCIDPostScript", &psEmbedCIDPostScript, + tokens, fileName, line); + } else if (!cmd->cmp("psEmbedCIDTrueTypeFonts")) { + parseYesNo("psEmbedCIDTrueType", &psEmbedCIDTrueType, + tokens, fileName, line); + } else if (!cmd->cmp("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("psLZW")) { + parseYesNo("psLZW", &psLZW, tokens, fileName, line); + } else if (!cmd->cmp("psUncompressPreloadedImages")) { + parseYesNo("psUncompressPreloadedImages", &psUncompressPreloadedImages, + tokens, fileName, line); + } else if (!cmd->cmp("psMinLineWidth")) { + parseFloat("psMinLineWidth", &psMinLineWidth, + tokens, fileName, line); + } else if (!cmd->cmp("psRasterResolution")) { + parseFloat("psRasterResolution", &psRasterResolution, + tokens, fileName, line); + } else if (!cmd->cmp("psRasterMono")) { + parseYesNo("psRasterMono", &psRasterMono, tokens, fileName, line); + } else if (!cmd->cmp("psRasterSliceSize")) { + parseInteger("psRasterSliceSize", &psRasterSliceSize, + tokens, fileName, line); + } else if (!cmd->cmp("psAlwaysRasterize")) { + parseYesNo("psAlwaysRasterize", &psAlwaysRasterize, + tokens, fileName, line); + } else if (!cmd->cmp("psNeverRasterize")) { + parseYesNo("psNeverRasterize", &psNeverRasterize, + tokens, fileName, line); + } else if (!cmd->cmp("textEncoding")) { + parseString("textEncoding", &textEncoding, tokens, fileName, line); + } else if (!cmd->cmp("textEOL")) { + parseTextEOL(tokens, fileName, line); + } else if (!cmd->cmp("textPageBreaks")) { + parseYesNo("textPageBreaks", &textPageBreaks, + tokens, fileName, line); + } else if (!cmd->cmp("textKeepTinyChars")) { + parseYesNo("textKeepTinyChars", &textKeepTinyChars, + tokens, fileName, line); + } else if (!cmd->cmp("initialZoom")) { + parseString("initialZoom", &initialZoom, tokens, fileName, line); + } else if (!cmd->cmp("defaultFitZoom")) { + parseInteger("defaultFitZoom", &defaultFitZoom, tokens, fileName, line); + } else if (!cmd->cmp("initialDisplayMode")) { + parseString("initialDisplayMode", &initialDisplayMode, + tokens, fileName, line); + } else if (!cmd->cmp("initialToolbarState")) { + parseYesNo("initialToolbarState", &initialToolbarState, + tokens, fileName, line); + } else if (!cmd->cmp("initialSidebarState")) { + parseYesNo("initialSidebarState", &initialSidebarState, + tokens, fileName, line); + } else if (!cmd->cmp("initialSidebarWidth")) { + parseInteger("initialSidebarWidth", &initialSidebarWidth, + tokens, fileName, line); + } else if (!cmd->cmp("initialSelectMode")) { + parseString("initialSelectMode", &initialSelectMode, + tokens, fileName, line); + } else if (!cmd->cmp("maxTileWidth")) { + parseInteger("maxTileWidth", &maxTileWidth, tokens, fileName, line); + } else if (!cmd->cmp("maxTileHeight")) { + parseInteger("maxTileHeight", &maxTileHeight, tokens, fileName, line); + } else if (!cmd->cmp("tileCacheSize")) { + parseInteger("tileCacheSize", &tileCacheSize, tokens, fileName, line); + } else if (!cmd->cmp("workerThreads")) { + parseInteger("workerThreads", &workerThreads, 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("imageMaskAntialias")) { + parseYesNo("imageMaskAntialias", &imageMaskAntialias, + tokens, fileName, line); + } else if (!cmd->cmp("antialiasPrinting")) { + parseYesNo("antialiasPrinting", &antialiasPrinting, + tokens, fileName, line); + } else if (!cmd->cmp("strokeAdjust")) { + parseStrokeAdjust(tokens, fileName, line); + } else if (!cmd->cmp("screenType")) { + parseScreenType(tokens, fileName, line); + } else if (!cmd->cmp("screenSize")) { + parseInteger("screenSize", &screenSize, tokens, fileName, line); + } else if (!cmd->cmp("screenDotRadius")) { + parseInteger("screenDotRadius", &screenDotRadius, + tokens, fileName, line); + } else if (!cmd->cmp("screenGamma")) { + parseFloat("screenGamma", &screenGamma, + tokens, fileName, line); + } else if (!cmd->cmp("screenBlackThreshold")) { + parseFloat("screenBlackThreshold", &screenBlackThreshold, + tokens, fileName, line); + } else if (!cmd->cmp("screenWhiteThreshold")) { + parseFloat("screenWhiteThreshold", &screenWhiteThreshold, + tokens, fileName, line); + } else if (!cmd->cmp("minLineWidth")) { + parseFloat("minLineWidth", &minLineWidth, + tokens, fileName, line); + } else if (!cmd->cmp("enablePathSimplification")) { + parseYesNo("enablePathSimplification", &enablePathSimplification, + tokens, fileName, line); + } else if (!cmd->cmp("drawAnnotations")) { + parseYesNo("drawAnnotations", &drawAnnotations, + tokens, fileName, line); + } else if (!cmd->cmp("drawFormFields")) { + parseYesNo("drawFormFields", &drawFormFields, + tokens, fileName, line); + } else if (!cmd->cmp("enableXFA")) { + parseYesNo("enableXFA", &enableXFA, + tokens, fileName, line); + } else if (!cmd->cmp("overprintPreview")) { + parseYesNo("overprintPreview", &overprintPreview, + tokens, fileName, line); + } else if (!cmd->cmp("paperColor")) { + parseString("paperColor", &paperColor, tokens, fileName, line); + } else if (!cmd->cmp("matteColor")) { + parseString("matteColor", &matteColor, tokens, fileName, line); + } else if (!cmd->cmp("fullScreenMatteColor")) { + parseString("fullScreenMatteColor", &fullScreenMatteColor, + tokens, fileName, line); + } else if (!cmd->cmp("selectionColor")) { + parseString("selectionColor", &selectionColor, tokens, fileName, line); + } else if (!cmd->cmp("reverseVideoInvertImages")) { + parseYesNo("reverseVideoInvertImages", &reverseVideoInvertImages, + tokens, fileName, line); + } else if (!cmd->cmp("launchCommand")) { + parseString("launchCommand", &launchCommand, tokens, fileName, line); + } else if (!cmd->cmp("movieCommand")) { + parseString("movieCommand", &movieCommand, tokens, fileName, line); + } else if (!cmd->cmp("defaultPrinter")) { + parseString("defaultPrinter", &defaultPrinter, tokens, fileName, line); + } else if (!cmd->cmp("mapNumericCharNames")) { + parseYesNo("mapNumericCharNames", &mapNumericCharNames, + tokens, fileName, line); + } else if (!cmd->cmp("mapUnknownCharNames")) { + parseYesNo("mapUnknownCharNames", &mapUnknownCharNames, + tokens, fileName, line); + } else if (!cmd->cmp("mapExtTrueTypeFontsViaUnicode")) { + parseYesNo("mapExtTrueTypeFontsViaUnicode", + &mapExtTrueTypeFontsViaUnicode, + tokens, fileName, line); + } else if (!cmd->cmp("useTrueTypeUnicodeMapping")) { + parseYesNo("useTrueTypeUnicodeMapping", + &useTrueTypeUnicodeMapping, + tokens, fileName, line); + } else if (!cmd->cmp("dropFont")) { + parseDropFont(tokens, fileName, line); + } else if (!cmd->cmp("bind")) { + parseBind(tokens, fileName, line); + } else if (!cmd->cmp("unbind")) { + parseUnbind(tokens, fileName, line); + } else if (!cmd->cmp("popupMenuCmd")) { + parsePopupMenuCmd(tokens, fileName, line); + } else if (!cmd->cmp("tabStateFile")) { + parseString("tabStateFile", &tabStateFile, tokens, fileName, line); + } else if (!cmd->cmp("savePageNumbers")) { + parseYesNo("savePageNumbers", &savePageNumbers, tokens, fileName, line); + } else if (!cmd->cmp("printCommands")) { + parseYesNo("printCommands", &printCommands, tokens, fileName, line); + } else if (!cmd->cmp("printStatusInfo")) { + parseYesNo("printStatusInfo", &printStatusInfo, tokens, fileName, line); + } else if (!cmd->cmp("errQuiet")) { + parseYesNo("errQuiet", &errQuiet, tokens, fileName, line); + } else if (!cmd->cmp("debugLogFile")) { + parseString("debugLogFile", &debugLogFile, tokens, fileName, line); + } else { + 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(errConfig, -1, "Xpdf no longer supports X fonts"); + } else if (!cmd->cmp("enableT1lib")) { + error(errConfig, -1, "Xpdf no longer uses t1lib"); + } else if (!cmd->cmp("t1libControl") || !cmd->cmp("freetypeControl")) { + error(errConfig, -1, + "The t1libControl and freetypeControl options have been replaced by the enableT1lib, enableFreeType, and antialias options"); + } else if (!cmd->cmp("fontpath") || !cmd->cmp("fontmap")) { + error(errConfig, -1, + "The config file format has changed since Xpdf 0.9x"); + } + } + } + + deleteGList(tokens, GString); +} + +// Split a line into a sequence of tokens. Tokens are separated by +// whitespace. Each token is one of: +// - unquoted string, which can contain any char other than +// whitespace, and which cannot start with a single quote, double +// quote, or at-double-quote (xxxx) +// - single-quoted string, which can contain any char other than the +// single quote ('xxxx') +// - double-quoted string, which can contain any char other than the +// double quote ("xxxx") +// - at-double-quoted string, which can contain variables and escape +// chars (@"xxxx") +// - variables look like ${name} +// - special chars (${}") can be escaped with %, e.g., +// @"foo%"bar", @"foo%$bar", @"foo%%bar" +GList *GlobalParams::parseLineTokens(char *buf, GString *fileName, int line) { + GList *tokens = new GList(); + char *p1 = buf; + while (*p1) { + for (; *p1 && isspace(*p1); ++p1) ; + if (!*p1) { + break; + } + if (*p1 == '"' || *p1 == '\'') { + char *p2; + for (p2 = p1 + 1; *p2 && *p2 != *p1; ++p2) ; + ++p1; + tokens->append(new GString(p1, (int)(p2 - p1))); + p1 = *p2 ? p2 + 1 : p2; + } else if (*p1 == '@' && p1[1] == '"') { + GString *token = new GString(); + char *p2 = p1 + 2; + while (*p2 && *p2 != '"') { + if (*p2 == '%' && p2[1]) { + token->append(p2[1]); + p2 += 2; + } else if (*p2 == '$' && p2[1] == '{') { + p2 += 2; + char *p3; + for (p3 = p2; *p3 && *p3 != '}'; ++p3) ; + GString *varName = new GString(p2, (int)(p3 - p2)); + GString *varValue = (GString *)configFileVars->lookup(varName); + if (varValue) { + token->append(varValue); + } else { + error(errConfig, -1, "Unknown config file variable '%t'", varName); + } + delete varName; + p2 = *p3 ? p3 + 1 : p3; + } else { + token->append(*p2); + ++p2; + } + } + tokens->append(token); + p1 = *p2 ? p2 + 1 : p2; + } else { + char *p2; + for (p2 = p1 + 1; *p2 && !isspace(*p2); ++p2) ; + tokens->append(new GString(p1, (int)(p2 - p1))); + p1 = p2; + } + } + return tokens; +} + +void GlobalParams::parseNameToUnicode(GList *tokens, GString *fileName, + int line) { + GString *name; + char *tok1, *tok2; + FILE *f; + char buf[256]; + int line2; + Unicode u; + + if (tokens->getLength() != 2) { + error(errConfig, -1, + "Bad 'nameToUnicode' config file command ({0:t}:{1:d})", + fileName, line); + return; + } + name = (GString *)tokens->get(1); + if (!(f = openFile(name->getCString(), "r"))) { + error(errConfig, -1, "Couldn't open 'nameToUnicode' file '{0:t}'", name); + return; + } + line2 = 1; + while (getLine(buf, sizeof(buf), f)) { + tok1 = strtok(buf, " \t\r\n"); + tok2 = strtok(NULL, " \t\r\n"); + if (tok1 && tok2) { + sscanf(tok1, "%x", &u); + nameToUnicode->add(tok2, u); + } else { + error(errConfig, -1, "Bad line in 'nameToUnicode' file ({0:t}:{1:d})", + name, line2); + } + ++line2; + } + fclose(f); +} + +void GlobalParams::parseCIDToUnicode(GList *tokens, GString *fileName, + int line) { + GString *collection, *name, *old; + + if (tokens->getLength() != 3) { + error(errConfig, -1, + "Bad 'cidToUnicode' config file command ({0:t}:{1:d})", + fileName, line); + return; + } + collection = (GString *)tokens->get(1); + name = (GString *)tokens->get(2); + if ((old = (GString *)cidToUnicodes->remove(collection))) { + delete old; + } + cidToUnicodes->add(collection->copy(), name->copy()); +} + +void GlobalParams::parseUnicodeToUnicode(GList *tokens, GString *fileName, + int line) { + GString *font, *file, *old; + + if (tokens->getLength() != 3) { + error(errConfig, -1, + "Bad 'unicodeToUnicode' config file command ({0:t}:{1:d})", + fileName, line); + return; + } + font = (GString *)tokens->get(1); + file = (GString *)tokens->get(2); + if ((old = (GString *)unicodeToUnicodes->remove(font))) { + delete old; + } + unicodeToUnicodes->add(font->copy(), file->copy()); +} + +void GlobalParams::parseUnicodeMap(GList *tokens, GString *fileName, + int line) { + GString *encodingName, *name, *old; + + if (tokens->getLength() != 3) { + error(errConfig, -1, "Bad 'unicodeMap' config file command ({0:t}:{1:d})", + fileName, line); + return; + } + encodingName = (GString *)tokens->get(1); + name = (GString *)tokens->get(2); + if ((old = (GString *)unicodeMaps->remove(encodingName))) { + delete old; + } + unicodeMaps->add(encodingName->copy(), name->copy()); +} + +void GlobalParams::parseCMapDir(GList *tokens, GString *fileName, int line) { + GString *collection, *dir; + GList *list; + + if (tokens->getLength() != 3) { + error(errConfig, -1, "Bad 'cMapDir' config file command ({0:t}:{1:d})", + fileName, line); + return; + } + collection = (GString *)tokens->get(1); + dir = (GString *)tokens->get(2); + if (!(list = (GList *)cMapDirs->lookup(collection))) { + list = new GList(); + cMapDirs->add(collection->copy(), list); + } + list->append(dir->copy()); +} + +void GlobalParams::parseToUnicodeDir(GList *tokens, GString *fileName, + int line) { + if (tokens->getLength() != 2) { + error(errConfig, -1, + "Bad 'toUnicodeDir' config file command ({0:t}:{1:d})", + fileName, line); + return; + } + toUnicodeDirs->append(((GString *)tokens->get(1))->copy()); +} + +void GlobalParams::parseUnicodeRemapping(GList *tokens, GString *fileName, + int line) { + if (tokens->getLength() != 2) { + error(errConfig, -1, + "Bad 'unicodeRemapping' config file command ({0:t}:{1:d})", + fileName, line); + return; + } + unicodeRemapping->parseFile((GString *)tokens->get(1)); +} + +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; + } + 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()); +} + +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; + } + ccFontFiles->add(((GString *)tokens->get(1))->copy(), + ((GString *)tokens->get(2))->copy()); +} + +void GlobalParams::parsePSPaperSize(GList *tokens, GString *fileName, + int line) { + GString *tok; + + if (tokens->getLength() == 2) { + tok = (GString *)tokens->get(1); + if (!setPSPaperSize(tok->getCString())) { + error(errConfig, -1, + "Bad 'psPaperSize' config file command ({0:s}:{1:d})", + fileName, line); + } + } else if (tokens->getLength() == 3) { + tok = (GString *)tokens->get(1); + psPaperWidth = atoi(tok->getCString()); + tok = (GString *)tokens->get(2); + psPaperHeight = atoi(tok->getCString()); + psImageableLLX = psImageableLLY = 0; + psImageableURX = psPaperWidth; + psImageableURY = psPaperHeight; + } else { + 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(errConfig, -1, + "Bad 'psImageableArea' config file command ({0:t}:{1:d})", + fileName, line); + return; + } + psImageableLLX = atoi(((GString *)tokens->get(1))->getCString()); + psImageableLLY = atoi(((GString *)tokens->get(2))->getCString()); + psImageableURX = atoi(((GString *)tokens->get(3))->getCString()); + psImageableURY = atoi(((GString *)tokens->get(4))->getCString()); +} + +void GlobalParams::parsePSLevel(GList *tokens, GString *fileName, int line) { + GString *tok; + + if (tokens->getLength() != 2) { + error(errConfig, -1, "Bad 'psLevel' config file command ({0:t}:{1:d})", + fileName, line); + return; + } + tok = (GString *)tokens->get(1); + if (!tok->cmp("level1")) { + psLevel = psLevel1; + } else if (!tok->cmp("level1sep")) { + psLevel = psLevel1Sep; + } else if (!tok->cmp("level2")) { + psLevel = psLevel2; + } else if (!tok->cmp("level2gray")) { + psLevel = psLevel2Gray; + } else if (!tok->cmp("level2sep")) { + psLevel = psLevel2Sep; + } else if (!tok->cmp("level3")) { + psLevel = psLevel3; + } else if (!tok->cmp("level3gray")) { + psLevel = psLevel3Gray; + } else if (!tok->cmp("level3Sep")) { + psLevel = psLevel3Sep; + } else { + error(errConfig, -1, "Bad 'psLevel' config file command ({0:t}:{1:d})", + fileName, 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; + } + psResidentFonts->add(((GString *)tokens->get(1))->copy(), + ((GString *)tokens->get(2))->copy()); +} + +void GlobalParams::parsePSResidentFont16(GList *tokens, GString *fileName, + int line) { + PSFontParam16 *param; + int wMode; + GString *tok; + + if (tokens->getLength() != 5) { + error(errConfig, -1, "Bad 'psResidentFont16' config file command ({0:t}:{1:d})", + fileName, line); + return; + } + 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::parsePSResidentFontCC(GList *tokens, GString *fileName, + int line) { + PSFontParam16 *param; + int wMode; + GString *tok; + + if (tokens->getLength() != 5) { + error(errConfig, -1, "Bad 'psResidentFontCC' config file command ({0:t}:{1:d})", + fileName, line); + return; + } + 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 psResidentFontCC 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()); + psResidentFontsCC->append(param); +} + +void GlobalParams::parseTextEOL(GList *tokens, GString *fileName, int line) { + GString *tok; + + if (tokens->getLength() != 2) { + error(errConfig, -1, "Bad 'textEOL' config file command ({0:t}:{1:d})", + fileName, line); + return; + } + tok = (GString *)tokens->get(1); + if (!tok->cmp("unix")) { + textEOL = eolUnix; + } else if (!tok->cmp("dos")) { + textEOL = eolDOS; + } else if (!tok->cmp("mac")) { + textEOL = eolMac; + } else { + error(errConfig, -1, "Bad 'textEOL' config file command ({0:t}:{1:d})", + fileName, line); + } +} + +void GlobalParams::parseStrokeAdjust(GList *tokens, GString *fileName, + int line) { + GString *tok; + + if (tokens->getLength() != 2) { + error(errConfig, -1, + "Bad 'strokeAdjust' config file command ({0:t}:{1:d})", + fileName, line); + return; + } + tok = (GString *)tokens->get(1); + if (!tok->cmp("no")) { + strokeAdjust = strokeAdjustOff; + } else if (!tok->cmp("yes")) { + strokeAdjust = strokeAdjustNormal; + } else if (!tok->cmp("cad")) { + strokeAdjust = strokeAdjustCAD; + } else { + error(errConfig, -1, + "Bad 'strokeAdjust' config file command ({0:t}:{1:d})", + fileName, line); + } +} + +void GlobalParams::parseScreenType(GList *tokens, GString *fileName, + int line) { + GString *tok; + + if (tokens->getLength() != 2) { + error(errConfig, -1, "Bad 'screenType' config file command ({0:t}:{1:d})", + fileName, line); + return; + } + tok = (GString *)tokens->get(1); + if (!tok->cmp("dispersed")) { + screenType = screenDispersed; + } else if (!tok->cmp("clustered")) { + screenType = screenClustered; + } else if (!tok->cmp("stochasticClustered")) { + screenType = screenStochasticClustered; + } else { + error(errConfig, -1, "Bad 'screenType' config file command ({0:t}:{1:d})", + fileName, line); + } +} + +void GlobalParams::parseDropFont(GList *tokens, GString *fileName, int line) { + if (tokens->getLength() != 2) { + error(errConfig, -1, "Bad 'dropFont' config file command ({0:t}:{1:d})", + fileName, line); + return; + } + droppedFonts->add(((GString *)tokens->get(1))->copy(), 1); +} + +void GlobalParams::parseBind(GList *tokens, GString *fileName, int line) { + KeyBinding *binding; + GList *cmds; + int code, mods, context, i; + + if (tokens->getLength() < 4) { + 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), + &code, &mods, &context, + "bind", tokens, fileName, line)) { + return; + } + for (i = 0; i < keyBindings->getLength(); ++i) { + binding = (KeyBinding *)keyBindings->get(i); + if (binding->code == code && + binding->mods == mods && + binding->context == context) { + delete (KeyBinding *)keyBindings->del(i); + break; + } + } + cmds = new GList(); + for (i = 3; i < tokens->getLength(); ++i) { + cmds->append(((GString *)tokens->get(i))->copy()); + } + keyBindings->append(new KeyBinding(code, mods, context, cmds)); +} + +void GlobalParams::parseUnbind(GList *tokens, GString *fileName, int line) { + KeyBinding *binding; + int code, mods, context, i; + + if (tokens->getLength() != 3) { + error(errConfig, -1, "Bad 'unbind' config file command ({0:t}:{1:d})", + fileName, line); + return; + } + if (!parseKey((GString *)tokens->get(1), (GString *)tokens->get(2), + &code, &mods, &context, + "unbind", tokens, fileName, line)) { + return; + } + for (i = 0; i < keyBindings->getLength(); ++i) { + binding = (KeyBinding *)keyBindings->get(i); + if (binding->code == code && + binding->mods == mods && + binding->context == context) { + delete (KeyBinding *)keyBindings->del(i); + break; + } + } +} + +GBool GlobalParams::parseKey(GString *modKeyStr, GString *contextStr, + int *code, int *mods, int *context, + const char *cmdName, + GList *tokens, GString *fileName, int line) { + char *p0; + int btn; + + *mods = xpdfKeyModNone; + p0 = modKeyStr->getCString(); + while (1) { + if (!strncmp(p0, "shift-", 6)) { + *mods |= xpdfKeyModShift; + p0 += 6; + } else if (!strncmp(p0, "ctrl-", 5)) { + *mods |= xpdfKeyModCtrl; + p0 += 5; + } else if (!strncmp(p0, "alt-", 4)) { + *mods |= xpdfKeyModAlt; + p0 += 4; + } else { + break; + } + } + + if (!strcmp(p0, "space")) { + *code = ' '; + } else if (!strcmp(p0, "tab")) { + *code = xpdfKeyCodeTab; + } else if (!strcmp(p0, "return")) { + *code = xpdfKeyCodeReturn; + } else if (!strcmp(p0, "enter")) { + *code = xpdfKeyCodeEnter; + } else if (!strcmp(p0, "backspace")) { + *code = xpdfKeyCodeBackspace; + } else if (!strcmp(p0, "esc")) { + *code = xpdfKeyCodeEsc; + } else if (!strcmp(p0, "insert")) { + *code = xpdfKeyCodeInsert; + } else if (!strcmp(p0, "delete")) { + *code = xpdfKeyCodeDelete; + } else if (!strcmp(p0, "home")) { + *code = xpdfKeyCodeHome; + } else if (!strcmp(p0, "end")) { + *code = xpdfKeyCodeEnd; + } else if (!strcmp(p0, "pgup")) { + *code = xpdfKeyCodePgUp; + } else if (!strcmp(p0, "pgdn")) { + *code = xpdfKeyCodePgDn; + } else if (!strcmp(p0, "left")) { + *code = xpdfKeyCodeLeft; + } else if (!strcmp(p0, "right")) { + *code = xpdfKeyCodeRight; + } else if (!strcmp(p0, "up")) { + *code = xpdfKeyCodeUp; + } else if (!strcmp(p0, "down")) { + *code = xpdfKeyCodeDown; + } else if (p0[0] == 'f' && p0[1] >= '1' && p0[1] <= '9' && !p0[2]) { + *code = xpdfKeyCodeF1 + (p0[1] - '1'); + } else if (p0[0] == 'f' && + ((p0[1] >= '1' && p0[1] <= '2' && p0[2] >= '0' && p0[2] <= '9') || + (p0[1] == '3' && p0[2] >= '0' && p0[2] <= '5')) && + !p0[3]) { + *code = xpdfKeyCodeF1 + 10 * (p0[1] - '0') + (p0[2] - '0') - 1; + } else if (!strncmp(p0, "mousePress", 10) && + p0[10] >= '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] >= '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 (!strncmp(p0, "mouseClick", 10) && + p0[10] >= '0' && p0[10] <= '9' && + (!p0[11] || (p0[11] >= '0' && p0[11] <= '9' && !p0[12])) && + (btn = atoi(p0 + 10)) >= 1 && btn <= 32) { + *code = xpdfKeyCodeMouseClick1 + btn - 1; + } else if (!strncmp(p0, "mouseDoubleClick", 16) && + p0[16] >= '0' && p0[16] <= '9' && + (!p0[17] || (p0[17] >= '0' && p0[17] <= '9' && !p0[18])) && + (btn = atoi(p0 + 16)) >= 1 && btn <= 32) { + *code = xpdfKeyCodeMouseDoubleClick1 + btn - 1; + } else if (!strncmp(p0, "mouseTripleClick", 16) && + p0[16] >= '0' && p0[16] <= '9' && + (!p0[17] || (p0[17] >= '0' && p0[17] <= '9' && !p0[18])) && + (btn = atoi(p0 + 16)) >= 1 && btn <= 32) { + *code = xpdfKeyCodeMouseTripleClick1 + btn - 1; + } else if (*p0 >= 0x20 && *p0 <= 0x7e && !p0[1]) { + *code = (int)*p0; + } else { + error(errConfig, -1, + "Bad key/modifier in '{0:s}' config file command ({1:t}:{2:d})", + cmdName, fileName, line); + return gFalse; + } + + p0 = contextStr->getCString(); + if (!strcmp(p0, "any")) { + *context = xpdfKeyContextAny; + } else { + *context = xpdfKeyContextAny; + while (1) { + if (!strncmp(p0, "fullScreen", 10)) { + *context |= xpdfKeyContextFullScreen; + p0 += 10; + } else if (!strncmp(p0, "window", 6)) { + *context |= xpdfKeyContextWindow; + p0 += 6; + } else if (!strncmp(p0, "continuous", 10)) { + *context |= xpdfKeyContextContinuous; + p0 += 10; + } else if (!strncmp(p0, "singlePage", 10)) { + *context |= xpdfKeyContextSinglePage; + p0 += 10; + } else if (!strncmp(p0, "overLink", 8)) { + *context |= xpdfKeyContextOverLink; + p0 += 8; + } else if (!strncmp(p0, "offLink", 7)) { + *context |= xpdfKeyContextOffLink; + p0 += 7; + } else if (!strncmp(p0, "outline", 7)) { + *context |= xpdfKeyContextOutline; + p0 += 7; + } else if (!strncmp(p0, "mainWin", 7)) { + *context |= xpdfKeyContextMainWin; + p0 += 7; + } else if (!strncmp(p0, "scrLockOn", 9)) { + *context |= xpdfKeyContextScrLockOn; + p0 += 9; + } else if (!strncmp(p0, "scrLockOff", 10)) { + *context |= xpdfKeyContextScrLockOff; + p0 += 10; + } else { + error(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(errConfig, -1, + "Bad context in '{0:s}' config file command ({1:t}:{2:d})", + cmdName, fileName, line); + return gFalse; + } + ++p0; + } + } + + return gTrue; +} + +void GlobalParams::parsePopupMenuCmd(GList *tokens, + GString *fileName, int line) { + GList *cmds; + int i; + + if (tokens->getLength() < 3) { + error(errConfig, -1, + "Bad 'popupMenuCmd' config file command ({0:t}:{1:d})", + fileName, line); + return; + } + cmds = new GList(); + for (i = 2; i < tokens->getLength(); ++i) { + cmds->append(((GString *)tokens->get(i))->copy()); + } + popupMenuCmds->append(new PopupMenuCmd(((GString *)tokens->get(1))->copy(), + cmds)); +} + +void GlobalParams::parseYesNo(const char *cmdName, GBool *flag, + GList *tokens, GString *fileName, int line) { + GString *tok; + + if (tokens->getLength() != 2) { + 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(errConfig, -1, "Bad '{0:s}' config file command ({1:t}:{2:d})", + cmdName, fileName, line); + } +} + +GBool GlobalParams::parseYesNo2(char *token, GBool *flag) { + if (!strcmp(token, "yes")) { + *flag = gTrue; + } else if (!strcmp(token, "no")) { + *flag = gFalse; + } else { + return gFalse; + } + return gTrue; +} + +void GlobalParams::parseString(const char *cmdName, GString **s, + GList *tokens, GString *fileName, int line) { + if (tokens->getLength() != 2) { + error(errConfig, -1, "Bad '{0:s}' config file command ({1:t}:{2:d})", + cmdName, fileName, line); + return; + } + if (*s) { + delete *s; + } + *s = ((GString *)tokens->get(1))->copy(); +} + +void GlobalParams::parseInteger(const char *cmdName, int *val, + GList *tokens, GString *fileName, int line) { + GString *tok; + int i; + + if (tokens->getLength() != 2) { + 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(errConfig, -1, "Bad '{0:s}' config file command ({1:t}:{2:d})", + cmdName, fileName, line); + return; + } + if (tok->getChar(0) == '-') { + i = 1; + } else { + i = 0; + } + for (; i < tok->getLength(); ++i) { + if (tok->getChar(i) < '0' || tok->getChar(i) > '9') { + error(errConfig, -1, "Bad '{0:s}' config file command ({1:t}:{2:d})", + cmdName, fileName, line); + return; + } + } + *val = atoi(tok->getCString()); +} + +void GlobalParams::parseFloat(const char *cmdName, double *val, + GList *tokens, GString *fileName, int line) { + GString *tok; + int i; + + if (tokens->getLength() != 2) { + 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(errConfig, -1, "Bad '{0:s}' config file command ({1:t}:{2:d})", + cmdName, fileName, line); + return; + } + if (tok->getChar(0) == '-') { + i = 1; + } else { + i = 0; + } + for (; i < tok->getLength(); ++i) { + if (!((tok->getChar(i) >= '0' && tok->getChar(i) <= '9') || + tok->getChar(i) == '.')) { + error(errConfig, -1, "Bad '{0:s}' config file command ({1:t}:{2:d})", + cmdName, fileName, line); + return; + } + } + *val = atof(tok->getCString()); +} + +GlobalParams::~GlobalParams() { + GHashIter *iter; + GString *key; + GList *list; + + freeBuiltinFontTables(); + + delete macRomanReverseMap; + + delete baseDir; + deleteGHash(configFileVars, GString); + delete nameToUnicode; + deleteGHash(cidToUnicodes, GString); + deleteGHash(unicodeToUnicodes, GString); + deleteGHash(residentUnicodeMaps, UnicodeMap); + deleteGHash(unicodeMaps, GString); + deleteGList(toUnicodeDirs, GString); + delete unicodeRemapping; + deleteGHash(fontFiles, GString); + deleteGList(fontDirs, GString); + deleteGHash(ccFontFiles, GString); + deleteGHash(base14SysFonts, Base14FontInfo); + delete sysFonts; + deleteGHash(psResidentFonts, GString); + deleteGList(psResidentFonts16, PSFontParam16); + deleteGList(psResidentFontsCC, PSFontParam16); + delete textEncoding; + delete initialZoom; + delete initialDisplayMode; + delete initialSelectMode; + if (paperColor) { + delete paperColor; + } + if (matteColor) { + delete matteColor; + } + if (fullScreenMatteColor) { + delete fullScreenMatteColor; + } + if (selectionColor) { + delete selectionColor; + } + if (launchCommand) { + delete launchCommand; + } + if (movieCommand) { + delete movieCommand; + } + if (defaultPrinter) { + delete defaultPrinter; + } + delete droppedFonts; + deleteGList(keyBindings, KeyBinding); + deleteGList(popupMenuCmds, PopupMenuCmd); + delete tabStateFile; + delete debugLogFile; + + cMapDirs->startIter(&iter); + while (cMapDirs->getNext(&iter, &key, (void **)&list)) { + deleteGList(list, GString); + } + delete cMapDirs; + + delete cidToUnicodeCache; + delete unicodeToUnicodeCache; + delete unicodeMapCache; + delete cMapCache; + +#if MULTITHREADED + gDestroyMutex(&mutex); + gDestroyMutex(&unicodeMapCacheMutex); + gDestroyMutex(&cMapCacheMutex); +#endif +} + +//------------------------------------------------------------------------ + +void GlobalParams::setBaseDir(const char *dir) { + delete baseDir; + baseDir = new GString(dir); +} + +#ifdef _WIN32 +static void getWinFontDir(char *winFontDir) { + HMODULE shell32Lib; + BOOL (__stdcall *SHGetSpecialFolderPathFunc)(HWND hwndOwner, + LPSTR lpszPath, + int nFolder, + BOOL fCreate); + char *p; + int i; + + // SHGetSpecialFolderPath isn't available in older versions of + // shell32.dll (Win95 and WinNT4), so do a dynamic load + winFontDir[0] = '\0'; + if ((shell32Lib = LoadLibraryA("shell32.dll"))) { + if ((SHGetSpecialFolderPathFunc = + (BOOL (__stdcall *)(HWND hwndOwner, LPSTR lpszPath, + int nFolder, BOOL fCreate)) + GetProcAddress(shell32Lib, "SHGetSpecialFolderPathA"))) { + if (!(*SHGetSpecialFolderPathFunc)(NULL, winFontDir, + CSIDL_FONTS, FALSE)) { + winFontDir[0] = '\0'; + } + // kludge: Terminal Server changes CSIDL_FONTS to something like + // "C:\Users\whatever\Windows\Fonts", which doesn't actually + // contain any fonts -- kill that, so we hit the fallback code + // below. + for (p = winFontDir; *p; ++p) { + if (!strncasecmp(p, "\\Users\\", 7)) { + winFontDir[0] = '\0'; + break; + } + } + } + FreeLibrary(shell32Lib); + } + // if something went wrong, or we're on a Terminal Server, try using + // %SYSTEMROOT%\Fonts + if (!winFontDir[0]) { + GetSystemWindowsDirectoryA(winFontDir, MAX_PATH - 6); + winFontDir[MAX_PATH - 7] = '\0'; + i = (int)strlen(winFontDir); + if (winFontDir[i-1] != '\\') { + winFontDir[i++] = '\\'; + } + strcpy(winFontDir + i, "Fonts"); + } +} +#endif + +#ifdef __APPLE__ +// Apple dfonts and ttc fonts seem to randomly and interchangeably use +// space and hyphen, and sometimes drop the separator entirely. +static GBool macFontNameMatches(GString *name1, const char *name2) { + const char *p1, *p2; + char c1, c2; + + p1 = name1->getCString(); + p2 = name2; + while (*p1 && *p2) { + c1 = *p1; + c2 = *p2; + if (c2 == ' ') { + // * space or hyphen matches a space in the pattern + // * separators can also be dropped, in which case we move to + // the next char in the pattern + if (c1 == ' ' || c1 == '-') { + ++p1; + } + } else { + if (c1 != c2) { + return gFalse; + } + ++p1; + } + ++p2; + } + if (*p1 || *p2) { + return gFalse; + } + return gTrue; +} +#endif + +void GlobalParams::setupBaseFonts(const char *dir) { + GString *fontName; + GString *fileName; + int fontNum; + const char *s; + Base14FontInfo *base14; +#ifdef _WIN32 + char winFontDir[MAX_PATH]; +#endif +#ifdef __APPLE__ + static const char *macFontExts[3] = { "dfont", "ttc", "ttf" }; + GList *dfontFontNames; + GBool found; + int k; +#endif + FILE *f; + int i, j; + +#ifdef _WIN32 + getWinFontDir(winFontDir); +#endif +#ifdef __APPLE__ + dfontFontNames = NULL; +#endif + for (i = 0; displayFontTab[i].name; ++i) { + if (fontFiles->lookup(displayFontTab[i].name)) { + continue; + } + fontName = new GString(displayFontTab[i].name); + fileName = NULL; + fontNum = 0; + if (dir) { + fileName = appendToPath(new GString(dir), displayFontTab[i].t1FileName); + if ((f = fopen(fileName->getCString(), "rb"))) { + fclose(f); + } else { + delete fileName; + fileName = NULL; + } + } +#ifdef _WIN32 + if (!fileName && winFontDir[0] && displayFontTab[i].ttFileName) { + fileName = appendToPath(new GString(winFontDir), + displayFontTab[i].ttFileName); + if ((f = fopen(fileName->getCString(), "rb"))) { + fclose(f); + } else { + delete fileName; + fileName = NULL; + } + } +#endif +#ifdef __APPLE__ + // Check for Mac OS X system fonts. + s = displayFontTab[i].macFileName; + if (dfontFontNames && i > 0 && + (!s || strcmp(s, displayFontTab[i-1].macFileName))) { + deleteGList(dfontFontNames, GString); + dfontFontNames = NULL; + } + if (!fileName && s) { + for (j = 0; j < 3; ++j) { + fileName = GString::format("{0:s}/{1:s}.{2:s}", + macSystemFontPath, s, macFontExts[j]); + if (!(f = fopen(fileName->getCString(), "rb"))) { + delete fileName; + fileName = NULL; + } else { + fclose(f); + found = gFalse; + // for .dfont or .ttc, we need to scan the font list + if (j < 2) { + if (!dfontFontNames) { + dfontFontNames = + FoFiIdentifier::getFontList(fileName->getCString()); + } + if (dfontFontNames) { + for (k = 0; k < dfontFontNames->getLength(); ++k) { + if (macFontNameMatches((GString *)dfontFontNames->get(k), + displayFontTab[i].macFontName)) { + fontNum = k; + found = gTrue; + break; + } + } + } + // for .ttf, we just use the font + } else { + found = gTrue; + } + if (!found) { + delete fileName; + fileName = NULL; + } + break; + } + } + } +#endif // __APPLE__ + // On Linux, this checks the "standard" ghostscript font + // directories. On Windows, it checks the "standard" system font + // directories (because SHGetSpecialFolderPath(CSIDL_FONTS) + // doesn't work on Win 2k Server or Win2003 Server, or with older + // versions of shell32.dll). +#ifdef _WIN32 + s = displayFontTab[i].ttFileName; +#else + s = displayFontTab[i].t1FileName; +#endif + if (!fileName && s) { + for (j = 0; !fileName && displayFontDirs[j]; ++j) { + fileName = appendToPath(new GString(displayFontDirs[j]), s); + if ((f = fopen(fileName->getCString(), "rb"))) { + fclose(f); + } else { + delete fileName; + fileName = NULL; + } + } + } + if (!fileName) { + delete fontName; + continue; + } + base14SysFonts->add(fontName, new Base14FontInfo(fileName, fontNum, 0)); + } +#ifdef __APPLE__ + if (dfontFontNames) { + deleteGList(dfontFontNames, GString); + } +#endif + for (i = 0; displayFontTab[i].name; ++i) { + if (!base14SysFonts->lookup(displayFontTab[i].name) && + !fontFiles->lookup(displayFontTab[i].name)) { + if (displayFontTab[i].obliqueFont && + ((base14 = (Base14FontInfo *)base14SysFonts + ->lookup(displayFontTab[i].obliqueFont)))) { + base14SysFonts->add( + new GString(displayFontTab[i].name), + new Base14FontInfo(base14->fileName->copy(), + base14->fontNum, + displayFontTab[i].obliqueFactor)); + } else { + error(errConfig, -1, "No display font for '{0:s}'", + displayFontTab[i].name); + } + } + } +#ifdef _WIN32 + if (winFontDir[0]) { + sysFonts->scanWindowsFonts(winFontDir); + } +#endif +#if HAVE_FONTCONFIG + sysFonts->scanFontconfigFonts(); +#endif +} + +//------------------------------------------------------------------------ +// accessors +//------------------------------------------------------------------------ + +CharCode GlobalParams::getMacRomanCharCode(char *charName) { + // no need to lock - macRomanReverseMap is constant + return macRomanReverseMap->lookup(charName); +} + +GString *GlobalParams::getBaseDir() { + GString *s; + + lockGlobalParams; + s = baseDir->copy(); + unlockGlobalParams; + return s; +} + +Unicode GlobalParams::mapNameToUnicode(const char *charName) { + // no need to lock - nameToUnicode is constant + return nameToUnicode->lookup(charName); +} + +UnicodeMap *GlobalParams::getResidentUnicodeMap(GString *encodingName) { + UnicodeMap *map; + + lockGlobalParams; + map = (UnicodeMap *)residentUnicodeMaps->lookup(encodingName); + unlockGlobalParams; + if (map) { + map->incRefCnt(); + } + return map; +} + +FILE *GlobalParams::getUnicodeMapFile(GString *encodingName) { + GString *fileName; + FILE *f; + + lockGlobalParams; + if ((fileName = (GString *)unicodeMaps->lookup(encodingName))) { + f = openFile(fileName->getCString(), "r"); + } else { + f = NULL; + } + unlockGlobalParams; + return f; +} + +FILE *GlobalParams::findCMapFile(GString *collection, GString *cMapName) { + GList *list; + GString *dir; + GString *fileName; + FILE *f; + int i; + + lockGlobalParams; + if (!(list = (GList *)cMapDirs->lookup(collection))) { + unlockGlobalParams; + return NULL; + } + for (i = 0; i < list->getLength(); ++i) { + dir = (GString *)list->get(i); + fileName = appendToPath(dir->copy(), cMapName->getCString()); + f = openFile(fileName->getCString(), "r"); + delete fileName; + if (f) { + unlockGlobalParams; + return f; + } + } + unlockGlobalParams; + return NULL; +} + +FILE *GlobalParams::findToUnicodeFile(GString *name) { + GString *dir, *fileName; + FILE *f; + int i; + + lockGlobalParams; + for (i = 0; i < toUnicodeDirs->getLength(); ++i) { + dir = (GString *)toUnicodeDirs->get(i); + fileName = appendToPath(dir->copy(), name->getCString()); + f = openFile(fileName->getCString(), "r"); + delete fileName; + if (f) { + unlockGlobalParams; + return f; + } + } + unlockGlobalParams; + return NULL; +} + +UnicodeRemapping *GlobalParams::getUnicodeRemapping() { + return unicodeRemapping; +} + +GString *GlobalParams::findFontFile(GString *fontName) { + static const char *exts[] = { ".pfa", ".pfb", ".ttf", ".ttc", ".otf" }; + GString *path, *dir; +#ifdef _WIN32 + GString *fontNameU; +#endif + const char *ext; + FILE *f; + int i, j; + + lockGlobalParams; + 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 NULL; +} + +GString *GlobalParams::findBase14FontFile(GString *fontName, int *fontNum, + double *oblique) { + Base14FontInfo *fi; + GString *path; + + lockGlobalParams; + if ((fi = (Base14FontInfo *)base14SysFonts->lookup(fontName))) { + path = fi->fileName->copy(); + *fontNum = fi->fontNum; + *oblique = fi->oblique; + unlockGlobalParams; + return path; + } + unlockGlobalParams; + *fontNum = 0; + *oblique = 0; + return findFontFile(fontName); +} + +GString *GlobalParams::findSystemFontFile(GString *fontName, + SysFontType *type, + int *fontNum) { + SysFontInfo *fi; + GString *path; + + path = NULL; + lockGlobalParams; + if ((fi = sysFonts->find(fontName))) { + path = fi->path->copy(); + *type = fi->type; + *fontNum = fi->fontNum; + } + unlockGlobalParams; + return path; +} + +GString *GlobalParams::findCCFontFile(GString *collection) { + GString *path; + + lockGlobalParams; + if ((path = (GString *)ccFontFiles->lookup(collection))) { + path = path->copy(); + } + unlockGlobalParams; + return path; +} + +int GlobalParams::getPSPaperWidth() { + int w; + + lockGlobalParams; + w = psPaperWidth; + unlockGlobalParams; + return w; +} + +int GlobalParams::getPSPaperHeight() { + int h; + + lockGlobalParams; + h = psPaperHeight; + unlockGlobalParams; + return h; +} + +void GlobalParams::getPSImageableArea(int *llx, int *lly, int *urx, int *ury) { + lockGlobalParams; + *llx = psImageableLLX; + *lly = psImageableLLY; + *urx = psImageableURX; + *ury = psImageableURY; + unlockGlobalParams; +} + +GBool GlobalParams::getPSCrop() { + GBool f; + + lockGlobalParams; + f = psCrop; + unlockGlobalParams; + return f; +} + +GBool GlobalParams::getPSUseCropBoxAsPage() { + GBool f; + + lockGlobalParams; + f = psUseCropBoxAsPage; + unlockGlobalParams; + return f; +} + +GBool GlobalParams::getPSExpandSmaller() { + GBool f; + + lockGlobalParams; + f = psExpandSmaller; + unlockGlobalParams; + return f; +} + +GBool GlobalParams::getPSShrinkLarger() { + GBool f; + + lockGlobalParams; + f = psShrinkLarger; + unlockGlobalParams; + return f; +} + +GBool GlobalParams::getPSCenter() { + GBool f; + + lockGlobalParams; + f = psCenter; + unlockGlobalParams; + return f; +} + +GBool GlobalParams::getPSDuplex() { + GBool d; + + lockGlobalParams; + d = psDuplex; + unlockGlobalParams; + return d; +} + +PSLevel GlobalParams::getPSLevel() { + PSLevel level; + + lockGlobalParams; + level = psLevel; + unlockGlobalParams; + return level; +} + +GString *GlobalParams::getPSResidentFont(GString *fontName) { + GString *psName; + + lockGlobalParams; + if ((psName = (GString *)psResidentFonts->lookup(fontName))) { + psName = psName->copy(); + } + unlockGlobalParams; + return psName; +} + +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; + for (i = 0; i < psResidentFonts16->getLength(); ++i) { + p = (PSFontParam16 *)psResidentFonts16->get(i); + if (!(p->name->cmp(fontName)) && 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; +} + +GBool GlobalParams::getPSEmbedType1() { + GBool e; + + lockGlobalParams; + e = psEmbedType1; + unlockGlobalParams; + return e; +} + +GBool GlobalParams::getPSEmbedTrueType() { + GBool e; + + lockGlobalParams; + e = psEmbedTrueType; + unlockGlobalParams; + return e; +} + +GBool GlobalParams::getPSEmbedCIDPostScript() { + GBool e; + + lockGlobalParams; + e = psEmbedCIDPostScript; + unlockGlobalParams; + return e; +} + +GBool GlobalParams::getPSEmbedCIDTrueType() { + GBool e; + + lockGlobalParams; + e = psEmbedCIDTrueType; + unlockGlobalParams; + return e; +} + +GBool GlobalParams::getPSFontPassthrough() { + GBool e; + + lockGlobalParams; + e = psFontPassthrough; + unlockGlobalParams; + return e; +} + +GBool GlobalParams::getPSPreload() { + GBool preload; + + lockGlobalParams; + preload = psPreload; + unlockGlobalParams; + return preload; +} + +GBool GlobalParams::getPSOPI() { + GBool opi; + + lockGlobalParams; + opi = psOPI; + unlockGlobalParams; + return opi; +} + +GBool GlobalParams::getPSASCIIHex() { + GBool ah; + + lockGlobalParams; + ah = psASCIIHex; + unlockGlobalParams; + return ah; +} + +GBool GlobalParams::getPSLZW() { + GBool ah; + + lockGlobalParams; + ah = psLZW; + unlockGlobalParams; + return ah; +} + +GBool GlobalParams::getPSUncompressPreloadedImages() { + GBool ah; + + lockGlobalParams; + ah = psUncompressPreloadedImages; + unlockGlobalParams; + return ah; +} + +double GlobalParams::getPSMinLineWidth() { + double w; + + lockGlobalParams; + w = psMinLineWidth; + unlockGlobalParams; + return w; +} + +double GlobalParams::getPSRasterResolution() { + double res; + + lockGlobalParams; + res = psRasterResolution; + unlockGlobalParams; + return res; +} + +GBool GlobalParams::getPSRasterMono() { + GBool mono; + + lockGlobalParams; + mono = psRasterMono; + unlockGlobalParams; + return mono; +} + +int GlobalParams::getPSRasterSliceSize() { + int slice; + + lockGlobalParams; + slice = psRasterSliceSize; + unlockGlobalParams; + return slice; +} + +GBool GlobalParams::getPSAlwaysRasterize() { + GBool rast; + + lockGlobalParams; + rast = psAlwaysRasterize; + unlockGlobalParams; + return rast; +} + +GBool GlobalParams::getPSNeverRasterize() { + GBool rast; + + lockGlobalParams; + rast = psNeverRasterize; + unlockGlobalParams; + return rast; +} + +GString *GlobalParams::getTextEncodingName() { + GString *s; + + lockGlobalParams; + s = textEncoding->copy(); + unlockGlobalParams; + return s; +} + +GList *GlobalParams::getAvailableTextEncodings() { + GList *list; // [GString] + GHashIter *iter; + GString *key; + void *val; + + list = new GList(); + lockGlobalParams; + residentUnicodeMaps->startIter(&iter); + while (residentUnicodeMaps->getNext(&iter, &key, &val)) { + list->append(key->copy()); + } + unicodeMaps->startIter(&iter); + while (unicodeMaps->getNext(&iter, &key, &val)) { + list->append(key->copy()); + } + unlockGlobalParams; + return list; +} + +EndOfLineKind GlobalParams::getTextEOL() { + EndOfLineKind eol; + + lockGlobalParams; + eol = textEOL; + unlockGlobalParams; + return eol; +} + +GBool GlobalParams::getTextPageBreaks() { + GBool pageBreaks; + + lockGlobalParams; + pageBreaks = textPageBreaks; + unlockGlobalParams; + return pageBreaks; +} + +GBool GlobalParams::getTextKeepTinyChars() { + GBool tiny; + + lockGlobalParams; + tiny = textKeepTinyChars; + unlockGlobalParams; + return tiny; +} + +GString *GlobalParams::getInitialZoom() { + GString *s; + + lockGlobalParams; + s = initialZoom->copy(); + unlockGlobalParams; + return s; +} + +int GlobalParams::getDefaultFitZoom() { + int z; + + lockGlobalParams; + z = defaultFitZoom; + unlockGlobalParams; + return z; +} + +GString *GlobalParams::getInitialDisplayMode() { + GString *s; + + lockGlobalParams; + s = initialDisplayMode->copy(); + unlockGlobalParams; + return s; +} + +GBool GlobalParams::getInitialToolbarState() { + GBool state; + + lockGlobalParams; + state = initialToolbarState; + unlockGlobalParams; + return state; +} + +GBool GlobalParams::getInitialSidebarState() { + GBool state; + + lockGlobalParams; + state = initialSidebarState; + unlockGlobalParams; + return state; +} + +int GlobalParams::getInitialSidebarWidth() { + int w; + + lockGlobalParams; + w = initialSidebarWidth; + unlockGlobalParams; + return w; +} + +GString *GlobalParams::getInitialSelectMode() { + GString *s; + + lockGlobalParams; + s = initialSelectMode->copy(); + unlockGlobalParams; + return s; +} + +int GlobalParams::getMaxTileWidth() { + int w; + + lockGlobalParams; + w = maxTileWidth; + unlockGlobalParams; + return w; +} + +int GlobalParams::getMaxTileHeight() { + int h; + + lockGlobalParams; + h = maxTileHeight; + unlockGlobalParams; + return h; +} + +int GlobalParams::getTileCacheSize() { + int n; + + lockGlobalParams; + n = tileCacheSize; + unlockGlobalParams; + return n; +} + +int GlobalParams::getWorkerThreads() { + int n; + + lockGlobalParams; + n = workerThreads; + unlockGlobalParams; + return n; +} + +GBool GlobalParams::getEnableFreeType() { + GBool f; + + lockGlobalParams; + f = enableFreeType; + unlockGlobalParams; + return f; +} + +GBool GlobalParams::getDisableFreeTypeHinting() { + GBool f; + + lockGlobalParams; + f = disableFreeTypeHinting; + unlockGlobalParams; + return f; +} + + +GBool GlobalParams::getAntialias() { + GBool f; + + lockGlobalParams; + f = antialias; + unlockGlobalParams; + return f; +} + +GBool GlobalParams::getVectorAntialias() { + GBool f; + + lockGlobalParams; + f = vectorAntialias; + unlockGlobalParams; + return f; +} + +GBool GlobalParams::getImageMaskAntialias() { + GBool f; + + lockGlobalParams; + f = imageMaskAntialias; + unlockGlobalParams; + return f; +} + +GBool GlobalParams::getAntialiasPrinting() { + GBool f; + + lockGlobalParams; + f = antialiasPrinting; + unlockGlobalParams; + return f; +} + +StrokeAdjustMode GlobalParams::getStrokeAdjust() { + StrokeAdjustMode mode; + + lockGlobalParams; + mode = strokeAdjust; + unlockGlobalParams; + return mode; +} + +ScreenType GlobalParams::getScreenType() { + ScreenType t; + + lockGlobalParams; + t = screenType; + unlockGlobalParams; + return t; +} + +int GlobalParams::getScreenSize() { + int size; + + lockGlobalParams; + size = screenSize; + unlockGlobalParams; + return size; +} + +int GlobalParams::getScreenDotRadius() { + int r; + + lockGlobalParams; + r = screenDotRadius; + unlockGlobalParams; + return r; +} + +double GlobalParams::getScreenGamma() { + double gamma; + + lockGlobalParams; + gamma = screenGamma; + unlockGlobalParams; + return gamma; +} + +double GlobalParams::getScreenBlackThreshold() { + double thresh; + + lockGlobalParams; + thresh = screenBlackThreshold; + unlockGlobalParams; + return thresh; +} + +double GlobalParams::getScreenWhiteThreshold() { + double thresh; + + lockGlobalParams; + thresh = screenWhiteThreshold; + unlockGlobalParams; + return thresh; +} + +double GlobalParams::getMinLineWidth() { + double w; + + lockGlobalParams; + w = minLineWidth; + unlockGlobalParams; + return w; +} + +GBool GlobalParams::getEnablePathSimplification() { + GBool en; + + lockGlobalParams; + en = enablePathSimplification; + unlockGlobalParams; + return en; +} + +GBool GlobalParams::getDrawAnnotations() { + GBool draw; + + lockGlobalParams; + draw = drawAnnotations; + unlockGlobalParams; + return draw; +} + +GBool GlobalParams::getDrawFormFields() { + GBool draw; + + lockGlobalParams; + draw = drawFormFields; + unlockGlobalParams; + return draw; +} + +GBool GlobalParams::getEnableXFA() { + GBool xfa; + + lockGlobalParams; + xfa = enableXFA; + unlockGlobalParams; + return xfa; +} + + + +GString *GlobalParams::getPaperColor() { + GString *s; + + lockGlobalParams; + s = paperColor->copy(); + unlockGlobalParams; + return s; +} + +GString *GlobalParams::getMatteColor() { + GString *s; + + lockGlobalParams; + s = matteColor->copy(); + unlockGlobalParams; + return s; +} + +GString *GlobalParams::getFullScreenMatteColor() { + GString *s; + + lockGlobalParams; + s = fullScreenMatteColor->copy(); + unlockGlobalParams; + return s; +} + +GString *GlobalParams::getSelectionColor() { + GString *s; + + lockGlobalParams; + s = selectionColor->copy(); + unlockGlobalParams; + return s; +} + +GBool GlobalParams::getReverseVideoInvertImages() { + GBool invert; + + lockGlobalParams; + invert = reverseVideoInvertImages; + unlockGlobalParams; + return invert; +} + +GString *GlobalParams::getDefaultPrinter() { + GString *s; + + lockGlobalParams; + s = defaultPrinter ? defaultPrinter->copy() : (GString *)NULL; + unlockGlobalParams; + return s; +} + +GBool GlobalParams::getMapNumericCharNames() { + GBool map; + + lockGlobalParams; + map = mapNumericCharNames; + unlockGlobalParams; + return map; +} + +GBool GlobalParams::getMapUnknownCharNames() { + GBool map; + + lockGlobalParams; + map = mapUnknownCharNames; + unlockGlobalParams; + return map; +} + +GBool GlobalParams::getMapExtTrueTypeFontsViaUnicode() { + GBool map; + + lockGlobalParams; + map = mapExtTrueTypeFontsViaUnicode; + unlockGlobalParams; + return map; +} + +GBool GlobalParams::getUseTrueTypeUnicodeMapping() { + GBool use; + + lockGlobalParams; + use = useTrueTypeUnicodeMapping; + unlockGlobalParams; + return use; +} + +GBool GlobalParams::isDroppedFont(const char *fontName) { + GBool isDropped; + + lockGlobalParams; + isDropped = droppedFonts->lookupInt(fontName) != 0; + unlockGlobalParams; + return isDropped; +} + +GList *GlobalParams::getKeyBinding(int code, int mods, int context) { + KeyBinding *binding; + GList *cmds; + int modMask; + int i, j; + + lockGlobalParams; + cmds = NULL; + // for ASCII chars, ignore the shift modifier + modMask = (code >= 0x21 && code <= 0xff) ? ~xpdfKeyModShift : ~0; + for (i = 0; i < keyBindings->getLength(); ++i) { + binding = (KeyBinding *)keyBindings->get(i); + if (binding->code == code && + (binding->mods & modMask) == (mods & modMask) && + (~binding->context | context) == ~0) { + cmds = new GList(); + for (j = 0; j < binding->cmds->getLength(); ++j) { + cmds->append(((GString *)binding->cmds->get(j))->copy()); + } + break; + } + } + unlockGlobalParams; + return cmds; +} + +GList *GlobalParams::getAllKeyBindings() { + return keyBindings; +} + +int GlobalParams::getNumPopupMenuCmds() { + int n; + + lockGlobalParams; + n = popupMenuCmds->getLength(); + unlockGlobalParams; + return n; +} + +PopupMenuCmd *GlobalParams::getPopupMenuCmd(int idx) { + PopupMenuCmd *cmd; + + lockGlobalParams; + if (idx < popupMenuCmds->getLength()) { + cmd = (PopupMenuCmd *)popupMenuCmds->get(idx); + } else { + cmd = NULL; + } + unlockGlobalParams; + return cmd; +} + +GString *GlobalParams::getTabStateFile() { + GString *s; + + lockGlobalParams; + s = tabStateFile->copy(); + unlockGlobalParams; + return s; +} + +GBool GlobalParams::getSavePageNumbers() { + GBool s; + + lockGlobalParams; + s = savePageNumbers; + unlockGlobalParams; + return s; +} + +GBool GlobalParams::getPrintCommands() { + GBool p; + + lockGlobalParams; + p = printCommands; + unlockGlobalParams; + return p; +} + +GBool GlobalParams::getPrintStatusInfo() { + GBool p; + + lockGlobalParams; + p = printStatusInfo; + unlockGlobalParams; + return p; +} + +GBool GlobalParams::getErrQuiet() { + // no locking -- this function may get called from inside a locked + // section + return errQuiet; +} + +GString *GlobalParams::getDebugLogFile() { + return debugLogFile; +} + +void GlobalParams::debugLogPrintf(const char *fmt, ...) { + GString *path; + FILE *f; + GBool needClose; + time_t t; + struct tm tm; + va_list args; + + if (!(path = getDebugLogFile())) { + return; + } + needClose = gFalse; + if (!path->cmp("-")) { + f = stdout; + } else if (!path->cmp("+")) { + f = stderr; + } else { + f = fopen(path->getCString(), "a"); + needClose = gTrue; + } + if (!f) { + return; + } + t = time(NULL); +#ifdef _WIN32 + localtime_s(&tm, &t); +#else + localtime_r(&t, &tm); +#endif + fprintf(f, "[%04d-%02d-%02d %02d:%02d:%02d] ", + tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, + tm.tm_hour, tm.tm_min, tm.tm_sec); + va_start(args, fmt); + vfprintf(f, fmt, args); + va_end(args); + fflush(f); + if (needClose) { + fclose(f); + } +} + +CharCodeToUnicode *GlobalParams::getCIDToUnicode(GString *collection) { + GString *fileName; + CharCodeToUnicode *ctu; + + lockGlobalParams; + if (!(ctu = cidToUnicodeCache->getCharCodeToUnicode(collection))) { + if ((fileName = (GString *)cidToUnicodes->lookup(collection)) && + (ctu = CharCodeToUnicode::parseCIDToUnicode(fileName, collection))) { + cidToUnicodeCache->add(ctu); + } + } + unlockGlobalParams; + return ctu; +} + +CharCodeToUnicode *GlobalParams::getUnicodeToUnicode(GString *fontName) { + CharCodeToUnicode *ctu; + GHashIter *iter; + GString *fontPattern, *fileName; + + lockGlobalParams; + fileName = NULL; + unicodeToUnicodes->startIter(&iter); + while (unicodeToUnicodes->getNext(&iter, &fontPattern, (void **)&fileName)) { + if (strstr(fontName->getCString(), fontPattern->getCString())) { + unicodeToUnicodes->killIter(&iter); + break; + } + fileName = NULL; + } + if (fileName) { + if (!(ctu = unicodeToUnicodeCache->getCharCodeToUnicode(fileName))) { + if ((ctu = CharCodeToUnicode::parseUnicodeToUnicode(fileName))) { + unicodeToUnicodeCache->add(ctu); + } + } + } else { + ctu = NULL; + } + unlockGlobalParams; + return ctu; +} + +UnicodeMap *GlobalParams::getUnicodeMap(GString *encodingName) { + return getUnicodeMap2(encodingName); +} + +UnicodeMap *GlobalParams::getUnicodeMap2(GString *encodingName) { + UnicodeMap *map; + + if (!(map = getResidentUnicodeMap(encodingName))) { + lockUnicodeMapCache; + map = unicodeMapCache->getUnicodeMap(encodingName); + unlockUnicodeMapCache; + } + return map; +} + +CMap *GlobalParams::getCMap(GString *collection, GString *cMapName) { + CMap *cMap; + + lockCMapCache; + cMap = cMapCache->getCMap(collection, cMapName); + unlockCMapCache; + return cMap; +} + +UnicodeMap *GlobalParams::getTextEncoding() { + return getUnicodeMap2(textEncoding); +} + +//------------------------------------------------------------------------ +// functions to set parameters +//------------------------------------------------------------------------ + +void GlobalParams::addUnicodeRemapping(Unicode in, Unicode *out, int len) { + unicodeRemapping->addRemapping(in, out, len); +} + +void GlobalParams::addFontFile(GString *fontName, GString *path) { + lockGlobalParams; + fontFiles->add(fontName, path); + unlockGlobalParams; +} + +GBool GlobalParams::setPSPaperSize(char *size) { + lockGlobalParams; + if (!strcmp(size, "match")) { + psPaperWidth = psPaperHeight = -1; + } else if (!strcmp(size, "letter")) { + psPaperWidth = 612; + psPaperHeight = 792; + } else if (!strcmp(size, "legal")) { + psPaperWidth = 612; + psPaperHeight = 1008; + } else if (!strcmp(size, "A4")) { + psPaperWidth = 595; + psPaperHeight = 842; + } else if (!strcmp(size, "A3")) { + psPaperWidth = 842; + psPaperHeight = 1190; + } else { + unlockGlobalParams; + return gFalse; + } + psImageableLLX = psImageableLLY = 0; + psImageableURX = psPaperWidth; + psImageableURY = psPaperHeight; + unlockGlobalParams; + return gTrue; +} + +void GlobalParams::setPSPaperWidth(int width) { + lockGlobalParams; + psPaperWidth = width; + psImageableLLX = 0; + psImageableURX = psPaperWidth; + unlockGlobalParams; +} + +void GlobalParams::setPSPaperHeight(int height) { + lockGlobalParams; + psPaperHeight = height; + psImageableLLY = 0; + psImageableURY = psPaperHeight; + unlockGlobalParams; +} + +void GlobalParams::setPSImageableArea(int llx, int lly, int urx, int ury) { + lockGlobalParams; + psImageableLLX = llx; + psImageableLLY = lly; + psImageableURX = urx; + psImageableURY = ury; + unlockGlobalParams; +} + +void GlobalParams::setPSCrop(GBool crop) { + lockGlobalParams; + psCrop = crop; + unlockGlobalParams; +} + +void GlobalParams::setPSUseCropBoxAsPage(GBool crop) { + lockGlobalParams; + psUseCropBoxAsPage = crop; + unlockGlobalParams; +} + +void GlobalParams::setPSExpandSmaller(GBool expand) { + lockGlobalParams; + psExpandSmaller = expand; + unlockGlobalParams; +} + +void GlobalParams::setPSShrinkLarger(GBool shrink) { + lockGlobalParams; + psShrinkLarger = shrink; + unlockGlobalParams; +} + +void GlobalParams::setPSCenter(GBool center) { + lockGlobalParams; + psCenter = center; + unlockGlobalParams; +} + +void GlobalParams::setPSDuplex(GBool duplex) { + lockGlobalParams; + psDuplex = duplex; + unlockGlobalParams; +} + +void GlobalParams::setPSLevel(PSLevel level) { + lockGlobalParams; + psLevel = level; + unlockGlobalParams; +} + +void GlobalParams::setPSEmbedType1(GBool embed) { + lockGlobalParams; + psEmbedType1 = embed; + unlockGlobalParams; +} + +void GlobalParams::setPSEmbedTrueType(GBool embed) { + lockGlobalParams; + psEmbedTrueType = embed; + unlockGlobalParams; +} + +void GlobalParams::setPSEmbedCIDPostScript(GBool embed) { + lockGlobalParams; + psEmbedCIDPostScript = embed; + unlockGlobalParams; +} + +void GlobalParams::setPSEmbedCIDTrueType(GBool embed) { + lockGlobalParams; + psEmbedCIDTrueType = embed; + unlockGlobalParams; +} + +void GlobalParams::setPSFontPassthrough(GBool passthrough) { + lockGlobalParams; + psFontPassthrough = passthrough; + unlockGlobalParams; +} + +void GlobalParams::setPSPreload(GBool preload) { + lockGlobalParams; + psPreload = preload; + unlockGlobalParams; +} + +void GlobalParams::setPSOPI(GBool opi) { + lockGlobalParams; + psOPI = opi; + unlockGlobalParams; +} + +void GlobalParams::setPSASCIIHex(GBool hex) { + lockGlobalParams; + psASCIIHex = hex; + unlockGlobalParams; +} + +void GlobalParams::setTextEncoding(const char *encodingName) { + lockGlobalParams; + delete textEncoding; + textEncoding = new GString(encodingName); + unlockGlobalParams; +} + +GBool GlobalParams::setTextEOL(char *s) { + lockGlobalParams; + if (!strcmp(s, "unix")) { + textEOL = eolUnix; + } else if (!strcmp(s, "dos")) { + textEOL = eolDOS; + } else if (!strcmp(s, "mac")) { + textEOL = eolMac; + } else { + unlockGlobalParams; + return gFalse; + } + unlockGlobalParams; + return gTrue; +} + +void GlobalParams::setTextPageBreaks(GBool pageBreaks) { + lockGlobalParams; + textPageBreaks = pageBreaks; + unlockGlobalParams; +} + +void GlobalParams::setTextKeepTinyChars(GBool keep) { + lockGlobalParams; + textKeepTinyChars = keep; + unlockGlobalParams; +} + +void GlobalParams::setInitialZoom(char *s) { + lockGlobalParams; + delete initialZoom; + initialZoom = new GString(s); + unlockGlobalParams; +} + +GBool GlobalParams::setEnableFreeType(char *s) { + GBool ok; + + lockGlobalParams; + ok = parseYesNo2(s, &enableFreeType); + unlockGlobalParams; + return ok; +} + + +GBool GlobalParams::setAntialias(char *s) { + GBool ok; + + lockGlobalParams; + ok = parseYesNo2(s, &antialias); + unlockGlobalParams; + return ok; +} + +GBool GlobalParams::setVectorAntialias(char *s) { + GBool ok; + + lockGlobalParams; + ok = parseYesNo2(s, &vectorAntialias); + unlockGlobalParams; + return ok; +} + +void GlobalParams::setScreenType(ScreenType t) { + lockGlobalParams; + screenType = t; + unlockGlobalParams; +} + +void GlobalParams::setScreenSize(int size) { + lockGlobalParams; + screenSize = size; + unlockGlobalParams; +} + +void GlobalParams::setScreenDotRadius(int r) { + lockGlobalParams; + screenDotRadius = r; + unlockGlobalParams; +} + +void GlobalParams::setScreenGamma(double gamma) { + lockGlobalParams; + screenGamma = gamma; + unlockGlobalParams; +} + +void GlobalParams::setScreenBlackThreshold(double thresh) { + lockGlobalParams; + screenBlackThreshold = thresh; + unlockGlobalParams; +} + +void GlobalParams::setScreenWhiteThreshold(double thresh) { + lockGlobalParams; + screenWhiteThreshold = thresh; + unlockGlobalParams; +} + +void GlobalParams::setDrawFormFields(GBool draw) { + lockGlobalParams; + drawFormFields = draw; + unlockGlobalParams; +} + +void GlobalParams::setOverprintPreview(GBool preview) { + lockGlobalParams; + overprintPreview = preview; + unlockGlobalParams; +} + + + +void GlobalParams::setMapNumericCharNames(GBool map) { + lockGlobalParams; + mapNumericCharNames = map; + unlockGlobalParams; +} + +void GlobalParams::setMapUnknownCharNames(GBool map) { + lockGlobalParams; + mapUnknownCharNames = map; + unlockGlobalParams; +} + +void GlobalParams::setMapExtTrueTypeFontsViaUnicode(GBool map) { + lockGlobalParams; + mapExtTrueTypeFontsViaUnicode = map; + unlockGlobalParams; +} + +void GlobalParams::setTabStateFile(char *tabStateFileA) { + lockGlobalParams; + delete tabStateFile; + tabStateFile = new GString(tabStateFileA); + unlockGlobalParams; +} + +void GlobalParams::setPrintCommands(GBool printCommandsA) { + lockGlobalParams; + printCommands = printCommandsA; + unlockGlobalParams; +} + +void GlobalParams::setPrintStatusInfo(GBool printStatusInfoA) { + lockGlobalParams; + printStatusInfo = printStatusInfoA; + unlockGlobalParams; +} + +void GlobalParams::setErrQuiet(GBool errQuietA) { + lockGlobalParams; + errQuiet = errQuietA; + unlockGlobalParams; +} + +#ifdef _WIN32 +void GlobalParams::setWin32ErrorInfo(const char *func, DWORD code) { + XpdfWin32ErrorInfo *errorInfo; + + if (tlsWin32ErrorInfo == TLS_OUT_OF_INDEXES) { + return; + } + errorInfo = (XpdfWin32ErrorInfo *)TlsGetValue(tlsWin32ErrorInfo); + if (!errorInfo) { + errorInfo = new XpdfWin32ErrorInfo(); + TlsSetValue(tlsWin32ErrorInfo, errorInfo); + } + errorInfo->func = func; + errorInfo->code = code; +} + +XpdfWin32ErrorInfo *GlobalParams::getWin32ErrorInfo() { + XpdfWin32ErrorInfo *errorInfo; + + if (tlsWin32ErrorInfo == TLS_OUT_OF_INDEXES) { + return NULL; + } + errorInfo = (XpdfWin32ErrorInfo *)TlsGetValue(tlsWin32ErrorInfo); + if (!errorInfo) { + errorInfo = new XpdfWin32ErrorInfo(); + TlsSetValue(tlsWin32ErrorInfo, errorInfo); + errorInfo->func = NULL; + errorInfo->code = 0; + } + return errorInfo; +} +#endif diff --git a/xpdf/GlobalParams.h b/xpdf/GlobalParams.h new file mode 100644 index 0000000..b8299fc --- /dev/null +++ b/xpdf/GlobalParams.h @@ -0,0 +1,623 @@ +//======================================================================== +// +// GlobalParams.h +// +// Copyright 2001-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef GLOBALPARAMS_H +#define GLOBALPARAMS_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include +#ifdef _WIN32 +# include +#endif +#include "gtypes.h" +#include "CharTypes.h" + +#if MULTITHREADED +#include "GMutex.h" +#endif + +class GString; +class GList; +class GHash; +class NameToCharCode; +class CharCodeToUnicode; +class CharCodeToUnicodeCache; +class UnicodeMap; +class UnicodeMapCache; +class UnicodeRemapping; +class CMap; +class CMapCache; +struct XpdfSecurityHandler; +class GlobalParams; +class SysFontList; + +//------------------------------------------------------------------------ + +// The global parameters object. +extern GlobalParams *globalParams; + +//------------------------------------------------------------------------ + +enum SysFontType { + sysFontPFA, + sysFontPFB, + sysFontTTF, + sysFontTTC, + sysFontOTF +}; + +//------------------------------------------------------------------------ + +class PSFontParam16 { +public: + + 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 + + PSFontParam16(GString *nameA, int wModeA, + GString *psFontNameA, GString *encodingA); + ~PSFontParam16(); +}; + +//------------------------------------------------------------------------ + +enum PSLevel { + psLevel1, + psLevel1Sep, + psLevel2, + psLevel2Gray, + psLevel2Sep, + psLevel3, + psLevel3Gray, + psLevel3Sep, +}; + +//------------------------------------------------------------------------ + +enum EndOfLineKind { + eolUnix, // LF + eolDOS, // CR+LF + eolMac // CR +}; + +//------------------------------------------------------------------------ + +enum StrokeAdjustMode { + strokeAdjustOff, + strokeAdjustNormal, + strokeAdjustCAD +}; + +//------------------------------------------------------------------------ + +enum ScreenType { + screenUnset, + screenDispersed, + screenClustered, + screenStochasticClustered +}; + +//------------------------------------------------------------------------ + +class KeyBinding { +public: + + int code; // 0x20 .. 0xfe = ASCII, + // >=0x10000 = special keys, mouse buttons, + // etc. (xpdfKeyCode* symbols) + int mods; // modifiers (xpdfKeyMod* symbols, or-ed + // together) + int context; // context (xpdfKeyContext* symbols, or-ed + // together) + GList *cmds; // list of commands [GString] + + KeyBinding(int codeA, int modsA, int contextA, 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(); +}; + +#define xpdfKeyCodeTab 0x1000 +#define xpdfKeyCodeReturn 0x1001 +#define xpdfKeyCodeEnter 0x1002 +#define xpdfKeyCodeBackspace 0x1003 +#define xpdfKeyCodeEsc 0x1004 +#define xpdfKeyCodeInsert 0x1005 +#define xpdfKeyCodeDelete 0x1006 +#define xpdfKeyCodeHome 0x1007 +#define xpdfKeyCodeEnd 0x1008 +#define xpdfKeyCodePgUp 0x1009 +#define xpdfKeyCodePgDn 0x100a +#define xpdfKeyCodeLeft 0x100b +#define xpdfKeyCodeRight 0x100c +#define xpdfKeyCodeUp 0x100d +#define xpdfKeyCodeDown 0x100e +#define xpdfKeyCodeF1 0x1100 +#define xpdfKeyCodeF35 0x1122 +#define xpdfKeyCodeMousePress1 0x2001 +#define xpdfKeyCodeMousePress2 0x2002 +#define xpdfKeyCodeMousePress3 0x2003 +#define xpdfKeyCodeMousePress4 0x2004 +#define xpdfKeyCodeMousePress5 0x2005 +#define xpdfKeyCodeMousePress6 0x2006 +#define xpdfKeyCodeMousePress7 0x2007 +// ... +#define xpdfKeyCodeMousePress32 0x2020 +#define xpdfKeyCodeMouseRelease1 0x2101 +#define xpdfKeyCodeMouseRelease2 0x2102 +#define xpdfKeyCodeMouseRelease3 0x2103 +#define xpdfKeyCodeMouseRelease4 0x2104 +#define xpdfKeyCodeMouseRelease5 0x2105 +#define xpdfKeyCodeMouseRelease6 0x2106 +#define xpdfKeyCodeMouseRelease7 0x2107 +// ... +#define xpdfKeyCodeMouseRelease32 0x2120 +#define xpdfKeyCodeMouseClick1 0x2201 +#define xpdfKeyCodeMouseClick2 0x2202 +#define xpdfKeyCodeMouseClick3 0x2203 +#define xpdfKeyCodeMouseClick4 0x2204 +#define xpdfKeyCodeMouseClick5 0x2205 +#define xpdfKeyCodeMouseClick6 0x2206 +#define xpdfKeyCodeMouseClick7 0x2207 +// ... +#define xpdfKeyCodeMouseClick32 0x2220 +#define xpdfKeyCodeMouseDoubleClick1 0x2301 +#define xpdfKeyCodeMouseDoubleClick2 0x2302 +#define xpdfKeyCodeMouseDoubleClick3 0x2303 +#define xpdfKeyCodeMouseDoubleClick4 0x2304 +#define xpdfKeyCodeMouseDoubleClick5 0x2305 +#define xpdfKeyCodeMouseDoubleClick6 0x2306 +#define xpdfKeyCodeMouseDoubleClick7 0x2307 +// ... +#define xpdfKeyCodeMouseDoubleClick32 0x2320 +#define xpdfKeyCodeMouseTripleClick1 0x2401 +#define xpdfKeyCodeMouseTripleClick2 0x2402 +#define xpdfKeyCodeMouseTripleClick3 0x2403 +#define xpdfKeyCodeMouseTripleClick4 0x2404 +#define xpdfKeyCodeMouseTripleClick5 0x2405 +#define xpdfKeyCodeMouseTripleClick6 0x2406 +#define xpdfKeyCodeMouseTripleClick7 0x2407 +// ... +#define xpdfKeyCodeMouseTripleClick32 0x2420 +#define xpdfKeyModNone 0 +#define xpdfKeyModShift (1 << 0) +#define xpdfKeyModCtrl (1 << 1) +#define xpdfKeyModAlt (1 << 2) +#define xpdfKeyContextAny 0 +#define xpdfKeyContextFullScreen (1 << 0) +#define xpdfKeyContextWindow (2 << 0) +#define xpdfKeyContextContinuous (1 << 2) +#define xpdfKeyContextSinglePage (2 << 2) +#define xpdfKeyContextOverLink (1 << 4) +#define xpdfKeyContextOffLink (2 << 4) +#define xpdfKeyContextOutline (1 << 6) +#define xpdfKeyContextMainWin (2 << 6) +#define xpdfKeyContextScrLockOn (1 << 8) +#define xpdfKeyContextScrLockOff (2 << 8) + +//------------------------------------------------------------------------ + +class PopupMenuCmd { +public: + + GString *label; // label for display in the menu + GList *cmds; // list of commands [GString] + + PopupMenuCmd(GString *labelA, GList *cmdsA); + ~PopupMenuCmd(); +}; + +//------------------------------------------------------------------------ + +#ifdef _WIN32 +struct XpdfWin32ErrorInfo { + const char *func; // last Win32 API function call to fail + DWORD code; // error code returned by that function +}; +#endif + +//------------------------------------------------------------------------ + +class GlobalParams { +public: + + // Initialize the global parameters by attempting to read a config + // file. + GlobalParams(const char *cfgFileName); + + ~GlobalParams(); + + void setBaseDir(const char *dir); + void setupBaseFonts(const char *dir); + + void parseLine(char *buf, GString *fileName, int line); + + //----- accessors + + CharCode getMacRomanCharCode(char *charName); + + GString *getBaseDir(); + Unicode mapNameToUnicode(const char *charName); + UnicodeMap *getResidentUnicodeMap(GString *encodingName); + FILE *getUnicodeMapFile(GString *encodingName); + FILE *findCMapFile(GString *collection, GString *cMapName); + FILE *findToUnicodeFile(GString *name); + UnicodeRemapping *getUnicodeRemapping(); + GString *findFontFile(GString *fontName); + GString *findBase14FontFile(GString *fontName, int *fontNum, + double *oblique); + GString *findSystemFontFile(GString *fontName, SysFontType *type, + int *fontNum); + GString *findCCFontFile(GString *collection); + int getPSPaperWidth(); + int getPSPaperHeight(); + void getPSImageableArea(int *llx, int *lly, int *urx, int *ury); + GBool getPSDuplex(); + GBool getPSCrop(); + GBool getPSUseCropBoxAsPage(); + GBool getPSExpandSmaller(); + GBool getPSShrinkLarger(); + GBool getPSCenter(); + PSLevel getPSLevel(); + 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 getPSLZW(); + GBool getPSUncompressPreloadedImages(); + double getPSMinLineWidth(); + double getPSRasterResolution(); + GBool getPSRasterMono(); + int getPSRasterSliceSize(); + GBool getPSAlwaysRasterize(); + GBool getPSNeverRasterize(); + GString *getTextEncodingName(); + GList *getAvailableTextEncodings(); + EndOfLineKind getTextEOL(); + GBool getTextPageBreaks(); + GBool getTextKeepTinyChars(); + GString *getInitialZoom(); + int getDefaultFitZoom(); + GString *getInitialDisplayMode(); + GBool getInitialToolbarState(); + GBool getInitialSidebarState(); + int getInitialSidebarWidth(); + GString *getInitialSelectMode(); + int getMaxTileWidth(); + int getMaxTileHeight(); + int getTileCacheSize(); + int getWorkerThreads(); + GBool getEnableFreeType(); + GBool getDisableFreeTypeHinting(); + GBool getAntialias(); + GBool getVectorAntialias(); + GBool getImageMaskAntialias(); + GBool getAntialiasPrinting(); + StrokeAdjustMode getStrokeAdjust(); + ScreenType getScreenType(); + int getScreenSize(); + int getScreenDotRadius(); + double getScreenGamma(); + double getScreenBlackThreshold(); + double getScreenWhiteThreshold(); + double getMinLineWidth(); + GBool getEnablePathSimplification(); + GBool getDrawAnnotations(); + GBool getDrawFormFields(); + GBool getEnableXFA(); + GBool getOverprintPreview() { return overprintPreview; } + GString *getPaperColor(); + GString *getMatteColor(); + GString *getFullScreenMatteColor(); + GString *getSelectionColor(); + GBool getReverseVideoInvertImages(); + GString *getLaunchCommand() { return launchCommand; } + GString *getMovieCommand() { return movieCommand; } + GString *getDefaultPrinter(); + GBool getMapNumericCharNames(); + GBool getMapUnknownCharNames(); + GBool getMapExtTrueTypeFontsViaUnicode(); + GBool getUseTrueTypeUnicodeMapping(); + GBool isDroppedFont(const char *fontName); + GList *getKeyBinding(int code, int mods, int context); + GList *getAllKeyBindings(); + int getNumPopupMenuCmds(); + PopupMenuCmd *getPopupMenuCmd(int idx); + GString *getTabStateFile(); + GBool getSavePageNumbers(); + GBool getPrintCommands(); + GBool getPrintStatusInfo(); + GBool getErrQuiet(); + GString *getDebugLogFile(); + void debugLogPrintf(const char *fmt, ...); + + CharCodeToUnicode *getCIDToUnicode(GString *collection); + CharCodeToUnicode *getUnicodeToUnicode(GString *fontName); + UnicodeMap *getUnicodeMap(GString *encodingName); + CMap *getCMap(GString *collection, GString *cMapName); + UnicodeMap *getTextEncoding(); + + //----- functions to set parameters + + void addUnicodeRemapping(Unicode in, Unicode *out, int len); + void addFontFile(GString *fontName, GString *path); + GBool setPSPaperSize(char *size); + void setPSPaperWidth(int width); + void setPSPaperHeight(int height); + void setPSImageableArea(int llx, int lly, int urx, int ury); + void setPSDuplex(GBool duplex); + void setPSCrop(GBool crop); + void setPSUseCropBoxAsPage(GBool crop); + void setPSExpandSmaller(GBool expand); + void setPSShrinkLarger(GBool shrink); + void setPSCenter(GBool center); + void setPSLevel(PSLevel level); + void setPSEmbedType1(GBool embed); + 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); + void setTextEncoding(const char *encodingName); + GBool setTextEOL(char *s); + void setTextPageBreaks(GBool pageBreaks); + void setTextKeepTinyChars(GBool keep); + void setInitialZoom(char *s); + GBool setEnableFreeType(char *s); + GBool setAntialias(char *s); + GBool setVectorAntialias(char *s); + void setScreenType(ScreenType t); + void setScreenSize(int size); + void setScreenDotRadius(int r); + void setScreenGamma(double gamma); + void setScreenBlackThreshold(double thresh); + void setScreenWhiteThreshold(double thresh); + void setDrawFormFields(GBool draw); + void setOverprintPreview(GBool preview); + void setMapNumericCharNames(GBool map); + void setMapUnknownCharNames(GBool map); + void setMapExtTrueTypeFontsViaUnicode(GBool map); + void setTabStateFile(char *tabStateFileA); + void setPrintCommands(GBool printCommandsA); + void setPrintStatusInfo(GBool printStatusInfoA); + void setErrQuiet(GBool errQuietA); + +#ifdef _WIN32 + void setWin32ErrorInfo(const char *func, DWORD code); + XpdfWin32ErrorInfo *getWin32ErrorInfo(); +#endif + + static const char *defaultTextEncoding; + +private: + + void setDataDirVar(); + void createDefaultKeyBindings(); + void parseFile(GString *fileName, FILE *f); + GList *parseLineTokens(char *buf, GString *fileName, int line); + void parseNameToUnicode(GList *tokens, GString *fileName, int line); + void parseCIDToUnicode(GList *tokens, GString *fileName, int line); + void parseUnicodeToUnicode(GList *tokens, GString *fileName, int line); + 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 parseUnicodeRemapping(GList *tokens, 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 parsePSPaperSize(GList *tokens, GString *fileName, int line); + void parsePSImageableArea(GList *tokens, GString *fileName, int line); + void parsePSLevel(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 parseTextEOL(GList *tokens, GString *fileName, int line); + void parseStrokeAdjust(GList *tokens, GString *fileName, int line); + void parseScreenType(GList *tokens, GString *fileName, int line); + void parseDropFont(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, + const char *cmdName, + GList *tokens, GString *fileName, int line); + void parsePopupMenuCmd(GList *tokens, GString *fileName, int line); + void parseYesNo(const char *cmdName, GBool *flag, + GList *tokens, GString *fileName, int line); + GBool parseYesNo2(char *token, GBool *flag); + void parseString(const char *cmdName, GString **s, + GList *tokens, GString *fileName, int line); + void parseInteger(const char *cmdName, int *val, + GList *tokens, GString *fileName, int line); + void parseFloat(const char *cmdName, double *val, + GList *tokens, GString *fileName, int line); + UnicodeMap *getUnicodeMap2(GString *encodingName); + + //----- static tables + + NameToCharCode * // mapping from char name to + macRomanReverseMap; // MacRomanEncoding index + + //----- meta settings + + GString *baseDir; // base directory - for plugins, etc. + GHash *configFileVars; // variables for use in the config file + // [GString] + + //----- user-modifiable settings + + NameToCharCode * // mapping from char name to Unicode + nameToUnicode; + GHash *cidToUnicodes; // files for mappings from char collections + // to Unicode, indexed by collection name + // [GString] + GHash *unicodeToUnicodes; // files for Unicode-to-Unicode mappings, + // indexed by font name pattern [GString] + GHash *residentUnicodeMaps; // mappings from Unicode to char codes, + // indexed by encoding name [UnicodeMap] + GHash *unicodeMaps; // files for mappings from Unicode to char + // codes, indexed by encoding name [GString] + GHash *cMapDirs; // list of CMap dirs, indexed by collection + // name [GList[GString]] + GList *toUnicodeDirs; // list of ToUnicode CMap dirs [GString] + UnicodeRemapping * // Unicode remapping for text output + unicodeRemapping; + 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] + GHash *base14SysFonts; // Base-14 system font files: font name + // mapped to path [Base14FontInfo] + SysFontList *sysFonts; // system fonts + int psPaperWidth; // paper size, in PostScript points, for + int psPaperHeight; // PostScript output + int psImageableLLX, // imageable area, in PostScript points, + psImageableLLY, // for PostScript output + psImageableURX, + psImageableURY; + GBool psCrop; // crop PS output to CropBox + GBool psUseCropBoxAsPage; // use CropBox as page size + GBool psExpandSmaller; // expand smaller pages to fill paper + GBool psShrinkLarger; // shrink larger pages to fit paper + GBool psCenter; // center pages on the paper + GBool psDuplex; // enable duplexing in PostScript? + PSLevel psLevel; // PostScript level to generate + 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 psLZW; // false to use RLE instead of LZW + GBool psUncompressPreloadedImages; // uncompress all preloaded images + double psMinLineWidth; // minimum line width for PostScript output + double psRasterResolution; // PostScript rasterization resolution (dpi) + GBool psRasterMono; // true to do PostScript rasterization + // in monochrome (gray); false to do it + // in color (RGB/CMYK) + int psRasterSliceSize; // maximum size (pixels) of PostScript + // rasterization slice + GBool psAlwaysRasterize; // force PostScript rasterization + GBool psNeverRasterize; // prevent 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 + GString *initialZoom; // initial zoom level + int defaultFitZoom; // default zoom factor if initialZoom is + // 'page' or 'width'. + GString *initialDisplayMode; // initial display mode (single, + // continuous, etc.) + GBool initialToolbarState; // initial toolbar state - open (true) + // or closed (false) + GBool initialSidebarState; // initial sidebar state - open (true) + // or closed (false) + int initialSidebarWidth; // initial sidebar width + GString *initialSelectMode; // initial selection mode (block or linear) + int maxTileWidth; // maximum rasterization tile width + int maxTileHeight; // maximum rasterization tile height + int tileCacheSize; // number of rasterization tiles in cache + int workerThreads; // number of rasterization worker threads + 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 imageMaskAntialias; // image mask anti-aliasing enable flag + GBool antialiasPrinting; // allow anti-aliasing when printing + StrokeAdjustMode strokeAdjust; // stroke adjustment mode + ScreenType screenType; // halftone screen type + int screenSize; // screen matrix size + int screenDotRadius; // screen dot radius + double screenGamma; // screen gamma correction + double screenBlackThreshold; // screen black clamping threshold + double screenWhiteThreshold; // screen white clamping threshold + double minLineWidth; // minimum line width + GBool // enable path simplification + enablePathSimplification; + GBool drawAnnotations; // draw annotations or not + GBool drawFormFields; // draw form fields or not + GBool enableXFA; // enable XFA form parsing + GBool overprintPreview; // enable overprint preview + GString *paperColor; // paper (page background) color + GString *matteColor; // matte (background outside of page) color + GString *fullScreenMatteColor; // matte color in full-screen mode + GString *selectionColor; // selection color + GBool reverseVideoInvertImages; // invert images in reverse video mode + GString *launchCommand; // command executed for 'launch' links + GString *movieCommand; // command executed for movie annotations + GString *defaultPrinter; // default printer (for interactive printing + // from the viewer) + GBool mapNumericCharNames; // map numeric char names (from font subsets)? + GBool mapUnknownCharNames; // map unknown char names? + GBool mapExtTrueTypeFontsViaUnicode; // map char codes to GID via Unicode + // for external TrueType fonts? + GBool useTrueTypeUnicodeMapping; // use the Unicode cmaps in TrueType + // fonts, rather than the PDF + // ToUnicode mapping + GHash *droppedFonts; // dropped fonts [int] + GList *keyBindings; // key & mouse button bindings [KeyBinding] + GList *popupMenuCmds; // popup menu commands [PopupMenuCmd] + GString *tabStateFile; // path for the tab state save file + GBool savePageNumbers; // save page number when file is closed + // and restore page number when opened + GBool printCommands; // print the drawing commands + GBool printStatusInfo; // print status info for each page + GBool errQuiet; // suppress error messages? + GString *debugLogFile; // path for debug log file + + CharCodeToUnicodeCache *cidToUnicodeCache; + CharCodeToUnicodeCache *unicodeToUnicodeCache; + UnicodeMapCache *unicodeMapCache; + CMapCache *cMapCache; + +#if MULTITHREADED + GMutex mutex; + GMutex unicodeMapCacheMutex; + GMutex cMapCacheMutex; +#endif +#ifdef _WIN32 + DWORD tlsWin32ErrorInfo; // TLS index for error info +#endif +}; + +#endif diff --git a/xpdf/HTMLGen.cc b/xpdf/HTMLGen.cc new file mode 100644 index 0000000..a077655 --- /dev/null +++ b/xpdf/HTMLGen.cc @@ -0,0 +1,1120 @@ +//======================================================================== +// +// HTMLGen.cc +// +// Copyright 2010-2021 Glyph & Cog, LLC +// +//======================================================================== + +//~ to do: +//~ - fonts +//~ - underlined? (underlines are present in the background image) +//~ - include the original font name in the CSS entry (before the +//~ generic serif/sans-serif/monospace name) +//~ - check that htmlDir exists and is a directory +//~ - links: +//~ - internal links (to pages, to named destinations) +//~ - links from non-text content +//~ - rotated text should go in the background image +//~ - metadata +//~ - PDF outline + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include +#include "gmem.h" +#include "gmempp.h" +#include "GString.h" +#include "GList.h" +#include "SplashBitmap.h" +#include "PDFDoc.h" +#include "GfxFont.h" +#include "AcroForm.h" +#include "TextOutputDev.h" +#include "SplashOutputDev.h" +#include "ErrorCodes.h" +#include "WebFont.h" +#include "HTMLGen.h" + +#ifdef _WIN32 +# define strcasecmp stricmp +# define strncasecmp strnicmp +#endif + +//------------------------------------------------------------------------ + +struct FontStyleTagInfo { + const char *tag; + int tagLen; + GBool bold; + GBool italic; +}; + +// NB: these are compared, in order, against the tail of the font +// name, so "BoldItalic" must come before "Italic", etc. +static FontStyleTagInfo fontStyleTags[] = { + {"Roman", 5, gFalse, gFalse}, + {"Regular", 7, gFalse, gFalse}, + {"Condensed", 9, gFalse, gFalse}, + {"CondensedBold", 13, gTrue, gFalse}, + {"CondensedLight", 14, gFalse, gFalse}, + {"SemiBold", 8, gTrue, gFalse}, + {"BoldItalicMT", 12, gTrue, gTrue}, + {"BoldItalic", 10, gTrue, gTrue}, + {"Bold_Italic", 11, gTrue, gTrue}, + {"BoldOblique", 11, gTrue, gTrue}, + {"Bold_Oblique", 12, gTrue, gTrue}, + {"BoldMT", 6, gTrue, gFalse}, + {"Bold", 4, gTrue, gFalse}, + {"ItalicMT", 8, gFalse, gTrue}, + {"Italic", 6, gFalse, gTrue}, + {"Oblique", 7, gFalse, gTrue}, + {"Light", 5, gFalse, gFalse}, + {NULL, 0, gFalse, gFalse} +}; + +struct StandardFontInfo { + const char *name; + GBool fixedWidth; + GBool serif; +}; + +static StandardFontInfo standardFonts[] = { + {"Arial", gFalse, gFalse}, + {"Courier", gTrue, gFalse}, + {"Futura", gFalse, gFalse}, + {"Helvetica", gFalse, gFalse}, + {"Minion", gFalse, gTrue}, + {"NewCenturySchlbk", gFalse, gTrue}, + {"Times", gFalse, gTrue}, + {"TimesNew", gFalse, gTrue}, + {"Times_New", gFalse, gTrue}, + {"Verdana", gFalse, gFalse}, + {"LucidaSans", gFalse, gFalse}, + {NULL, gFalse, gFalse} +}; + +struct SubstFontInfo { + double mWidth; +}; + +// index: {fixed:8, serif:4, sans-serif:0} + bold*2 + italic +static SubstFontInfo substFonts[16] = { + {0.833}, + {0.833}, + {0.889}, + {0.889}, + {0.788}, + {0.722}, + {0.833}, + {0.778}, + {0.600}, + {0.600}, + {0.600}, + {0.600} +}; + +// Map Unicode indexes from the private use area, following the Adobe +// Glyph list. +#define privateUnicodeMapStart 0xf6f9 +#define privateUnicodeMapEnd 0xf7ff +static int +privateUnicodeMap[privateUnicodeMapEnd - privateUnicodeMapStart + 1] = { + 0x0141, 0x0152, 0, 0, 0x0160, 0, 0x017d, // f6f9 + 0, 0, 0, 0, 0, 0, 0, 0, // f700 + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, // f710 + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0x0021, 0, 0, 0x0024, 0, 0x0026, 0, // f720 + 0, 0, 0, 0, 0, 0, 0, 0, + 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, // f730 + 0x0038, 0x0039, 0, 0, 0, 0, 0, 0x003f, + 0, 0, 0, 0, 0, 0, 0, 0, // f740 + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, // f750 + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, // f760 + 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, + 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, // f770 + 0x0058, 0x0059, 0x005a, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, // f780 + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, // f790 + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0x00a1, 0x00a2, 0, 0, 0, 0, 0, // f7a0 + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, // f7b0 + 0, 0, 0, 0, 0, 0, 0, 0x00bf, + 0, 0, 0, 0, 0, 0, 0, 0, // f7c0 + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, // f7d0 + 0, 0, 0, 0, 0, 0, 0, 0, + 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7, // f7e0 + 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf, + 0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0, // f7f0 + 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x0178 +}; + +enum VerticalAlignment { + vertAlignBaseline, + vertAlignSub, + vertAlignSuper, + vertAlignTop +}; + +static const char *vertAlignNames[] = { + "baseline", + "sub", + "super", + "top" +}; + +//------------------------------------------------------------------------ + +class HTMLGenFontDefn { +public: + + HTMLGenFontDefn(Ref fontIDA, GString *fontFaceA, GString *fontSpecA, + double scaleA) + : fontID(fontIDA), fontFace(fontFaceA), fontSpec(fontSpecA) + , scale(scaleA), used(gFalse) {} + ~HTMLGenFontDefn() { delete fontFace; delete fontSpec; } + GBool match(Ref fontIDA) + { return fontIDA.num == fontID.num && fontIDA.gen == fontID.gen; } + + Ref fontID; + GString *fontFace; // NULL for substituted fonts + GString *fontSpec; + double scale; + GBool used; // set when used (per page) +}; + +//------------------------------------------------------------------------ + +class HTMLGenFormFieldInfo { +public: + + HTMLGenFormFieldInfo(AcroFormField *acroFormFieldA) + : acroFormField(acroFormFieldA) {} + + AcroFormField *acroFormField; +}; + +//------------------------------------------------------------------------ + +class Base64Encoder { +public: + + Base64Encoder(int (*writeFuncA)(void *stream, const char *data, int size), + void *streamA); + void encode(const unsigned char *data, size_t size); + void flush(); + +private: + + int (*writeFunc)(void *stream, const char *data, int size); + void *stream; + unsigned char buf[3]; + int bufLen; +}; + +static char base64Chars[65] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +Base64Encoder::Base64Encoder(int (*writeFuncA)(void *stream, const char *data, + int size), + void *streamA) { + writeFunc = writeFuncA; + stream = streamA; + bufLen = 0; +} + +void Base64Encoder::encode(const unsigned char *data, size_t size) { + size_t i = 0; + while (1) { + while (bufLen < 3) { + if (i >= size) { + return; + } + buf[bufLen++] = data[i++]; + } + char out[4]; + out[0] = base64Chars[(buf[0] >> 2) & 0x3f]; + out[1] = base64Chars[((buf[0] << 4) | (buf[1] >> 4)) & 0x3f]; + out[2] = base64Chars[((buf[1] << 2) | (buf[2] >> 6)) & 0x3f]; + out[3] = base64Chars[buf[2] & 0x3f]; + writeFunc(stream, out, 4); + bufLen = 0; + } +} + +void Base64Encoder::flush() { + // if bufLen == 0, this does nothing + // bufLen should never be 3 here + char out[4]; + if (bufLen == 1) { + out[0] = base64Chars[(buf[0] >> 2) & 0x3f]; + out[1] = base64Chars[(buf[0] << 4) & 0x3f]; + out[2] = '='; + out[3] = '='; + writeFunc(stream, out, 4); + } else if (bufLen == 2) { + out[0] = base64Chars[(buf[0] >> 2) & 0x3f]; + out[1] = base64Chars[((buf[0] << 4) | (buf[1] >> 4)) & 0x3f]; + out[2] = base64Chars[(buf[1] << 2) & 0x3f]; + out[3] = '='; + writeFunc(stream, out, 4); + } +} + +static int writeToString(void *stream, const char *data, int size) { + ((GString *)stream)->append(data, size); + return size; +} + +//------------------------------------------------------------------------ + + +//------------------------------------------------------------------------ + +HTMLGen::HTMLGen(double backgroundResolutionA, GBool tableMode) { + TextOutputControl textOutControl; + SplashColor paperColor; + + ok = gTrue; + + backgroundResolution = backgroundResolutionA; + zoom = 1.0; + vStretch = 1.0; + drawInvisibleText = gTrue; + allTextInvisible = gFalse; + extractFontFiles = gFalse; + convertFormFields = gFalse; + embedBackgroundImage = gFalse; + embedFonts = gFalse; + + // set up the TextOutputDev + textOutControl.mode = tableMode ? textOutTableLayout : textOutReadingOrder; + textOutControl.html = gTrue; + textOutControl.splitRotatedWords = gTrue; + textOut = new TextOutputDev(NULL, &textOutControl, gFalse); + if (!textOut->isOk()) { + ok = gFalse; + } + + // set up the SplashOutputDev + paperColor[0] = paperColor[1] = paperColor[2] = 0xff; + splashOut = new SplashOutputDev(splashModeRGB8, 1, gFalse, paperColor); + + fontDefns = NULL; +} + +HTMLGen::~HTMLGen() { + delete textOut; + delete splashOut; + if (fontDefns) { + deleteGList(fontDefns, HTMLGenFontDefn); + } +} + +void HTMLGen::startDoc(PDFDoc *docA) { + doc = docA; + splashOut->startDoc(doc->getXRef()); + + if (fontDefns) { + deleteGList(fontDefns, HTMLGenFontDefn); + } + fontDefns = new GList(); + nextFontFaceIdx = 0; +} + +static inline int pr(int (*writeFunc)(void *stream, const char *data, int size), + void *stream, const char *data) { + return writeFunc(stream, data, (int)strlen(data)); +} + +static int pf(int (*writeFunc)(void *stream, const char *data, int size), + void *stream, const char *fmt, ...) { + va_list args; + GString *s; + int ret; + + va_start(args, fmt); + s = GString::formatv(fmt, args); + va_end(args); + ret = writeFunc(stream, s->getCString(), s->getLength()); + delete s; + return ret; +} + +struct PNGWriteInfo { + Base64Encoder *base64; + int (*writePNG)(void *stream, const char *data, int size); + void *pngStream; +}; + +static void pngWriteFunc(png_structp png, png_bytep data, png_size_t size) { + PNGWriteInfo *info = (PNGWriteInfo *)png_get_progressive_ptr(png); + if (info->base64) { + info->base64->encode(data, size); + } else { + info->writePNG(info->pngStream, (char *)data, (int)size); + } +} + +int HTMLGen::convertPage( + int pg, const char *pngURL, const char *htmlDir, + int (*writeHTML)(void *stream, const char *data, int size), + void *htmlStream, + int (*writePNG)(void *stream, const char *data, int size), + void *pngStream) { + png_structp png; + png_infop pngInfo; + PNGWriteInfo writeInfo; + SplashBitmap *bitmap; + Guchar *p; + double pageW, pageH; + TextPage *text; + GList *cols, *pars, *lines, *words; + TextFontInfo *font; + TextColumn *col; + TextParagraph *par; + TextLine *line; + HTMLGenFontDefn *fontDefn; + GString *s; + double base; + int primaryDir, spanDir; + int colIdx, parIdx, lineIdx, firstWordIdx, lastWordIdx; + int y, i; + + // generate the background bitmap + splashOut->setSkipText(!allTextInvisible, gFalse); + doc->displayPage(splashOut, pg, + backgroundResolution, backgroundResolution * vStretch, + 0, gFalse, gTrue, gFalse); + bitmap = splashOut->getBitmap(); + + // page size + if (doc->getPageRotate(pg) == 90 || doc->getPageRotate(pg) == 270) { + pageW = doc->getPageCropHeight(pg); + pageH = doc->getPageCropWidth(pg); + } else { + pageW = doc->getPageCropWidth(pg); + pageH = doc->getPageCropHeight(pg); + } + + // get the PDF text + doc->displayPage(textOut, pg, 72, 72, 0, gFalse, gTrue, gFalse); + doc->processLinks(textOut, pg); + text = textOut->takeText(); + primaryDir = text->primaryDirectionIsLR() ? 1 : -1; + + // insert a special character for each form field; + // remove existing characters inside field bboxes; + // erase background content inside field bboxes + formFieldFont = NULL; + formFieldInfo = NULL; + if (convertFormFields) { + AcroForm *form = doc->getCatalog()->getForm(); + if (form) { + formFieldInfo = new GList(); + formFieldFont = new TextFontInfo(); + double yTop = doc->getCatalog()->getPage(pg)->getMediaBox()->y2; + for (i = 0; i < form->getNumFields(); ++i) { + AcroFormField *field = form->getField(i); + AcroFormFieldType fieldType = field->getAcroFormFieldType(); + if (field->getPageNum() == pg && + (fieldType == acroFormFieldText || + fieldType == acroFormFieldCheckbox)) { + double llx, lly, urx, ury; + field->getBBox(&llx, &lly, &urx, &ury); + lly = yTop - lly; + ury = yTop - ury; + + // add the field info + int fieldIdx = formFieldInfo->getLength(); + formFieldInfo->append(new HTMLGenFormFieldInfo(field)); + + // remove exsting chars + text->removeChars(llx, ury, urx, lly, 0.75, 0.5); + + // erase background content + int llxI = (int)(llx * backgroundResolution / 72 + 0.5); + int llyI = (int)(lly * backgroundResolution * vStretch / 72 + 0.5); + int urxI = (int)(urx * backgroundResolution / 72 + 0.5); + int uryI = (int)(ury * backgroundResolution * vStretch / 72 + 0.5); + llyI += (int)(backgroundResolution * vStretch / 20); + if (llxI < 0) { + llxI = 0; + } + if (urxI >= bitmap->getWidth()) { + urxI = bitmap->getWidth() - 1; + } + if (uryI < 0) { + uryI = 0; + } + if (llyI > bitmap->getHeight()) { + llyI = bitmap->getHeight() - 1; + } + if (uryI <= llyI && llxI <= urxI) { + SplashColorPtr p = bitmap->getDataPtr() + + uryI * bitmap->getRowSize() + llxI * 3; + for (int y = uryI; y <= llyI; ++y) { + memset(p, 0xff, (urxI - llxI + 1) * 3); + p += bitmap->getRowSize(); + } + } + + // add a special char + // (the font size is unused -- 10 is an arbitrary value) + text->addSpecialChar(llx, ury, urx, lly, + 0, formFieldFont, 10, 0x80000000 + fieldIdx); + } + } + } + } + + // HTML header + pr(writeHTML, htmlStream, "\n"); + pr(writeHTML, htmlStream, "\n"); + pr(writeHTML, htmlStream, "\n"); + pr(writeHTML, htmlStream, "\n"); + pr(writeHTML, htmlStream, "\n"); + if (primaryDir >= 0) { + pr(writeHTML, htmlStream, "\n"); + } else { + pr(writeHTML, htmlStream, "\n"); + } + + // background image element (part 1) + if (primaryDir >= 0) { + pf(writeHTML, htmlStream, "getWidth(), bitmap->getHeight(), + 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); + png_write_info(png, pngInfo); + p = bitmap->getDataPtr(); + for (y = 0; y < bitmap->getHeight(); ++y) { + png_write_row(png, (png_bytep)p); + p += bitmap->getRowSize(); + } + png_write_end(png, pngInfo); + png_destroy_write_struct(&png, &pngInfo); + if (embedBackgroundImage) { + writeInfo.base64->flush(); + delete writeInfo.base64; + } + + // background image element (part 2) + pr(writeHTML, htmlStream, "\">\n"); + + // generate the HTML text + nextFieldID = 0; + cols = text->makeColumns(); + for (colIdx = 0; colIdx < cols->getLength(); ++colIdx) { + col = (TextColumn *)cols->get(colIdx); + pars = col->getParagraphs(); + for (parIdx = 0; parIdx < pars->getLength(); ++parIdx) { + par = (TextParagraph *)pars->get(parIdx); + lines = par->getLines(); + for (lineIdx = 0; lineIdx < lines->getLength(); ++lineIdx) { + line = (TextLine *)lines->get(lineIdx); + if (line->getRotation() != 0) { + continue; + } + words = line->getWords(); + if (lineIdx == 0 && par->hasDropCap() && words->getLength() >= 2) { + base = ((TextWord *)words->get(1))->getBaseline(); + } else { + base = line->getBaseline(); + } + s = new GString(); + for (firstWordIdx = (primaryDir >= 0) ? 0 : words->getLength() - 1; + (primaryDir >= 0) ? firstWordIdx < words->getLength() + : firstWordIdx >= 0; + firstWordIdx = lastWordIdx + primaryDir) { + lastWordIdx = findDirSpan(words, firstWordIdx, + primaryDir, &spanDir); + appendSpans(words, firstWordIdx, lastWordIdx, + primaryDir, spanDir, + base, lineIdx == 0 && par->hasDropCap(), + s); + } + if (primaryDir >= 0) { + pf(writeHTML, htmlStream, "
{2:t}
\n", + (int)(line->getXMin() * zoom), + (int)(line->getYMin() * zoom * vStretch), s); + } else { + pf(writeHTML, htmlStream, "
{2:t}
\n", + (int)((pageW - line->getXMax()) * zoom), + (int)(line->getYMin() * zoom * vStretch), s); + } + delete s; + } + } + } + gfree(fontScales); + delete text; + deleteGList(cols, TextColumn); + if (formFieldFont) { + delete formFieldFont; + formFieldFont = NULL; + } + if (formFieldInfo) { + deleteGList(formFieldInfo, HTMLGenFormFieldInfo); + formFieldInfo = NULL; + } + + // HTML trailer + pr(writeHTML, htmlStream, "\n"); + pr(writeHTML, htmlStream, "\n"); + + return errNone; +} + +// Find a sequence of words, starting at , that have the +// same writing direction. Returns the index of the last word, and +// sets * to the span direction. +int HTMLGen::findDirSpan(GList *words, int firstWordIdx, int primaryDir, + int *spanDir) { + int dir0, dir1, nextWordIdx; + + dir0 = ((TextWord *)words->get(firstWordIdx))->getDirection(); + for (nextWordIdx = firstWordIdx + primaryDir; + (primaryDir >= 0) ? nextWordIdx < words->getLength() + : nextWordIdx >= 0; + nextWordIdx += primaryDir) { + dir1 = ((TextWord *)words->get(nextWordIdx))->getDirection(); + if (dir0 == 0) { + dir0 = dir1; + } else if (dir1 != 0 && dir1 != dir0) { + break; + } + } + + if (dir0 == 0) { + *spanDir = primaryDir; + } else { + *spanDir = dir0; + } + + return nextWordIdx - primaryDir; +} + +// Create HTML spans for words .. , and +// append them to . +void HTMLGen::appendSpans(GList *words, int firstWordIdx, int lastWordIdx, + int primaryDir, int spanDir, + double base, GBool dropCapLine, GString *s) { + if (allTextInvisible && !drawInvisibleText) { + return; + } + + if (spanDir != primaryDir) { + int t = firstWordIdx; + firstWordIdx = lastWordIdx; + lastWordIdx = t; + } + + int wordIdx = firstWordIdx; + while ((spanDir >= 0) ? wordIdx <= lastWordIdx + : wordIdx >= lastWordIdx) { + TextWord *word0 = (TextWord *)words->get(wordIdx); + + // form field(s): generate element(s) + if (convertFormFields && word0->getFontInfo() == formFieldFont) { + for (int i = (spanDir >= 0) ? 0 : word0->getLength() - 1; + (spanDir >= 0) ? i < word0->getLength() : i >= 0; + i += spanDir) { + int fieldIdx = word0->getChar(0) - 0x80000000; + if (fieldIdx >= 0 && fieldIdx < formFieldInfo->getLength()) { + HTMLGenFormFieldInfo *ffi = + (HTMLGenFormFieldInfo *)formFieldInfo->get(fieldIdx); + AcroFormField *field = ffi->acroFormField; + AcroFormFieldType fieldType = field->getAcroFormFieldType(); + double llx, lly, urx, ury; + field->getBBox(&llx, &lly, &urx, &ury); + int width = (int)(urx - llx); + Ref fontID; + double fontSize; + field->getFont(&fontID, &fontSize); + if (fontSize == 0) { + fontSize = 12; + } + if (fieldType == acroFormFieldText) { + s->appendf("", nextFieldID, width, (int)(fontSize + 0.5)); + ++nextFieldID; + } else if (fieldType == acroFormFieldCheckbox) { + s->appendf("", nextFieldID, width, (int)(fontSize + 0.5)); + ++nextFieldID; + } + } + } + + if (word0->getSpaceAfter()) { + s->append(' '); + } + + wordIdx += spanDir; + + // skip invisible words + } else if (!drawInvisibleText && + (word0->isInvisible() || word0->isRotated())) { + wordIdx += spanDir; + + // generate a containing one or more words + } else { + + double r0 = 0, g0 = 0, b0 = 0; // make gcc happy + VerticalAlignment vertAlign0 = vertAlignBaseline; // make gcc happy + GString *linkURI0 = NULL; + + GBool invisible = word0->isInvisible() || word0->isRotated(); + + do { + TextWord *word1 = (TextWord *)words->get(wordIdx); + + // get word parameters + double r1, g1, b1; + word0->getColor(&r1, &g1, &b1); + double base1 = word1->getBaseline(); + VerticalAlignment vertAlign1; + if (dropCapLine) { + //~ this will fail if there are subscripts or superscripts in + //~ the first line of a paragraph with a drop cap + vertAlign1 = vertAlignTop; + } else if (base1 - base < -1) { + vertAlign1 = vertAlignSuper; + } else if (base1 - base > 1) { + vertAlign1 = vertAlignSub; + } else { + vertAlign1 = vertAlignBaseline; + } + GString *linkURI1 = word1->getLinkURI(); + + // start of span + if (word1 == word0) { + r0 = r1; + g0 = g1; + b0 = b1; + vertAlign0 = vertAlign1; + linkURI0 = linkURI1; + + int i; + for (i = 0; i < fonts->getLength(); ++i) { + if (word1->getFontInfo() == (TextFontInfo *)fonts->get(i)) { + break; + } + } + if (linkURI1) { + s->appendf("
", linkURI0); + } + // we force spans to be LTR or RTL; this is a kludge, but it's + // far easier than implementing the full Unicode bidi algorithm + const char *dirTag; + if (spanDir == primaryDir) { + dirTag = ""; + } else if (spanDir < 0) { + dirTag = " dir=\"rtl\""; + } else { + dirTag = " dir=\"ltr\""; + } + s->appendf("", + i, + dirTag, + (int)(fontScales[i] * word1->getFontSize() * zoom), + vertAlignNames[vertAlign1], + (dropCapLine && wordIdx == 0) ? "line-height:75%;" : "", + (int)(r0 * 255), (int)(g0 * 255), (int)(b0 * 255), + invisible ? 0 : 1); + + // end of span + } else if (word1->getFontInfo() != word0->getFontInfo() || + word1->getFontSize() != word0->getFontSize() || + word1->isInvisible() != word0->isInvisible() || + word1->isRotated() != word0->isRotated() || + vertAlign1 != vertAlign0 || + r1 != r0 || g1 != g0 || b1 != b0 || + linkURI1 != linkURI0) { + break; + } + + // add a space before the word, if needed + // -- this only happens with the first word in a reverse section + if (spanDir != primaryDir && wordIdx == firstWordIdx) { + GBool sp; + if (spanDir >= 0) { + if (wordIdx > 0) { + sp = ((TextWord *)words->get(wordIdx - 1))->getSpaceAfter(); + } else { + sp = gFalse; + } + } else { + sp = word1->getSpaceAfter(); + } + if (sp) { + s->append(' '); + } + } + + // generate the word text + for (int i = (spanDir >= 0) ? 0 : word1->getLength() - 1; + (spanDir >= 0) ? i < word1->getLength() : i >= 0; + i += spanDir) { + Unicode u = word1->getChar(i); + if (u >= privateUnicodeMapStart && + u <= privateUnicodeMapEnd && + privateUnicodeMap[u - privateUnicodeMapStart]) { + u = privateUnicodeMap[u - privateUnicodeMapStart]; + } + appendUTF8(u, s); + } + + // add a space after the word, if needed + // -- there is never a space after the last word in a reverse + // section (this will be handled as a space after the last + // word in the previous primary-direction section) + GBool sp; + if (spanDir != primaryDir && wordIdx == lastWordIdx) { + sp = gFalse; + } else if (spanDir >= 0) { + sp = word1->getSpaceAfter(); + } else { + if (wordIdx > 0) { + sp = ((TextWord *)words->get(wordIdx - 1))->getSpaceAfter(); + } else { + sp = gFalse; + } + } + if (sp) { + s->append(' '); + } + + wordIdx += spanDir; + } while ((spanDir >= 0) ? wordIdx <= lastWordIdx + : wordIdx >= lastWordIdx); + + s->append(""); + if (linkURI0) { + s->append(""); + } + } + } +} + +void HTMLGen::appendUTF8(Unicode u, GString *s) { + if (u <= 0x7f) { + if (u == '&') { + s->append("&"); + } else if (u == '<') { + s->append("<"); + } else if (u == '>') { + s->append(">"); + } else { + s->append((char)u); + } + } else if (u <= 0x7ff) { + s->append((char)(0xc0 + (u >> 6))); + s->append((char)(0x80 + (u & 0x3f))); + } else if (u <= 0xffff) { + s->append((char)(0xe0 + (u >> 12))); + s->append((char)(0x80 + ((u >> 6) & 0x3f))); + s->append((char)(0x80 + (u & 0x3f))); + } else if (u <= 0x1fffff) { + s->append((char)(0xf0 + (u >> 18))); + s->append((char)(0x80 + ((u >> 12) & 0x3f))); + s->append((char)(0x80 + ((u >> 6) & 0x3f))); + s->append((char)(0x80 + (u & 0x3f))); + } else if (u <= 0x3ffffff) { + s->append((char)(0xf8 + (u >> 24))); + s->append((char)(0x80 + ((u >> 18) & 0x3f))); + s->append((char)(0x80 + ((u >> 12) & 0x3f))); + s->append((char)(0x80 + ((u >> 6) & 0x3f))); + s->append((char)(0x80 + (u & 0x3f))); + } else if (u <= 0x7fffffff) { + s->append((char)(0xfc + (u >> 30))); + s->append((char)(0x80 + ((u >> 24) & 0x3f))); + s->append((char)(0x80 + ((u >> 18) & 0x3f))); + s->append((char)(0x80 + ((u >> 12) & 0x3f))); + s->append((char)(0x80 + ((u >> 6) & 0x3f))); + s->append((char)(0x80 + (u & 0x3f))); + } +} + +HTMLGenFontDefn *HTMLGen::getFontDefn(TextFontInfo *font, + const char *htmlDir) { + Ref id; + HTMLGenFontDefn *fontDefn; + int i; + + // check the existing font defns + id = font->getFontID(); + if (id.num >= 0) { + for (i = 0; i < fontDefns->getLength(); ++i) { + fontDefn = (HTMLGenFontDefn *)fontDefns->get(i); + if (fontDefn->match(id)) { + return fontDefn; + } + } + } + + // try to extract a font file + if (!extractFontFiles || + !(fontDefn = getFontFile(font, htmlDir))) { + + // get a substitute font + fontDefn = getSubstituteFont(font); + } + + fontDefns->append(fontDefn); + return fontDefn; +} + +HTMLGenFontDefn *HTMLGen::getFontFile(TextFontInfo *font, + const char *htmlDir) { + Ref id; + HTMLGenFontDefn *fontDefn; + Object fontObj; + GfxFont *gfxFont; + WebFont *webFont; + GString *fontFile, *fontPath, *fontFace, *fontSpec; + const char *family, *weight, *style; + double scale; + + id = font->getFontID(); + if (id.num < 0) { + return NULL; + } + + doc->getXRef()->fetch(id.num, id.gen, &fontObj); + if (!fontObj.isDict()) { + fontObj.free(); + return NULL; + } + + gfxFont = GfxFont::makeFont(doc->getXRef(), "F", id, fontObj.getDict()); + webFont = new WebFont(gfxFont, doc->getXRef()); + fontDefn = NULL; + fontFace = NULL; + + if (webFont->canWriteTTF()) { + if (embedFonts) { + GString *ttfData = webFont->getTTFData(); + if (ttfData) { + fontFace = GString::format("@font-face {{ font-family: ff{0:d}; src: url(\"data:font/ttf;base64,", + nextFontFaceIdx); + Base64Encoder enc(writeToString, fontFace); + enc.encode((unsigned char *)ttfData->getCString(), + (size_t)ttfData->getLength()); + enc.flush(); + fontFace->append("\"); }\n"); + delete ttfData; + } + } else { + fontFile = GString::format("{0:d}.ttf", nextFontFaceIdx); + fontPath = GString::format("{0:s}/{1:t}", htmlDir, fontFile); + if (webFont->writeTTF(fontPath->getCString())) { + fontFace = GString::format("@font-face {{ font-family: ff{0:d}; src: url(\"{1:t}\"); }}\n", + nextFontFaceIdx, fontFile); + } + delete fontPath; + delete fontFile; + } + if (fontFace) { + getFontDetails(font, &family, &weight, &style, &scale); + fontSpec = GString::format("font-family:ff{0:d},{1:s}; font-weight:{2:s}; font-style:{3:s};", + nextFontFaceIdx, family, weight, style); + ++nextFontFaceIdx; + fontDefn = new HTMLGenFontDefn(id, fontFace, fontSpec, 1.0); + } + + } else if (webFont->canWriteOTF()) { + if (embedFonts) { + GString *otfData = webFont->getOTFData(); + if (otfData) { + fontFace = GString::format("@font-face {{ font-family: ff{0:d}; src: url(\"data:font/otf;base64,", + nextFontFaceIdx); + Base64Encoder enc(writeToString, fontFace); + enc.encode((unsigned char *)otfData->getCString(), + (size_t)otfData->getLength()); + enc.flush(); + fontFace->append("\"); }\n"); + delete otfData; + } + } else { + fontFile = GString::format("{0:d}.otf", nextFontFaceIdx); + fontPath = GString::format("{0:s}/{1:t}", htmlDir, fontFile); + if (webFont->writeOTF(fontPath->getCString())) { + fontFace = GString::format("@font-face {{ font-family: ff{0:d}; src: url(\"{1:t}\"); }}\n", + nextFontFaceIdx, fontFile); + } + delete fontPath; + delete fontFile; + } + if (fontFace) { + getFontDetails(font, &family, &weight, &style, &scale); + fontSpec = GString::format("font-family:ff{0:d},{1:s}; font-weight:{2:s}; font-style:{3:s};", + nextFontFaceIdx, family, weight, style); + ++nextFontFaceIdx; + fontDefn = new HTMLGenFontDefn(id, fontFace, fontSpec, 1.0); + } + } + + delete webFont; + delete gfxFont; + fontObj.free(); + + return fontDefn; +} + +HTMLGenFontDefn *HTMLGen::getSubstituteFont(TextFontInfo *font) { + const char *family, *weight, *style; + double scale; + GString *fontSpec; + + getFontDetails(font, &family, &weight, &style, &scale); + fontSpec = GString::format("font-family:{0:s}; font-weight:{1:s}; font-style:{2:s};", + family, weight, style); + return new HTMLGenFontDefn(font->getFontID(), NULL, fontSpec, scale); +} + +void HTMLGen::getFontDetails(TextFontInfo *font, const char **family, + const char **weight, const char **style, + double *scale) { + GString *fontName; + char *fontName2; + FontStyleTagInfo *fst; + StandardFontInfo *sf; + GBool fixedWidth, serif, bold, italic; + double s; + int n, i; + + // get the font name, remove any subset tag + fontName = font->getFontName(); + if (fontName) { + fontName2 = fontName->getCString(); + n = fontName->getLength(); + for (i = 0; i < n && i < 7; ++i) { + if (fontName2[i] < 'A' || fontName2[i] > 'Z') { + break; + } + } + if (i == 6 && n > 7 && fontName2[6] == '+') { + fontName2 += 7; + n -= 7; + } + } else { + fontName2 = NULL; + n = 0; + } + + // get the style info from the font descriptor flags + fixedWidth = font->isFixedWidth(); + serif = font->isSerif(); + bold = font->isBold(); + italic = font->isItalic(); + + if (fontName2) { + + // look for a style tag at the end of the font name -- this + // overrides the font descriptor bold/italic flags + for (fst = fontStyleTags; fst->tag; ++fst) { + if (n > fst->tagLen && + !strcasecmp(fontName2 + n - fst->tagLen, fst->tag)) { + bold = fst->bold; + italic = fst->italic; + n -= fst->tagLen; + if (n > 1 && (fontName2[n-1] == '-' || + fontName2[n-1] == ',' || + fontName2[n-1] == '.' || + fontName2[n-1] == '_')) { + --n; + } + break; + } + } + + // look for a known font name -- this overrides the font descriptor + // fixedWidth/serif flags + for (sf = standardFonts; sf->name; ++sf) { + if (!strncasecmp(fontName2, sf->name, n)) { + fixedWidth = sf->fixedWidth; + serif = sf->serif; + break; + } + } + } + + // compute the scaling factor + *scale = 1; + if ((s = font->getMWidth())) { + i = (fixedWidth ? 8 : serif ? 4 : 0) + (bold ? 2 : 0) + (italic ? 1 : 0); + if (s < substFonts[i].mWidth) { + *scale = s / substFonts[i].mWidth; + } + } + + *family = fixedWidth ? "monospace" : serif ? "serif" : "sans-serif"; + *weight = bold ? "bold" : "normal"; + *style = italic ? "italic" : "normal"; +} diff --git a/xpdf/HTMLGen.h b/xpdf/HTMLGen.h new file mode 100644 index 0000000..66ee2d2 --- /dev/null +++ b/xpdf/HTMLGen.h @@ -0,0 +1,113 @@ +//======================================================================== +// +// HTMLGen.h +// +// Copyright 2010-2021 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef HTMLGEN_H +#define HTMLGEN_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +class GString; +class PDFDoc; +class TextOutputDev; +class TextFontInfo; +class SplashOutputDev; +class HTMLGenFontDefn; + +//------------------------------------------------------------------------ + +class HTMLGen { +public: + + HTMLGen(double backgroundResolutionA, GBool tableMode); + ~HTMLGen(); + + GBool isOk() { return ok; } + + double getBackgroundResolution() { return backgroundResolution; } + void setBackgroundResolution(double backgroundResolutionA) + { backgroundResolution = backgroundResolutionA; } + + double getZoom() { return zoom; } + void setZoom(double zoomA) { zoom = zoomA; } + + void setVStretch(double vStretchA) { vStretch = vStretchA; } + + GBool getDrawInvisibleText() { return drawInvisibleText; } + void setDrawInvisibleText(GBool drawInvisibleTextA) + { drawInvisibleText = drawInvisibleTextA; } + + GBool getAllTextInvisible() { return allTextInvisible; } + void setAllTextInvisible(GBool allTextInvisibleA) + { allTextInvisible = allTextInvisibleA; } + + void setExtractFontFiles(GBool extractFontFilesA) + { extractFontFiles = extractFontFilesA; } + + void setConvertFormFields(GBool convertFormFieldsA) + { convertFormFields = convertFormFieldsA; } + + void setEmbedBackgroundImage(GBool embedBackgroundImageA) + { embedBackgroundImage = embedBackgroundImageA; } + + void setEmbedFonts(GBool embedFontsA) + { embedFonts = embedFontsA; } + + void startDoc(PDFDoc *docA); + int convertPage(int pg, const char *pngURL, const char *htmlDir, + int (*writeHTML)(void *stream, const char *data, int size), + void *htmlStream, + int (*writePNG)(void *stream, const char *data, int size), + void *pngStream); + +private: + + int findDirSpan(GList *words, int firstWordIdx, int primaryDir, + int *spanDir); + void appendSpans(GList *words, int firstWordIdx, int lastWordIdx, + int primaryDir, int spanDir, + double base, GBool dropCapLine, GString *s); + void appendUTF8(Unicode u, GString *s); + HTMLGenFontDefn *getFontDefn(TextFontInfo *font, const char *htmlDir); + HTMLGenFontDefn *getFontFile(TextFontInfo *font, const char *htmlDir); + HTMLGenFontDefn *getSubstituteFont(TextFontInfo *font); + void getFontDetails(TextFontInfo *font, const char **family, + const char **weight, const char **style, + double *scale); + + double backgroundResolution; + double zoom; + double vStretch; + GBool drawInvisibleText; + GBool allTextInvisible; + GBool extractFontFiles; + GBool convertFormFields; + GBool embedBackgroundImage; + GBool embedFonts; + + PDFDoc *doc; + TextOutputDev *textOut; + SplashOutputDev *splashOut; + + GList *fonts; // [TextFontInfo] + double *fontScales; + + GList *fontDefns; // [HTMLGenFontDefn] + int nextFontFaceIdx; + + TextFontInfo *formFieldFont; + GList *formFieldInfo; // [HTMLGenFormFieldInfo] + int nextFieldID; + + GBool ok; +}; + +#endif diff --git a/xpdf/ImageOutputDev.cc b/xpdf/ImageOutputDev.cc new file mode 100644 index 0000000..5a694d7 --- /dev/null +++ b/xpdf/ImageOutputDev.cc @@ -0,0 +1,453 @@ +//======================================================================== +// +// ImageOutputDev.cc +// +// Copyright 1998-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include +#include +#include +#include +#include "gmem.h" +#include "gmempp.h" +#include "config.h" +#include "Error.h" +#include "GfxState.h" +#include "Object.h" +#include "Stream.h" +#include "ImageOutputDev.h" + +ImageOutputDev::ImageOutputDev(char *fileRootA, GBool dumpJPEGA, + GBool dumpRawA, GBool listA) { + fileRoot = copyString(fileRootA); + dumpJPEG = dumpJPEGA; + dumpRaw = dumpRawA; + list = listA; + imgNum = 0; + curPageNum = 0; + ok = gTrue; +} + +ImageOutputDev::~ImageOutputDev() { + gfree(fileRoot); +} + +void ImageOutputDev::startPage(int pageNum, GfxState *state) { + curPageNum = pageNum; +} + +void ImageOutputDev::tilingPatternFill(GfxState *state, Gfx *gfx, + Object *strRef, + int paintType, int tilingType, + 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, GBool interpolate) { + GString *fileName; + FILE *f; + char buf[4096]; + int size, n, i; + + // dump raw file + if (dumpRaw && !inlineImg) { + + // open the image file + fileName = GString::format("{0:s}-{1:04d}.{2:s}", + fileRoot, imgNum, getRawFileExtension(str)); + ++imgNum; + if (!(f = openFile(fileName->getCString(), "wb"))) { + error(errIO, -1, "Couldn't open image file '{0:t}'", fileName); + delete fileName; + return; + } + + // initialize stream + str = getRawStream(str); + str->reset(); + + // copy the stream + while ((n = str->getBlock(buf, sizeof(buf))) > 0) { + fwrite(buf, 1, n, f); + } + + str->close(); + fclose(f); + + // dump JPEG file + } else if (dumpJPEG && str->getKind() == strDCT && !inlineImg) { + + // open the image file + fileName = GString::format("{0:s}-{1:04d}.jpg", fileRoot, imgNum); + ++imgNum; + if (!(f = openFile(fileName->getCString(), "wb"))) { + error(errIO, -1, "Couldn't open image file '{0:t}'", fileName); + delete fileName; + return; + } + + // initialize stream + str = ((DCTStream *)str)->getRawStream(); + str->reset(); + + // copy the stream + while ((n = str->getBlock(buf, sizeof(buf))) > 0) { + fwrite(buf, 1, n, f); + } + + str->close(); + fclose(f); + + // dump PBM file + } else { + + // open the image file and write the PBM header + fileName = GString::format("{0:s}-{1:04d}.pbm", fileRoot, imgNum); + ++imgNum; + if (!(f = openFile(fileName->getCString(), "wb"))) { + error(errIO, -1, "Couldn't open image file '{0:t}'", fileName); + delete fileName; + return; + } + fprintf(f, "P4\n"); + fprintf(f, "%d %d\n", width, height); + + // initialize stream + str->reset(); + + // copy the stream + size = height * ((width + 7) / 8); + while (size > 0) { + i = size < (int)sizeof(buf) ? size : (int)sizeof(buf); + n = str->getBlock(buf, i); + fwrite(buf, 1, n, f); + if (n < i) { + break; + } + size -= n; + } + + str->close(); + fclose(f); + } + + if (list) { + writeImageInfo(fileName, width, height, state, NULL); + } + + delete fileName; +} + +void ImageOutputDev::drawImage(GfxState *state, Object *ref, Stream *str, + int width, int height, + GfxImageColorMap *colorMap, + int *maskColors, GBool inlineImg, + GBool interpolate) { + GfxColorSpaceMode csMode; + GString *fileName; + FILE *f; + ImageStream *imgStr; + Guchar *p; + GfxRGB rgb; + GfxGray gray; + int x, y; + char buf[4096]; + int size, n, i, j; + + csMode = colorMap->getColorSpace()->getMode(); + if (csMode == csIndexed) { + csMode = ((GfxIndexedColorSpace *)colorMap->getColorSpace()) + ->getBase()->getMode(); + } + + // dump raw file + if (dumpRaw && !inlineImg) { + + // open the image file + fileName = GString::format("{0:s}-{1:04d}.{2:s}", + fileRoot, imgNum, getRawFileExtension(str)); + ++imgNum; + if (!(f = openFile(fileName->getCString(), "wb"))) { + error(errIO, -1, "Couldn't open image file '{0:t}'", fileName); + delete fileName; + return; + } + + // initialize stream + str = getRawStream(str); + str->reset(); + + // copy the stream + while ((n = str->getBlock(buf, sizeof(buf))) > 0) { + fwrite(buf, 1, n, f); + } + + str->close(); + fclose(f); + + // dump JPEG file + } else if (dumpJPEG && str->getKind() == strDCT && + (colorMap->getNumPixelComps() == 1 || + colorMap->getNumPixelComps() == 3) && + !inlineImg) { + + // open the image file + fileName = GString::format("{0:s}-{1:04d}.jpg", fileRoot, imgNum); + ++imgNum; + if (!(f = openFile(fileName->getCString(), "wb"))) { + error(errIO, -1, "Couldn't open image file '{0:t}'", fileName); + delete fileName; + return; + } + + // initialize stream + str = ((DCTStream *)str)->getRawStream(); + str->reset(); + + // copy the stream + while ((n = str->getBlock(buf, sizeof(buf))) > 0) { + fwrite(buf, 1, n, f); + } + + str->close(); + fclose(f); + + // dump PBM file + } else if (colorMap->getNumPixelComps() == 1 && + colorMap->getBits() == 1) { + + // open the image file and write the PBM header + fileName = GString::format("{0:s}-{1:04d}.pbm", fileRoot, imgNum); + ++imgNum; + if (!(f = openFile(fileName->getCString(), "wb"))) { + error(errIO, -1, "Couldn't open image file '{0:t}'", fileName); + delete fileName; + return; + } + fprintf(f, "P4\n"); + fprintf(f, "%d %d\n", width, height); + + // initialize stream + str->reset(); + + // copy the stream + size = height * ((width + 7) / 8); + while (size > 0) { + i = size < (int)sizeof(buf) ? size : (int)sizeof(buf); + n = str->getBlock(buf, i); + for (j = 0; j < n; ++j) { + buf[j] = (char)(buf[j] ^ 0xff); + } + fwrite(buf, 1, n, f); + if (n < i) { + break; + } + size -= n; + } + + str->close(); + fclose(f); + + // dump PGM file + } else if (colorMap->getNumPixelComps() == 1 && + (csMode == csDeviceGray || csMode == csCalGray)) { + + // open the image file and write the PGM header + fileName = GString::format("{0:s}-{1:04d}.pgm", fileRoot, imgNum); + ++imgNum; + if (!(f = openFile(fileName->getCString(), "wb"))) { + error(errIO, -1, "Couldn't open image file '{0:t}'", fileName); + delete fileName; + return; + } + fprintf(f, "P5\n"); + fprintf(f, "%d %d\n", width, height); + fprintf(f, "255\n"); + + // initialize stream + imgStr = new ImageStream(str, width, colorMap->getNumPixelComps(), + colorMap->getBits()); + imgStr->reset(); + + // for each line... + for (y = 0; y < height; ++y) { + + // write the line + if ((p = imgStr->getLine())) { + for (x = 0; x < width; ++x) { + colorMap->getGray(p, &gray, state->getRenderingIntent()); + fputc(colToByte(gray), f); + ++p; + } + } else { + for (x = 0; x < width; ++x) { + fputc(0, f); + } + } + } + + imgStr->close(); + delete imgStr; + + fclose(f); + + // dump PPM file + } else { + + // open the image file and write the PPM header + fileName = GString::format("{0:s}-{1:04d}.ppm", fileRoot, imgNum); + ++imgNum; + if (!(f = openFile(fileName->getCString(), "wb"))) { + error(errIO, -1, "Couldn't open image file '{0:t}'", fileName); + delete fileName; + return; + } + fprintf(f, "P6\n"); + fprintf(f, "%d %d\n", width, height); + fprintf(f, "255\n"); + + // initialize stream + imgStr = new ImageStream(str, width, colorMap->getNumPixelComps(), + colorMap->getBits()); + imgStr->reset(); + + // for each line... + for (y = 0; y < height; ++y) { + + // write the line + if ((p = imgStr->getLine())) { + for (x = 0; x < width; ++x) { + colorMap->getRGB(p, &rgb, state->getRenderingIntent()); + 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); + } + } + } + + imgStr->close(); + delete imgStr; + + fclose(f); + } + + if (list) { + writeImageInfo(fileName, width, height, state, colorMap); + } + + delete fileName; +} + +void ImageOutputDev::drawMaskedImage(GfxState *state, Object *ref, Stream *str, + int width, int height, + GfxImageColorMap *colorMap, + Object *maskRef, Stream *maskStr, + int maskWidth, int maskHeight, + GBool maskInvert, GBool interpolate) { + drawImage(state, ref, str, width, height, colorMap, + NULL, gFalse, interpolate); + drawImageMask(state, maskRef, maskStr, maskWidth, maskHeight, maskInvert, + gFalse, interpolate); +} + +void ImageOutputDev::drawSoftMaskedImage(GfxState *state, Object *ref, + Stream *str, + int width, int height, + GfxImageColorMap *colorMap, + Object *maskRef, Stream *maskStr, + int maskWidth, int maskHeight, + GfxImageColorMap *maskColorMap, + double *matte, GBool interpolate) { + drawImage(state, ref, str, width, height, colorMap, + NULL, gFalse, interpolate); + drawImage(state, maskRef, maskStr, maskWidth, maskHeight, maskColorMap, + NULL, gFalse, interpolate); +} + +Stream *ImageOutputDev::getRawStream(Stream *str) { + switch (str->getKind()) { + case strLZW: + case strRunLength: + case strCCITTFax: + case strDCT: + case strFlate: + case strJBIG2: + case strJPX: + return ((FilterStream *)str)->getNextStream(); + default: + return str; + } +} + +const char *ImageOutputDev::getRawFileExtension(Stream *str) { + switch (str->getKind()) { + case strLZW: return "lzw"; + case strRunLength: return "rle"; + case strCCITTFax: return "fax"; + case strDCT: return "jpg"; + case strFlate: return "flate"; + case strJBIG2: return "jb2"; + case strJPX: return "jpx"; + default: return "unknown"; + } +} + +void ImageOutputDev::writeImageInfo(GString *fileName, + int width, int height, GfxState *state, + GfxImageColorMap *colorMap) { + const char *mode; + double hdpi, vdpi, x0, y0, x1, y1; + int bpc; + + // this works for 0/90/180/270-degree rotations, along with + // horizontal/vertical flips + state->transformDelta(1, 0, &x0, &y0); + state->transformDelta(0, 1, &x1, &y1); + x0 = fabs(x0); + y0 = fabs(y0); + x1 = fabs(x1); + y1 = fabs(y1); + if (x0 > y0) { + hdpi = (72 * width) / x0; + vdpi = (72 * height) / y1; + } else { + hdpi = (72 * height) / x1; + vdpi = (72 * width) / y0; + } + + if (colorMap) { + mode = GfxColorSpace::getColorSpaceModeName( + colorMap->getColorSpace()->getMode()); + bpc = colorMap->getBits(); + } else { + mode = NULL; + bpc = 1; + } + + printf("%s: page=%d width=%d height=%d hdpi=%.2f vdpi=%.2f %s%s bpc=%d\n", + fileName->getCString(), curPageNum, width, height, hdpi, vdpi, + mode ? "colorspace=" : "mask", + mode ? mode : "", + bpc); +} diff --git a/xpdf/ImageOutputDev.h b/xpdf/ImageOutputDev.h new file mode 100644 index 0000000..5a72925 --- /dev/null +++ b/xpdf/ImageOutputDev.h @@ -0,0 +1,116 @@ +//======================================================================== +// +// ImageOutputDev.h +// +// Copyright 1998-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef IMAGEOUTPUTDEV_H +#define IMAGEOUTPUTDEV_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include +#include "gtypes.h" +#include "OutputDev.h" + +class GfxImageColorMap; +class GfxState; + +//------------------------------------------------------------------------ +// ImageOutputDev +//------------------------------------------------------------------------ + +class ImageOutputDev: public OutputDev { +public: + + // Create an OutputDev which will write images to files named + // -NNN.. Normally, all images are written as PBM + // (.pbm) or PPM (.ppm) files. If is set, JPEG images + // are written as JPEG (.jpg) files. If is set, all + // images are written in PDF-native formats. If is set, a + // one-line summary will be written to stdout for each image. + ImageOutputDev(char *fileRootA, GBool dumpJPEGA, GBool dumpRawA, + GBool listA); + + // Destructor. + virtual ~ImageOutputDev(); + + // 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; } + + // Does this device need non-text content? + virtual GBool needNonText() { return gTrue; } + + //---- get info about output device + + // 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; } + + // Does this device use drawChar() or drawString()? + virtual GBool useDrawChar() { return gFalse; } + + //----- initialization and control + virtual void startPage(int pageNum, GfxState *state); + + //----- path painting + virtual void tilingPatternFill(GfxState *state, Gfx *gfx, Object *strRef, + int paintType, int tilingType, 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, + GBool inlineImg, GBool interpolate); + virtual void drawImage(GfxState *state, Object *ref, Stream *str, + int width, int height, GfxImageColorMap *colorMap, + int *maskColors, GBool inlineImg, GBool interpolate); + virtual void drawMaskedImage(GfxState *state, Object *ref, Stream *str, + int width, int height, + GfxImageColorMap *colorMap, + Object *maskRef, Stream *maskStr, + int maskWidth, int maskHeight, + GBool maskInvert, GBool interpolate); + virtual void drawSoftMaskedImage(GfxState *state, Object *ref, Stream *str, + int width, int height, + GfxImageColorMap *colorMap, + Object *maskRef, Stream *maskStr, + int maskWidth, int maskHeight, + GfxImageColorMap *maskColorMap, + double *matte, GBool interpolate); + +private: + + Stream *getRawStream(Stream *str); + const char *getRawFileExtension(Stream *str); + void writeImageInfo(GString *fileName, + int width, int height, GfxState *state, + GfxImageColorMap *colorMap); + + char *fileRoot; // root of output file names + GBool dumpJPEG; // set to dump native JPEG files + GBool dumpRaw; // set to dump raw PDF-native image files + GBool list; // set to write image info to stdout + int imgNum; // current image number + int curPageNum; // current page number + GBool ok; // set up ok? +}; + +#endif diff --git a/xpdf/JArithmeticDecoder.cc b/xpdf/JArithmeticDecoder.cc new file mode 100644 index 0000000..3d10cb4 --- /dev/null +++ b/xpdf/JArithmeticDecoder.cc @@ -0,0 +1,370 @@ +//======================================================================== +// +// JArithmeticDecoder.cc +// +// Copyright 2002-2004 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include "gmempp.h" +#include "Object.h" +#include "Stream.h" +#include "JArithmeticDecoder.h" + +//------------------------------------------------------------------------ +// JArithmeticDecoderStates +//------------------------------------------------------------------------ + +JArithmeticDecoderStats::JArithmeticDecoderStats(int contextSizeA) { + contextSize = contextSizeA; + cxTab = (Guchar *)gmallocn(contextSize, sizeof(Guchar)); + reset(); +} + +JArithmeticDecoderStats::~JArithmeticDecoderStats() { + gfree(cxTab); +} + +JArithmeticDecoderStats *JArithmeticDecoderStats::copy() { + JArithmeticDecoderStats *stats; + + stats = new JArithmeticDecoderStats(contextSize); + memcpy(stats->cxTab, cxTab, contextSize); + return stats; +} + +void JArithmeticDecoderStats::reset() { + memset(cxTab, 0, contextSize); +} + +void JArithmeticDecoderStats::copyFrom(JArithmeticDecoderStats *stats) { + memcpy(cxTab, stats->cxTab, contextSize); +} + +void JArithmeticDecoderStats::setEntry(Guint cx, int i, int mps) { + cxTab[cx] = (Guchar)((i << 1) + mps); +} + +//------------------------------------------------------------------------ +// JArithmeticDecoder +//------------------------------------------------------------------------ + +Guint JArithmeticDecoder::qeTab[47] = { + 0x56010000, 0x34010000, 0x18010000, 0x0AC10000, + 0x05210000, 0x02210000, 0x56010000, 0x54010000, + 0x48010000, 0x38010000, 0x30010000, 0x24010000, + 0x1C010000, 0x16010000, 0x56010000, 0x54010000, + 0x51010000, 0x48010000, 0x38010000, 0x34010000, + 0x30010000, 0x28010000, 0x24010000, 0x22010000, + 0x1C010000, 0x18010000, 0x16010000, 0x14010000, + 0x12010000, 0x11010000, 0x0AC10000, 0x09C10000, + 0x08A10000, 0x05210000, 0x04410000, 0x02A10000, + 0x02210000, 0x01410000, 0x01110000, 0x00850000, + 0x00490000, 0x00250000, 0x00150000, 0x00090000, + 0x00050000, 0x00010000, 0x56010000 +}; + +int JArithmeticDecoder::nmpsTab[47] = { + 1, 2, 3, 4, 5, 38, 7, 8, 9, 10, 11, 12, 13, 29, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 45, 46 +}; + +int JArithmeticDecoder::nlpsTab[47] = { + 1, 6, 9, 12, 29, 33, 6, 14, 14, 14, 17, 18, 20, 21, 14, 14, + 15, 16, 17, 18, 19, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, + 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 46 +}; + +int JArithmeticDecoder::switchTab[47] = { + 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +JArithmeticDecoder::JArithmeticDecoder() { + str = NULL; + dataLen = 0; + limitStream = gFalse; + nBytesRead = 0; + readBuf = -1; +} + +inline Guint JArithmeticDecoder::readByte() { + Guint x; + + if (limitStream) { + if (readBuf >= 0) { + x = (Guint)readBuf; + readBuf = -1; + return x; + } + --dataLen; + if (dataLen < 0) { + return 0xff; + } + } + ++nBytesRead; + return (Guint)str->getChar() & 0xff; +} + +JArithmeticDecoder::~JArithmeticDecoder() { + cleanup(); +} + +void JArithmeticDecoder::start() { + buf0 = readByte(); + buf1 = readByte(); + + // INITDEC + c = (buf0 ^ 0xff) << 16; + byteIn(); + c <<= 7; + ct -= 7; + a = 0x80000000; +} + +void JArithmeticDecoder::restart(int dataLenA) { + Guint cAdd; + GBool prevFF; + int k, nBits; + + if (dataLen >= 0) { + dataLen = dataLenA; + } else if (dataLen == -1) { + dataLen = dataLenA; + buf1 = 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(); + } +} + +void JArithmeticDecoder::cleanup() { + if (limitStream) { + // This saves one extra byte of data from the end of packet i, to + // be used in packet i+1. It's not clear from the JPEG 2000 spec + // exactly how this should work, but this kludge does seem to fix + // decode of some problematic JPEG 2000 streams. It may actually + // be necessary to buffer an arbitrary number of bytes (not just + // one byte), but I haven't run into that case yet. + while (dataLen > 0) { + readBuf = -1; + readBuf = readByte(); + } + } +} + +int JArithmeticDecoder::decodeBit(Guint context, + JArithmeticDecoderStats *stats) { + int bit; + Guint qe; + int iCX, mpsCX; + + iCX = stats->cxTab[context] >> 1; + mpsCX = stats->cxTab[context] & 1; + qe = qeTab[iCX]; + a -= qe; + if (c < a) { + if (a & 0x80000000) { + bit = mpsCX; + } else { + // MPS_EXCHANGE + if (a < qe) { + bit = 1 - mpsCX; + if (switchTab[iCX]) { + stats->cxTab[context] = (Guchar)((nlpsTab[iCX] << 1) | (1 - mpsCX)); + } else { + stats->cxTab[context] = (Guchar)((nlpsTab[iCX] << 1) | mpsCX); + } + } else { + bit = mpsCX; + stats->cxTab[context] = (Guchar)((nmpsTab[iCX] << 1) | mpsCX); + } + // RENORMD + do { + if (ct == 0) { + byteIn(); + } + a <<= 1; + c <<= 1; + --ct; + } while (!(a & 0x80000000)); + } + } else { + c -= a; + // LPS_EXCHANGE + if (a < qe) { + bit = mpsCX; + stats->cxTab[context] = (Guchar)((nmpsTab[iCX] << 1) | mpsCX); + } else { + bit = 1 - mpsCX; + if (switchTab[iCX]) { + stats->cxTab[context] = (Guchar)((nlpsTab[iCX] << 1) | (1 - mpsCX)); + } else { + stats->cxTab[context] = (Guchar)((nlpsTab[iCX] << 1) | mpsCX); + } + } + a = qe; + // RENORMD + do { + if (ct == 0) { + byteIn(); + } + a <<= 1; + c <<= 1; + --ct; + } while (!(a & 0x80000000)); + } + return bit; +} + +int JArithmeticDecoder::decodeByte(Guint context, + JArithmeticDecoderStats *stats) { + int byte; + int i; + + byte = 0; + for (i = 0; i < 8; ++i) { + byte = (byte << 1) | decodeBit(context, stats); + } + return byte; +} + +GBool JArithmeticDecoder::decodeInt(int *x, JArithmeticDecoderStats *stats) { + int s; + Guint v; + int i; + + prev = 1; + s = decodeIntBit(stats); + if (decodeIntBit(stats)) { + if (decodeIntBit(stats)) { + if (decodeIntBit(stats)) { + if (decodeIntBit(stats)) { + if (decodeIntBit(stats)) { + v = 0; + for (i = 0; i < 32; ++i) { + v = (v << 1) | decodeIntBit(stats); + } + v += 4436; + } else { + v = 0; + for (i = 0; i < 12; ++i) { + v = (v << 1) | decodeIntBit(stats); + } + v += 340; + } + } else { + v = 0; + for (i = 0; i < 8; ++i) { + v = (v << 1) | decodeIntBit(stats); + } + v += 84; + } + } else { + v = 0; + for (i = 0; i < 6; ++i) { + v = (v << 1) | decodeIntBit(stats); + } + v += 20; + } + } else { + v = decodeIntBit(stats); + v = (v << 1) | decodeIntBit(stats); + v = (v << 1) | decodeIntBit(stats); + v = (v << 1) | decodeIntBit(stats); + v += 4; + } + } else { + v = decodeIntBit(stats); + v = (v << 1) | decodeIntBit(stats); + } + + if (s) { + if (v == 0) { + return gFalse; + } + *x = -(int)v; + } else { + *x = (int)v; + } + return gTrue; +} + +int JArithmeticDecoder::decodeIntBit(JArithmeticDecoderStats *stats) { + int bit; + + bit = decodeBit(prev, stats); + if (prev < 0x100) { + prev = (prev << 1) | bit; + } else { + prev = (((prev << 1) | bit) & 0x1ff) | 0x100; + } + return bit; +} + +Guint JArithmeticDecoder::decodeIAID(Guint codeLen, + JArithmeticDecoderStats *stats) { + Guint i; + int bit; + + prev = 1; + for (i = 0; i < codeLen; ++i) { + bit = decodeBit(prev, stats); + prev = (prev << 1) | bit; + } + return prev - (1 << 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; + buf1 = readByte(); + c = c + 0xfe00 - (buf0 << 9); + ct = 7; + } + } else { + buf0 = buf1; + buf1 = readByte(); + c = c + 0xff00 - (buf0 << 8); + ct = 8; + } +} diff --git a/xpdf/JArithmeticDecoder.h b/xpdf/JArithmeticDecoder.h new file mode 100644 index 0000000..c0f773f --- /dev/null +++ b/xpdf/JArithmeticDecoder.h @@ -0,0 +1,114 @@ +//======================================================================== +// +// JArithmeticDecoder.h +// +// Arithmetic decoder used by the JBIG2 and JPEG2000 decoders. +// +// Copyright 2002-2004 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef JARITHMETICDECODER_H +#define JARITHMETICDECODER_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "gtypes.h" + +class Stream; + +//------------------------------------------------------------------------ +// JArithmeticDecoderStats +//------------------------------------------------------------------------ + +class JArithmeticDecoderStats { +public: + + JArithmeticDecoderStats(int contextSizeA); + ~JArithmeticDecoderStats(); + JArithmeticDecoderStats *copy(); + void reset(); + int getContextSize() { return contextSize; } + void copyFrom(JArithmeticDecoderStats *stats); + void setEntry(Guint cx, int i, int mps); + +private: + + Guchar *cxTab; // cxTab[cx] = (i[cx] << 1) + mps[cx] + int contextSize; + + friend class JArithmeticDecoder; +}; + +//------------------------------------------------------------------------ +// JArithmeticDecoder +//------------------------------------------------------------------------ + +class JArithmeticDecoder { +public: + + JArithmeticDecoder(); + ~JArithmeticDecoder(); + + void setStream(Stream *strA) + { str = strA; dataLen = 0; limitStream = gFalse; } + void setStream(Stream *strA, int dataLenA) + { str = strA; dataLen = dataLenA; limitStream = gTrue; } + + // Start decoding on a new stream. This fills the byte buffers and + // runs INITDEC. + void start(); + + // Restart decoding on an interrupted stream. This refills the + // buffers if needed, but does not run INITDEC. (This is used in + // JPEG 2000 streams when codeblock data is split across multiple + // packets/layers.) + void restart(int dataLenA); + + // Read any leftover data in the stream. + void cleanup(); + + // Decode one bit. + int decodeBit(Guint context, JArithmeticDecoderStats *stats); + + // Decode eight bits. + int decodeByte(Guint context, JArithmeticDecoderStats *stats); + + // Returns false for OOB, otherwise sets * and returns true. + GBool decodeInt(int *x, JArithmeticDecoderStats *stats); + + Guint decodeIAID(Guint codeLen, + JArithmeticDecoderStats *stats); + + void resetByteCounter() { nBytesRead = 0; } + Guint getByteCounter() { return nBytesRead; } + +private: + + Guint readByte(); + int decodeIntBit(JArithmeticDecoderStats *stats); + void byteIn(); + + static Guint qeTab[47]; + static int nmpsTab[47]; + static int nlpsTab[47]; + static int switchTab[47]; + + Guint buf0, buf1; + Guint c, a; + int ct; + + Guint prev; // for the integer decoder + + Stream *str; + Guint nBytesRead; + int dataLen; + GBool limitStream; + int readBuf; +}; + +#endif diff --git a/xpdf/JBIG2Stream.cc b/xpdf/JBIG2Stream.cc new file mode 100644 index 0000000..02450b4 --- /dev/null +++ b/xpdf/JBIG2Stream.cc @@ -0,0 +1,4234 @@ +//======================================================================== +// +// JBIG2Stream.cc +// +// Copyright 2002-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include +#include "gmempp.h" +#include "GList.h" +#include "Error.h" +#include "JArithmeticDecoder.h" +#include "JBIG2Stream.h" + +//~ share these tables +#include "Stream-CCITT.h" + +//------------------------------------------------------------------------ + +static int contextSize[4] = { 16, 13, 10, 10 }; +static int refContextSize[2] = { 13, 10 }; + +//------------------------------------------------------------------------ +// JBIG2HuffmanTable +//------------------------------------------------------------------------ + +#define jbig2HuffmanLOW 0xfffffffd +#define jbig2HuffmanOOB 0xfffffffe +#define jbig2HuffmanEOT 0xffffffff + +struct JBIG2HuffmanTable { + int val; + Guint prefixLen; + Guint rangeLen; // can also be LOW, OOB, or EOT + Guint prefix; +}; + +JBIG2HuffmanTable huffTableA[] = { + { 0, 1, 4, 0x000 }, + { 16, 2, 8, 0x002 }, + { 272, 3, 16, 0x006 }, + { 65808, 3, 32, 0x007 }, + { 0, 0, jbig2HuffmanEOT, 0 } +}; + +JBIG2HuffmanTable huffTableB[] = { + { 0, 1, 0, 0x000 }, + { 1, 2, 0, 0x002 }, + { 2, 3, 0, 0x006 }, + { 3, 4, 3, 0x00e }, + { 11, 5, 6, 0x01e }, + { 75, 6, 32, 0x03e }, + { 0, 6, jbig2HuffmanOOB, 0x03f }, + { 0, 0, jbig2HuffmanEOT, 0 } +}; + +JBIG2HuffmanTable huffTableC[] = { + { 0, 1, 0, 0x000 }, + { 1, 2, 0, 0x002 }, + { 2, 3, 0, 0x006 }, + { 3, 4, 3, 0x00e }, + { 11, 5, 6, 0x01e }, + { 0, 6, jbig2HuffmanOOB, 0x03e }, + { 75, 7, 32, 0x0fe }, + { -256, 8, 8, 0x0fe }, + { -257, 8, jbig2HuffmanLOW, 0x0ff }, + { 0, 0, jbig2HuffmanEOT, 0 } +}; + +JBIG2HuffmanTable huffTableD[] = { + { 1, 1, 0, 0x000 }, + { 2, 2, 0, 0x002 }, + { 3, 3, 0, 0x006 }, + { 4, 4, 3, 0x00e }, + { 12, 5, 6, 0x01e }, + { 76, 5, 32, 0x01f }, + { 0, 0, jbig2HuffmanEOT, 0 } +}; + +JBIG2HuffmanTable huffTableE[] = { + { 1, 1, 0, 0x000 }, + { 2, 2, 0, 0x002 }, + { 3, 3, 0, 0x006 }, + { 4, 4, 3, 0x00e }, + { 12, 5, 6, 0x01e }, + { 76, 6, 32, 0x03e }, + { -255, 7, 8, 0x07e }, + { -256, 7, jbig2HuffmanLOW, 0x07f }, + { 0, 0, jbig2HuffmanEOT, 0 } +}; + +JBIG2HuffmanTable huffTableF[] = { + { 0, 2, 7, 0x000 }, + { 128, 3, 7, 0x002 }, + { 256, 3, 8, 0x003 }, + { -1024, 4, 9, 0x008 }, + { -512, 4, 8, 0x009 }, + { -256, 4, 7, 0x00a }, + { -32, 4, 5, 0x00b }, + { 512, 4, 9, 0x00c }, + { 1024, 4, 10, 0x00d }, + { -2048, 5, 10, 0x01c }, + { -128, 5, 6, 0x01d }, + { -64, 5, 5, 0x01e }, + { -2049, 6, jbig2HuffmanLOW, 0x03e }, + { 2048, 6, 32, 0x03f }, + { 0, 0, jbig2HuffmanEOT, 0 } +}; + +JBIG2HuffmanTable huffTableG[] = { + { -512, 3, 8, 0x000 }, + { 256, 3, 8, 0x001 }, + { 512, 3, 9, 0x002 }, + { 1024, 3, 10, 0x003 }, + { -1024, 4, 9, 0x008 }, + { -256, 4, 7, 0x009 }, + { -32, 4, 5, 0x00a }, + { 0, 4, 5, 0x00b }, + { 128, 4, 7, 0x00c }, + { -128, 5, 6, 0x01a }, + { -64, 5, 5, 0x01b }, + { 32, 5, 5, 0x01c }, + { 64, 5, 6, 0x01d }, + { -1025, 5, jbig2HuffmanLOW, 0x01e }, + { 2048, 5, 32, 0x01f }, + { 0, 0, jbig2HuffmanEOT, 0 } +}; + +JBIG2HuffmanTable huffTableH[] = { + { 0, 2, 1, 0x000 }, + { 0, 2, jbig2HuffmanOOB, 0x001 }, + { 4, 3, 4, 0x004 }, + { -1, 4, 0, 0x00a }, + { 22, 4, 4, 0x00b }, + { 38, 4, 5, 0x00c }, + { 2, 5, 0, 0x01a }, + { 70, 5, 6, 0x01b }, + { 134, 5, 7, 0x01c }, + { 3, 6, 0, 0x03a }, + { 20, 6, 1, 0x03b }, + { 262, 6, 7, 0x03c }, + { 646, 6, 10, 0x03d }, + { -2, 7, 0, 0x07c }, + { 390, 7, 8, 0x07d }, + { -15, 8, 3, 0x0fc }, + { -5, 8, 1, 0x0fd }, + { -7, 9, 1, 0x1fc }, + { -3, 9, 0, 0x1fd }, + { -16, 9, jbig2HuffmanLOW, 0x1fe }, + { 1670, 9, 32, 0x1ff }, + { 0, 0, jbig2HuffmanEOT, 0 } +}; + +JBIG2HuffmanTable huffTableI[] = { + { 0, 2, jbig2HuffmanOOB, 0x000 }, + { -1, 3, 1, 0x002 }, + { 1, 3, 1, 0x003 }, + { 7, 3, 5, 0x004 }, + { -3, 4, 1, 0x00a }, + { 43, 4, 5, 0x00b }, + { 75, 4, 6, 0x00c }, + { 3, 5, 1, 0x01a }, + { 139, 5, 7, 0x01b }, + { 267, 5, 8, 0x01c }, + { 5, 6, 1, 0x03a }, + { 39, 6, 2, 0x03b }, + { 523, 6, 8, 0x03c }, + { 1291, 6, 11, 0x03d }, + { -5, 7, 1, 0x07c }, + { 779, 7, 9, 0x07d }, + { -31, 8, 4, 0x0fc }, + { -11, 8, 2, 0x0fd }, + { -15, 9, 2, 0x1fc }, + { -7, 9, 1, 0x1fd }, + { -32, 9, jbig2HuffmanLOW, 0x1fe }, + { 3339, 9, 32, 0x1ff }, + { 0, 0, jbig2HuffmanEOT, 0 } +}; + +JBIG2HuffmanTable huffTableJ[] = { + { -2, 2, 2, 0x000 }, + { 6, 2, 6, 0x001 }, + { 0, 2, jbig2HuffmanOOB, 0x002 }, + { -3, 5, 0, 0x018 }, + { 2, 5, 0, 0x019 }, + { 70, 5, 5, 0x01a }, + { 3, 6, 0, 0x036 }, + { 102, 6, 5, 0x037 }, + { 134, 6, 6, 0x038 }, + { 198, 6, 7, 0x039 }, + { 326, 6, 8, 0x03a }, + { 582, 6, 9, 0x03b }, + { 1094, 6, 10, 0x03c }, + { -21, 7, 4, 0x07a }, + { -4, 7, 0, 0x07b }, + { 4, 7, 0, 0x07c }, + { 2118, 7, 11, 0x07d }, + { -5, 8, 0, 0x0fc }, + { 5, 8, 0, 0x0fd }, + { -22, 8, jbig2HuffmanLOW, 0x0fe }, + { 4166, 8, 32, 0x0ff }, + { 0, 0, jbig2HuffmanEOT, 0 } +}; + +JBIG2HuffmanTable huffTableK[] = { + { 1, 1, 0, 0x000 }, + { 2, 2, 1, 0x002 }, + { 4, 4, 0, 0x00c }, + { 5, 4, 1, 0x00d }, + { 7, 5, 1, 0x01c }, + { 9, 5, 2, 0x01d }, + { 13, 6, 2, 0x03c }, + { 17, 7, 2, 0x07a }, + { 21, 7, 3, 0x07b }, + { 29, 7, 4, 0x07c }, + { 45, 7, 5, 0x07d }, + { 77, 7, 6, 0x07e }, + { 141, 7, 32, 0x07f }, + { 0, 0, jbig2HuffmanEOT, 0 } +}; + +JBIG2HuffmanTable huffTableL[] = { + { 1, 1, 0, 0x000 }, + { 2, 2, 0, 0x002 }, + { 3, 3, 1, 0x006 }, + { 5, 5, 0, 0x01c }, + { 6, 5, 1, 0x01d }, + { 8, 6, 1, 0x03c }, + { 10, 7, 0, 0x07a }, + { 11, 7, 1, 0x07b }, + { 13, 7, 2, 0x07c }, + { 17, 7, 3, 0x07d }, + { 25, 7, 4, 0x07e }, + { 41, 8, 5, 0x0fe }, + { 73, 8, 32, 0x0ff }, + { 0, 0, jbig2HuffmanEOT, 0 } +}; + +JBIG2HuffmanTable huffTableM[] = { + { 1, 1, 0, 0x000 }, + { 2, 3, 0, 0x004 }, + { 7, 3, 3, 0x005 }, + { 3, 4, 0, 0x00c }, + { 5, 4, 1, 0x00d }, + { 4, 5, 0, 0x01c }, + { 15, 6, 1, 0x03a }, + { 17, 6, 2, 0x03b }, + { 21, 6, 3, 0x03c }, + { 29, 6, 4, 0x03d }, + { 45, 6, 5, 0x03e }, + { 77, 7, 6, 0x07e }, + { 141, 7, 32, 0x07f }, + { 0, 0, jbig2HuffmanEOT, 0 } +}; + +JBIG2HuffmanTable huffTableN[] = { + { 0, 1, 0, 0x000 }, + { -2, 3, 0, 0x004 }, + { -1, 3, 0, 0x005 }, + { 1, 3, 0, 0x006 }, + { 2, 3, 0, 0x007 }, + { 0, 0, jbig2HuffmanEOT, 0 } +}; + +JBIG2HuffmanTable huffTableO[] = { + { 0, 1, 0, 0x000 }, + { -1, 3, 0, 0x004 }, + { 1, 3, 0, 0x005 }, + { -2, 4, 0, 0x00c }, + { 2, 4, 0, 0x00d }, + { -4, 5, 1, 0x01c }, + { 3, 5, 1, 0x01d }, + { -8, 6, 2, 0x03c }, + { 5, 6, 2, 0x03d }, + { -24, 7, 4, 0x07c }, + { 9, 7, 4, 0x07d }, + { -25, 7, jbig2HuffmanLOW, 0x07e }, + { 25, 7, 32, 0x07f }, + { 0, 0, jbig2HuffmanEOT, 0 } +}; + +//------------------------------------------------------------------------ +// JBIG2HuffmanDecoder +//------------------------------------------------------------------------ + +class JBIG2HuffmanDecoder { +public: + + JBIG2HuffmanDecoder(); + ~JBIG2HuffmanDecoder(); + void setStream(Stream *strA) { str = strA; } + + void reset(); + + // Returns false for OOB, otherwise sets * and returns true. + GBool decodeInt(int *x, JBIG2HuffmanTable *table); + + Guint readBits(Guint n); + Guint readBit(); + + // 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(); +} + +JBIG2HuffmanDecoder::~JBIG2HuffmanDecoder() { +} + +void JBIG2HuffmanDecoder::reset() { + buf = 0; + bufLen = 0; +} + +//~ optimize this +GBool JBIG2HuffmanDecoder::decodeInt(int *x, JBIG2HuffmanTable *table) { + Guint i, len, prefix; + + i = 0; + len = 0; + prefix = 0; + while (table[i].rangeLen != jbig2HuffmanEOT) { + while (len < table[i].prefixLen) { + prefix = (prefix << 1) | readBit(); + ++len; + } + if (prefix == table[i].prefix) { + if (table[i].rangeLen == jbig2HuffmanOOB) { + return gFalse; + } + if (table[i].rangeLen == jbig2HuffmanLOW) { + *x = table[i].val - readBits(32); + } else if (table[i].rangeLen > 0) { + *x = table[i].val + readBits(table[i].rangeLen); + } else { + *x = table[i].val; + } + return gTrue; + } + ++i; + } + return gFalse; +} + +Guint JBIG2HuffmanDecoder::readBits(Guint n) { + Guint x, mask, nLeft; + + mask = (n == 32) ? 0xffffffff : ((1 << n) - 1); + if (bufLen >= n) { + x = (buf >> (bufLen - n)) & mask; + bufLen -= n; + } else { + x = buf & ((1 << bufLen) - 1); + nLeft = n - bufLen; + 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)); + } + } + return x; +} + +Guint JBIG2HuffmanDecoder::readBit() { + if (bufLen == 0) { + buf = str->getChar(); + ++byteCounter; + bufLen = 8; + } + --bufLen; + return (buf >> bufLen) & 1; +} + +void JBIG2HuffmanDecoder::buildTable(JBIG2HuffmanTable *table, Guint len) { + Guint i, j, k, prefix; + JBIG2HuffmanTable tab; + + // stable selection sort: + // - entries with prefixLen > 0, in ascending prefixLen order + // - entry with prefixLen = 0, rangeLen = EOT + // - all other entries with prefixLen = 0 + // (on entry, table[len] has prefixLen = 0, rangeLen = EOT) + for (i = 0; i < len; ++i) { + for (j = i; j < len && table[j].prefixLen == 0; ++j) ; + if (j == len) { + break; + } + for (k = j + 1; k < len; ++k) { + if (table[k].prefixLen > 0 && + table[k].prefixLen < table[j].prefixLen) { + j = k; + } + } + if (j != i) { + tab = table[j]; + for (k = j; k > i; --k) { + table[k] = table[k - 1]; + } + table[i] = tab; + } + } + table[i] = table[len]; + + // assign prefixes + 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++; + } + } +} + +//------------------------------------------------------------------------ +// JBIG2MMRDecoder +//------------------------------------------------------------------------ + +class JBIG2MMRDecoder { +public: + + JBIG2MMRDecoder(); + ~JBIG2MMRDecoder(); + void setStream(Stream *strA) { str = strA; } + void reset(); + int get2DCode(); + int getBlackCode(); + int getWhiteCode(); + Guint get24Bits(); + void resetByteCounter() { byteCounter = 0; } + Guint getByteCounter() { return byteCounter; } + void skipTo(Guint length); + +private: + + Stream *str; + Guint buf; + Guint bufLen; + Guint nBytesRead; + Guint byteCounter; +}; + +JBIG2MMRDecoder::JBIG2MMRDecoder() { + str = NULL; + byteCounter = 0; + reset(); +} + +JBIG2MMRDecoder::~JBIG2MMRDecoder() { +} + +void JBIG2MMRDecoder::reset() { + buf = 0; + bufLen = 0; + nBytesRead = 0; +} + +int JBIG2MMRDecoder::get2DCode() { + CCITTCode *p; + + if (bufLen == 0) { + buf = str->getChar() & 0xff; + bufLen = 8; + ++nBytesRead; + ++byteCounter; + p = &twoDimTab1[(buf >> 1) & 0x7f]; + } else if (bufLen >= 7) { + p = &twoDimTab1[(buf >> (bufLen - 7)) & 0x7f]; + } else { + p = &twoDimTab1[(buf << (7 - bufLen)) & 0x7f]; + if (p->bits < 0 || p->bits > (int)bufLen) { + buf = (buf << 8) | (str->getChar() & 0xff); + bufLen += 8; + ++nBytesRead; + ++byteCounter; + p = &twoDimTab1[(buf >> (bufLen - 7)) & 0x7f]; + } + } + if (p->bits < 0) { + error(errSyntaxError, str->getPos(), + "Bad two dim code in JBIG2 MMR stream"); + return EOF; + } + bufLen -= p->bits; + return p->n; +} + +int JBIG2MMRDecoder::getWhiteCode() { + CCITTCode *p; + Guint code; + + if (bufLen == 0) { + buf = str->getChar() & 0xff; + bufLen = 8; + ++nBytesRead; + ++byteCounter; + } + while (1) { + if (bufLen >= 11 && ((buf >> (bufLen - 7)) & 0x7f) == 0) { + if (bufLen <= 12) { + code = buf << (12 - bufLen); + } else { + code = buf >> (bufLen - 12); + } + p = &whiteTab1[code & 0x1f]; + } else { + if (bufLen <= 9) { + code = buf << (9 - bufLen); + } else { + code = buf >> (bufLen - 9); + } + p = &whiteTab2[code & 0x1ff]; + } + if (p->bits > 0 && p->bits <= (int)bufLen) { + bufLen -= p->bits; + return p->n; + } + if (bufLen >= 12) { + break; + } + buf = (buf << 8) | (str->getChar() & 0xff); + bufLen += 8; + ++nBytesRead; + ++byteCounter; + } + 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; + return 1; +} + +int JBIG2MMRDecoder::getBlackCode() { + CCITTCode *p; + Guint code; + + if (bufLen == 0) { + buf = str->getChar() & 0xff; + bufLen = 8; + ++nBytesRead; + ++byteCounter; + } + while (1) { + 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 >= 7 && ((buf >> (bufLen - 4)) & 0x0f) == 0 && + ((buf >> (bufLen - 6)) & 0x03) != 0) { + if (bufLen <= 12) { + code = buf << (12 - bufLen); + } else { + code = buf >> (bufLen - 12); + } + p = &blackTab2[(code & 0xff) - 64]; + } else { + if (bufLen <= 6) { + code = buf << (6 - bufLen); + } else { + code = buf >> (bufLen - 6); + } + p = &blackTab3[code & 0x3f]; + } + if (p->bits > 0 && p->bits <= (int)bufLen) { + bufLen -= p->bits; + return p->n; + } + if (bufLen >= 13) { + break; + } + buf = (buf << 8) | (str->getChar() & 0xff); + bufLen += 8; + ++nBytesRead; + ++byteCounter; + } + 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; + return 1; +} + +Guint JBIG2MMRDecoder::get24Bits() { + while (bufLen < 24) { + buf = (buf << 8) | (str->getChar() & 0xff); + bufLen += 8; + ++nBytesRead; + ++byteCounter; + } + return (buf >> (bufLen - 24)) & 0xffffff; +} + +void JBIG2MMRDecoder::skipTo(Guint length) { + int n; + + n = str->discardChars(length - nBytesRead); + nBytesRead += n; + byteCounter += n; +} + +//------------------------------------------------------------------------ +// JBIG2Segment +//------------------------------------------------------------------------ + +enum JBIG2SegmentType { + jbig2SegBitmap, + jbig2SegSymbolDict, + jbig2SegPatternDict, + jbig2SegCodeTable +}; + +class JBIG2Segment { +public: + + JBIG2Segment(Guint segNumA) { segNum = segNumA; } + virtual ~JBIG2Segment() {} + void setSegNum(Guint segNumA) { segNum = segNumA; } + Guint getSegNum() { return segNum; } + virtual JBIG2SegmentType getType() = 0; + +private: + + Guint segNum; +}; + +//------------------------------------------------------------------------ +// JBIG2Bitmap +//------------------------------------------------------------------------ + +struct JBIG2BitmapPtr { + Guchar *p; + int shift; + int x; +}; + +class JBIG2Bitmap: public JBIG2Segment { +public: + + JBIG2Bitmap(Guint segNumA, int wA, int hA); + virtual ~JBIG2Bitmap(); + virtual JBIG2SegmentType getType() { return jbig2SegBitmap; } + JBIG2Bitmap *copy() { return new JBIG2Bitmap(0, this); } + JBIG2Bitmap *getSlice(Guint x, Guint y, Guint wA, Guint hA); + void expand(int newH, Guint pixel); + void clearToZero(); + 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; } + void setPixel(int x, int y) + { data[y * line + (x >> 3)] |= (Guchar)(1 << (7 - (x & 7))); } + void clearPixel(int x, int y) + { data[y * line + (x >> 3)] &= (Guchar)(0x7f7f >> (x & 7)); } + void getPixelPtr(int x, int y, JBIG2BitmapPtr *ptr); + int nextPixel(JBIG2BitmapPtr *ptr); + void duplicateRow(int yDest, int ySrc); + void combine(JBIG2Bitmap *bitmap, int x, int y, Guint combOp); + Guchar *getDataPtr() { return data; } + int getDataSize() { return h * line; } + +private: + + JBIG2Bitmap(Guint segNumA, JBIG2Bitmap *bitmap); + + int w, h, line; + Guchar *data; +}; + +JBIG2Bitmap::JBIG2Bitmap(Guint segNumA, int wA, int hA): + JBIG2Segment(segNumA) +{ + w = wA; + h = hA; + line = (wA + 7) >> 3; + if (w <= 0 || h <= 0 || line <= 0 || h >= (INT_MAX - 1) / line) { + // 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); + data[h * line] = 0; +} + +JBIG2Bitmap::JBIG2Bitmap(Guint segNumA, JBIG2Bitmap *bitmap): + JBIG2Segment(segNumA) +{ + w = bitmap->w; + h = bitmap->h; + line = bitmap->line; + if (w <= 0 || h <= 0 || line <= 0 || h >= (INT_MAX - 1) / line) { + // 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); + memcpy(data, bitmap->data, h * line); + data[h * line] = 0; +} + +JBIG2Bitmap::~JBIG2Bitmap() { + gfree(data); +} + +//~ optimize this +JBIG2Bitmap *JBIG2Bitmap::getSlice(Guint x, Guint y, Guint wA, Guint hA) { + JBIG2Bitmap *slice; + Guint xx, yy; + + slice = new JBIG2Bitmap(0, wA, hA); + slice->clearToZero(); + for (yy = 0; yy < hA; ++yy) { + for (xx = 0; xx < wA; ++xx) { + if (getPixel(x + xx, y + yy)) { + slice->setPixel(xx, yy); + } + } + } + return slice; +} + +void JBIG2Bitmap::expand(int newH, Guint pixel) { + if (newH <= h || line <= 0 || newH >= (INT_MAX - 1) / line) { + return; + } + // need to allocate one extra guard byte for use in combine() + data = (Guchar *)grealloc(data, newH * line + 1); + if (pixel) { + memset(data + h * line, 0xff, (newH - h) * line); + } else { + memset(data + h * line, 0x00, (newH - h) * line); + } + h = newH; + data[h * line] = 0; +} + +void JBIG2Bitmap::clearToZero() { + memset(data, 0, h * line); +} + +void JBIG2Bitmap::clearToOne() { + memset(data, 0xff, h * line); +} + +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; + ptr->x = x; + } else { + ptr->p = &data[y * line + (x >> 3)]; + ptr->shift = 7 - (x & 7); + ptr->x = x; + } +} + +inline int JBIG2Bitmap::nextPixel(JBIG2BitmapPtr *ptr) { + int pix; + + if (!ptr->p) { + pix = 0; + } else if (ptr->x < 0) { + ++ptr->x; + pix = 0; + } else { + pix = (*ptr->p >> ptr->shift) & 1; + if (++ptr->x == w) { + ptr->p = NULL; + } else if (ptr->shift == 0) { + ++ptr->p; + ptr->shift = 7; + } else { + --ptr->shift; + } + } + return pix; +} + +void JBIG2Bitmap::duplicateRow(int yDest, int ySrc) { + memcpy(data + yDest * line, data + ySrc * line, line); +} + +void JBIG2Bitmap::combine(JBIG2Bitmap *bitmap, int x, int y, + Guint combOp) { + int x0, x1, y0, y1, xx, yy; + Guchar *srcPtr, *destPtr; + Guchar dest, src0, src1, src, m1, m2, m3; + Guint s1, s2; + GBool oneByte; + + // check for the pathological case where y = -2^31 + if (y < -0x7fffffff) { + return; + } + if (y < 0) { + y0 = -y; + } else { + y0 = 0; + } + if (y > INT_MAX - bitmap->h) { + return; + } + if (y + bitmap->h > h) { + y1 = h - y; + } else { + y1 = bitmap->h; + } + if (y0 >= y1) { + return; + } + + if (x >= 0) { + x0 = x & ~7; + } else { + x0 = 0; + } + x1 = x + bitmap->w; + if (x1 > w) { + x1 = w; + } + if (x0 >= x1) { + return; + } + + s1 = x & 7; + s2 = 8 - s1; + m1 = (Guchar)(0xff >> (x1 & 7)); + m2 = (Guchar)(0xff << (((x1 & 7) == 0) ? 0 : 8 - (x1 & 7))); + m3 = (Guchar)((0xff >> s1) & m2); + + oneByte = x0 == ((x1 - 1) & ~7); + + for (yy = y0; yy < y1; ++yy) { + + // one byte per line -- need to mask both left and right side + if (oneByte) { + if (x >= 0) { + destPtr = data + (y + yy) * line + (x >> 3); + srcPtr = bitmap->data + yy * bitmap->line; + dest = *destPtr; + src1 = *srcPtr; + switch (combOp) { + case 0: // or + dest |= (Guchar)((src1 >> s1) & m2); + break; + case 1: // and + dest &= (Guchar)(((0xff00 | src1) >> s1) | m1); + break; + case 2: // xor + dest ^= (Guchar)((src1 >> s1) & m2); + break; + case 3: // xnor + dest ^= (Guchar)(((src1 ^ 0xff) >> s1) & m2); + break; + case 4: // replace + dest = (Guchar)((dest & ~m3) | ((src1 >> s1) & m3)); + break; + } + *destPtr = dest; + } else { + destPtr = data + (y + yy) * line; + srcPtr = bitmap->data + yy * bitmap->line + (-x >> 3); + dest = *destPtr; + src1 = *srcPtr; + switch (combOp) { + case 0: // or + dest |= src1 & m2; + break; + case 1: // and + dest &= src1 | m1; + break; + case 2: // xor + dest ^= src1 & m2; + break; + case 3: // xnor + dest ^= (src1 ^ 0xff) & m2; + break; + case 4: // replace + dest = (src1 & m2) | (dest & m1); + break; + } + *destPtr = dest; + } + + // multiple bytes per line -- need to mask left side of left-most + // byte and right side of right-most byte + } else { + + // left-most byte + if (x >= 0) { + destPtr = data + (y + yy) * line + (x >> 3); + srcPtr = bitmap->data + yy * bitmap->line; + src1 = *srcPtr++; + dest = *destPtr; + switch (combOp) { + case 0: // or + dest |= (Guchar)(src1 >> s1); + break; + case 1: // and + dest &= (Guchar)((0xff00 | src1) >> s1); + break; + case 2: // xor + dest ^= (Guchar)(src1 >> s1); + break; + case 3: // xnor + dest ^= (Guchar)((src1 ^ 0xff) >> s1); + break; + case 4: // replace + dest = (Guchar)((dest & (0xff << s2)) | (src1 >> s1)); + break; + } + *destPtr++ = dest; + xx = x0 + 8; + } else { + destPtr = data + (y + yy) * line; + srcPtr = bitmap->data + yy * bitmap->line + (-x >> 3); + src1 = *srcPtr++; + xx = x0; + } + + // middle bytes + for (; xx < x1 - 8; xx += 8) { + dest = *destPtr; + src0 = src1; + src1 = *srcPtr++; + src = (Guchar)(((src0 << 8) | src1) >> s1); + switch (combOp) { + case 0: // or + dest |= src; + break; + case 1: // and + dest &= src; + break; + case 2: // xor + dest ^= src; + break; + case 3: // xnor + dest ^= src ^ 0xff; + break; + case 4: // replace + dest = src; + break; + } + *destPtr++ = dest; + } + + // right-most byte + // note: this last byte (src1) may not actually be used, depending + // on the values of s1, m1, and m2 - and in fact, it may be off + // the edge of the source bitmap, which means we need to allocate + // one extra guard byte at the end of each bitmap + dest = *destPtr; + src0 = src1; + src1 = *srcPtr++; + src = (Guchar)(((src0 << 8) | src1) >> s1); + switch (combOp) { + case 0: // or + dest |= src & m2; + break; + case 1: // and + dest &= src | m1; + break; + case 2: // xor + dest ^= src & m2; + break; + case 3: // xnor + dest ^= (src ^ 0xff) & m2; + break; + case 4: // replace + dest = (src & m2) | (dest & m1); + break; + } + *destPtr = dest; + } + } +} + +//------------------------------------------------------------------------ +// JBIG2SymbolDict +//------------------------------------------------------------------------ + +class JBIG2SymbolDict: public JBIG2Segment { +public: + + JBIG2SymbolDict(Guint segNumA, Guint sizeA); + virtual ~JBIG2SymbolDict(); + virtual JBIG2SegmentType getType() { return jbig2SegSymbolDict; } + Guint getSize() { return size; } + void setBitmap(Guint idx, JBIG2Bitmap *bitmap) { bitmaps[idx] = bitmap; } + JBIG2Bitmap *getBitmap(Guint idx) { return bitmaps[idx]; } + void setGenericRegionStats(JArithmeticDecoderStats *stats) + { genericRegionStats = stats; } + void setRefinementRegionStats(JArithmeticDecoderStats *stats) + { refinementRegionStats = stats; } + JArithmeticDecoderStats *getGenericRegionStats() + { return genericRegionStats; } + JArithmeticDecoderStats *getRefinementRegionStats() + { return refinementRegionStats; } + +private: + + Guint size; + JBIG2Bitmap **bitmaps; + JArithmeticDecoderStats *genericRegionStats; + JArithmeticDecoderStats *refinementRegionStats; +}; + +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; +} + +JBIG2SymbolDict::~JBIG2SymbolDict() { + Guint i; + + for (i = 0; i < size; ++i) { + if (bitmaps[i]) { + delete bitmaps[i]; + } + } + gfree(bitmaps); + if (genericRegionStats) { + delete genericRegionStats; + } + if (refinementRegionStats) { + delete refinementRegionStats; + } +} + +//------------------------------------------------------------------------ +// JBIG2PatternDict +//------------------------------------------------------------------------ + +class JBIG2PatternDict: public JBIG2Segment { +public: + + JBIG2PatternDict(Guint segNumA, Guint sizeA); + virtual ~JBIG2PatternDict(); + virtual JBIG2SegmentType getType() { return jbig2SegPatternDict; } + Guint getSize() { return size; } + void setBitmap(Guint idx, JBIG2Bitmap *bitmap) { bitmaps[idx] = bitmap; } + JBIG2Bitmap *getBitmap(Guint idx) { return bitmaps[idx]; } + +private: + + Guint size; + JBIG2Bitmap **bitmaps; +}; + +JBIG2PatternDict::JBIG2PatternDict(Guint segNumA, Guint sizeA): + JBIG2Segment(segNumA) +{ + size = sizeA; + bitmaps = (JBIG2Bitmap **)gmallocn(size, sizeof(JBIG2Bitmap *)); +} + +JBIG2PatternDict::~JBIG2PatternDict() { + Guint i; + + for (i = 0; i < size; ++i) { + delete bitmaps[i]; + } + gfree(bitmaps); +} + +//------------------------------------------------------------------------ +// JBIG2CodeTable +//------------------------------------------------------------------------ + +class JBIG2CodeTable: public JBIG2Segment { +public: + + JBIG2CodeTable(Guint segNumA, JBIG2HuffmanTable *tableA); + virtual ~JBIG2CodeTable(); + virtual JBIG2SegmentType getType() { return jbig2SegCodeTable; } + JBIG2HuffmanTable *getHuffTable() { return table; } + +private: + + JBIG2HuffmanTable *table; +}; + +JBIG2CodeTable::JBIG2CodeTable(Guint segNumA, JBIG2HuffmanTable *tableA): + JBIG2Segment(segNumA) +{ + table = tableA; +} + +JBIG2CodeTable::~JBIG2CodeTable() { + gfree(table); +} + +//------------------------------------------------------------------------ +// JBIG2Stream +//------------------------------------------------------------------------ + +JBIG2Stream::JBIG2Stream(Stream *strA, Object *globalsStreamA): + FilterStream(strA) +{ + decoded = gFalse; + pageBitmap = NULL; + + arithDecoder = new JArithmeticDecoder(); + genericRegionStats = new JArithmeticDecoderStats(1 << 1); + refinementRegionStats = new JArithmeticDecoderStats(1 << 1); + iadhStats = new JArithmeticDecoderStats(1 << 9); + iadwStats = new JArithmeticDecoderStats(1 << 9); + iaexStats = new JArithmeticDecoderStats(1 << 9); + iaaiStats = new JArithmeticDecoderStats(1 << 9); + iadtStats = new JArithmeticDecoderStats(1 << 9); + iaitStats = new JArithmeticDecoderStats(1 << 9); + iafsStats = new JArithmeticDecoderStats(1 << 9); + iadsStats = new JArithmeticDecoderStats(1 << 9); + iardxStats = new JArithmeticDecoderStats(1 << 9); + iardyStats = new JArithmeticDecoderStats(1 << 9); + iardwStats = new JArithmeticDecoderStats(1 << 9); + iardhStats = new JArithmeticDecoderStats(1 << 9); + iariStats = new JArithmeticDecoderStats(1 << 9); + iaidStats = new JArithmeticDecoderStats(1 << 1); + huffDecoder = new JBIG2HuffmanDecoder(); + mmrDecoder = new JBIG2MMRDecoder(); + + globalsStreamA->copy(&globalsStream); + segments = globalSegments = NULL; + curStr = NULL; + dataPtr = dataEnd = NULL; +} + +JBIG2Stream::~JBIG2Stream() { + close(); + globalsStream.free(); + delete arithDecoder; + delete genericRegionStats; + delete refinementRegionStats; + delete iadhStats; + delete iadwStats; + delete iaexStats; + delete iaaiStats; + delete iadtStats; + delete iaitStats; + delete iafsStats; + delete iadsStats; + delete iardxStats; + delete iardyStats; + delete iardwStats; + delete iardhStats; + delete iariStats; + delete iaidStats; + delete huffDecoder; + delete mmrDecoder; + delete str; +} + +Stream *JBIG2Stream::copy() { + return new JBIG2Stream(str->copy(), &globalsStream); +} + +void JBIG2Stream::reset() { + segments = new GList(); + globalSegments = new GList(); + decoded = gFalse; +} + +void JBIG2Stream::close() { + if (pageBitmap) { + delete pageBitmap; + pageBitmap = NULL; + } + if (segments) { + deleteGList(segments, JBIG2Segment); + segments = NULL; + } + if (globalSegments) { + deleteGList(globalSegments, JBIG2Segment); + globalSegments = NULL; + } + dataPtr = dataEnd = NULL; + FilterStream::close(); +} + +int JBIG2Stream::getChar() { + if (!decoded) { + decodeImage(); + } + if (dataPtr && dataPtr < dataEnd) { + return (*dataPtr++ ^ 0xff) & 0xff; + } + return EOF; +} + +int JBIG2Stream::lookChar() { + if (!decoded) { + decodeImage(); + } + if (dataPtr && dataPtr < dataEnd) { + return (*dataPtr ^ 0xff) & 0xff; + } + return EOF; +} + +int JBIG2Stream::getBlock(char *blk, int size) { + int n, i; + + if (!decoded) { + decodeImage(); + } + 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, + GBool okToReadStream) { + return NULL; +} + +GBool JBIG2Stream::isBinary(GBool last) { + return str->isBinary(gTrue); +} + +void JBIG2Stream::decodeImage() { + GList *t; + + // read the globals stream + if (globalsStream.isStream()) { + curStr = globalsStream.getStream(); + curStr->reset(); + arithDecoder->setStream(curStr); + huffDecoder->setStream(curStr); + mmrDecoder->setStream(curStr); + readSegments(); + curStr->close(); + // swap the newly read segments list into globalSegments + t = segments; + segments = globalSegments; + globalSegments = t; + } + + // read the main stream + curStr = str; + curStr->reset(); + arithDecoder->setStream(curStr); + huffDecoder->setStream(curStr); + mmrDecoder->setStream(curStr); + readSegments(); + + if (pageBitmap) { + dataPtr = pageBitmap->getDataPtr(); + dataEnd = dataPtr + pageBitmap->getDataSize(); + } else { + dataPtr = dataEnd = NULL; + } + + decoded = gTrue; +} + +void JBIG2Stream::readSegments() { + Guint segNum, segFlags, segType, page, segLength; + Guint refFlags, nRefSegs; + Guint *refSegs; + int c1, c2, c3; + Guint i; + + done = gFalse; + while (!done && readULong(&segNum)) { + + // segment header flags + if (!readUByte(&segFlags)) { + goto eofError1; + } + segType = segFlags & 0x3f; + + // referred-to segment count and retention flags + if (!readUByte(&refFlags)) { + goto eofError1; + } + nRefSegs = refFlags >> 5; + if (nRefSegs == 7) { + if ((c1 = curStr->getChar()) == EOF || + (c2 = curStr->getChar()) == EOF || + (c3 = curStr->getChar()) == EOF) { + goto eofError1; + } + refFlags = (refFlags << 24) | (c1 << 16) | (c2 << 8) | c3; + nRefSegs = refFlags & 0x1fffffff; + i = (nRefSegs + 9) >> 3; + if (curStr->discardChars(i) != i) { + goto eofError1; + } + } + + // referred-to segment numbers + refSegs = (Guint *)gmallocn(nRefSegs, sizeof(Guint)); + if (segNum <= 256) { + for (i = 0; i < nRefSegs; ++i) { + if (!readUByte(&refSegs[i])) { + goto eofError2; + } + } + } else if (segNum <= 65536) { + for (i = 0; i < nRefSegs; ++i) { + if (!readUWord(&refSegs[i])) { + goto eofError2; + } + } + } else { + for (i = 0; i < nRefSegs; ++i) { + if (!readULong(&refSegs[i])) { + goto eofError2; + } + } + } + + // segment page association + if (segFlags & 0x40) { + if (!readULong(&page)) { + goto eofError2; + } + } else { + if (!readUByte(&page)) { + goto eofError2; + } + } + + // segment data length + if (!readULong(&segLength)) { + 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)) { + goto syntaxError; + } + break; + case 4: + readTextRegionSeg(segNum, gFalse, gFalse, segLength, refSegs, nRefSegs); + break; + case 6: + readTextRegionSeg(segNum, gTrue, gFalse, segLength, refSegs, nRefSegs); + break; + case 7: + readTextRegionSeg(segNum, gTrue, gTrue, segLength, refSegs, nRefSegs); + break; + case 16: + readPatternDictSeg(segNum, segLength); + break; + case 20: + readHalftoneRegionSeg(segNum, gFalse, gFalse, segLength, + refSegs, nRefSegs); + break; + case 22: + readHalftoneRegionSeg(segNum, gTrue, gFalse, segLength, + refSegs, nRefSegs); + break; + case 23: + readHalftoneRegionSeg(segNum, gTrue, gTrue, segLength, + refSegs, nRefSegs); + break; + case 36: + readGenericRegionSeg(segNum, gFalse, gFalse, segLength); + break; + case 38: + readGenericRegionSeg(segNum, gTrue, gFalse, segLength); + break; + case 39: + readGenericRegionSeg(segNum, gTrue, gTrue, segLength); + break; + case 40: + readGenericRefinementRegionSeg(segNum, gFalse, gFalse, segLength, + refSegs, nRefSegs); + break; + case 42: + readGenericRefinementRegionSeg(segNum, gTrue, gFalse, segLength, + refSegs, nRefSegs); + break; + case 43: + readGenericRefinementRegionSeg(segNum, gTrue, gTrue, segLength, + refSegs, nRefSegs); + break; + case 48: + readPageInfoSeg(segLength); + break; + case 50: + readEndOfStripeSeg(segLength); + break; + case 51: + // end of file segment + done = gTrue; + break; + case 52: + readProfilesSeg(segLength); + break; + case 53: + readCodeTableSeg(segNum, segLength); + break; + case 62: + readExtensionSeg(segLength); + break; + default: + error(errSyntaxError, getPos(), "Unknown segment type in JBIG2 stream"); + if (curStr->discardChars(segLength) != segLength) { + goto eofError2; + } + 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; + } + byteCounter += curStr->discardChars(segLength - byteCounter); + } + + gfree(refSegs); + } + + return; + + syntaxError: + gfree(refSegs); + return; + + eofError2: + gfree(refSegs); + eofError1: + error(errSyntaxError, getPos(), "Unexpected EOF in JBIG2 stream"); +} + +GBool JBIG2Stream::readSymbolDictSeg(Guint segNum, Guint length, + Guint *refSegs, Guint nRefSegs) { + JBIG2SymbolDict *symbolDict; + JBIG2HuffmanTable *huffDHTable, *huffDWTable; + JBIG2HuffmanTable *huffBMSizeTable, *huffAggInstTable; + JBIG2Segment *seg; + GList *codeTables; + JBIG2SymbolDict *inputSymbolDict; + Guint flags, sdTemplate, sdrTemplate, huff, refAgg; + Guint huffDH, huffDW, huffBMSize, huffAggInst; + Guint contextUsed, contextRetained; + int sdATX[4], sdATY[4], sdrATX[2], sdrATY[2]; + Guint numExSyms, numNewSyms, numInputSyms, symCodeLen; + JBIG2Bitmap **bitmaps; + JBIG2Bitmap *collBitmap, *refBitmap; + Guint *symWidths; + Guint symHeight, symWidth, totalWidth, x, symID; + int dh, dw, refAggNum, refDX, refDY, bmSize; + GBool ex; + int run, prevRun, cnt; + Guint i, j, k; + + symWidths = NULL; + + // symbol dictionary flags + if (!readUWord(&flags)) { + goto eofError; + } + sdTemplate = (flags >> 10) & 3; + sdrTemplate = (flags >> 12) & 1; + huff = flags & 1; + refAgg = (flags >> 1) & 1; + huffDH = (flags >> 2) & 3; + huffDW = (flags >> 4) & 3; + huffBMSize = (flags >> 6) & 1; + huffAggInst = (flags >> 7) & 1; + contextUsed = (flags >> 8) & 1; + contextRetained = (flags >> 9) & 1; + + // symbol dictionary AT flags + if (!huff) { + if (sdTemplate == 0) { + if (!readByte(&sdATX[0]) || + !readByte(&sdATY[0]) || + !readByte(&sdATX[1]) || + !readByte(&sdATY[1]) || + !readByte(&sdATX[2]) || + !readByte(&sdATY[2]) || + !readByte(&sdATX[3]) || + !readByte(&sdATY[3])) { + goto eofError; + } + } else { + if (!readByte(&sdATX[0]) || + !readByte(&sdATY[0])) { + goto eofError; + } + } + } + + // symbol dictionary refinement AT flags + if (refAgg && !sdrTemplate) { + if (!readByte(&sdrATX[0]) || + !readByte(&sdrATY[0]) || + !readByte(&sdrATX[1]) || + !readByte(&sdrATY[1])) { + goto eofError; + } + } + + // SDNUMEXSYMS and SDNUMNEWSYMS + if (!readULong(&numExSyms) || !readULong(&numNewSyms)) { + goto eofError; + } + + // get referenced segments: input symbol dictionaries and code tables + codeTables = new GList(); + numInputSyms = 0; + for (i = 0; i < nRefSegs; ++i) { + if ((seg = findSegment(refSegs[i]))) { + if (seg->getType() == jbig2SegSymbolDict) { + j = ((JBIG2SymbolDict *)seg)->getSize(); + if (j > INT_MAX || numInputSyms > INT_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 (numNewSyms > INT_MAX || numInputSyms > INT_MAX - numNewSyms) { + error(errSyntaxError, getPos(), + "Too many input symbols in JBIG2 symbol dictionary"); + delete codeTables; + goto eofError; + } + + // compute symbol code length + 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 + bitmaps = (JBIG2Bitmap **)gmallocn(numInputSyms + numNewSyms, + sizeof(JBIG2Bitmap *)); + for (i = 0; i < numInputSyms + numNewSyms; ++i) { + bitmaps[i] = NULL; + } + k = 0; + inputSymbolDict = NULL; + for (i = 0; i < nRefSegs; ++i) { + if ((seg = findSegment(refSegs[i]))) { + if (seg->getType() == jbig2SegSymbolDict) { + inputSymbolDict = (JBIG2SymbolDict *)seg; + for (j = 0; j < inputSymbolDict->getSize(); ++j) { + bitmaps[k++] = inputSymbolDict->getBitmap(j); + } + } + } + } + + // get the Huffman tables + huffDHTable = huffDWTable = NULL; // make gcc happy + huffBMSizeTable = huffAggInstTable = NULL; // make gcc happy + i = 0; + if (huff) { + if (huffDH == 0) { + huffDHTable = huffTableD; + } else if (huffDH == 1) { + huffDHTable = huffTableE; + } else { + if (i >= (Guint)codeTables->getLength()) { + goto codeTableError; + } + huffDHTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable(); + } + if (huffDW == 0) { + huffDWTable = huffTableB; + } 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(); + } + } + delete codeTables; + + // set up the Huffman decoder + if (huff) { + huffDecoder->reset(); + + // set up the arithmetic decoder + } else { + if (contextUsed && inputSymbolDict) { + resetGenericStats(sdTemplate, inputSymbolDict->getGenericRegionStats()); + } else { + resetGenericStats(sdTemplate, NULL); + } + resetIntStats(symCodeLen); + arithDecoder->start(); + } + + // set up the arithmetic decoder for refinement/aggregation + if (refAgg) { + if (contextUsed && inputSymbolDict) { + resetRefinementStats(sdrTemplate, + inputSymbolDict->getRefinementRegionStats()); + } else { + resetRefinementStats(sdrTemplate, NULL); + } + } + + // allocate symbol widths storage + if (huff && !refAgg) { + symWidths = (Guint *)gmallocn(numNewSyms, sizeof(Guint)); + } + + symHeight = 0; + i = 0; + while (i < numNewSyms) { + + // read the height class delta height + if (huff) { + huffDecoder->decodeInt(&dh, huffDHTable); + } else { + arithDecoder->decodeInt(&dh, iadhStats); + } + if ((dh <= 0 && (Guint)-dh >= symHeight) || + (dh > 0 && (Guint)dh > UINT_MAX - symHeight)) { + error(errSyntaxError, getPos(), + "Bad delta-height value in JBIG2 symbol dictionary"); + goto syntaxError; + } + symHeight += dh; + symWidth = 0; + totalWidth = 0; + j = i; + + // sanity check to avoid extremely long run-times with damaged streams + if (symHeight > 100000) { + error(errSyntaxError, getPos(), + "Bogus symbol height value in JBIG2 symbol dictionary"); + goto syntaxError; + } + + // read the symbols in this height class + while (1) { + + // read the delta width + if (huff) { + if (!huffDecoder->decodeInt(&dw, huffDWTable)) { + break; + } + } else { + if (!arithDecoder->decodeInt(&dw, iadwStats)) { + break; + } + } + if ((dw <= 0 && (Guint)-dw >= symWidth) || + (dw > 0 && (Guint)dw > UINT_MAX - symWidth)) { + 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; + } + + // sanity check to avoid extremely long run-times with damaged streams + if (symWidth > 100000) { + error(errSyntaxError, getPos(), + "Bogus symbol width value in JBIG2 symbol dictionary"); + goto syntaxError; + } + + // using a collective bitmap, so don't read a bitmap here + if (huff && !refAgg) { + symWidths[i] = symWidth; + totalWidth += symWidth; + + // refinement/aggregate coding + } else if (refAgg) { + if (huff) { + if (!huffDecoder->decodeInt(&refAggNum, huffAggInstTable)) { + break; + } + } else { + if (!arithDecoder->decodeInt(&refAggNum, iaaiStats)) { + break; + } + } +#if 0 //~ This special case was added about a year before the final draft + //~ of the JBIG2 spec was released. I have encountered some old + //~ JBIG2 images that predate it. + if (0) { +#else + if (refAggNum == 1) { +#endif + if (huff) { + symID = huffDecoder->readBits(symCodeLen); + huffDecoder->decodeInt(&refDX, huffTableO); + huffDecoder->decodeInt(&refDY, huffTableO); + huffDecoder->decodeInt(&bmSize, huffTableA); + huffDecoder->reset(); + arithDecoder->start(); + } else { + symID = arithDecoder->decodeIAID(symCodeLen, iaidStats); + 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, + sdrTemplate, gFalse, + refBitmap, refDX, refDY, + sdrATX, sdrATY); + //~ do we need to use the bmSize value here (in Huffman mode)? + } else { + bitmaps[numInputSyms + i] = + readTextRegion(huff, gTrue, symWidth, symHeight, + refAggNum, 0, numInputSyms + i, NULL, + symCodeLen, bitmaps, 0, 0, 0, 1, 0, + huffTableF, huffTableH, huffTableK, huffTableO, + huffTableO, huffTableO, huffTableO, huffTableA, + sdrTemplate, sdrATX, sdrATY); + } + + // non-ref/agg coding + } else { + bitmaps[numInputSyms + i] = + readGenericBitmap(gFalse, symWidth, symHeight, + sdTemplate, gFalse, gFalse, NULL, + sdATX, sdATY, 0); + } + + ++i; + } + + // read the collective bitmap + if (huff && !refAgg) { + if (totalWidth == 0) { + error(errSyntaxError, getPos(), + "Invalid height class width in JBIG2 symbol dictionary"); + goto syntaxError; + } + huffDecoder->decodeInt(&bmSize, huffBMSizeTable); + huffDecoder->reset(); + if (bmSize == 0) { + collBitmap = new JBIG2Bitmap(0, totalWidth, symHeight); + bmSize = symHeight * ((totalWidth + 7) >> 3); + byteCounter += curStr->getBlock((char *)collBitmap->getDataPtr(), + bmSize); + } else { + collBitmap = readGenericBitmap(gTrue, totalWidth, symHeight, + 0, gFalse, gFalse, NULL, NULL, NULL, + bmSize); + } + x = 0; + for (; j < i; ++j) { + bitmaps[numInputSyms + j] = + collBitmap->getSlice(x, 0, symWidths[j], symHeight); + x += symWidths[j]; + } + delete collBitmap; + } + } + + // create the symbol dict object + symbolDict = new JBIG2SymbolDict(segNum, numExSyms); + + // exported symbol list + i = j = 0; + ex = gFalse; + prevRun = 1; + while (i < numInputSyms + numNewSyms) { + if (huff) { + huffDecoder->decodeInt(&run, huffTableA); + } else { + arithDecoder->decodeInt(&run, iaexStats); + } + if (run == 0 && prevRun == 0) { + // this avoids infinite loops with damaged files (consecutive + // zero runs are never useful) + error(errSyntaxError, getPos(), + "Invalid exported symbol list in JBIG2 symbol dictionary"); + delete symbolDict; + goto syntaxError; + } + 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()); + } + } else { + i += run; + } + ex = !ex; + prevRun = run; + } + 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]; + } + gfree(bitmaps); + if (symWidths) { + gfree(symWidths); + } + + // save the arithmetic decoder stats + if (!huff && contextRetained) { + symbolDict->setGenericRegionStats(genericRegionStats->copy()); + if (refAgg) { + symbolDict->setRefinementRegionStats(refinementRegionStats->copy()); + } + } + + // store the new symbol dict + segments->append(symbolDict); + + 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]) { + delete bitmaps[numInputSyms + i]; + } + } + gfree(bitmaps); + if (symWidths) { + gfree(symWidths); + } + return gFalse; + + eofError: + error(errSyntaxError, getPos(), "Unexpected EOF in JBIG2 stream"); + return gFalse; +} + +void JBIG2Stream::readTextRegionSeg(Guint segNum, GBool imm, + GBool lossless, Guint length, + Guint *refSegs, Guint nRefSegs) { + JBIG2Bitmap *bitmap; + JBIG2HuffmanTable runLengthTab[36]; + JBIG2HuffmanTable *symCodeTab; + JBIG2HuffmanTable *huffFSTable, *huffDSTable, *huffDTTable; + JBIG2HuffmanTable *huffRDWTable, *huffRDHTable; + JBIG2HuffmanTable *huffRDXTable, *huffRDYTable, *huffRSizeTable; + JBIG2Segment *seg; + GList *codeTables; + JBIG2SymbolDict *symbolDict; + JBIG2Bitmap **syms; + Guint w, h, x, y, segInfoFlags, extCombOp; + Guint flags, huff, refine, logStrips, refCorner, transposed; + Guint combOp, defPixel, templ; + int sOffset; + Guint huffFlags, huffFS, huffDS, huffDT; + Guint huffRDW, huffRDH, huffRDX, huffRDY, huffRSize; + Guint numInstances, numSyms, symCodeLen; + int atx[2], aty[2]; + Guint i, k, kk; + int j; + + // region segment info field + if (!readULong(&w) || !readULong(&h) || + !readULong(&x) || !readULong(&y) || + !readUByte(&segInfoFlags)) { + goto eofError; + } + if (w == 0 || h == 0) { + error(errSyntaxError, getPos(), "Bad size in JBIG2 text region segment"); + return; + } + // sanity check: if the w/h/x/y values are way out of range, it likely + // indicates a damaged JBIG2 stream + if (w / 10 > pageW || h / 10 > pageH || + x / 10 > pageW || y / 10 > pageH) { + error(errSyntaxError, getPos(), + "Bad size or position in JBIG2 text region segment"); + done = gTrue; + return; + } + extCombOp = segInfoFlags & 7; + + // rest of the text region header + if (!readUWord(&flags)) { + goto eofError; + } + huff = flags & 1; + refine = (flags >> 1) & 1; + logStrips = (flags >> 2) & 3; + refCorner = (flags >> 4) & 3; + transposed = (flags >> 6) & 1; + combOp = (flags >> 7) & 3; + defPixel = (flags >> 9) & 1; + sOffset = (flags >> 10) & 0x1f; + if (sOffset & 0x10) { + sOffset |= -1 - 0x0f; + } + templ = (flags >> 15) & 1; + huffFS = huffDS = huffDT = 0; // make gcc happy + huffRDW = huffRDH = huffRDX = huffRDY = huffRSize = 0; // make gcc happy + if (huff) { + if (!readUWord(&huffFlags)) { + goto eofError; + } + huffFS = huffFlags & 3; + huffDS = (huffFlags >> 2) & 3; + huffDT = (huffFlags >> 4) & 3; + huffRDW = (huffFlags >> 6) & 3; + huffRDH = (huffFlags >> 8) & 3; + huffRDX = (huffFlags >> 10) & 3; + huffRDY = (huffFlags >> 12) & 3; + huffRSize = (huffFlags >> 14) & 1; + } + if (refine && templ == 0) { + if (!readByte(&atx[0]) || !readByte(&aty[0]) || + !readByte(&atx[1]) || !readByte(&aty[1])) { + goto eofError; + } + } + if (!readULong(&numInstances)) { + goto eofError; + } + + // get symbol dictionaries and tables + codeTables = new GList(); + numSyms = 0; + for (i = 0; i < nRefSegs; ++i) { + if ((seg = findSegment(refSegs[i]))) { + if (seg->getType() == jbig2SegSymbolDict) { + Guint segSize = ((JBIG2SymbolDict *)seg)->getSize(); + if (segSize > INT_MAX || numSyms > INT_MAX - segSize) { + error(errSyntaxError, getPos(), + "Too many symbols in JBIG2 text region"); + delete codeTables; + return; + } + numSyms += segSize; + } else if (seg->getType() == jbig2SegCodeTable) { + codeTables->append(seg); + } + } else { + error(errSyntaxError, getPos(), + "Invalid segment reference in JBIG2 text region"); + delete codeTables; + return; + } + } + 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 + syms = (JBIG2Bitmap **)gmallocn(numSyms, sizeof(JBIG2Bitmap *)); + kk = 0; + for (i = 0; i < nRefSegs; ++i) { + if ((seg = findSegment(refSegs[i]))) { + if (seg->getType() == jbig2SegSymbolDict) { + symbolDict = (JBIG2SymbolDict *)seg; + for (k = 0; k < symbolDict->getSize(); ++k) { + syms[kk++] = symbolDict->getBitmap(k); + } + } + } + } + + // get the Huffman tables + huffFSTable = huffDSTable = huffDTTable = NULL; // make gcc happy + huffRDWTable = huffRDHTable = NULL; // make gcc happy + huffRDXTable = huffRDYTable = huffRSizeTable = NULL; // make gcc happy + i = 0; + if (huff) { + if (huffFS == 0) { + huffFSTable = huffTableF; + } else if (huffFS == 1) { + huffFSTable = huffTableG; + } else { + if (i >= (Guint)codeTables->getLength()) { + goto codeTableError; + } + huffFSTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable(); + } + if (huffDS == 0) { + huffDSTable = huffTableH; + } else if (huffDS == 1) { + huffDSTable = huffTableI; + } else if (huffDS == 2) { + huffDSTable = huffTableJ; + } else { + if (i >= (Guint)codeTables->getLength()) { + goto codeTableError; + } + huffDSTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable(); + } + if (huffDT == 0) { + huffDTTable = huffTableK; + } else if (huffDT == 1) { + huffDTTable = huffTableL; + } else if (huffDT == 2) { + huffDTTable = huffTableM; + } else { + if (i >= (Guint)codeTables->getLength()) { + goto codeTableError; + } + huffDTTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable(); + } + if (huffRDW == 0) { + huffRDWTable = huffTableN; + } else if (huffRDW == 1) { + huffRDWTable = huffTableO; + } else { + if (i >= (Guint)codeTables->getLength()) { + goto codeTableError; + } + huffRDWTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable(); + } + if (huffRDH == 0) { + huffRDHTable = huffTableN; + } else if (huffRDH == 1) { + huffRDHTable = huffTableO; + } else { + if (i >= (Guint)codeTables->getLength()) { + goto codeTableError; + } + huffRDHTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable(); + } + if (huffRDX == 0) { + huffRDXTable = huffTableN; + } else if (huffRDX == 1) { + huffRDXTable = huffTableO; + } else { + if (i >= (Guint)codeTables->getLength()) { + goto codeTableError; + } + huffRDXTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable(); + } + if (huffRDY == 0) { + huffRDYTable = huffTableN; + } 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(); + } + } + delete codeTables; + + // symbol ID Huffman decoding table + if (huff) { + huffDecoder->reset(); + for (i = 0; i < 32; ++i) { + runLengthTab[i].val = i; + runLengthTab[i].prefixLen = huffDecoder->readBits(4); + runLengthTab[i].rangeLen = 0; + runLengthTab[i].prefix = 0; + } + runLengthTab[32].val = 0x103; + runLengthTab[32].prefixLen = huffDecoder->readBits(4); + runLengthTab[32].rangeLen = 2; + runLengthTab[32].prefix = 0; + runLengthTab[33].val = 0x203; + runLengthTab[33].prefixLen = huffDecoder->readBits(4); + runLengthTab[33].rangeLen = 3; + runLengthTab[33].prefix = 0; + runLengthTab[34].val = 0x20b; + runLengthTab[34].prefixLen = huffDecoder->readBits(4); + runLengthTab[34].rangeLen = 7; + runLengthTab[34].prefix = 0; + runLengthTab[35].prefixLen = 0; + runLengthTab[35].rangeLen = jbig2HuffmanEOT; + runLengthTab[35].prefix = 0; + huffDecoder->buildTable(runLengthTab, 35); + symCodeTab = (JBIG2HuffmanTable *)gmallocn(numSyms + 1, + sizeof(JBIG2HuffmanTable)); + for (i = 0; i < numSyms; ++i) { + symCodeTab[i].val = i; + symCodeTab[i].rangeLen = 0; + } + i = 0; + while (i < numSyms) { + huffDecoder->decodeInt(&j, runLengthTab); + if (j > 0x200) { + for (j -= 0x200; j && i < numSyms; --j) { + symCodeTab[i++].prefixLen = 0; + } + } else if (j > 0x100) { + if (i == 0) { + error(errSyntaxError, getPos(), "Invalid code in JBIG2 text region"); + gfree(syms); + gfree(symCodeTab); + return; + } + for (j -= 0x100; j && i < numSyms; --j) { + symCodeTab[i].prefixLen = symCodeTab[i-1].prefixLen; + ++i; + } + } else { + symCodeTab[i++].prefixLen = j; + } + } + symCodeTab[numSyms].prefixLen = 0; + symCodeTab[numSyms].rangeLen = jbig2HuffmanEOT; + huffDecoder->buildTable(symCodeTab, numSyms); + huffDecoder->reset(); + + // set up the arithmetic decoder + } else { + symCodeTab = NULL; + resetIntStats(symCodeLen); + arithDecoder->start(); + } + if (refine) { + resetRefinementStats(templ, NULL); + } + + bitmap = readTextRegion(huff, refine, w, h, numInstances, + logStrips, numSyms, symCodeTab, symCodeLen, syms, + defPixel, combOp, transposed, refCorner, sOffset, + huffFSTable, huffDSTable, huffDTTable, + huffRDWTable, huffRDHTable, + huffRDXTable, huffRDYTable, huffRSizeTable, + templ, atx, aty); + + gfree(syms); + + // combine the region bitmap into the page bitmap + if (imm) { + if (pageH == 0xffffffff && y + h > curPageH) { + pageBitmap->expand(y + h, pageDefPixel); + } + pageBitmap->combine(bitmap, x, y, extCombOp); + delete bitmap; + + // store the region bitmap + } else { + bitmap->setSegNum(segNum); + segments->append(bitmap); + } + + // clean up the Huffman decoder + if (huff) { + gfree(symCodeTab); + } + + return; + + codeTableError: + error(errSyntaxError, getPos(), "Missing code table in JBIG2 text region"); + delete codeTables; + gfree(syms); + return; + + eofError: + error(errSyntaxError, getPos(), "Unexpected EOF in JBIG2 stream"); + return; +} + +JBIG2Bitmap *JBIG2Stream::readTextRegion(GBool huff, GBool refine, + int w, int h, + Guint numInstances, + Guint logStrips, + int numSyms, + JBIG2HuffmanTable *symCodeTab, + Guint symCodeLen, + JBIG2Bitmap **syms, + Guint defPixel, Guint combOp, + Guint transposed, Guint refCorner, + int sOffset, + JBIG2HuffmanTable *huffFSTable, + JBIG2HuffmanTable *huffDSTable, + JBIG2HuffmanTable *huffDTTable, + JBIG2HuffmanTable *huffRDWTable, + JBIG2HuffmanTable *huffRDHTable, + JBIG2HuffmanTable *huffRDXTable, + JBIG2HuffmanTable *huffRDYTable, + JBIG2HuffmanTable *huffRSizeTable, + Guint templ, + int *atx, int *aty) { + JBIG2Bitmap *bitmap; + JBIG2Bitmap *symbolBitmap; + Guint strips; + int t, dt, tt, s, ds, sFirst, j; + int rdw, rdh, rdx, rdy, ri, refDX, refDY, bmSize; + Guint symID, inst, bw, bh; + + strips = 1 << logStrips; + + // allocate the bitmap + bitmap = new JBIG2Bitmap(0, w, h); + if (defPixel) { + bitmap->clearToOne(); + } else { + bitmap->clearToZero(); + } + + // decode initial T value + if (huff) { + huffDecoder->decodeInt(&t, huffDTTable); + } else { + arithDecoder->decodeInt(&t, iadtStats); + } + t *= -(int)strips; + + inst = 0; + sFirst = 0; + while (inst < numInstances) { + + // decode delta-T + if (huff) { + if (!huffDecoder->decodeInt(&dt, huffDTTable)) { + break; + } + } else { + if (!arithDecoder->decodeInt(&dt, iadtStats)) { + break; + } + } + t += dt * strips; + + // first S value + if (huff) { + if (!huffDecoder->decodeInt(&ds, huffFSTable)) { + break; + } + } else { + if (!arithDecoder->decodeInt(&ds, iafsStats)) { + break; + } + } + sFirst += ds; + s = sFirst; + + // read the instances + // (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) { + dt = 0; + } else if (huff) { + dt = huffDecoder->readBits(logStrips); + } else { + arithDecoder->decodeInt(&dt, iaitStats); + } + tt = t + dt; + + // symbol ID + if (huff) { + if (symCodeTab) { + huffDecoder->decodeInt(&j, symCodeTab); + symID = (Guint)j; + } else { + symID = huffDecoder->readBits(symCodeLen); + } + } else { + symID = arithDecoder->decodeIAID(symCodeLen, iaidStats); + } + + if (symID >= (Guint)numSyms) { + error(errSyntaxError, getPos(), + "Invalid symbol number in JBIG2 text region"); + } else { + + // get the symbol bitmap + symbolBitmap = NULL; + if (refine) { + if (huff) { + ri = (int)huffDecoder->readBit(); + } else { + arithDecoder->decodeInt(&ri, iariStats); + } + } else { + ri = 0; + } + if (ri) { + if (huff) { + huffDecoder->decodeInt(&rdw, huffRDWTable); + huffDecoder->decodeInt(&rdh, huffRDHTable); + huffDecoder->decodeInt(&rdx, huffRDXTable); + huffDecoder->decodeInt(&rdy, huffRDYTable); + huffDecoder->decodeInt(&bmSize, huffRSizeTable); + huffDecoder->reset(); + arithDecoder->start(); + } else { + arithDecoder->decodeInt(&rdw, iardwStats); + arithDecoder->decodeInt(&rdh, iardhStats); + arithDecoder->decodeInt(&rdx, iardxStats); + arithDecoder->decodeInt(&rdy, iardyStats); + } + refDX = ((rdw >= 0) ? rdw : rdw - 1) / 2 + rdx; + refDY = ((rdh >= 0) ? rdh : rdh - 1) / 2 + rdy; + + symbolBitmap = + readGenericRefinementRegion(rdw + syms[symID]->getWidth(), + rdh + syms[symID]->getHeight(), + templ, gFalse, syms[symID], + refDX, refDY, atx, aty); + //~ do we need to use the bmSize value here (in Huffman mode)? + } else { + symbolBitmap = syms[symID]; + } + + // combine the symbol bitmap into the region bitmap + //~ something is wrong here - refCorner shouldn't degenerate into + //~ two cases + bw = symbolBitmap->getWidth() - 1; + bh = symbolBitmap->getHeight() - 1; + if (transposed) { + switch (refCorner) { + case 0: // bottom left + bitmap->combine(symbolBitmap, tt, s, combOp); + break; + case 1: // top left + bitmap->combine(symbolBitmap, tt, s, combOp); + break; + case 2: // bottom right + bitmap->combine(symbolBitmap, tt - bw, s, combOp); + break; + case 3: // top right + bitmap->combine(symbolBitmap, tt - bw, s, combOp); + break; + } + s += bh; + } else { + switch (refCorner) { + case 0: // bottom left + bitmap->combine(symbolBitmap, s, tt - bh, combOp); + break; + case 1: // top left + bitmap->combine(symbolBitmap, s, tt, combOp); + break; + case 2: // bottom right + bitmap->combine(symbolBitmap, s, tt - bh, combOp); + break; + case 3: // top right + bitmap->combine(symbolBitmap, s, tt, combOp); + break; + } + s += bw; + } + if (ri) { + delete symbolBitmap; + } + } + + // next instance + ++inst; + + // next S value + if (huff) { + if (!huffDecoder->decodeInt(&ds, huffDSTable)) { + break; + } + } else { + if (!arithDecoder->decodeInt(&ds, iadsStats)) { + break; + } + } + s += sOffset + ds; + } + } + + return bitmap; +} + +void JBIG2Stream::readPatternDictSeg(Guint segNum, Guint length) { + JBIG2PatternDict *patternDict; + JBIG2Bitmap *bitmap; + Guint flags, patternW, patternH, grayMax, templ, mmr; + int atx[4], aty[4]; + Guint i, x; + + // halftone dictionary flags, pattern width and height, max gray value + if (!readUByte(&flags) || + !readUByte(&patternW) || + !readUByte(&patternH) || + !readULong(&grayMax)) { + goto eofError; + } + if (patternW == 0 || patternH == 0) { + error(errSyntaxError, getPos(), + "Bad size in JBIG2 pattern dictionary segment"); + return; + } + templ = (flags >> 1) & 3; + mmr = flags & 1; + + // set up the arithmetic decoder + if (!mmr) { + resetGenericStats(templ, NULL); + arithDecoder->start(); + } + + // read the bitmap + atx[0] = -(int)patternW; aty[0] = 0; + atx[1] = -3; aty[1] = -1; + atx[2] = 2; aty[2] = -2; + atx[3] = -2; aty[3] = -2; + bitmap = readGenericBitmap(mmr, (grayMax + 1) * patternW, patternH, + templ, gFalse, gFalse, NULL, + atx, aty, length - 7); + + // create the pattern dict object + patternDict = new JBIG2PatternDict(segNum, grayMax + 1); + + // split up the bitmap + x = 0; + for (i = 0; i <= grayMax; ++i) { + patternDict->setBitmap(i, bitmap->getSlice(x, 0, patternW, patternH)); + x += patternW; + } + + // free memory + delete bitmap; + + // store the new pattern dict + segments->append(patternDict); + + return; + + eofError: + error(errSyntaxError, getPos(), "Unexpected EOF in JBIG2 stream"); +} + +void JBIG2Stream::readHalftoneRegionSeg(Guint segNum, GBool imm, + GBool lossless, Guint length, + Guint *refSegs, Guint nRefSegs) { + JBIG2Bitmap *bitmap; + JBIG2Segment *seg; + JBIG2PatternDict *patternDict; + JBIG2Bitmap *skipBitmap; + Guint *grayImg; + JBIG2Bitmap *grayBitmap; + JBIG2Bitmap *patternBitmap; + Guint w, h, x, y, segInfoFlags, extCombOp; + Guint flags, mmr, templ, enableSkip, combOp; + Guint gridW, gridH, stepX, stepY, patW, patH; + int atx[4], aty[4]; + int gridX, gridY, xx, yy, bit, j; + Guint bpp, m, n, i; + + // region segment info field + if (!readULong(&w) || !readULong(&h) || + !readULong(&x) || !readULong(&y) || + !readUByte(&segInfoFlags)) { + goto eofError; + } + // sanity check: if the w/h/x/y values are way out of range, it likely + // indicates a damaged JBIG2 stream + if (w / 10 > pageW || h / 10 > pageH || + x / 10 > pageW || y / 10 > pageH) { + error(errSyntaxError, getPos(), + "Bad size or position in JBIG2 halftone region segment"); + done = gTrue; + return; + } + extCombOp = segInfoFlags & 7; + + // rest of the halftone region header + if (!readUByte(&flags)) { + goto eofError; + } + mmr = flags & 1; + templ = (flags >> 1) & 3; + enableSkip = (flags >> 3) & 1; + combOp = (flags >> 4) & 7; + if (!readULong(&gridW) || !readULong(&gridH) || + !readLong(&gridX) || !readLong(&gridY) || + !readUWord(&stepX) || !readUWord(&stepY)) { + goto eofError; + } + if (w == 0 || h == 0 || w >= INT_MAX / h) { + error(errSyntaxError, getPos(), + "Bad bitmap size in JBIG2 halftone segment"); + return; + } + if (gridW == 0 || gridH == 0 || gridW >= INT_MAX / gridH) { + error(errSyntaxError, getPos(), "Bad grid size in JBIG2 halftone segment"); + return; + } + + // get pattern dictionary + if (nRefSegs != 1) { + error(errSyntaxError, getPos(), + "Bad symbol dictionary reference in JBIG2 halftone segment"); + return; + } + if (!(seg = findSegment(refSegs[0])) || + seg->getType() != jbig2SegPatternDict) { + error(errSyntaxError, getPos(), + "Bad symbol dictionary reference in JBIG2 halftone segment"); + return; + } + patternDict = (JBIG2PatternDict *)seg; + 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(); + + // set up the arithmetic decoder + if (!mmr) { + resetGenericStats(templ, NULL); + arithDecoder->start(); + } + + // allocate the bitmap + bitmap = new JBIG2Bitmap(segNum, w, h); + if (flags & 0x80) { // HDEFPIXEL + bitmap->clearToOne(); + } else { + bitmap->clearToZero(); + } + + // compute the skip bitmap + skipBitmap = NULL; + if (enableSkip) { + skipBitmap = new JBIG2Bitmap(0, gridW, gridH); + skipBitmap->clearToZero(); + for (m = 0; m < gridH; ++m) { + for (n = 0; n < gridW; ++n) { + xx = gridX + m * stepY + n * stepX; + yy = gridY + m * stepX - n * stepY; + if (((xx + (int)patW) >> 8) <= 0 || (xx >> 8) >= (int)w || + ((yy + (int)patH) >> 8) <= 0 || (yy >> 8) >= (int)h) { + skipBitmap->setPixel(n, m); + } + } + } + } + + // read the gray-scale image + grayImg = (Guint *)gmallocn(gridW * gridH, sizeof(Guint)); + memset(grayImg, 0, gridW * gridH * sizeof(Guint)); + atx[0] = templ <= 1 ? 3 : 2; aty[0] = -1; + atx[1] = -3; aty[1] = -1; + atx[2] = 2; aty[2] = -2; + atx[3] = -2; aty[3] = -2; + for (j = bpp - 1; j >= 0; --j) { + grayBitmap = readGenericBitmap(mmr, gridW, gridH, templ, gFalse, + enableSkip, skipBitmap, atx, aty, -1); + i = 0; + for (m = 0; m < gridH; ++m) { + for (n = 0; n < gridW; ++n) { + bit = grayBitmap->getPixel(n, m) ^ (grayImg[i] & 1); + grayImg[i] = (grayImg[i] << 1) | bit; + ++i; + } + } + delete grayBitmap; + } + + // decode the image + i = 0; + for (m = 0; m < gridH; ++m) { + xx = gridX + m * stepY; + yy = gridY + m * stepX; + for (n = 0; n < gridW; ++n) { + if (!(enableSkip && skipBitmap->getPixel(n, m))) { + patternBitmap = patternDict->getBitmap(grayImg[i]); + bitmap->combine(patternBitmap, xx >> 8, yy >> 8, combOp); + } + xx += stepX; + yy -= stepY; + ++i; + } + } + + gfree(grayImg); + if (skipBitmap) { + delete skipBitmap; + } + + // combine the region bitmap into the page bitmap + if (imm) { + if (pageH == 0xffffffff && y + h > curPageH) { + pageBitmap->expand(y + h, pageDefPixel); + } + pageBitmap->combine(bitmap, x, y, extCombOp); + delete bitmap; + + // store the region bitmap + } else { + segments->append(bitmap); + } + + return; + + eofError: + 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, rowCount; + Guint flags, mmr, templ, tpgdOn; + int atx[4], aty[4]; + + // region segment info field + if (!readULong(&w) || !readULong(&h) || + !readULong(&x) || !readULong(&y) || + !readUByte(&segInfoFlags)) { + goto eofError; + } + if (w == 0 || h == 0) { + error(errSyntaxError, getPos(), + "Bad bitmap size in JBIG2 generic region segment"); + return; + } + // sanity check: if the w/h/x/y values are way out of range, it likely + // indicates a damaged JBIG2 stream + if (w / 10 > pageW || h / 10 > pageH || + x / 10 > pageW || y / 10 > pageH) { + error(errSyntaxError, getPos(), + "Bad size or position in JBIG2 generic region segment"); + done = gTrue; + return; + } + extCombOp = segInfoFlags & 7; + + // rest of the generic region segment header + if (!readUByte(&flags)) { + goto eofError; + } + mmr = flags & 1; + templ = (flags >> 1) & 3; + tpgdOn = (flags >> 3) & 1; + + // AT flags + if (!mmr) { + if (templ == 0) { + if (!readByte(&atx[0]) || + !readByte(&aty[0]) || + !readByte(&atx[1]) || + !readByte(&aty[1]) || + !readByte(&atx[2]) || + !readByte(&aty[2]) || + !readByte(&atx[3]) || + !readByte(&aty[3])) { + goto eofError; + } + } else { + if (!readByte(&atx[0]) || + !readByte(&aty[0])) { + goto eofError; + } + } + } + + // set up the arithmetic decoder + if (!mmr) { + resetGenericStats(templ, NULL); + arithDecoder->start(); + } + + // read the bitmap + bitmap = readGenericBitmap(mmr, w, h, templ, tpgdOn, gFalse, + NULL, atx, aty, mmr ? length - 18 : 0); + + // combine the region bitmap into the page bitmap + if (imm) { + if (pageH == 0xffffffff && y + h > curPageH) { + pageBitmap->expand(y + h, pageDefPixel); + } + pageBitmap->combine(bitmap, x, y, extCombOp); + delete bitmap; + + // store the region bitmap + } else { + bitmap->setSegNum(segNum); + 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(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, + int templ, GBool tpgdOn, + GBool useSkip, JBIG2Bitmap *skip, + int *atx, int *aty, + int mmrDataLength) { + JBIG2Bitmap *bitmap; + GBool ltp; + Guint ltpCX, cx, cx0, cx1, cx2; + int *refLine, *codingLine; + int code1, code2, code3; + 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(); + + //----- MMR decode + + if (mmr) { + + mmrDecoder->reset(); + if (w > INT_MAX - 3) { + error(errSyntaxError, getPos(), "Bad width in JBIG2 generic bitmap"); + // force a call to gmalloc(-1), which will throw an exception + w = -4; + } + // 0 <= codingLine[0] < codingLine[1] < ... < codingLine[n] = w + // ---> max codingLine size = w + 1 + // refLine has two extra guard entries at the end + // ---> max refLine size = w + 3 + codingLine = (int *)gmallocn(w + 1, sizeof(int)); + refLine = (int *)gmallocn(w + 3, sizeof(int)); + codingLine[0] = w; + + for (y = 0; y < h; ++y) { + + // copy coding line to ref line + for (i = 0; codingLine[i] < w; ++i) { + refLine[i] = codingLine[i]; + } + refLine[i++] = w; + refLine[i++] = w; + refLine[i] = w; + + // decode a line + 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: + mmrAddPixels(refLine[b1i + 1], blackPixels, codingLine, &a0i, w); + if (refLine[b1i + 1] < w) { + b1i += 2; + } + break; + case twoDimHoriz: + 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: + 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: + 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(errSyntaxError, getPos(), + "Illegal code in JBIG2 MMR bitmap data"); + mmrAddPixels(w, 0, codingLine, &a0i, w); + break; + } + } + + // convert the run lengths to a bitmap line + i = 0; + while (1) { + if (codingLine[i] >= w) { + break; + } + for (x = codingLine[i]; x < codingLine[i+1]; ++x) { + bitmap->setPixel(x, y); + } + if (codingLine[i+1] >= w) { + break; + } + i += 2; + } + } + + if (mmrDataLength >= 0) { + mmrDecoder->skipTo(mmrDataLength); + } else { + if (mmrDecoder->get24Bits() != 0x001001) { + error(errSyntaxError, getPos(), + "Missing EOFB in JBIG2 MMR bitmap data"); + } + } + + gfree(refLine); + gfree(codingLine); + + //----- arithmetic decode + + } else { + // set up the typical row context + ltpCX = 0; // make gcc happy + if (tpgdOn) { + switch (templ) { + case 0: + ltpCX = 0x3953; // 001 11001 0101 0011 + break; + case 1: + ltpCX = 0x079a; // 0011 11001 101 0 + break; + case 2: + ltpCX = 0x0e3; // 001 1100 01 1 + break; + case 3: + ltpCX = 0x18b; // 01100 0101 1 + break; + } + } + + ltp = 0; + cx = cx0 = cx1 = cx2 = 0; // make gcc happy + for (y = 0; y < h; ++y) { + + // check for a "typical" (duplicate) row + if (tpgdOn) { + if (arithDecoder->decodeBit(ltpCX, genericRegionStats)) { + ltp = !ltp; + } + if (ltp) { + if (y > 0) { + bitmap->duplicateRow(y, y-1); + } + continue; + } + } + + switch (templ) { + case 0: + + // set up the context + 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 && + atx[1] >= -8 && atx[1] <= 8 && + atx[2] >= -8 && atx[2] <= 8 && + atx[3] >= -8 && atx[3] <= 8) { + // set up the adaptive context + if (aty[0] <= 0 && 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 (aty[1] <= 0 && 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 (aty[2] <= 0 && 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 (aty[3] <= 0 && 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 = (Guchar)(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 = (Guchar)(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 + 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 (aty[0] <= 0 && 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 = (Guchar)(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; + } + } + + } 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 = (Guchar)(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 + 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 (aty[0] <= 0 && 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 = (Guchar)(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; + } + } + + } 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 = (Guchar)(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 + 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; + } + + if (atx[0] >= -8 && atx[0] <= 8) { + // set up the adaptive context + if (aty[0] <= 0 && 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 = (Guchar)(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; + } + } + + } 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 = (Guchar)(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; + } + } + } + + return bitmap; +} + +void JBIG2Stream::readGenericRefinementRegionSeg(Guint segNum, GBool imm, + GBool lossless, Guint length, + Guint *refSegs, + Guint nRefSegs) { + JBIG2Bitmap *bitmap, *refBitmap; + Guint w, h, x, y, segInfoFlags, extCombOp; + Guint flags, templ, tpgrOn; + int atx[2], aty[2]; + JBIG2Segment *seg; + + // region segment info field + if (!readULong(&w) || !readULong(&h) || + !readULong(&x) || !readULong(&y) || + !readUByte(&segInfoFlags)) { + goto eofError; + } + if (w == 0 || h == 0) { + error(errSyntaxError, getPos(), + "Bad size in JBIG2 generic refinement region segment"); + return; + } + // sanity check: if the w/h/x/y values are way out of range, it likely + // indicates a damaged JBIG2 stream + if (w / 10 > pageW || h / 10 > pageH || + x / 10 > pageW || y / 10 > pageH) { + error(errSyntaxError, getPos(), + "Bad size or position in JBIG2 generic refinement region segment"); + done = gTrue; + return; + } + extCombOp = segInfoFlags & 7; + + // rest of the generic refinement region segment header + if (!readUByte(&flags)) { + goto eofError; + } + templ = flags & 1; + tpgrOn = (flags >> 1) & 1; + + // AT flags + if (!templ) { + if (!readByte(&atx[0]) || !readByte(&aty[0]) || + !readByte(&atx[1]) || !readByte(&aty[1])) { + goto eofError; + } + } + + // resize the page bitmap if needed + if (nRefSegs == 0 || imm) { + if (pageH == 0xffffffff && y + h > curPageH) { + pageBitmap->expand(y + h, pageDefPixel); + } + } + + // get referenced bitmap + if (nRefSegs > 1) { + error(errSyntaxError, getPos(), + "Bad reference in JBIG2 generic refinement segment"); + return; + } + if (nRefSegs == 1) { + if (!(seg = findSegment(refSegs[0])) || + seg->getType() != jbig2SegBitmap) { + error(errSyntaxError, getPos(), + "Bad bitmap reference in JBIG2 generic refinement segment"); + return; + } + refBitmap = (JBIG2Bitmap *)seg; + } else { + refBitmap = pageBitmap->getSlice(x, y, w, h); + } + + // set up the arithmetic decoder + resetRefinementStats(templ, NULL); + arithDecoder->start(); + + // read + bitmap = readGenericRefinementRegion(w, h, templ, tpgrOn, + refBitmap, 0, 0, atx, aty); + + // combine the region bitmap into the page bitmap + if (imm) { + pageBitmap->combine(bitmap, x, y, extCombOp); + delete bitmap; + + // store the region bitmap + } else { + bitmap->setSegNum(segNum); + segments->append(bitmap); + } + + // delete the referenced bitmap + if (nRefSegs == 1) { + discardSegment(refSegs[0]); + } else { + delete refBitmap; + } + + return; + + eofError: + error(errSyntaxError, getPos(), "Unexpected EOF in JBIG2 stream"); +} + +JBIG2Bitmap *JBIG2Stream::readGenericRefinementRegion(int w, int h, + int templ, GBool tpgrOn, + JBIG2Bitmap *refBitmap, + int refDX, int refDY, + int *atx, int *aty) { + JBIG2Bitmap *bitmap; + GBool ltp; + Guint ltpCX, cx, cx0, cx2, cx3, cx4, tpgrCX0, tpgrCX1, tpgrCX2; + JBIG2BitmapPtr cxPtr0, cxPtr1, cxPtr2, cxPtr3, cxPtr4, cxPtr5, cxPtr6; + JBIG2BitmapPtr tpgrCXPtr0, tpgrCXPtr1, tpgrCXPtr2; + int x, y, pix; + + bitmap = new JBIG2Bitmap(0, w, h); + bitmap->clearToZero(); + + // set up the typical row context + if (templ) { + ltpCX = 0x008; + } else { + ltpCX = 0x0010; + } + + ltp = 0; + for (y = 0; y < h; ++y) { + + if (templ) { + + // set up the context + bitmap->getPixelPtr(0, y-1, &cxPtr0); + cx0 = bitmap->nextPixel(&cxPtr0); + bitmap->getPixelPtr(-1, y, &cxPtr1); + refBitmap->getPixelPtr(-refDX, y-1-refDY, &cxPtr2); + refBitmap->getPixelPtr(-1-refDX, y-refDY, &cxPtr3); + cx3 = refBitmap->nextPixel(&cxPtr3); + cx3 = (cx3 << 1) | refBitmap->nextPixel(&cxPtr3); + refBitmap->getPixelPtr(-refDX, y+1-refDY, &cxPtr4); + cx4 = refBitmap->nextPixel(&cxPtr4); + + // set up the typical prediction context + tpgrCX0 = tpgrCX1 = tpgrCX2 = 0; // make gcc happy + if (tpgrOn) { + refBitmap->getPixelPtr(-1-refDX, y-1-refDY, &tpgrCXPtr0); + tpgrCX0 = refBitmap->nextPixel(&tpgrCXPtr0); + tpgrCX0 = (tpgrCX0 << 1) | refBitmap->nextPixel(&tpgrCXPtr0); + tpgrCX0 = (tpgrCX0 << 1) | refBitmap->nextPixel(&tpgrCXPtr0); + refBitmap->getPixelPtr(-1-refDX, y-refDY, &tpgrCXPtr1); + tpgrCX1 = refBitmap->nextPixel(&tpgrCXPtr1); + tpgrCX1 = (tpgrCX1 << 1) | refBitmap->nextPixel(&tpgrCXPtr1); + tpgrCX1 = (tpgrCX1 << 1) | refBitmap->nextPixel(&tpgrCXPtr1); + refBitmap->getPixelPtr(-1-refDX, y+1-refDY, &tpgrCXPtr2); + 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) { + + // update the context + cx0 = ((cx0 << 1) | bitmap->nextPixel(&cxPtr0)) & 7; + cx3 = ((cx3 << 1) | refBitmap->nextPixel(&cxPtr3)) & 7; + cx4 = ((cx4 << 1) | refBitmap->nextPixel(&cxPtr4)) & 3; + + if (tpgrOn) { + // update the typical predictor context + tpgrCX0 = ((tpgrCX0 << 1) | refBitmap->nextPixel(&tpgrCXPtr0)) & 7; + tpgrCX1 = ((tpgrCX1 << 1) | refBitmap->nextPixel(&tpgrCXPtr1)) & 7; + tpgrCX2 = ((tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2)) & 7; + + // check for a "typical" pixel + if (arithDecoder->decodeBit(ltpCX, refinementRegionStats)) { + ltp = !ltp; + } + if (tpgrCX0 == 0 && tpgrCX1 == 0 && tpgrCX2 == 0) { + bitmap->clearPixel(x, y); + continue; + } else if (tpgrCX0 == 7 && tpgrCX1 == 7 && tpgrCX2 == 7) { + bitmap->setPixel(x, y); + continue; + } + } + + // build the context + cx = (cx0 << 7) | (bitmap->nextPixel(&cxPtr1) << 6) | + (refBitmap->nextPixel(&cxPtr2) << 5) | + (cx3 << 2) | cx4; + + // decode the pixel + if ((pix = arithDecoder->decodeBit(cx, refinementRegionStats))) { + bitmap->setPixel(x, y); + } + } + + } else { + + // set up the context + bitmap->getPixelPtr(0, y-1, &cxPtr0); + cx0 = bitmap->nextPixel(&cxPtr0); + bitmap->getPixelPtr(-1, y, &cxPtr1); + refBitmap->getPixelPtr(-refDX, y-1-refDY, &cxPtr2); + cx2 = refBitmap->nextPixel(&cxPtr2); + refBitmap->getPixelPtr(-1-refDX, y-refDY, &cxPtr3); + cx3 = refBitmap->nextPixel(&cxPtr3); + cx3 = (cx3 << 1) | refBitmap->nextPixel(&cxPtr3); + refBitmap->getPixelPtr(-1-refDX, y+1-refDY, &cxPtr4); + cx4 = refBitmap->nextPixel(&cxPtr4); + cx4 = (cx4 << 1) | refBitmap->nextPixel(&cxPtr4); + bitmap->getPixelPtr(atx[0], y+aty[0], &cxPtr5); + refBitmap->getPixelPtr(atx[1]-refDX, y+aty[1]-refDY, &cxPtr6); + + // set up the typical prediction context + tpgrCX0 = tpgrCX1 = tpgrCX2 = 0; // make gcc happy + if (tpgrOn) { + refBitmap->getPixelPtr(-1-refDX, y-1-refDY, &tpgrCXPtr0); + tpgrCX0 = refBitmap->nextPixel(&tpgrCXPtr0); + tpgrCX0 = (tpgrCX0 << 1) | refBitmap->nextPixel(&tpgrCXPtr0); + tpgrCX0 = (tpgrCX0 << 1) | refBitmap->nextPixel(&tpgrCXPtr0); + refBitmap->getPixelPtr(-1-refDX, y-refDY, &tpgrCXPtr1); + tpgrCX1 = refBitmap->nextPixel(&tpgrCXPtr1); + tpgrCX1 = (tpgrCX1 << 1) | refBitmap->nextPixel(&tpgrCXPtr1); + tpgrCX1 = (tpgrCX1 << 1) | refBitmap->nextPixel(&tpgrCXPtr1); + refBitmap->getPixelPtr(-1-refDX, y+1-refDY, &tpgrCXPtr2); + 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) { + + // update the context + cx0 = ((cx0 << 1) | bitmap->nextPixel(&cxPtr0)) & 3; + cx2 = ((cx2 << 1) | refBitmap->nextPixel(&cxPtr2)) & 3; + cx3 = ((cx3 << 1) | refBitmap->nextPixel(&cxPtr3)) & 7; + cx4 = ((cx4 << 1) | refBitmap->nextPixel(&cxPtr4)) & 7; + + if (tpgrOn) { + // update the typical predictor context + tpgrCX0 = ((tpgrCX0 << 1) | refBitmap->nextPixel(&tpgrCXPtr0)) & 7; + tpgrCX1 = ((tpgrCX1 << 1) | refBitmap->nextPixel(&tpgrCXPtr1)) & 7; + tpgrCX2 = ((tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2)) & 7; + + // check for a "typical" pixel + if (arithDecoder->decodeBit(ltpCX, refinementRegionStats)) { + ltp = !ltp; + } + if (tpgrCX0 == 0 && tpgrCX1 == 0 && tpgrCX2 == 0) { + bitmap->clearPixel(x, y); + continue; + } else if (tpgrCX0 == 7 && tpgrCX1 == 7 && tpgrCX2 == 7) { + bitmap->setPixel(x, y); + continue; + } + } + + // build the context + cx = (cx0 << 11) | (bitmap->nextPixel(&cxPtr1) << 10) | + (cx2 << 8) | (cx3 << 5) | (cx4 << 2) | + (bitmap->nextPixel(&cxPtr5) << 1) | + refBitmap->nextPixel(&cxPtr6); + + // decode the pixel + if ((pix = arithDecoder->decodeBit(cx, refinementRegionStats))) { + bitmap->setPixel(x, y); + } + } + } + } + + return bitmap; +} + +void JBIG2Stream::readPageInfoSeg(Guint length) { + Guint xRes, yRes, flags, striping; + + if (!readULong(&pageW) || !readULong(&pageH) || + !readULong(&xRes) || !readULong(&yRes) || + !readUByte(&flags) || !readUWord(&striping)) { + goto eofError; + } + if (pageW == 0 || pageH == 0 || pageW > INT_MAX / pageW) { + error(errSyntaxError, getPos(), "Bad page size in JBIG2 stream"); + return; + } + pageDefPixel = (flags >> 2) & 1; + defCombOp = (flags >> 3) & 3; + + // this will only happen if there are multiple page info segments + if (pageBitmap) { + delete pageBitmap; + } + + // allocate the page bitmap + if (pageH == 0xffffffff) { + curPageH = striping & 0x7fff; + } else { + curPageH = pageH; + } + pageBitmap = new JBIG2Bitmap(0, pageW, curPageH); + + // default pixel value + if (pageDefPixel) { + pageBitmap->clearToOne(); + } else { + pageBitmap->clearToZero(); + } + + return; + + eofError: + error(errSyntaxError, getPos(), "Unexpected EOF in JBIG2 stream"); +} + +void JBIG2Stream::readEndOfStripeSeg(Guint length) { + // skip the segment + byteCounter += curStr->discardChars(length); +} + +void JBIG2Stream::readProfilesSeg(Guint length) { + // skip the segment + byteCounter += curStr->discardChars(length); +} + +void JBIG2Stream::readCodeTableSeg(Guint segNum, Guint length) { + JBIG2HuffmanTable *huffTab; + Guint flags, oob, prefixBits, rangeBits; + int lowVal, highVal, val; + Guint huffTabSize, i; + + if (!readUByte(&flags) || !readLong(&lowVal) || !readLong(&highVal)) { + goto eofError; + } + oob = flags & 1; + prefixBits = ((flags >> 1) & 7) + 1; + rangeBits = ((flags >> 4) & 7) + 1; + + huffDecoder->reset(); + huffTabSize = 8; + huffTab = (JBIG2HuffmanTable *) + gmallocn(huffTabSize, sizeof(JBIG2HuffmanTable)); + i = 0; + val = lowVal; + while (val < highVal) { + if (i == huffTabSize) { + huffTabSize *= 2; + huffTab = (JBIG2HuffmanTable *) + greallocn(huffTab, huffTabSize, sizeof(JBIG2HuffmanTable)); + } + huffTab[i].val = val; + huffTab[i].prefixLen = huffDecoder->readBits(prefixBits); + huffTab[i].rangeLen = huffDecoder->readBits(rangeBits); + val += 1 << huffTab[i].rangeLen; + ++i; + } + if (i + oob + 3 > huffTabSize) { + huffTabSize = i + oob + 3; + huffTab = (JBIG2HuffmanTable *) + greallocn(huffTab, huffTabSize, sizeof(JBIG2HuffmanTable)); + } + huffTab[i].val = lowVal - 1; + huffTab[i].prefixLen = huffDecoder->readBits(prefixBits); + huffTab[i].rangeLen = jbig2HuffmanLOW; + ++i; + huffTab[i].val = highVal; + huffTab[i].prefixLen = huffDecoder->readBits(prefixBits); + huffTab[i].rangeLen = 32; + ++i; + if (oob) { + huffTab[i].val = 0; + huffTab[i].prefixLen = huffDecoder->readBits(prefixBits); + huffTab[i].rangeLen = jbig2HuffmanOOB; + ++i; + } + huffTab[i].val = 0; + huffTab[i].prefixLen = 0; + huffTab[i].rangeLen = jbig2HuffmanEOT; + huffDecoder->buildTable(huffTab, i); + + // create and store the new table segment + segments->append(new JBIG2CodeTable(segNum, huffTab)); + + return; + + eofError: + error(errSyntaxError, getPos(), "Unexpected EOF in JBIG2 stream"); +} + +void JBIG2Stream::readExtensionSeg(Guint length) { + // skip the segment + byteCounter += curStr->discardChars(length); +} + +JBIG2Segment *JBIG2Stream::findSegment(Guint segNum) { + JBIG2Segment *seg; + int i; + + for (i = 0; i < globalSegments->getLength(); ++i) { + seg = (JBIG2Segment *)globalSegments->get(i); + if (seg->getSegNum() == segNum) { + return seg; + } + } + for (i = 0; i < segments->getLength(); ++i) { + seg = (JBIG2Segment *)segments->get(i); + if (seg->getSegNum() == segNum) { + return seg; + } + } + return NULL; +} + +void JBIG2Stream::discardSegment(Guint segNum) { + JBIG2Segment *seg; + int i; + + for (i = 0; i < globalSegments->getLength(); ++i) { + seg = (JBIG2Segment *)globalSegments->get(i); + if (seg->getSegNum() == segNum) { + globalSegments->del(i); + return; + } + } + for (i = 0; i < segments->getLength(); ++i) { + seg = (JBIG2Segment *)segments->get(i); + if (seg->getSegNum() == segNum) { + segments->del(i); + return; + } + } +} + +void JBIG2Stream::resetGenericStats(Guint templ, + JArithmeticDecoderStats *prevStats) { + int size; + + size = contextSize[templ]; + if (prevStats && prevStats->getContextSize() == size) { + if (genericRegionStats->getContextSize() == size) { + genericRegionStats->copyFrom(prevStats); + } else { + delete genericRegionStats; + genericRegionStats = prevStats->copy(); + } + } else { + if (genericRegionStats->getContextSize() == size) { + genericRegionStats->reset(); + } else { + delete genericRegionStats; + genericRegionStats = new JArithmeticDecoderStats(1 << size); + } + } +} + +void JBIG2Stream::resetRefinementStats(Guint templ, + JArithmeticDecoderStats *prevStats) { + int size; + + size = refContextSize[templ]; + if (prevStats && prevStats->getContextSize() == size) { + if (refinementRegionStats->getContextSize() == size) { + refinementRegionStats->copyFrom(prevStats); + } else { + delete refinementRegionStats; + refinementRegionStats = prevStats->copy(); + } + } else { + if (refinementRegionStats->getContextSize() == size) { + refinementRegionStats->reset(); + } else { + delete refinementRegionStats; + refinementRegionStats = new JArithmeticDecoderStats(1 << size); + } + } +} + +void JBIG2Stream::resetIntStats(int symCodeLen) { + iadhStats->reset(); + iadwStats->reset(); + iaexStats->reset(); + iaaiStats->reset(); + iadtStats->reset(); + iaitStats->reset(); + iafsStats->reset(); + iadsStats->reset(); + iardxStats->reset(); + iardyStats->reset(); + iardwStats->reset(); + iardhStats->reset(); + iariStats->reset(); + if (iaidStats->getContextSize() == 1 << (symCodeLen + 1)) { + iaidStats->reset(); + } else { + delete iaidStats; + iaidStats = new JArithmeticDecoderStats(1 << (symCodeLen + 1)); + } +} + +GBool JBIG2Stream::readUByte(Guint *x) { + int c0; + + if ((c0 = curStr->getChar()) == EOF) { + return gFalse; + } + ++byteCounter; + *x = (Guint)c0; + return gTrue; +} + +GBool JBIG2Stream::readByte(int *x) { + int c0; + + if ((c0 = curStr->getChar()) == EOF) { + return gFalse; + } + ++byteCounter; + *x = c0; + if (c0 & 0x80) { + *x |= -1 - 0xff; + } + return gTrue; +} + +GBool JBIG2Stream::readUWord(Guint *x) { + int c0, c1; + + if ((c0 = curStr->getChar()) == EOF || + (c1 = curStr->getChar()) == EOF) { + return gFalse; + } + byteCounter += 2; + *x = (Guint)((c0 << 8) | c1); + return gTrue; +} + +GBool JBIG2Stream::readULong(Guint *x) { + int c0, c1, c2, c3; + + if ((c0 = curStr->getChar()) == EOF || + (c1 = curStr->getChar()) == EOF || + (c2 = curStr->getChar()) == EOF || + (c3 = curStr->getChar()) == EOF) { + return gFalse; + } + byteCounter += 4; + *x = (Guint)((c0 << 24) | (c1 << 16) | (c2 << 8) | c3); + return gTrue; +} + +GBool JBIG2Stream::readLong(int *x) { + int c0, c1, c2, c3; + + if ((c0 = curStr->getChar()) == EOF || + (c1 = curStr->getChar()) == EOF || + (c2 = curStr->getChar()) == EOF || + (c3 = curStr->getChar()) == EOF) { + return gFalse; + } + byteCounter += 4; + *x = ((c0 << 24) | (c1 << 16) | (c2 << 8) | c3); + if (c0 & 0x80) { + *x |= -1 - (int)0xffffffff; + } + return gTrue; +} diff --git a/xpdf/JBIG2Stream.h b/xpdf/JBIG2Stream.h new file mode 100644 index 0000000..bb44ba1 --- /dev/null +++ b/xpdf/JBIG2Stream.h @@ -0,0 +1,156 @@ +//======================================================================== +// +// JBIG2Stream.h +// +// Copyright 2002-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef JBIG2STREAM_H +#define JBIG2STREAM_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "gtypes.h" +#include "Object.h" +#include "Stream.h" + +class GList; +class JBIG2Segment; +class JBIG2Bitmap; +class JArithmeticDecoder; +class JArithmeticDecoderStats; +class JBIG2HuffmanDecoder; +struct JBIG2HuffmanTable; +class JBIG2MMRDecoder; + +//------------------------------------------------------------------------ + +class JBIG2Stream: public FilterStream { +public: + + JBIG2Stream(Stream *strA, Object *globalsStreamA); + virtual ~JBIG2Stream(); + virtual Stream *copy(); + virtual StreamKind getKind() { return strJBIG2; } + virtual void reset(); + virtual void close(); + virtual int getChar(); + virtual int lookChar(); + virtual int getBlock(char *blk, int size); + virtual GString *getPSFilter(int psLevel, const char *indent, + GBool okToReadStream); + virtual GBool isBinary(GBool last = gTrue); + +private: + + void decodeImage(); + void readSegments(); + GBool readSymbolDictSeg(Guint segNum, Guint length, + Guint *refSegs, Guint nRefSegs); + void readTextRegionSeg(Guint segNum, GBool imm, + GBool lossless, Guint length, + Guint *refSegs, Guint nRefSegs); + JBIG2Bitmap *readTextRegion(GBool huff, GBool refine, + int w, int h, + Guint numInstances, + Guint logStrips, + int numSyms, + JBIG2HuffmanTable *symCodeTab, + Guint symCodeLen, + JBIG2Bitmap **syms, + Guint defPixel, Guint combOp, + Guint transposed, Guint refCorner, + int sOffset, + JBIG2HuffmanTable *huffFSTable, + JBIG2HuffmanTable *huffDSTable, + JBIG2HuffmanTable *huffDTTable, + JBIG2HuffmanTable *huffRDWTable, + JBIG2HuffmanTable *huffRDHTable, + JBIG2HuffmanTable *huffRDXTable, + JBIG2HuffmanTable *huffRDYTable, + JBIG2HuffmanTable *huffRSizeTable, + Guint templ, + int *atx, int *aty); + void readPatternDictSeg(Guint segNum, Guint length); + void readHalftoneRegionSeg(Guint segNum, GBool imm, + GBool lossless, Guint length, + 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, + int *atx, int *aty, + int mmrDataLength); + void readGenericRefinementRegionSeg(Guint segNum, GBool imm, + GBool lossless, Guint length, + Guint *refSegs, + Guint nRefSegs); + JBIG2Bitmap *readGenericRefinementRegion(int w, int h, + int templ, GBool tpgrOn, + JBIG2Bitmap *refBitmap, + int refDX, int refDY, + int *atx, int *aty); + void readPageInfoSeg(Guint length); + void readEndOfStripeSeg(Guint length); + void readProfilesSeg(Guint length); + void readCodeTableSeg(Guint segNum, Guint length); + void readExtensionSeg(Guint length); + JBIG2Segment *findSegment(Guint segNum); + void discardSegment(Guint segNum); + void resetGenericStats(Guint templ, + JArithmeticDecoderStats *prevStats); + void resetRefinementStats(Guint templ, + JArithmeticDecoderStats *prevStats); + void resetIntStats(int symCodeLen); + GBool readUByte(Guint *x); + GBool readByte(int *x); + GBool readUWord(Guint *x); + GBool readULong(Guint *x); + GBool readLong(int *x); + + GBool decoded; + Object globalsStream; + Guint pageW, pageH, curPageH; + Guint pageDefPixel; + JBIG2Bitmap *pageBitmap; + Guint defCombOp; + GList *segments; // [JBIG2Segment] + GList *globalSegments; // [JBIG2Segment] + Stream *curStr; + Guchar *dataPtr; + Guchar *dataEnd; + Guint byteCounter; + GBool done; + + JArithmeticDecoder *arithDecoder; + JArithmeticDecoderStats *genericRegionStats; + JArithmeticDecoderStats *refinementRegionStats; + JArithmeticDecoderStats *iadhStats; + JArithmeticDecoderStats *iadwStats; + JArithmeticDecoderStats *iaexStats; + JArithmeticDecoderStats *iaaiStats; + JArithmeticDecoderStats *iadtStats; + JArithmeticDecoderStats *iaitStats; + JArithmeticDecoderStats *iafsStats; + JArithmeticDecoderStats *iadsStats; + JArithmeticDecoderStats *iardxStats; + JArithmeticDecoderStats *iardyStats; + JArithmeticDecoderStats *iardwStats; + JArithmeticDecoderStats *iardhStats; + JArithmeticDecoderStats *iariStats; + JArithmeticDecoderStats *iaidStats; + JBIG2HuffmanDecoder *huffDecoder; + JBIG2MMRDecoder *mmrDecoder; +}; + +#endif diff --git a/xpdf/JPXStream.cc b/xpdf/JPXStream.cc new file mode 100644 index 0000000..a1f7395 --- /dev/null +++ b/xpdf/JPXStream.cc @@ -0,0 +1,3610 @@ +//======================================================================== +// +// JPXStream.cc +// +// Copyright 2002-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include "gmem.h" +#include "gmempp.h" +#include "Error.h" +#include "JArithmeticDecoder.h" +#include "JPXStream.h" + +//~ to do: +// - ROI +// - progression order changes +// - packed packet headers +// - 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? +// - handle tilePartToEOC in readTilePartData +// - in coefficient decoding (readCodeBlockData): +// - selective arithmetic coding bypass +// (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 + +//------------------------------------------------------------------------ + +// number of contexts for the arithmetic decoder +#define jpxNContexts 19 + +#define jpxContextSigProp 0 // 0 - 8: significance prop and cleanup +#define jpxContextSign 9 // 9 - 13: sign +#define jpxContextMagRef 14 // 14 - 16: magnitude refinement +#define jpxContextRunLength 17 // cleanup: run length +#define jpxContextUniform 18 // cleanup: first signif coeff + +//------------------------------------------------------------------------ + +#define jpxPassSigProp 0 +#define jpxPassMagRef 1 +#define jpxPassCleanup 2 + +//------------------------------------------------------------------------ + +// arithmetic decoder context for the significance propagation and +// cleanup passes: +// [horiz][vert][diag][subband] +// where subband = 0 for HL +// = 1 for LH and LL +// = 2 for HH +static Guint sigPropContext[3][3][5][3] = { + {{{ 0, 0, 0 }, // horiz=0, vert=0, diag=0 + { 1, 1, 3 }, // horiz=0, vert=0, diag=1 + { 2, 2, 6 }, // horiz=0, vert=0, diag=2 + { 2, 2, 8 }, // horiz=0, vert=0, diag=3 + { 2, 2, 8 }}, // horiz=0, vert=0, diag=4 + {{ 5, 3, 1 }, // horiz=0, vert=1, diag=0 + { 6, 3, 4 }, // horiz=0, vert=1, diag=1 + { 6, 3, 7 }, // horiz=0, vert=1, diag=2 + { 6, 3, 8 }, // horiz=0, vert=1, diag=3 + { 6, 3, 8 }}, // horiz=0, vert=1, diag=4 + {{ 8, 4, 2 }, // horiz=0, vert=2, diag=0 + { 8, 4, 5 }, // horiz=0, vert=2, diag=1 + { 8, 4, 7 }, // horiz=0, vert=2, diag=2 + { 8, 4, 8 }, // horiz=0, vert=2, diag=3 + { 8, 4, 8 }}}, // horiz=0, vert=2, diag=4 + {{{ 3, 5, 1 }, // horiz=1, vert=0, diag=0 + { 3, 6, 4 }, // horiz=1, vert=0, diag=1 + { 3, 6, 7 }, // horiz=1, vert=0, diag=2 + { 3, 6, 8 }, // horiz=1, vert=0, diag=3 + { 3, 6, 8 }}, // horiz=1, vert=0, diag=4 + {{ 7, 7, 2 }, // horiz=1, vert=1, diag=0 + { 7, 7, 5 }, // horiz=1, vert=1, diag=1 + { 7, 7, 7 }, // horiz=1, vert=1, diag=2 + { 7, 7, 8 }, // horiz=1, vert=1, diag=3 + { 7, 7, 8 }}, // horiz=1, vert=1, diag=4 + {{ 8, 7, 2 }, // horiz=1, vert=2, diag=0 + { 8, 7, 5 }, // horiz=1, vert=2, diag=1 + { 8, 7, 7 }, // horiz=1, vert=2, diag=2 + { 8, 7, 8 }, // horiz=1, vert=2, diag=3 + { 8, 7, 8 }}}, // horiz=1, vert=2, diag=4 + {{{ 4, 8, 2 }, // horiz=2, vert=0, diag=0 + { 4, 8, 5 }, // horiz=2, vert=0, diag=1 + { 4, 8, 7 }, // horiz=2, vert=0, diag=2 + { 4, 8, 8 }, // horiz=2, vert=0, diag=3 + { 4, 8, 8 }}, // horiz=2, vert=0, diag=4 + {{ 7, 8, 2 }, // horiz=2, vert=1, diag=0 + { 7, 8, 5 }, // horiz=2, vert=1, diag=1 + { 7, 8, 7 }, // horiz=2, vert=1, diag=2 + { 7, 8, 8 }, // horiz=2, vert=1, diag=3 + { 7, 8, 8 }}, // horiz=2, vert=1, diag=4 + {{ 8, 8, 2 }, // horiz=2, vert=2, diag=0 + { 8, 8, 5 }, // horiz=2, vert=2, diag=1 + { 8, 8, 7 }, // horiz=2, vert=2, diag=2 + { 8, 8, 8 }, // horiz=2, vert=2, diag=3 + { 8, 8, 8 }}} // horiz=2, vert=2, diag=4 +}; + +// arithmetic decoder context and xor bit for the sign bit in the +// significance propagation pass: +// [horiz][vert][k] +// where horiz/vert are offset by 2 (i.e., range is -2 .. 2) +// and k = 0 for the context +// = 1 for the xor bit +static Guint signContext[5][5][2] = { + {{ 13, 1 }, // horiz=-2, vert=-2 + { 13, 1 }, // horiz=-2, vert=-1 + { 12, 1 }, // horiz=-2, vert= 0 + { 11, 1 }, // horiz=-2, vert=+1 + { 11, 1 }}, // horiz=-2, vert=+2 + {{ 13, 1 }, // horiz=-1, vert=-2 + { 13, 1 }, // horiz=-1, vert=-1 + { 12, 1 }, // horiz=-1, vert= 0 + { 11, 1 }, // horiz=-1, vert=+1 + { 11, 1 }}, // horiz=-1, vert=+2 + {{ 10, 1 }, // horiz= 0, vert=-2 + { 10, 1 }, // horiz= 0, vert=-1 + { 9, 0 }, // horiz= 0, vert= 0 + { 10, 0 }, // horiz= 0, vert=+1 + { 10, 0 }}, // horiz= 0, vert=+2 + {{ 11, 0 }, // horiz=+1, vert=-2 + { 11, 0 }, // horiz=+1, vert=-1 + { 12, 0 }, // horiz=+1, vert= 0 + { 13, 0 }, // horiz=+1, vert=+1 + { 13, 0 }}, // horiz=+1, vert=+2 + {{ 11, 0 }, // horiz=+2, vert=-2 + { 11, 0 }, // horiz=+2, vert=-1 + { 12, 0 }, // horiz=+2, vert= 0 + { 13, 0 }, // horiz=+2, vert=+1 + { 13, 0 }}, // horiz=+2, vert=+2 +}; + +//------------------------------------------------------------------------ + +// constants used in the IDWT +#define idwtAlpha -1.586134342059924 +#define idwtBeta -0.052980118572961 +#define idwtGamma 0.882911075530934 +#define idwtDelta 0.443506852043971 +#define idwtKappa 1.230174104914001 +#define idwtIKappa (1.0 / idwtKappa) + +// sum of the sample size (number of bits) and the number of bits to +// the right of the decimal point for the fixed point arithmetic used +// in the IDWT +#define fracBits 24 + +//------------------------------------------------------------------------ + +// floor(x / y) +#define jpxFloorDiv(x, y) ((x) / (y)) + +// floor(x / 2^y) +#define jpxFloorDivPow2(x, y) ((x) >> (y)) + +// ceil(x / y) +#define jpxCeilDiv(x, y) (((x) + (y) - 1) / (y)) + +// ceil(x / 2^y) +#define jpxCeilDivPow2(x, y) (((x) + (1 << (y)) - 1) >> (y)) + +//------------------------------------------------------------------------ + +#if 1 //----- disable coverage tracking + +#define cover(idx) + +#else //----- enable coverage tracking + +class JPXCover { +public: + + JPXCover(int sizeA); + ~JPXCover(); + void incr(int idx); + +private: + + int size, used; + int *data; +}; + +JPXCover::JPXCover(int sizeA) { + size = sizeA; + used = -1; + data = (int *)gmallocn(size, sizeof(int)); + memset(data, 0, size * sizeof(int)); +} + +JPXCover::~JPXCover() { + int i; + + printf("JPX coverage:\n"); + for (i = 0; i <= used; ++i) { + printf(" %4d: %8d\n", i, data[i]); + } + gfree(data); +} + +void JPXCover::incr(int idx) { + if (idx < size) { + ++data[idx]; + if (idx > used) { + used = idx; + } + } +} + +JPXCover jpxCover(150); + +#define cover(idx) jpxCover.incr(idx) + +#endif //----- coverage tracking + +//------------------------------------------------------------------------ + +JPXStream::JPXStream(Stream *strA): + FilterStream(strA) +{ + bufStr = new BufStream(str, 3); + + decoded = gFalse; + nComps = 0; + bpc = NULL; + width = height = 0; + reduction = 0; + haveCS = gFalse; + + palette.bpc = NULL; + palette.c = NULL; + havePalette = gFalse; + + compMap.comp = NULL; + compMap.type = NULL; + compMap.pComp = NULL; + haveCompMap = gFalse; + + channelDefn.idx = NULL; + channelDefn.type = NULL; + channelDefn.assoc = NULL; + haveChannelDefn = gFalse; + + img.tiles = NULL; + + bitBuf = 0; + bitBufLen = 0; + bitBufSkip = gFalse; + byteCount = 0; +} + +JPXStream::~JPXStream() { + close(); + delete bufStr; +} + +Stream *JPXStream::copy() { + return new JPXStream(str->copy()); +} + +void JPXStream::reset() { + img.ySize = 0; + bufStr->reset(); + decoded = gFalse; +} + +void JPXStream::close() { + JPXTile *tile; + JPXTileComp *tileComp; + JPXResLevel *resLevel; + JPXPrecinct *precinct; + JPXSubband *subband; + JPXCodeBlock *cb; + Guint comp, i, k, r, pre, sb; + + gfree(bpc); + bpc = NULL; + if (havePalette) { + gfree(palette.bpc); + gfree(palette.c); + havePalette = gFalse; + } + if (haveCompMap) { + gfree(compMap.comp); + gfree(compMap.type); + gfree(compMap.pComp); + haveCompMap = gFalse; + } + if (haveChannelDefn) { + gfree(channelDefn.idx); + gfree(channelDefn.type); + gfree(channelDefn.assoc); + haveChannelDefn = gFalse; + } + + if (img.tiles) { + for (i = 0; i < img.nXTiles * img.nYTiles; ++i) { + tile = &img.tiles[i]; + if (tile->tileComps) { + for (comp = 0; comp < img.nComps; ++comp) { + tileComp = &tile->tileComps[comp]; + gfree(tileComp->quantSteps); + gfree(tileComp->data); + gfree(tileComp->buf); + if (tileComp->resLevels) { + for (r = 0; r <= tileComp->nDecompLevels; ++r) { + resLevel = &tileComp->resLevels[r]; + if (resLevel->precincts) { + for (pre = 0; pre < resLevel->nPrecincts; ++pre) { + precinct = &resLevel->precincts[pre]; + if (precinct->subbands) { + for (sb = 0; sb < (Guint)(r == 0 ? 1 : 3); ++sb) { + subband = &precinct->subbands[sb]; + gfree(subband->inclusion); + gfree(subband->zeroBitPlane); + if (subband->cbs) { + for (k = 0; k < subband->nXCBs * subband->nYCBs; ++k) { + cb = &subband->cbs[k]; + gfree(cb->dataLen); + gfree(cb->touched); + if (cb->arithDecoder) { + delete cb->arithDecoder; + } + if (cb->stats) { + delete cb->stats; + } + } + gfree(subband->cbs); + } + } + gfree(precinct->subbands); + } + } + gfree(resLevel->precincts); + } + } + gfree(tileComp->resLevels); + } + } + gfree(tile->tileComps); + } + } + gfree(img.tiles); + img.tiles = NULL; + } + bufStr->close(); +} + +void JPXStream::decodeImage() { + if (readBoxes() == jpxDecodeFatalError) { + // readBoxes reported an error, so we go immediately to EOF + curY = img.ySize >> reduction; + } else { + curY = img.yOffsetR; + } + curX = img.xOffsetR; + curComp = 0; + readBufLen = 0; + decoded = gTrue; +} + +int JPXStream::getChar() { + int c; + + if (!decoded) { + decodeImage(); + } + if (readBufLen < 8) { + fillReadBuf(); + } + if (readBufLen == 8) { + c = readBuf & 0xff; + readBufLen = 0; + } else if (readBufLen > 8) { + c = (readBuf >> (readBufLen - 8)) & 0xff; + readBufLen -= 8; + } else if (readBufLen == 0) { + c = EOF; + } else { + c = (readBuf << (8 - readBufLen)) & 0xff; + readBufLen = 0; + } + return c; +} + +int JPXStream::lookChar() { + int c; + + if (!decoded) { + decodeImage(); + } + if (readBufLen < 8) { + fillReadBuf(); + } + if (readBufLen == 8) { + c = readBuf & 0xff; + } else if (readBufLen > 8) { + c = (readBuf >> (readBufLen - 8)) & 0xff; + } else if (readBufLen == 0) { + c = EOF; + } else { + c = (readBuf << (8 - readBufLen)) & 0xff; + } + return c; +} + +void JPXStream::fillReadBuf() { + JPXTileComp *tileComp; + Guint tileIdx, tx, ty; + int pix, pixBits, k; + GBool eol; + + do { + if (curY >= (img.ySize >> reduction)) { + return; + } + tileIdx = (((curY << reduction) - img.yTileOffset) / img.yTileSize) + * img.nXTiles + + ((curX << reduction) - img.xTileOffset) / img.xTileSize; +#if 1 //~ ignore the palette, assume the PDF ColorSpace object is valid + tileComp = &img.tiles[tileIdx].tileComps[curComp]; +#else + tileComp = &img.tiles[tileIdx].tileComps[havePalette ? 0 : curComp]; +#endif + tx = jpxFloorDiv(curX, tileComp->hSep); + if (tx < tileComp->x0r) { + tx = 0; + } else { + tx -= tileComp->x0r; + } + ty = jpxFloorDiv(curY, tileComp->vSep); + if (ty < tileComp->y0r) { + ty = 0; + } else { + ty -= tileComp->y0r; + } + pix = (int)tileComp->data[ty * tileComp->w + tx]; + pixBits = tileComp->prec; + eol = gFalse; +#if 1 //~ ignore the palette, assume the PDF ColorSpace object is valid + if (++curComp == img.nComps) { +#else + if (havePalette) { + if (pix >= 0 && pix < palette.nEntries) { + pix = palette.c[pix * palette.nComps + curComp]; + } else { + pix = 0; + } + pixBits = palette.bpc[curComp]; + } + if (++curComp == (Guint)(havePalette ? palette.nComps : img.nComps)) { +#endif + curComp = 0; + if (++curX == (img.xSize >> reduction)) { + curX = img.xOffsetR; + ++curY; + eol = gTrue; + } + } + if (pixBits == 8) { + readBuf = (readBuf << 8) | (pix & 0xff); + } else { + readBuf = (readBuf << pixBits) | (pix & ((1 << pixBits) - 1)); + } + readBufLen += pixBits; + if (eol && (k = readBufLen & 7)) { + readBuf <<= 8 - k; + readBufLen += 8 - k; + } + } while (readBufLen < 8); +} + +GString *JPXStream::getPSFilter(int psLevel, const char *indent, + GBool okToReadStream) { + return NULL; +} + +GBool JPXStream::isBinary(GBool last) { + return str->isBinary(gTrue); +} + +void JPXStream::getImageParams(int *bitsPerComponent, + StreamColorSpaceMode *csMode) { + Guint boxType, boxLen, dataLen, csEnum; + Guint bpc1, dummy; + int csMeth, csPrec, csPrec1, dummy2; + StreamColorSpaceMode csMode1; + GBool haveBPC, haveCSMode; + + csPrec = 0; // make gcc happy + haveBPC = haveCSMode = gFalse; + bufStr->reset(); + if (bufStr->lookChar() == 0xff) { + getImageParams2(bitsPerComponent, csMode); + } else { + while (readBoxHdr(&boxType, &boxLen, &dataLen)) { + if (boxType == 0x6a703268) { // JP2 header + cover(0); + // skip the superbox + } else if (boxType == 0x69686472) { // image header + cover(1); + if (readULong(&dummy) && + readULong(&dummy) && + readUWord(&dummy) && + readUByte(&bpc1) && + readUByte(&dummy) && + readUByte(&dummy) && + readUByte(&dummy)) { + *bitsPerComponent = bpc1 + 1; + haveBPC = gTrue; + } + } else if (boxType == 0x636F6C72) { // color specification + cover(2); + if (readByte(&csMeth) && + readByte(&csPrec1) && + readByte(&dummy2)) { + if (csMeth == 1) { + if (readULong(&csEnum)) { + csMode1 = streamCSNone; + if (csEnum == jpxCSBiLevel || + csEnum == jpxCSGrayscale) { + csMode1 = streamCSDeviceGray; + } else if (csEnum == jpxCSCMYK) { + csMode1 = streamCSDeviceCMYK; + } else if (csEnum == jpxCSsRGB || + csEnum == jpxCSCISesRGB || + csEnum == jpxCSROMMRGB) { + csMode1 = streamCSDeviceRGB; + } + if (csMode1 != streamCSNone && + (!haveCSMode || csPrec1 > csPrec)) { + *csMode = csMode1; + csPrec = csPrec1; + haveCSMode = gTrue; + } + if (dataLen > 7) { + bufStr->discardChars(dataLen - 7); + } + } + } else { + if (dataLen > 3) { + bufStr->discardChars(dataLen - 3); + } + } + } + } else if (boxType == 0x6A703263) { // codestream + cover(3); + if (!(haveBPC && haveCSMode)) { + getImageParams2(bitsPerComponent, csMode); + } + break; + } else { + cover(4); + bufStr->discardChars(dataLen); + } + } + } + bufStr->close(); +} + +// Get image parameters from the codestream. +void JPXStream::getImageParams2(int *bitsPerComponent, + StreamColorSpaceMode *csMode) { + int segType; + Guint segLen, nComps1, bpc1, dummy; + + while (readMarkerHdr(&segType, &segLen)) { + if (segType == 0x51) { // SIZ - image and tile size + cover(5); + if (readUWord(&dummy) && + readULong(&dummy) && + readULong(&dummy) && + readULong(&dummy) && + readULong(&dummy) && + readULong(&dummy) && + readULong(&dummy) && + readULong(&dummy) && + readULong(&dummy) && + readUWord(&nComps1) && + readUByte(&bpc1)) { + *bitsPerComponent = (bpc1 & 0x7f) + 1; + // if there's no color space info, take a guess + if (nComps1 == 1) { + *csMode = streamCSDeviceGray; + } else if (nComps1 == 3) { + *csMode = streamCSDeviceRGB; + } else if (nComps1 == 4) { + *csMode = streamCSDeviceCMYK; + } + } + break; + } else { + cover(6); + if (segLen > 2) { + bufStr->discardChars(segLen - 2); + } + } + } +} + +JPXDecodeResult JPXStream::readBoxes() { + JPXDecodeResult result; + GBool haveCodestream; + Guint boxType, boxLen, dataLen; + Guint w, h, n, bpc1, compression, unknownColorspace, ipr; + Guint i, j; + + haveImgHdr = gFalse; + haveCodestream = gFalse; + + // 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 (bufStr->lookChar() == 0xff) { + cover(7); + error(errSyntaxWarning, getPos(), + "Naked JPEG 2000 codestream, missing JP2/JPX wrapper"); + if ((result = readCodestream(0)) == jpxDecodeFatalError) { + return result; + } + nComps = img.nComps; + bpc = (Guint *)gmallocn(nComps, sizeof(Guint)); + for (i = 0; i < nComps; ++i) { + bpc[i] = img.tiles[0].tileComps[i].prec; + } + width = img.xSize - img.xOffset; + height = img.ySize - img.yOffset; + return result; + } + + while (readBoxHdr(&boxType, &boxLen, &dataLen)) { + switch (boxType) { + case 0x6a703268: // JP2 header + // this is a grouping box ('superbox') which has no real + // contents and doesn't appear to be used consistently, i.e., + // some things which should be subboxes of the JP2 header box + // show up outside of it - so we simply ignore the JP2 header + // box + cover(8); + break; + case 0x69686472: // image header + cover(9); + if (!readULong(&h) || + !readULong(&w) || + !readUWord(&n) || + !readUByte(&bpc1) || + !readUByte(&compression) || + !readUByte(&unknownColorspace) || + !readUByte(&ipr)) { + error(errSyntaxError, getPos(), "Unexpected EOF in JPX stream"); + return jpxDecodeFatalError; + } + if (compression != 7) { + error(errSyntaxError, getPos(), + "Unknown compression type in JPX stream"); + return jpxDecodeFatalError; + } + height = h; + width = w; + nComps = n; + bpc = (Guint *)gmallocn(nComps, sizeof(Guint)); + for (i = 0; i < nComps; ++i) { + bpc[i] = bpc1; + } + haveImgHdr = gTrue; + break; + case 0x62706363: // bits per component + cover(10); + if (!haveImgHdr) { + error(errSyntaxError, getPos(), + "Found bits per component box before image header box in JPX stream"); + return jpxDecodeFatalError; + } + if (dataLen != nComps) { + error(errSyntaxError, getPos(), + "Invalid bits per component box in JPX stream"); + return jpxDecodeFatalError; + } + for (i = 0; i < nComps; ++i) { + if (!readUByte(&bpc[i])) { + error(errSyntaxError, getPos(), "Unexpected EOF in JPX stream"); + return jpxDecodeFatalError; + } + } + break; + case 0x636F6C72: // color specification + cover(11); + if (!readColorSpecBox(dataLen)) { + return jpxDecodeFatalError; + } + break; + case 0x70636c72: // palette + cover(12); + if (!readUWord(&palette.nEntries) || + !readUByte(&palette.nComps)) { + error(errSyntaxError, getPos(), "Unexpected EOF in JPX stream"); + return jpxDecodeFatalError; + } + havePalette = gTrue; + palette.bpc = (Guint *)gmallocn(palette.nComps, sizeof(Guint)); + palette.c = + (int *)gmallocn(palette.nEntries * palette.nComps, sizeof(int)); + for (i = 0; i < palette.nComps; ++i) { + if (!readUByte(&palette.bpc[i])) { + error(errSyntaxError, getPos(), "Unexpected EOF in JPX stream"); + return jpxDecodeFatalError; + } + ++palette.bpc[i]; + } + for (i = 0; i < palette.nEntries; ++i) { + for (j = 0; j < palette.nComps; ++j) { + if (!readNBytes(((palette.bpc[j] & 0x7f) + 7) >> 3, + (palette.bpc[j] & 0x80) ? gTrue : gFalse, + &palette.c[i * palette.nComps + j])) { + error(errSyntaxError, getPos(), "Unexpected EOF in JPX stream"); + return jpxDecodeFatalError; + } + } + } + break; + case 0x636d6170: // component mapping + cover(13); + haveCompMap = gTrue; + compMap.nChannels = dataLen / 4; + compMap.comp = (Guint *)gmallocn(compMap.nChannels, sizeof(Guint)); + compMap.type = (Guint *)gmallocn(compMap.nChannels, sizeof(Guint)); + compMap.pComp = (Guint *)gmallocn(compMap.nChannels, sizeof(Guint)); + for (i = 0; i < compMap.nChannels; ++i) { + if (!readUWord(&compMap.comp[i]) || + !readUByte(&compMap.type[i]) || + !readUByte(&compMap.pComp[i])) { + error(errSyntaxError, getPos(), "Unexpected EOF in JPX stream"); + return jpxDecodeFatalError; + } + } + break; + case 0x63646566: // channel definition + cover(14); + if (!readUWord(&channelDefn.nChannels)) { + error(errSyntaxError, getPos(), "Unexpected EOF in JPX stream"); + return jpxDecodeFatalError; + } + haveChannelDefn = gTrue; + channelDefn.idx = + (Guint *)gmallocn(channelDefn.nChannels, sizeof(Guint)); + channelDefn.type = + (Guint *)gmallocn(channelDefn.nChannels, sizeof(Guint)); + channelDefn.assoc = + (Guint *)gmallocn(channelDefn.nChannels, sizeof(Guint)); + for (i = 0; i < channelDefn.nChannels; ++i) { + if (!readUWord(&channelDefn.idx[i]) || + !readUWord(&channelDefn.type[i]) || + !readUWord(&channelDefn.assoc[i])) { + error(errSyntaxError, getPos(), "Unexpected EOF in JPX stream"); + return jpxDecodeFatalError; + } + } + break; + case 0x6A703263: // contiguous codestream + cover(15); + if (!bpc) { + error(errSyntaxError, getPos(), + "JPX stream is missing the image header box"); + } + if (!haveCS) { + error(errSyntaxError, getPos(), + "JPX stream has no supported color spec"); + } + if ((result = readCodestream(dataLen)) != jpxDecodeOk) { + return result; + } + haveCodestream = gTrue; + break; + default: + cover(16); + if (bufStr->discardChars(dataLen) != dataLen) { + error(errSyntaxError, getPos(), "Unexpected EOF in JPX stream"); + return haveCodestream ? jpxDecodeNonFatalError : jpxDecodeFatalError; + } + break; + } + } + return jpxDecodeOk; +} + +GBool JPXStream::readColorSpecBox(Guint dataLen) { + JPXColorSpec newCS; + Guint csApprox, csEnum; + GBool ok; + + ok = gFalse; + if (!readUByte(&newCS.meth) || + !readByte(&newCS.prec) || + !readUByte(&csApprox)) { + goto err; + } + switch (newCS.meth) { + case 1: // enumerated colorspace + cover(17); + if (!readULong(&csEnum)) { + goto err; + } + newCS.enumerated.type = (JPXColorSpaceType)csEnum; + switch (newCS.enumerated.type) { + case jpxCSBiLevel: + ok = gTrue; + break; + case jpxCSYCbCr1: + ok = gTrue; + break; + case jpxCSYCbCr2: + ok = gTrue; + break; + case jpxCSYCBCr3: + ok = gTrue; + break; + case jpxCSPhotoYCC: + ok = gTrue; + break; + case jpxCSCMY: + ok = gTrue; + break; + case jpxCSCMYK: + ok = gTrue; + break; + case jpxCSYCCK: + ok = gTrue; + break; + case jpxCSCIELab: + if (dataLen == 7 + 7*4) { + if (!readULong(&newCS.enumerated.cieLab.rl) || + !readULong(&newCS.enumerated.cieLab.ol) || + !readULong(&newCS.enumerated.cieLab.ra) || + !readULong(&newCS.enumerated.cieLab.oa) || + !readULong(&newCS.enumerated.cieLab.rb) || + !readULong(&newCS.enumerated.cieLab.ob) || + !readULong(&newCS.enumerated.cieLab.il)) { + goto err; + } + } else if (dataLen == 7) { + //~ this assumes the 8-bit case + cover(92); + newCS.enumerated.cieLab.rl = 100; + newCS.enumerated.cieLab.ol = 0; + newCS.enumerated.cieLab.ra = 255; + newCS.enumerated.cieLab.oa = 128; + newCS.enumerated.cieLab.rb = 255; + newCS.enumerated.cieLab.ob = 96; + newCS.enumerated.cieLab.il = 0x00443530; + } else { + goto err; + } + ok = gTrue; + break; + case jpxCSsRGB: + ok = gTrue; + break; + case jpxCSGrayscale: + ok = gTrue; + break; + case jpxCSBiLevel2: + ok = gTrue; + break; + case jpxCSCIEJab: + // not allowed in PDF + goto err; + case jpxCSCISesRGB: + ok = gTrue; + break; + case jpxCSROMMRGB: + ok = gTrue; + break; + case jpxCSsRGBYCbCr: + ok = gTrue; + break; + case jpxCSYPbPr1125: + ok = gTrue; + break; + case jpxCSYPbPr1250: + ok = gTrue; + break; + default: + goto err; + } + break; + case 2: // restricted ICC profile + case 3: // any ICC profile (JPX) + case 4: // vendor color (JPX) + cover(18); + if (dataLen > 3 && + bufStr->discardChars(dataLen - 3) != dataLen - 3) { + goto err; + } + break; + } + + if (ok && (!haveCS || newCS.prec > cs.prec)) { + cs = newCS; + haveCS = gTrue; + } + + return gTrue; + + err: + error(errSyntaxError, getPos(), "Error in JPX color spec"); + return gFalse; +} + +JPXDecodeResult JPXStream::readCodestream(Guint len) { + JPXTile *tile; + JPXTileComp *tileComp; + int segType; + GBool haveSIZ, haveCOD, haveQCD, haveSOT, ok; + Guint style, progOrder, nLayers, multiComp, nDecompLevels; + Guint codeBlockW, codeBlockH, codeBlockStyle, transform; + Guint precinctSize; + Guint segLen, capabilities, comp, i, j, r; + + //----- main header + haveSIZ = haveCOD = haveQCD = haveSOT = gFalse; + do { + if (!readMarkerHdr(&segType, &segLen)) { + error(errSyntaxError, getPos(), "Error in JPX codestream"); + return jpxDecodeFatalError; + } + switch (segType) { + case 0x4f: // SOC - start of codestream + // marker only + cover(19); + break; + case 0x51: // SIZ - image and tile size + cover(20); + if (haveSIZ) { + error(errSyntaxError, getPos(), + "Duplicate SIZ marker segment in JPX stream"); + return jpxDecodeFatalError; + } + if (!readUWord(&capabilities) || + !readULong(&img.xSize) || + !readULong(&img.ySize) || + !readULong(&img.xOffset) || + !readULong(&img.yOffset) || + !readULong(&img.xTileSize) || + !readULong(&img.yTileSize) || + !readULong(&img.xTileOffset) || + !readULong(&img.yTileOffset) || + !readUWord(&img.nComps)) { + error(errSyntaxError, getPos(), "Error in JPX SIZ marker segment"); + return jpxDecodeFatalError; + } + if (haveImgHdr && img.nComps != nComps) { + error(errSyntaxError, getPos(), + "Different number of components in JPX SIZ marker segment"); + return jpxDecodeFatalError; + } + 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 || + img.nComps == 0) { + error(errSyntaxError, getPos(), "Error in JPX SIZ marker segment"); + return jpxDecodeFatalError; + } + img.xSizeR = jpxCeilDivPow2(img.xSize, reduction); + img.ySizeR = jpxCeilDivPow2(img.ySize, reduction); + img.xOffsetR = jpxCeilDivPow2(img.xOffset, reduction); + img.yOffsetR = jpxCeilDivPow2(img.yOffset, reduction); + img.nXTiles = (img.xSize - img.xTileOffset + img.xTileSize - 1) + / img.xTileSize; + img.nYTiles = (img.ySize - img.yTileOffset + img.yTileSize - 1) + / img.yTileSize; + // check for overflow before allocating memory + if (img.nXTiles <= 0 || img.nYTiles <= 0 || + img.nXTiles >= INT_MAX / img.nYTiles) { + error(errSyntaxError, getPos(), + "Bad tile count in JPX SIZ marker segment"); + return jpxDecodeFatalError; + } + img.tiles = (JPXTile *)gmallocn(img.nXTiles * img.nYTiles, + sizeof(JPXTile)); + for (i = 0; i < img.nXTiles * img.nYTiles; ++i) { + img.tiles[i].init = gFalse; + img.tiles[i].nextTilePart = 0; + img.tiles[i].tileComps = NULL; + } + for (i = 0; i < img.nXTiles * img.nYTiles; ++i) { + img.tiles[i].tileComps = (JPXTileComp *)gmallocn(img.nComps, + sizeof(JPXTileComp)); + for (comp = 0; comp < img.nComps; ++comp) { + img.tiles[i].tileComps[comp].quantSteps = NULL; + img.tiles[i].tileComps[comp].data = NULL; + img.tiles[i].tileComps[comp].buf = NULL; + img.tiles[i].tileComps[comp].resLevels = NULL; + } + } + for (comp = 0; comp < img.nComps; ++comp) { + if (!readUByte(&img.tiles[0].tileComps[comp].prec) || + !readUByte(&img.tiles[0].tileComps[comp].hSep) || + !readUByte(&img.tiles[0].tileComps[comp].vSep)) { + error(errSyntaxError, getPos(), "Error in JPX SIZ marker segment"); + return jpxDecodeFatalError; + } + if (img.tiles[0].tileComps[comp].hSep == 0 || + img.tiles[0].tileComps[comp].vSep == 0) { + error(errSyntaxError, getPos(), "Error in JPX SIZ marker segment"); + return jpxDecodeFatalError; + } + img.tiles[0].tileComps[comp].sgned = + (img.tiles[0].tileComps[comp].prec & 0x80) ? gTrue : gFalse; + img.tiles[0].tileComps[comp].prec = + (img.tiles[0].tileComps[comp].prec & 0x7f) + 1; + for (i = 1; i < img.nXTiles * img.nYTiles; ++i) { + img.tiles[i].tileComps[comp] = img.tiles[0].tileComps[comp]; + } + } + haveSIZ = gTrue; + break; + case 0x52: // COD - coding style default + cover(21); + if (!haveSIZ) { + error(errSyntaxError, getPos(), + "JPX COD marker segment before SIZ segment"); + return jpxDecodeFatalError; + } + if (!readUByte(&style) || + !readUByte(&progOrder) || + !readUWord(&nLayers) || + !readUByte(&multiComp) || + !readUByte(&nDecompLevels) || + !readUByte(&codeBlockW) || + !readUByte(&codeBlockH) || + !readUByte(&codeBlockStyle) || + !readUByte(&transform)) { + error(errSyntaxError, getPos(), "Error in JPX COD marker segment"); + return jpxDecodeFatalError; + } + if (nDecompLevels < 1 || + nDecompLevels > 31 || + codeBlockW > 8 || + codeBlockH > 8) { + error(errSyntaxError, getPos(), "Error in JPX COD marker segment"); + return jpxDecodeFatalError; + } + codeBlockW += 2; + codeBlockH += 2; + for (i = 0; i < img.nXTiles * img.nYTiles; ++i) { + img.tiles[i].progOrder = progOrder; + img.tiles[i].nLayers = nLayers; + img.tiles[i].multiComp = multiComp; + for (comp = 0; comp < img.nComps; ++comp) { + img.tiles[i].tileComps[comp].style = style; + img.tiles[i].tileComps[comp].nDecompLevels = nDecompLevels; + img.tiles[i].tileComps[comp].codeBlockW = codeBlockW; + img.tiles[i].tileComps[comp].codeBlockH = codeBlockH; + img.tiles[i].tileComps[comp].codeBlockStyle = codeBlockStyle; + img.tiles[i].tileComps[comp].transform = transform; + img.tiles[i].tileComps[comp].resLevels = + (JPXResLevel *)gmallocn(nDecompLevels + 1, sizeof(JPXResLevel)); + for (r = 0; r <= nDecompLevels; ++r) { + img.tiles[i].tileComps[comp].resLevels[r].precincts = NULL; + } + } + } + for (r = 0; r <= nDecompLevels; ++r) { + if (style & 0x01) { + cover(91); + if (!readUByte(&precinctSize)) { + error(errSyntaxError, getPos(), "Error in JPX COD marker segment"); + return jpxDecodeFatalError; + } + if (r > 0 && ((precinctSize & 0x0f) == 0 || + (precinctSize & 0xf0) == 0)) { + error(errSyntaxError, getPos(), + "Invalid precinct size in JPX COD marker segment"); + return jpxDecodeFatalError; + } + img.tiles[0].tileComps[0].resLevels[r].precinctWidth = + precinctSize & 0x0f; + img.tiles[0].tileComps[0].resLevels[r].precinctHeight = + (precinctSize >> 4) & 0x0f; + } else { + img.tiles[0].tileComps[0].resLevels[r].precinctWidth = 15; + img.tiles[0].tileComps[0].resLevels[r].precinctHeight = 15; + } + } + for (i = 0; i < img.nXTiles * img.nYTiles; ++i) { + for (comp = 0; comp < img.nComps; ++comp) { + if (!(i == 0 && comp == 0)) { + for (r = 0; r <= nDecompLevels; ++r) { + img.tiles[i].tileComps[comp].resLevels[r].precinctWidth = + img.tiles[0].tileComps[0].resLevels[r].precinctWidth; + img.tiles[i].tileComps[comp].resLevels[r].precinctHeight = + img.tiles[0].tileComps[0].resLevels[r].precinctHeight; + } + } + } + } + haveCOD = gTrue; + break; + case 0x53: // COC - coding style component + cover(22); + if (!haveCOD) { + error(errSyntaxError, getPos(), + "JPX COC marker segment before COD segment"); + return jpxDecodeFatalError; + } + if ((img.nComps > 256 && !readUWord(&comp)) || + (img.nComps <= 256 && !readUByte(&comp)) || + comp >= img.nComps || + !readUByte(&style) || + !readUByte(&nDecompLevels) || + !readUByte(&codeBlockW) || + !readUByte(&codeBlockH) || + !readUByte(&codeBlockStyle) || + !readUByte(&transform)) { + error(errSyntaxError, getPos(), "Error in JPX COC marker segment"); + return jpxDecodeFatalError; + } + if (nDecompLevels < 1 || + nDecompLevels > 31 || + codeBlockW > 8 || + codeBlockH > 8) { + error(errSyntaxError, getPos(), "Error in JPX COC marker segment"); + return jpxDecodeFatalError; + } + style = (img.tiles[0].tileComps[comp].style & ~1) | (style & 1); + codeBlockW += 2; + codeBlockH += 2; + for (i = 0; i < img.nXTiles * img.nYTiles; ++i) { + img.tiles[i].tileComps[comp].style = style; + img.tiles[i].tileComps[comp].nDecompLevels = nDecompLevels; + img.tiles[i].tileComps[comp].codeBlockW = codeBlockW; + img.tiles[i].tileComps[comp].codeBlockH = codeBlockH; + img.tiles[i].tileComps[comp].codeBlockStyle = codeBlockStyle; + img.tiles[i].tileComps[comp].transform = transform; + img.tiles[i].tileComps[comp].resLevels = + (JPXResLevel *)greallocn( + img.tiles[i].tileComps[comp].resLevels, + nDecompLevels + 1, + sizeof(JPXResLevel)); + for (r = 0; r <= nDecompLevels; ++r) { + img.tiles[i].tileComps[comp].resLevels[r].precincts = NULL; + } + } + for (r = 0; r <= nDecompLevels; ++r) { + if (style & 0x01) { + if (!readUByte(&precinctSize)) { + error(errSyntaxError, getPos(), "Error in JPX COD marker segment"); + return jpxDecodeFatalError; + } + if (r > 0 && ((precinctSize & 0x0f) == 0 || + (precinctSize & 0xf0) == 0)) { + error(errSyntaxError, getPos(), + "Invalid precinct size in JPX COD marker segment"); + return jpxDecodeFatalError; + } + img.tiles[0].tileComps[comp].resLevels[r].precinctWidth = + precinctSize & 0x0f; + img.tiles[0].tileComps[comp].resLevels[r].precinctHeight = + (precinctSize >> 4) & 0x0f; + } else { + img.tiles[0].tileComps[comp].resLevels[r].precinctWidth = 15; + img.tiles[0].tileComps[comp].resLevels[r].precinctHeight = 15; + } + } + for (i = 1; i < img.nXTiles * img.nYTiles; ++i) { + for (r = 0; r <= img.tiles[i].tileComps[comp].nDecompLevels; ++r) { + img.tiles[i].tileComps[comp].resLevels[r].precinctWidth = + img.tiles[0].tileComps[comp].resLevels[r].precinctWidth; + img.tiles[i].tileComps[comp].resLevels[r].precinctHeight = + img.tiles[0].tileComps[comp].resLevels[r].precinctHeight; + } + } + break; + case 0x5c: // QCD - quantization default + cover(23); + if (!haveSIZ) { + error(errSyntaxError, getPos(), + "JPX QCD marker segment before SIZ segment"); + return jpxDecodeFatalError; + } + if (!readUByte(&img.tiles[0].tileComps[0].quantStyle)) { + error(errSyntaxError, getPos(), "Error in JPX QCD marker segment"); + return jpxDecodeFatalError; + } + if ((img.tiles[0].tileComps[0].quantStyle & 0x1f) == 0x00) { + if (segLen <= 3) { + error(errSyntaxError, getPos(), "Error in JPX QCD marker segment"); + return jpxDecodeFatalError; + } + img.tiles[0].tileComps[0].nQuantSteps = segLen - 3; + img.tiles[0].tileComps[0].quantSteps = + (Guint *)greallocn(img.tiles[0].tileComps[0].quantSteps, + img.tiles[0].tileComps[0].nQuantSteps, + sizeof(Guint)); + for (i = 0; i < img.tiles[0].tileComps[0].nQuantSteps; ++i) { + if (!readUByte(&img.tiles[0].tileComps[0].quantSteps[i])) { + error(errSyntaxError, getPos(), "Error in JPX QCD marker segment"); + return jpxDecodeFatalError; + } + } + } else if ((img.tiles[0].tileComps[0].quantStyle & 0x1f) == 0x01) { + img.tiles[0].tileComps[0].nQuantSteps = 1; + img.tiles[0].tileComps[0].quantSteps = + (Guint *)greallocn(img.tiles[0].tileComps[0].quantSteps, + img.tiles[0].tileComps[0].nQuantSteps, + sizeof(Guint)); + if (!readUWord(&img.tiles[0].tileComps[0].quantSteps[0])) { + error(errSyntaxError, getPos(), "Error in JPX QCD marker segment"); + return jpxDecodeFatalError; + } + } else if ((img.tiles[0].tileComps[0].quantStyle & 0x1f) == 0x02) { + if (segLen < 5) { + error(errSyntaxError, getPos(), "Error in JPX QCD marker segment"); + return jpxDecodeFatalError; + } + img.tiles[0].tileComps[0].nQuantSteps = (segLen - 3) / 2; + img.tiles[0].tileComps[0].quantSteps = + (Guint *)greallocn(img.tiles[0].tileComps[0].quantSteps, + img.tiles[0].tileComps[0].nQuantSteps, + sizeof(Guint)); + for (i = 0; i < img.tiles[0].tileComps[0].nQuantSteps; ++i) { + if (!readUWord(&img.tiles[0].tileComps[0].quantSteps[i])) { + error(errSyntaxError, getPos(), "Error in JPX QCD marker segment"); + return jpxDecodeFatalError; + } + } + } else { + error(errSyntaxError, getPos(), "Error in JPX QCD marker segment"); + return jpxDecodeFatalError; + } + for (i = 0; i < img.nXTiles * img.nYTiles; ++i) { + for (comp = 0; comp < img.nComps; ++comp) { + if (!(i == 0 && comp == 0)) { + img.tiles[i].tileComps[comp].quantStyle = + img.tiles[0].tileComps[0].quantStyle; + img.tiles[i].tileComps[comp].nQuantSteps = + img.tiles[0].tileComps[0].nQuantSteps; + img.tiles[i].tileComps[comp].quantSteps = + (Guint *)greallocn(img.tiles[i].tileComps[comp].quantSteps, + img.tiles[0].tileComps[0].nQuantSteps, + sizeof(Guint)); + for (j = 0; j < img.tiles[0].tileComps[0].nQuantSteps; ++j) { + img.tiles[i].tileComps[comp].quantSteps[j] = + img.tiles[0].tileComps[0].quantSteps[j]; + } + } + } + } + haveQCD = gTrue; + break; + case 0x5d: // QCC - quantization component + cover(24); + if (!haveQCD) { + error(errSyntaxError, getPos(), + "JPX QCC marker segment before QCD segment"); + return jpxDecodeFatalError; + } + if ((img.nComps > 256 && !readUWord(&comp)) || + (img.nComps <= 256 && !readUByte(&comp)) || + comp >= img.nComps || + !readUByte(&img.tiles[0].tileComps[comp].quantStyle)) { + error(errSyntaxError, getPos(), "Error in JPX QCC marker segment"); + return jpxDecodeFatalError; + } + if ((img.tiles[0].tileComps[comp].quantStyle & 0x1f) == 0x00) { + if (segLen <= (img.nComps > 256 ? 5U : 4U)) { + error(errSyntaxError, getPos(), "Error in JPX QCC marker segment"); + return jpxDecodeFatalError; + } + img.tiles[0].tileComps[comp].nQuantSteps = + segLen - (img.nComps > 256 ? 5 : 4); + img.tiles[0].tileComps[comp].quantSteps = + (Guint *)greallocn(img.tiles[0].tileComps[comp].quantSteps, + img.tiles[0].tileComps[comp].nQuantSteps, + sizeof(Guint)); + for (i = 0; i < img.tiles[0].tileComps[comp].nQuantSteps; ++i) { + if (!readUByte(&img.tiles[0].tileComps[comp].quantSteps[i])) { + error(errSyntaxError, getPos(), "Error in JPX QCC marker segment"); + return jpxDecodeFatalError; + } + } + } else if ((img.tiles[0].tileComps[comp].quantStyle & 0x1f) == 0x01) { + img.tiles[0].tileComps[comp].nQuantSteps = 1; + img.tiles[0].tileComps[comp].quantSteps = + (Guint *)greallocn(img.tiles[0].tileComps[comp].quantSteps, + img.tiles[0].tileComps[comp].nQuantSteps, + sizeof(Guint)); + if (!readUWord(&img.tiles[0].tileComps[comp].quantSteps[0])) { + error(errSyntaxError, getPos(), "Error in JPX QCC marker segment"); + return jpxDecodeFatalError; + } + } else if ((img.tiles[0].tileComps[comp].quantStyle & 0x1f) == 0x02) { + if (segLen < (img.nComps > 256 ? 5U : 4U) + 2) { + error(errSyntaxError, getPos(), "Error in JPX QCC marker segment"); + return jpxDecodeFatalError; + } + img.tiles[0].tileComps[comp].nQuantSteps = + (segLen - (img.nComps > 256 ? 5 : 4)) / 2; + img.tiles[0].tileComps[comp].quantSteps = + (Guint *)greallocn(img.tiles[0].tileComps[comp].quantSteps, + img.tiles[0].tileComps[comp].nQuantSteps, + sizeof(Guint)); + for (i = 0; i < img.tiles[0].tileComps[comp].nQuantSteps; ++i) { + if (!readUWord(&img.tiles[0].tileComps[comp].quantSteps[i])) { + error(errSyntaxError, getPos(), "Error in JPX QCD marker segment"); + return jpxDecodeFatalError; + } + } + } else { + error(errSyntaxError, getPos(), "Error in JPX QCC marker segment"); + return jpxDecodeFatalError; + } + for (i = 1; i < img.nXTiles * img.nYTiles; ++i) { + img.tiles[i].tileComps[comp].quantStyle = + img.tiles[0].tileComps[comp].quantStyle; + img.tiles[i].tileComps[comp].nQuantSteps = + img.tiles[0].tileComps[comp].nQuantSteps; + img.tiles[i].tileComps[comp].quantSteps = + (Guint *)greallocn(img.tiles[i].tileComps[comp].quantSteps, + img.tiles[0].tileComps[comp].nQuantSteps, + sizeof(Guint)); + for (j = 0; j < img.tiles[0].tileComps[comp].nQuantSteps; ++j) { + img.tiles[i].tileComps[comp].quantSteps[j] = + img.tiles[0].tileComps[comp].quantSteps[j]; + } + } + break; + case 0x5e: // RGN - region of interest + cover(25); +#if 1 //~ ROI is unimplemented + error(errUnimplemented, -1, "got a JPX RGN segment"); + if (segLen > 2 && + bufStr->discardChars(segLen - 2) != segLen - 2) { + error(errSyntaxError, getPos(), "Error in JPX RGN marker segment"); + return jpxDecodeFatalError; + } +#else + if ((img.nComps > 256 && !readUWord(&comp)) || + (img.nComps <= 256 && !readUByte(&comp)) || + comp >= img.nComps || + !readUByte(&compInfo[comp].defROI.style) || + !readUByte(&compInfo[comp].defROI.shift)) { + error(errSyntaxError, getPos(), "Error in JPX RGN marker segment"); + return jpxDecodeFatalError; + } +#endif + break; + case 0x5f: // POC - progression order change + cover(26); +#if 1 //~ progression order changes are unimplemented + error(errUnimplemented, -1, "got a JPX POC segment"); + if (segLen > 2 && + bufStr->discardChars(segLen - 2) != segLen - 2) { + error(errSyntaxError, getPos(), "Error in JPX POC marker segment"); + return jpxDecodeFatalError; + } +#else + nProgs = (segLen - 2) / (img.nComps > 256 ? 9 : 7); + progs = (JPXProgOrder *)gmallocn(nProgs, sizeof(JPXProgOrder)); + for (i = 0; i < nProgs; ++i) { + if (!readUByte(&progs[i].startRes) || + !(img.nComps > 256 && readUWord(&progs[i].startComp)) || + !(img.nComps <= 256 && readUByte(&progs[i].startComp)) || + !readUWord(&progs[i].endLayer) || + !readUByte(&progs[i].endRes) || + !(img.nComps > 256 && readUWord(&progs[i].endComp)) || + !(img.nComps <= 256 && readUByte(&progs[i].endComp)) || + !readUByte(&progs[i].progOrder)) { + error(errSyntaxError, getPos(), "Error in JPX POC marker segment"); + return jpxDecodeFatalError; + } + } +#endif + break; + case 0x60: // PPM - packed packet headers, main header + cover(27); +#if 1 //~ packed packet headers are unimplemented + error(errUnimplemented, -1, "Got a JPX PPM segment"); + if (segLen > 2 && + bufStr->discardChars(segLen - 2) != segLen - 2) { + error(errSyntaxError, getPos(), "Error in JPX PPM marker segment"); + return jpxDecodeFatalError; + } +#endif + break; + case 0x55: // TLM - tile-part lengths + // skipped + cover(28); + if (segLen > 2 && + bufStr->discardChars(segLen - 2) != segLen - 2) { + error(errSyntaxError, getPos(), "Error in JPX TLM marker segment"); + return jpxDecodeFatalError; + } + break; + case 0x57: // PLM - packet length, main header + // skipped + cover(29); + if (segLen > 2 && + bufStr->discardChars(segLen - 2) != segLen - 2) { + error(errSyntaxError, getPos(), "Error in JPX PLM marker segment"); + return jpxDecodeFatalError; + } + break; + case 0x63: // CRG - component registration + // skipped + cover(30); + if (segLen > 2 && + bufStr->discardChars(segLen - 2) != segLen - 2) { + error(errSyntaxError, getPos(), "Error in JPX CRG marker segment"); + return jpxDecodeFatalError; + } + break; + case 0x64: // COM - comment + // skipped + cover(31); + if (segLen > 2 && + bufStr->discardChars(segLen - 2) != segLen - 2) { + error(errSyntaxError, getPos(), "Error in JPX COM marker segment"); + return jpxDecodeFatalError; + } + break; + case 0x90: // SOT - start of tile + cover(32); + haveSOT = gTrue; + break; + default: + cover(33); + error(errSyntaxError, getPos(), + "Unknown marker segment {0:02x} in JPX stream", segType); + if (segLen > 2) { + bufStr->discardChars(segLen - 2); + } + break; + } + } while (!haveSOT); + + if (!haveSIZ) { + error(errSyntaxError, getPos(), + "Missing SIZ marker segment in JPX stream"); + return jpxDecodeFatalError; + } + if (!haveCOD) { + error(errSyntaxError, getPos(), + "Missing COD marker segment in JPX stream"); + return jpxDecodeFatalError; + } + if (!haveQCD) { + error(errSyntaxError, getPos(), + "Missing QCD marker segment in JPX stream"); + return jpxDecodeFatalError; + } + + //----- read the tile-parts + ok = gTrue; + while (1) { + if (!readTilePart()) { + ok = gFalse; + break; + } + if (!readMarkerHdr(&segType, &segLen)) { + error(errSyntaxError, getPos(), "Error in JPX codestream"); + ok = gFalse; + break; + } + if (segType != 0x90) { // SOT - start of tile + break; + } + } + + if (segType != 0xd9) { // EOC - end of codestream + error(errSyntaxError, getPos(), "Missing EOC marker in JPX codestream"); + ok = 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 jpxDecodeFatalError; + } + for (comp = 0; comp < img.nComps; ++comp) { + tileComp = &tile->tileComps[comp]; + inverseTransform(tileComp); + } + if (!inverseMultiCompAndDC(tile)) { + return jpxDecodeFatalError; + } + } + + //~ can free memory below tileComps here, and also tileComp.buf + + return ok ? jpxDecodeOk : jpxDecodeNonFatalError; +} + +GBool JPXStream::readTilePart() { + JPXTile *tile; + JPXTileComp *tileComp; + JPXResLevel *resLevel; + JPXPrecinct *precinct; + JPXSubband *subband; + JPXCodeBlock *cb; + int *sbCoeffs; + GBool haveSOD; + Guint tileIdx, tilePartLen, tilePartIdx, nTileParts; + GBool tilePartToEOC; + Guint style, progOrder, nLayers, multiComp, nDecompLevels; + Guint codeBlockW, codeBlockH, codeBlockStyle, transform; + Guint precinctSize, qStyle; + Guint px0, py0, px1, py1; + Guint preCol0, preCol1, preRow0, preRow1, preCol, preRow; + Guint cbCol0, cbCol1, cbRow0, cbRow1, cbX, cbY; + Guint n, nSBs, nx, ny, comp, segLen; + Guint i, j, k, r, pre, sb, cbi, cbj; + int segType, level; + + // process the SOT marker segment + if (!readUWord(&tileIdx) || + !readULong(&tilePartLen) || + !readUByte(&tilePartIdx) || + !readUByte(&nTileParts)) { + error(errSyntaxError, getPos(), "Error in JPX SOT marker segment"); + return gFalse; + } + + // check tileIdx and tilePartIdx + // (this ignores nTileParts, because some encoders get it wrong) + if (tileIdx >= img.nXTiles * img.nYTiles || + tilePartIdx != img.tiles[tileIdx].nextTilePart || + (tilePartIdx > 0 && !img.tiles[tileIdx].init) || + (tilePartIdx == 0 && img.tiles[tileIdx].init)) { + error(errSyntaxError, getPos(), "Weird tile-part header in JPX stream"); + return gFalse; + } + ++img.tiles[tileIdx].nextTilePart; + + tilePartToEOC = tilePartLen == 0; + tilePartLen -= 12; // subtract size of SOT segment + + haveSOD = gFalse; + do { + if (!readMarkerHdr(&segType, &segLen)) { + error(errSyntaxError, getPos(), "Error in JPX tile-part codestream"); + return gFalse; + } + tilePartLen -= 2 + segLen; + switch (segType) { + case 0x52: // COD - coding style default + cover(34); + if (tilePartIdx != 0) { + error(errSyntaxError, getPos(), "Extraneous JPX COD marker segment"); + return gFalse; + } + if (!readUByte(&style) || + !readUByte(&progOrder) || + !readUWord(&nLayers) || + !readUByte(&multiComp) || + !readUByte(&nDecompLevels) || + !readUByte(&codeBlockW) || + !readUByte(&codeBlockH) || + !readUByte(&codeBlockStyle) || + !readUByte(&transform)) { + error(errSyntaxError, getPos(), "Error in JPX COD marker segment"); + return gFalse; + } + if (nDecompLevels < 1 || + nDecompLevels > 31 || + codeBlockW > 8 || + codeBlockH > 8) { + error(errSyntaxError, getPos(), "Error in JPX COD marker segment"); + return gFalse; + } + codeBlockW += 2; + codeBlockH += 2; + img.tiles[tileIdx].progOrder = progOrder; + img.tiles[tileIdx].nLayers = nLayers; + img.tiles[tileIdx].multiComp = multiComp; + for (comp = 0; comp < img.nComps; ++comp) { + img.tiles[tileIdx].tileComps[comp].style = style; + img.tiles[tileIdx].tileComps[comp].nDecompLevels = nDecompLevels; + img.tiles[tileIdx].tileComps[comp].codeBlockW = codeBlockW; + img.tiles[tileIdx].tileComps[comp].codeBlockH = codeBlockH; + img.tiles[tileIdx].tileComps[comp].codeBlockStyle = codeBlockStyle; + img.tiles[tileIdx].tileComps[comp].transform = transform; + img.tiles[tileIdx].tileComps[comp].resLevels = + (JPXResLevel *)greallocn( + img.tiles[tileIdx].tileComps[comp].resLevels, + nDecompLevels + 1, + sizeof(JPXResLevel)); + for (r = 0; r <= nDecompLevels; ++r) { + img.tiles[tileIdx].tileComps[comp].resLevels[r].precincts = NULL; + } + } + for (r = 0; r <= nDecompLevels; ++r) { + if (style & 0x01) { + if (!readUByte(&precinctSize)) { + error(errSyntaxError, getPos(), "Error in JPX COD marker segment"); + return gFalse; + } + if (r > 0 && ((precinctSize & 0x0f) == 0 || + (precinctSize & 0xf0) == 0)) { + error(errSyntaxError, getPos(), + "Invalid precinct size in JPX COD marker segment"); + return gFalse; + } + img.tiles[tileIdx].tileComps[0].resLevels[r].precinctWidth = + precinctSize & 0x0f; + img.tiles[tileIdx].tileComps[0].resLevels[r].precinctHeight = + (precinctSize >> 4) & 0x0f; + } else { + img.tiles[tileIdx].tileComps[0].resLevels[r].precinctWidth = 15; + img.tiles[tileIdx].tileComps[0].resLevels[r].precinctHeight = 15; + } + } + for (comp = 1; comp < img.nComps; ++comp) { + for (r = 0; r <= nDecompLevels; ++r) { + img.tiles[tileIdx].tileComps[comp].resLevels[r].precinctWidth = + img.tiles[tileIdx].tileComps[0].resLevels[r].precinctWidth; + img.tiles[tileIdx].tileComps[comp].resLevels[r].precinctHeight = + img.tiles[tileIdx].tileComps[0].resLevels[r].precinctHeight; + } + } + break; + case 0x53: // COC - coding style component + cover(35); + if (tilePartIdx != 0) { + error(errSyntaxError, getPos(), "Extraneous JPX COC marker segment"); + return gFalse; + } + if ((img.nComps > 256 && !readUWord(&comp)) || + (img.nComps <= 256 && !readUByte(&comp)) || + comp >= img.nComps || + !readUByte(&style) || + !readUByte(&nDecompLevels) || + !readUByte(&codeBlockW) || + !readUByte(&codeBlockH) || + !readUByte(&codeBlockStyle) || + !readUByte(&transform)) { + error(errSyntaxError, getPos(), "Error in JPX COC marker segment"); + return gFalse; + } + if (nDecompLevels < 1 || + nDecompLevels > 31 || + codeBlockW > 8 || + codeBlockH > 8) { + error(errSyntaxError, getPos(), "Error in JPX COC marker segment"); + return gFalse; + } + img.tiles[tileIdx].tileComps[comp].style = + (img.tiles[tileIdx].tileComps[comp].style & ~1) | (style & 1); + img.tiles[tileIdx].tileComps[comp].nDecompLevels = nDecompLevels; + img.tiles[tileIdx].tileComps[comp].codeBlockW = codeBlockW + 2; + img.tiles[tileIdx].tileComps[comp].codeBlockH = codeBlockH + 2; + img.tiles[tileIdx].tileComps[comp].codeBlockStyle = codeBlockStyle; + img.tiles[tileIdx].tileComps[comp].transform = transform; + img.tiles[tileIdx].tileComps[comp].resLevels = + (JPXResLevel *)greallocn( + img.tiles[tileIdx].tileComps[comp].resLevels, + nDecompLevels + 1, + sizeof(JPXResLevel)); + for (r = 0; r <= nDecompLevels; ++r) { + img.tiles[tileIdx].tileComps[comp].resLevels[r].precincts = NULL; + } + for (r = 0; r <= nDecompLevels; ++r) { + if (style & 0x01) { + if (!readUByte(&precinctSize)) { + error(errSyntaxError, getPos(), "Error in JPX COD marker segment"); + return gFalse; + } + if (r > 0 && ((precinctSize & 0x0f) == 0 || + (precinctSize & 0xf0) == 0)) { + error(errSyntaxError, getPos(), + "Invalid precinct size in JPX COD marker segment"); + return gFalse; + } + img.tiles[tileIdx].tileComps[comp].resLevels[r].precinctWidth = + precinctSize & 0x0f; + img.tiles[tileIdx].tileComps[comp].resLevels[r].precinctHeight = + (precinctSize >> 4) & 0x0f; + } else { + img.tiles[tileIdx].tileComps[comp].resLevels[r].precinctWidth = 15; + img.tiles[tileIdx].tileComps[comp].resLevels[r].precinctHeight = 15; + } + } + break; + case 0x5c: // QCD - quantization default + cover(36); + if (tilePartIdx != 0) { + error(errSyntaxError, getPos(), "Extraneous JPX QCD marker segment"); + return gFalse; + } + if (!readUByte(&img.tiles[tileIdx].tileComps[0].quantStyle)) { + error(errSyntaxError, getPos(), "Error in JPX QCD marker segment"); + return gFalse; + } + if ((img.tiles[tileIdx].tileComps[0].quantStyle & 0x1f) == 0x00) { + 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(errSyntaxError, getPos(), "Error in JPX QCD marker segment"); + return gFalse; + } + } + } else if ((img.tiles[tileIdx].tileComps[0].quantStyle & 0x1f) == 0x01) { + img.tiles[tileIdx].tileComps[0].nQuantSteps = 1; + img.tiles[tileIdx].tileComps[0].quantSteps = + (Guint *)greallocn(img.tiles[tileIdx].tileComps[0].quantSteps, + img.tiles[tileIdx].tileComps[0].nQuantSteps, + sizeof(Guint)); + if (!readUWord(&img.tiles[tileIdx].tileComps[0].quantSteps[0])) { + 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, + img.tiles[tileIdx].tileComps[0].nQuantSteps, + sizeof(Guint)); + for (i = 0; i < img.tiles[tileIdx].tileComps[0].nQuantSteps; ++i) { + if (!readUWord(&img.tiles[tileIdx].tileComps[0].quantSteps[i])) { + error(errSyntaxError, getPos(), "Error in JPX QCD marker segment"); + return gFalse; + } + } + } else { + error(errSyntaxError, getPos(), "Error in JPX QCD marker segment"); + return gFalse; + } + for (comp = 1; comp < img.nComps; ++comp) { + img.tiles[tileIdx].tileComps[comp].quantStyle = + img.tiles[tileIdx].tileComps[0].quantStyle; + img.tiles[tileIdx].tileComps[comp].nQuantSteps = + img.tiles[tileIdx].tileComps[0].nQuantSteps; + img.tiles[tileIdx].tileComps[comp].quantSteps = + (Guint *)greallocn(img.tiles[tileIdx].tileComps[comp].quantSteps, + img.tiles[tileIdx].tileComps[0].nQuantSteps, + sizeof(Guint)); + for (j = 0; j < img.tiles[tileIdx].tileComps[0].nQuantSteps; ++j) { + img.tiles[tileIdx].tileComps[comp].quantSteps[j] = + img.tiles[tileIdx].tileComps[0].quantSteps[j]; + } + } + break; + case 0x5d: // QCC - quantization component + cover(37); + if (tilePartIdx != 0) { + error(errSyntaxError, getPos(), "Extraneous JPX QCC marker segment"); + return gFalse; + } + if ((img.nComps > 256 && !readUWord(&comp)) || + (img.nComps <= 256 && !readUByte(&comp)) || + comp >= img.nComps || + !readUByte(&img.tiles[tileIdx].tileComps[comp].quantStyle)) { + 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 = + (Guint *)greallocn(img.tiles[tileIdx].tileComps[comp].quantSteps, + img.tiles[tileIdx].tileComps[comp].nQuantSteps, + sizeof(Guint)); + for (i = 0; i < img.tiles[tileIdx].tileComps[comp].nQuantSteps; ++i) { + if (!readUByte(&img.tiles[tileIdx].tileComps[comp].quantSteps[i])) { + error(errSyntaxError, getPos(), "Error in JPX QCC marker segment"); + return gFalse; + } + } + } else if ((img.tiles[tileIdx].tileComps[comp].quantStyle & 0x1f) + == 0x01) { + img.tiles[tileIdx].tileComps[comp].nQuantSteps = 1; + img.tiles[tileIdx].tileComps[comp].quantSteps = + (Guint *)greallocn(img.tiles[tileIdx].tileComps[comp].quantSteps, + img.tiles[tileIdx].tileComps[comp].nQuantSteps, + sizeof(Guint)); + if (!readUWord(&img.tiles[tileIdx].tileComps[comp].quantSteps[0])) { + 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 = + (Guint *)greallocn(img.tiles[tileIdx].tileComps[comp].quantSteps, + img.tiles[tileIdx].tileComps[comp].nQuantSteps, + sizeof(Guint)); + for (i = 0; i < img.tiles[tileIdx].tileComps[comp].nQuantSteps; ++i) { + if (!readUWord(&img.tiles[tileIdx].tileComps[comp].quantSteps[i])) { + error(errSyntaxError, getPos(), "Error in JPX QCD marker segment"); + return gFalse; + } + } + } else { + error(errSyntaxError, getPos(), "Error in JPX QCC marker segment"); + return gFalse; + } + break; + case 0x5e: // RGN - region of interest + cover(38); + if (tilePartIdx != 0) { + error(errSyntaxError, getPos(), "Extraneous JPX RGN marker segment"); + return gFalse; + } +#if 1 //~ ROI is unimplemented + error(errUnimplemented, -1, "Got a JPX RGN segment"); + if (segLen > 2 && + bufStr->discardChars(segLen - 2) != segLen - 2) { + error(errSyntaxError, getPos(), "Error in JPX RGN marker segment"); + return gFalse; + } +#else + if ((img.nComps > 256 && !readUWord(&comp)) || + (img.nComps <= 256 && !readUByte(&comp)) || + comp >= img.nComps || + !readUByte(&compInfo[comp].roi.style) || + !readUByte(&compInfo[comp].roi.shift)) { + error(errSyntaxError, getPos(), "Error in JPX RGN marker segment"); + return gFalse; + } +#endif + break; + case 0x5f: // POC - progression order change + cover(39); +#if 1 //~ progression order changes are unimplemented + error(errUnimplemented, -1, "Got a JPX POC segment"); + if (segLen > 2 && + bufStr->discardChars(segLen - 2) != segLen - 2) { + error(errSyntaxError, getPos(), "Error in JPX POC marker segment"); + return gFalse; + } +#else + nTileProgs = (segLen - 2) / (img.nComps > 256 ? 9 : 7); + tileProgs = (JPXProgOrder *)gmallocn(nTileProgs, sizeof(JPXProgOrder)); + for (i = 0; i < nTileProgs; ++i) { + if (!readUByte(&tileProgs[i].startRes) || + !(img.nComps > 256 && readUWord(&tileProgs[i].startComp)) || + !(img.nComps <= 256 && readUByte(&tileProgs[i].startComp)) || + !readUWord(&tileProgs[i].endLayer) || + !readUByte(&tileProgs[i].endRes) || + !(img.nComps > 256 && readUWord(&tileProgs[i].endComp)) || + !(img.nComps <= 256 && readUByte(&tileProgs[i].endComp)) || + !readUByte(&tileProgs[i].progOrder)) { + error(errSyntaxError, getPos(), "Error in JPX POC marker segment"); + return gFalse; + } + } +#endif + break; + case 0x61: // PPT - packed packet headers, tile-part hdr + cover(40); +#if 1 //~ packed packet headers are unimplemented + error(errUnimplemented, -1, "Got a JPX PPT segment"); + if (segLen > 2 && + bufStr->discardChars(segLen - 2) != segLen - 2) { + error(errSyntaxError, getPos(), "Error in JPX PPT marker segment"); + return gFalse; + } +#endif + case 0x58: // PLT - packet length, tile-part header + // skipped + cover(41); + if (segLen > 2 && + bufStr->discardChars(segLen - 2) != segLen - 2) { + error(errSyntaxError, getPos(), "Error in JPX PLT marker segment"); + return gFalse; + } + break; + case 0x64: // COM - comment + // skipped + cover(42); + if (segLen > 2 && + bufStr->discardChars(segLen - 2) != segLen - 2) { + error(errSyntaxError, getPos(), "Error in JPX COM marker segment"); + return gFalse; + } + break; + case 0x93: // SOD - start of data + cover(43); + haveSOD = gTrue; + break; + default: + cover(44); + error(errSyntaxError, getPos(), + "Unknown marker segment {0:02x} in JPX tile-part stream", + segType); + if (segLen > 2) { + bufStr->discardChars(segLen - 2); + } + break; + } + } while (!haveSOD); + + for (comp = 0; comp < img.nComps; ++comp) { + tileComp = &img.tiles[tileIdx].tileComps[comp]; + qStyle = tileComp->quantStyle & 0x1f; + if ((qStyle == 0 && tileComp->nQuantSteps < 3 * tileComp->nDecompLevels + 1) || + (qStyle == 1 && tileComp->nQuantSteps < 1) || + (qStyle == 2 && tileComp->nQuantSteps < 3 * tileComp->nDecompLevels + 1)) { + error(errSyntaxError, getPos(), "Too few quant steps in JPX tile part"); + return gFalse; + } + } + + //----- initialize the tile, precincts, and code-blocks + if (tilePartIdx == 0) { + tile = &img.tiles[tileIdx]; + i = tileIdx / img.nXTiles; + j = tileIdx % img.nXTiles; + if ((tile->x0 = img.xTileOffset + j * img.xTileSize) < img.xOffset) { + tile->x0 = img.xOffset; + } + if ((tile->y0 = img.yTileOffset + i * img.yTileSize) < img.yOffset) { + tile->y0 = img.yOffset; + } + if ((tile->x1 = img.xTileOffset + (j + 1) * img.xTileSize) > img.xSize) { + tile->x1 = img.xSize; + } + if ((tile->y1 = img.yTileOffset + (i + 1) * img.yTileSize) > img.ySize) { + tile->y1 = img.ySize; + } + tile->comp = 0; + tile->res = 0; + tile->precinct = 0; + tile->layer = 0; + tile->done = gFalse; + tile->maxNDecompLevels = 0; + tile->maxNPrecincts = 0; + for (comp = 0; comp < img.nComps; ++comp) { + tileComp = &tile->tileComps[comp]; + if (tileComp->nDecompLevels > tile->maxNDecompLevels) { + tile->maxNDecompLevels = tileComp->nDecompLevels; + } + tileComp->x0 = jpxCeilDiv(tile->x0, tileComp->hSep); + tileComp->y0 = jpxCeilDiv(tile->y0, tileComp->vSep); + tileComp->x1 = jpxCeilDiv(tile->x1, tileComp->hSep); + tileComp->y1 = jpxCeilDiv(tile->y1, tileComp->vSep); + tileComp->x0r = jpxCeilDivPow2(tileComp->x0, reduction); + tileComp->w = jpxCeilDivPow2(tileComp->x1, reduction) - tileComp->x0r; + tileComp->y0r = jpxCeilDivPow2(tileComp->y0, reduction); + tileComp->h = jpxCeilDivPow2(tileComp->y1, reduction) - tileComp->y0r; + if (tileComp->w == 0 || tileComp->h == 0 || + tileComp->w > INT_MAX / tileComp->h) { + error(errSyntaxError, getPos(), + "Invalid tile size or sample separation in JPX stream"); + return gFalse; + } + tileComp->data = (int *)gmallocn(tileComp->w * tileComp->h, sizeof(int)); + if (tileComp->x1 - tileComp->x0 > tileComp->y1 - tileComp->y0) { + n = tileComp->x1 - tileComp->x0; + } else { + n = tileComp->y1 - tileComp->y0; + } + tileComp->buf = (int *)gmallocn(n + 8, sizeof(int)); + for (r = 0; r <= tileComp->nDecompLevels; ++r) { + resLevel = &tileComp->resLevels[r]; + resLevel->x0 = jpxCeilDivPow2(tileComp->x0, + tileComp->nDecompLevels - r); + resLevel->y0 = jpxCeilDivPow2(tileComp->y0, + tileComp->nDecompLevels - r); + resLevel->x1 = jpxCeilDivPow2(tileComp->x1, + tileComp->nDecompLevels - r); + resLevel->y1 = jpxCeilDivPow2(tileComp->y1, + tileComp->nDecompLevels - r); + resLevel->codeBlockW = r == 0 ? resLevel->precinctWidth + : resLevel->precinctWidth - 1; + if (resLevel->codeBlockW > tileComp->codeBlockW) { + resLevel->codeBlockW = tileComp->codeBlockW; + } + resLevel->cbW = 1 << resLevel->codeBlockW; + resLevel->codeBlockH = r == 0 ? resLevel->precinctHeight + : resLevel->precinctHeight - 1; + if (resLevel->codeBlockH > tileComp->codeBlockH) { + resLevel->codeBlockH = tileComp->codeBlockH; + } + resLevel->cbH = 1 << resLevel->codeBlockH; + // the JPEG 2000 spec says that packets for empty res levels + // should all be present in the codestream (B.6, B.9, B.10), + // but it appears that encoders drop packets if the res level + // AND the subbands are all completely empty + resLevel->empty = resLevel->x0 == resLevel->x1 || + resLevel->y0 == resLevel->y1; + if (r == 0) { + nSBs = 1; + resLevel->bx0[0] = resLevel->x0; + resLevel->by0[0] = resLevel->y0; + resLevel->bx1[0] = resLevel->x1; + resLevel->by1[0] = resLevel->y1; + resLevel->empty = resLevel->empty && + (resLevel->bx0[0] == resLevel->bx1[0] || + resLevel->by0[0] == resLevel->by1[0]); + } else { + nSBs = 3; + resLevel->bx0[0] = jpxCeilDivPow2(resLevel->x0 - 1, 1); + resLevel->by0[0] = jpxCeilDivPow2(resLevel->y0, 1); + resLevel->bx1[0] = jpxCeilDivPow2(resLevel->x1 - 1, 1); + resLevel->by1[0] = jpxCeilDivPow2(resLevel->y1, 1); + resLevel->bx0[1] = jpxCeilDivPow2(resLevel->x0, 1); + resLevel->by0[1] = jpxCeilDivPow2(resLevel->y0 - 1, 1); + resLevel->bx1[1] = jpxCeilDivPow2(resLevel->x1, 1); + resLevel->by1[1] = jpxCeilDivPow2(resLevel->y1 - 1, 1); + resLevel->bx0[2] = jpxCeilDivPow2(resLevel->x0 - 1, 1); + resLevel->by0[2] = jpxCeilDivPow2(resLevel->y0 - 1, 1); + resLevel->bx1[2] = jpxCeilDivPow2(resLevel->x1 - 1, 1); + resLevel->by1[2] = jpxCeilDivPow2(resLevel->y1 - 1, 1); + resLevel->empty = resLevel->empty && + (resLevel->bx0[0] == resLevel->bx1[0] || + resLevel->by0[0] == resLevel->by1[0]) && + (resLevel->bx0[1] == resLevel->bx1[1] || + resLevel->by0[1] == resLevel->by1[1]) && + (resLevel->bx0[2] == resLevel->bx1[2] || + resLevel->by0[2] == resLevel->by1[2]); + } + preCol0 = jpxFloorDivPow2(resLevel->x0, resLevel->precinctWidth); + preCol1 = jpxCeilDivPow2(resLevel->x1, resLevel->precinctWidth); + preRow0 = jpxFloorDivPow2(resLevel->y0, resLevel->precinctHeight); + preRow1 = jpxCeilDivPow2(resLevel->y1, resLevel->precinctHeight); + resLevel->nPrecincts = (preCol1 - preCol0) * (preRow1 - preRow0); + resLevel->precincts = (JPXPrecinct *)gmallocn(resLevel->nPrecincts, + sizeof(JPXPrecinct)); + if (resLevel->nPrecincts > tile->maxNPrecincts) { + tile->maxNPrecincts = resLevel->nPrecincts; + } + for (pre = 0; pre < resLevel->nPrecincts; ++pre) { + resLevel->precincts[pre].subbands = NULL; + } + precinct = resLevel->precincts; + for (preRow = preRow0; preRow < preRow1; ++preRow) { + for (preCol = preCol0; preCol < preCol1; ++preCol) { + precinct->subbands = + (JPXSubband *)gmallocn(nSBs, sizeof(JPXSubband)); + for (sb = 0; sb < nSBs; ++sb) { + precinct->subbands[sb].inclusion = NULL; + precinct->subbands[sb].zeroBitPlane = NULL; + precinct->subbands[sb].cbs = NULL; + } + for (sb = 0; sb < nSBs; ++sb) { + subband = &precinct->subbands[sb]; + if (r == 0) { + px0 = preCol << resLevel->precinctWidth; + px1 = (preCol + 1) << resLevel->precinctWidth; + py0 = preRow << resLevel->precinctHeight; + py1 = (preRow + 1) << resLevel->precinctHeight; + } else { + px0 = preCol << (resLevel->precinctWidth - 1); + px1 = (preCol + 1) << (resLevel->precinctWidth - 1); + py0 = preRow << (resLevel->precinctHeight - 1); + py1 = (preRow + 1) << (resLevel->precinctHeight - 1); + } + if (px0 < resLevel->bx0[sb]) { + px0 = resLevel->bx0[sb]; + } + if (px1 > resLevel->bx1[sb]) { + px1 = resLevel->bx1[sb]; + } + if (py0 < resLevel->by0[sb]) { + py0 = resLevel->by0[sb]; + } + if (py1 > resLevel->by1[sb]) { + py1 = resLevel->by1[sb]; + } + 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]); + } + cbCol0 = jpxFloorDivPow2(px0, resLevel->codeBlockW); + cbCol1 = jpxCeilDivPow2(px1, resLevel->codeBlockW); + cbRow0 = jpxFloorDivPow2(py0, resLevel->codeBlockH); + cbRow1 = jpxCeilDivPow2(py1, resLevel->codeBlockH); + subband->nXCBs = cbCol1 - cbCol0; + subband->nYCBs = cbRow1 - cbRow0; + n = subband->nXCBs > subband->nYCBs ? subband->nXCBs + : subband->nYCBs; + for (subband->maxTTLevel = 0, --n; + n; + ++subband->maxTTLevel, n >>= 1) ; + n = 0; + for (level = subband->maxTTLevel; level >= 0; --level) { + nx = jpxCeilDivPow2(subband->nXCBs, level); + ny = jpxCeilDivPow2(subband->nYCBs, level); + n += nx * ny; + } + subband->inclusion = + (JPXTagTreeNode *)gmallocn(n, sizeof(JPXTagTreeNode)); + subband->zeroBitPlane = + (JPXTagTreeNode *)gmallocn(n, sizeof(JPXTagTreeNode)); + for (k = 0; k < n; ++k) { + subband->inclusion[k].finished = gFalse; + subband->inclusion[k].val = 0; + subband->zeroBitPlane[k].finished = gFalse; + subband->zeroBitPlane[k].val = 0; + } + subband->cbs = (JPXCodeBlock *)gmallocn(subband->nXCBs * + subband->nYCBs, + sizeof(JPXCodeBlock)); + for (k = 0; k < subband->nXCBs * subband->nYCBs; ++k) { + subband->cbs[k].dataLen = NULL; + subband->cbs[k].touched = NULL; + subband->cbs[k].arithDecoder = NULL; + subband->cbs[k].stats = NULL; + } + cb = subband->cbs; + for (cbY = cbRow0; cbY < cbRow1; ++cbY) { + for (cbX = cbCol0; cbX < cbCol1; ++cbX) { + cb->x0 = cbX << resLevel->codeBlockW; + cb->x1 = cb->x0 + resLevel->cbW; + if (cb->x0 < px0) { + cb->x0 = px0; + } + if (cb->x1 > px1) { + cb->x1 = px1; + } + cb->y0 = cbY << resLevel->codeBlockH; + cb->y1 = cb->y0 + resLevel->cbH; + if (cb->y0 < py0) { + cb->y0 = py0; + } + if (cb->y1 > py1) { + cb->y1 = py1; + } + cb->seen = gFalse; + cb->lBlock = 3; + cb->nextPass = jpxPassCleanup; + cb->nZeroBitPlanes = 0; + cb->dataLenSize = 1; + cb->dataLen = (Guint *)gmalloc(sizeof(Guint)); + if (r <= tileComp->nDecompLevels - reduction) { + cb->coeffs = sbCoeffs + + (cb->y0 - resLevel->by0[sb]) * tileComp->w + + (cb->x0 - resLevel->bx0[sb]); + cb->touched = (char *)gmalloc(1 << (resLevel->codeBlockW + + resLevel->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, + ((size_t)1 << (resLevel->codeBlockW + + resLevel->codeBlockH))); + } else { + cb->coeffs = NULL; + cb->touched = NULL; + cb->len = 0; + } + ++cb; + } + } + } + ++precinct; + } + } + } + } + tile->init = gTrue; + } + + return readTilePartData(tileIdx, tilePartLen, tilePartToEOC); +} + +GBool JPXStream::readTilePartData(Guint tileIdx, + Guint tilePartLen, GBool tilePartToEOC) { + JPXTile *tile; + JPXTileComp *tileComp; + JPXResLevel *resLevel; + JPXPrecinct *precinct; + JPXSubband *subband; + JPXCodeBlock *cb; + Guint ttVal; + Guint bits, cbX, cbY, nx, ny, i, j, n, sb; + int level; + + tile = &img.tiles[tileIdx]; + + // read all packets from this tile-part + while (1) { + + // if the tile is finished, skip any remaining data + if (tile->done) { + bufStr->discardChars(tilePartLen); + return gTrue; + } + + if (tilePartToEOC) { + //~ peek for an EOC marker + cover(93); + } else if (tilePartLen == 0) { + break; + } + + tileComp = &tile->tileComps[tile->comp]; + resLevel = &tileComp->resLevels[tile->res]; + precinct = &resLevel->precincts[tile->precinct]; + + if (resLevel->empty) { + goto nextPacket; + } + + //----- packet header + + // setup + startBitBuf(tilePartLen); + if (tileComp->style & 0x02) { + skipSOP(); + } + + // zero-length flag + if (!readBits(1, &bits)) { + goto err; + } + if (!bits) { + // packet is empty -- clear all code-block inclusion flags + cover(45); + for (sb = 0; sb < (Guint)(tile->res == 0 ? 1 : 3); ++sb) { + subband = &precinct->subbands[sb]; + for (cbY = 0; cbY < subband->nYCBs; ++cbY) { + for (cbX = 0; cbX < subband->nXCBs; ++cbX) { + cb = &subband->cbs[cbY * subband->nXCBs + cbX]; + cb->included = gFalse; + } + } + } + } else { + + for (sb = 0; sb < (Guint)(tile->res == 0 ? 1 : 3); ++sb) { + subband = &precinct->subbands[sb]; + for (cbY = 0; cbY < subband->nYCBs; ++cbY) { + for (cbX = 0; cbX < subband->nXCBs; ++cbX) { + cb = &subband->cbs[cbY * subband->nXCBs + cbX]; + + // skip code-blocks with no coefficients + if (cb->x0 >= cb->x1 || cb->y0 >= cb->y1) { + cover(46); + cb->included = gFalse; + continue; + } + + // code-block inclusion + if (cb->seen) { + cover(47); + if (!readBits(1, &cb->included)) { + goto err; + } + } else { + cover(48); + ttVal = 0; + i = 0; + for (level = subband->maxTTLevel; level >= 0; --level) { + nx = jpxCeilDivPow2(subband->nXCBs, level); + ny = jpxCeilDivPow2(subband->nYCBs, level); + j = i + (cbY >> level) * nx + (cbX >> level); + if (!subband->inclusion[j].finished && + !subband->inclusion[j].val) { + subband->inclusion[j].val = ttVal; + } else { + ttVal = subband->inclusion[j].val; + } + while (!subband->inclusion[j].finished && + ttVal <= tile->layer) { + if (!readBits(1, &bits)) { + goto err; + } + if (bits == 1) { + subband->inclusion[j].finished = gTrue; + } else { + ++ttVal; + } + } + subband->inclusion[j].val = ttVal; + if (ttVal > tile->layer) { + break; + } + i += nx * ny; + } + cb->included = level < 0; + } + + if (cb->included) { + cover(49); + + // zero bit-plane count + if (!cb->seen) { + cover(50); + ttVal = 0; + i = 0; + for (level = subband->maxTTLevel; level >= 0; --level) { + nx = jpxCeilDivPow2(subband->nXCBs, level); + ny = jpxCeilDivPow2(subband->nYCBs, level); + j = i + (cbY >> level) * nx + (cbX >> level); + if (!subband->zeroBitPlane[j].finished && + !subband->zeroBitPlane[j].val) { + subband->zeroBitPlane[j].val = ttVal; + } else { + ttVal = subband->zeroBitPlane[j].val; + } + while (!subband->zeroBitPlane[j].finished) { + if (!readBits(1, &bits)) { + goto err; + } + if (bits == 1) { + subband->zeroBitPlane[j].finished = gTrue; + } else { + ++ttVal; + } + } + subband->zeroBitPlane[j].val = ttVal; + i += nx * ny; + } + cb->nZeroBitPlanes = ttVal; + } + + // number of coding passes + if (!readBits(1, &bits)) { + goto err; + } + if (bits == 0) { + cover(51); + cb->nCodingPasses = 1; + } else { + if (!readBits(1, &bits)) { + goto err; + } + if (bits == 0) { + cover(52); + cb->nCodingPasses = 2; + } else { + cover(53); + if (!readBits(2, &bits)) { + goto err; + } + if (bits < 3) { + cover(54); + cb->nCodingPasses = 3 + bits; + } else { + cover(55); + if (!readBits(5, &bits)) { + goto err; + } + if (bits < 31) { + cover(56); + cb->nCodingPasses = 6 + bits; + } else { + cover(57); + if (!readBits(7, &bits)) { + goto err; + } + cb->nCodingPasses = 37 + bits; + } + } + } + } + + // update Lblock + while (1) { + if (!readBits(1, &bits)) { + goto err; + } + if (!bits) { + break; + } + ++cb->lBlock; + } + + // 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 + + for (sb = 0; sb < (Guint)(tile->res == 0 ? 1 : 3); ++sb) { + subband = &precinct->subbands[sb]; + for (cbY = 0; cbY < subband->nYCBs; ++cbY) { + for (cbX = 0; cbX < subband->nXCBs; ++cbX) { + cb = &subband->cbs[cbY * subband->nXCBs + cbX]; + if (cb->included) { + if (!readCodeBlockData(tileComp, resLevel, precinct, subband, + tile->res, sb, cb)) { + return gFalse; + } + if (tileComp->codeBlockStyle & 0x04) { + for (i = 0; i < cb->nCodingPasses; ++i) { + tilePartLen -= cb->dataLen[i]; + } + } else { + tilePartLen -= cb->dataLen[0]; + } + cb->seen = gTrue; + } + } + } + } + + //----- next packet + + nextPacket: + switch (tile->progOrder) { + case 0: // layer, resolution level, component, precinct + cover(58); + do { + if (++tile->precinct == tile->maxNPrecincts) { + tile->precinct = 0; + if (++tile->comp == img.nComps) { + tile->comp = 0; + if (++tile->res == tile->maxNDecompLevels + 1) { + tile->res = 0; + if (++tile->layer == tile->nLayers) { + tile->layer = 0; + tile->done = gTrue; + } + } + } + } + } while (!tile->done && + (tile->res > tile->tileComps[tile->comp].nDecompLevels || + tile->precinct >= tile->tileComps[tile->comp] + .resLevels[tile->res].nPrecincts)); + break; + case 1: // resolution level, layer, component, precinct + cover(59); + do { + if (++tile->precinct == tile->maxNPrecincts) { + tile->precinct = 0; + if (++tile->comp == img.nComps) { + tile->comp = 0; + if (++tile->layer == tile->nLayers) { + tile->layer = 0; + if (++tile->res == tile->maxNDecompLevels + 1) { + tile->res = 0; + tile->done = gTrue; + } + } + } + } + } while (!tile->done && + (tile->res > tile->tileComps[tile->comp].nDecompLevels || + tile->precinct >= tile->tileComps[tile->comp] + .resLevels[tile->res].nPrecincts)); + break; + case 2: // resolution level, precinct, component, layer + cover(60); + //~ this is incorrect if there are subsampled components (?) + do { + if (++tile->layer == tile->nLayers) { + tile->layer = 0; + if (++tile->comp == img.nComps) { + tile->comp = 0; + if (++tile->precinct == tile->maxNPrecincts) { + tile->precinct = 0; + if (++tile->res == tile->maxNDecompLevels + 1) { + tile->res = 0; + tile->done = gTrue; + } + } + } + } + } while (!tile->done && + (tile->res > tile->tileComps[tile->comp].nDecompLevels || + tile->precinct >= tile->tileComps[tile->comp] + .resLevels[tile->res].nPrecincts)); + break; + case 3: // precinct, component, resolution level, layer + cover(61); + //~ this is incorrect if there are subsampled components (?) + do { + if (++tile->layer == tile->nLayers) { + tile->layer = 0; + if (++tile->res == tile->maxNDecompLevels + 1) { + tile->res = 0; + if (++tile->comp == img.nComps) { + tile->comp = 0; + if (++tile->precinct == tile->maxNPrecincts) { + tile->precinct = 0; + tile->done = gTrue; + } + } + } + } + } while (!tile->done && + (tile->res > tile->tileComps[tile->comp].nDecompLevels || + tile->precinct >= tile->tileComps[tile->comp] + .resLevels[tile->res].nPrecincts)); + break; + case 4: // component, precinct, resolution level, layer + cover(62); + do { + if (++tile->layer == tile->nLayers) { + tile->layer = 0; + if (++tile->res == tile->maxNDecompLevels + 1) { + tile->res = 0; + if (++tile->precinct == tile->maxNPrecincts) { + tile->precinct = 0; + if (++tile->comp == img.nComps) { + tile->comp = 0; + tile->done = gTrue; + } + } + } + } + } while (!tile->done && + (tile->res > tile->tileComps[tile->comp].nDecompLevels || + tile->precinct >= tile->tileComps[tile->comp] + .resLevels[tile->res].nPrecincts)); + break; + } + } + + return gTrue; + + err: + error(errSyntaxError, getPos(), "Error in JPX stream"); + return gFalse; +} + +GBool JPXStream::readCodeBlockData(JPXTileComp *tileComp, + JPXResLevel *resLevel, + JPXPrecinct *precinct, + JPXSubband *subband, + Guint res, Guint sb, + JPXCodeBlock *cb) { + int *coeff0, *coeff1, *coeff; + char *touched0, *touched1, *touched; + Guint horiz, vert, diag, all, cx, xorBit; + int horizSign, vertSign, bit; + int segSym; + Guint n, i, x, y0, y1; + + if (res > tileComp->nDecompLevels - reduction) { + // skip the codeblock data + if (tileComp->codeBlockStyle & 0x04) { + n = 0; + for (i = 0; i < cb->nCodingPasses; ++i) { + n += cb->dataLen[i]; + } + } else { + n = cb->dataLen[0]; + } + bufStr->discardChars(n); + return gTrue; + } + + if (cb->arithDecoder) { + cover(63); + cb->arithDecoder->restart(cb->dataLen[0]); + } else { + cover(64); + cb->arithDecoder = new JArithmeticDecoder(); + cb->arithDecoder->setStream(bufStr, cb->dataLen[0]); + cb->arithDecoder->start(); + cb->stats = new JArithmeticDecoderStats(jpxNContexts); + cb->stats->setEntry(jpxContextSigProp, 4, 0); + cb->stats->setEntry(jpxContextRunLength, 3, 0); + cb->stats->setEntry(jpxContextUniform, 46, 0); + } + + 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, touched0 = cb->touched; + y0 < cb->y1; + y0 += 4, coeff0 += 4 * tileComp->w, + touched0 += 4 << resLevel->codeBlockW) { + for (x = cb->x0, coeff1 = coeff0, touched1 = touched0; + x < cb->x1; + ++x, ++coeff1, ++touched1) { + for (y1 = 0, coeff = coeff1, touched = touched1; + y1 < 4 && y0+y1 < cb->y1; + ++y1, coeff += tileComp->w, touched += resLevel->cbW) { + if (!*coeff) { + horiz = vert = diag = 0; + horizSign = vertSign = 2; + if (x > cb->x0) { + if (coeff[-1]) { + ++horiz; + horizSign += coeff[-1] < 0 ? -1 : 1; + } + if (y0+y1 > cb->y0) { + diag += coeff[-(int)tileComp->w - 1] ? 1 : 0; + } + 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]) { + ++horiz; + horizSign += coeff[1] < 0 ? -1 : 1; + } + if (y0+y1 > cb->y0) { + diag += coeff[-(int)tileComp->w + 1] ? 1 : 0; + } + 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->w]) { + ++vert; + vertSign += coeff[-(int)tileComp->w] < 0 ? -1 : 1; + } + } + if (y0+y1 < cb->y1 - 1 && + (!(tileComp->codeBlockStyle & 0x08) || y1 < 3)) { + if (coeff[tileComp->w]) { + ++vert; + 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)) { + cx = signContext[horizSign][vertSign][0]; + xorBit = signContext[horizSign][vertSign][1]; + if (cb->arithDecoder->decodeBit(cx, cb->stats) ^ xorBit) { + *coeff = -1; + } else { + *coeff = 1; + } + } + *touched = 1; + } + } + } + } + } + ++cb->nextPass; + break; + + //----- magnitude refinement pass + case jpxPassMagRef: + cover(66); + for (y0 = cb->y0, coeff0 = cb->coeffs, touched0 = cb->touched; + y0 < cb->y1; + y0 += 4, coeff0 += 4 * tileComp->w, + touched0 += 4 << resLevel->codeBlockW) { + for (x = cb->x0, coeff1 = coeff0, touched1 = touched0; + x < cb->x1; + ++x, ++coeff1, ++touched1) { + for (y1 = 0, coeff = coeff1, touched = touched1; + y1 < 4 && y0+y1 < cb->y1; + ++y1, coeff += tileComp->w, touched += resLevel->cbW) { + if (*coeff && !*touched) { + if (*coeff == 1 || *coeff == -1) { + all = 0; + if (x > cb->x0) { + all += coeff[-1] ? 1 : 0; + if (y0+y1 > cb->y0) { + all += coeff[-(int)tileComp->w - 1] ? 1 : 0; + } + 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] ? 1 : 0; + if (y0+y1 > cb->y0) { + all += coeff[-(int)tileComp->w + 1] ? 1 : 0; + } + 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->w] ? 1 : 0; + } + if (y0+y1 < cb->y1 - 1 && + (!(tileComp->codeBlockStyle & 0x08) || y1 < 3)) { + all += coeff[tileComp->w] ? 1 : 0; + } + cx = all ? 15 : 14; + } else { + cx = 16; + } + bit = cb->arithDecoder->decodeBit(cx, cb->stats); + if (*coeff < 0) { + *coeff = (*coeff << 1) - bit; + } else { + *coeff = (*coeff << 1) + bit; + } + *touched = 1; + } + } + } + } + ++cb->nextPass; + break; + + //----- cleanup pass + case jpxPassCleanup: + cover(67); + for (y0 = cb->y0, coeff0 = cb->coeffs, touched0 = cb->touched; + y0 < cb->y1; + y0 += 4, coeff0 += 4 * tileComp->w, + touched0 += 4 << resLevel->codeBlockW) { + for (x = cb->x0, coeff1 = coeff0, touched1 = touched0; + x < cb->x1; + ++x, ++coeff1, ++touched1) { + y1 = 0; + if (y0 + 3 < cb->y1 && + !(*touched1) && + !(touched1[resLevel->cbW]) && + !(touched1[2 * resLevel->cbW]) && + !(touched1[3 * resLevel->cbW]) && + (x == cb->x0 || y0 == cb->y0 || + !coeff1[-(int)tileComp->w - 1]) && + (y0 == cb->y0 || + !coeff1[-(int)tileComp->w]) && + (x == cb->x1 - 1 || y0 == cb->y0 || + !coeff1[-(int)tileComp->w + 1]) && + (x == cb->x0 || + (!coeff1[-1] && + !coeff1[tileComp->w - 1] && + !coeff1[2 * tileComp->w - 1] && + !coeff1[3 * tileComp->w - 1])) && + (x == cb->x1 - 1 || + (!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); + coeff = &coeff1[y1 * tileComp->w]; + cx = signContext[2][2][0]; + xorBit = signContext[2][2][1]; + if (cb->arithDecoder->decodeBit(cx, cb->stats) ^ xorBit) { + *coeff = -1; + } else { + *coeff = 1; + } + ++y1; + } else { + y1 = 4; + } + } + for (coeff = &coeff1[y1 * tileComp->w], + touched = &touched1[y1 << resLevel->codeBlockW]; + y1 < 4 && y0 + y1 < cb->y1; + ++y1, coeff += tileComp->w, touched += resLevel->cbW) { + if (!*touched) { + horiz = vert = diag = 0; + horizSign = vertSign = 2; + if (x > cb->x0) { + if (coeff[-1]) { + ++horiz; + horizSign += coeff[-1] < 0 ? -1 : 1; + } + if (y0+y1 > cb->y0) { + diag += coeff[-(int)tileComp->w - 1] ? 1 : 0; + } + 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]) { + ++horiz; + horizSign += coeff[1] < 0 ? -1 : 1; + } + if (y0+y1 > cb->y0) { + diag += coeff[-(int)tileComp->w + 1] ? 1 : 0; + } + 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->w]) { + ++vert; + vertSign += coeff[-(int)tileComp->w] < 0 ? -1 : 1; + } + } + if (y0+y1 < cb->y1 - 1 && + (!(tileComp->codeBlockStyle & 0x08) || y1 < 3)) { + if (coeff[tileComp->w]) { + ++vert; + vertSign += coeff[tileComp->w] < 0 ? -1 : 1; + } + } + cx = sigPropContext[horiz][vert][diag][res == 0 ? 1 : sb]; + if (cb->arithDecoder->decodeBit(cx, cb->stats)) { + cx = signContext[horizSign][vertSign][0]; + xorBit = signContext[horizSign][vertSign][1]; + if (cb->arithDecoder->decodeBit(cx, cb->stats) ^ xorBit) { + *coeff = -1; + } else { + *coeff = 1; + } + } + } else { + *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(); + return gTrue; +} + +// Inverse quantization, and wavelet transform (IDWT). This also does +// the initial shift to convert to fixed point format. +void JPXStream::inverseTransform(JPXTileComp *tileComp) { + JPXResLevel *resLevel; + JPXPrecinct *precinct; + JPXSubband *subband; + JPXCodeBlock *cb; + int *coeff0, *coeff; + char *touched0, *touched; + Guint qStyle, guard, eps, shift; + int shift2; + double mu; + int val; + Guint r, pre, cbX, cbY, x, y; + + cover(68); + + //----- (NL)LL subband (resolution level 0) + + resLevel = &tileComp->resLevels[0]; + + // i-quant parameters + qStyle = tileComp->quantStyle & 0x1f; + guard = (tileComp->quantStyle >> 5) & 7; + if (qStyle == 0) { + cover(69); + eps = (tileComp->quantSteps[0] >> 3) & 0x1f; + shift = guard + eps - 1; + mu = 0; // make gcc happy + } else { + cover(70); + shift = guard - 1 + tileComp->prec; + mu = (double)(0x800 + (tileComp->quantSteps[0] & 0x7ff)) / 2048.0; + } + if (tileComp->transform == 0) { + cover(71); + shift += fracBits - tileComp->prec; + } + + // do fixed point adjustment and dequantization on (NL)LL + for (pre = 0; pre < resLevel->nPrecincts; ++pre) { + precinct = &resLevel->precincts[pre]; + subband = &precinct->subbands[0]; + cb = subband->cbs; + for (cbY = 0; cbY < subband->nYCBs; ++cbY) { + for (cbX = 0; cbX < subband->nXCBs; ++cbX) { + for (y = cb->y0, coeff0 = cb->coeffs, touched0 = cb->touched; + y < cb->y1; + ++y, coeff0 += tileComp->w, touched0 += resLevel->cbW) { + for (x = cb->x0, coeff = coeff0, touched = touched0; + x < cb->x1; + ++x, ++coeff, ++touched) { + val = *coeff; + if (val != 0) { + shift2 = shift - (cb->nZeroBitPlanes + cb->len + *touched); + if (shift2 > 0) { + cover(94); + if (val < 0) { + val = (val << shift2) - (1 << (shift2 - 1)); + } else { + val = (val << shift2) + (1 << (shift2 - 1)); + } + } else { + cover(95); + val >>= -shift2; + } + if (qStyle == 0) { + cover(96); + if (tileComp->transform == 0) { + cover(97); + val &= -1 << (fracBits - tileComp->prec); + } + } else { + cover(98); + val = (int)((double)val * mu); + } + } + *coeff = val; + } + } + ++cb; + } + } + } + + //----- IDWT for each level + + for (r = 1; r <= tileComp->nDecompLevels - reduction; ++r) { + resLevel = &tileComp->resLevels[r]; + + // (n)LL is already in the upper-left corner of the + // 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 + inverseTransformLevel(tileComp, r, resLevel); + } +} + +// Do one level of the inverse transform: +// - 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) { + JPXPrecinct *precinct; + JPXSubband *subband; + JPXCodeBlock *cb; + int *coeff0, *coeff; + char *touched0, *touched; + Guint qStyle, guard, eps, shift, t; + int shift2; + double mu; + int val; + int *dataPtr, *bufPtr; + Guint nx1, nx2, ny1, ny2, offset; + Guint x, y, sb, pre, cbX, cbY; + + qStyle = tileComp->quantStyle & 0x1f; + guard = (tileComp->quantStyle >> 5) & 7; + + //----- compute subband bounds + + // 0 nx1 nx2 + // | | | + // v v v + // +----+----+ + // | LL | HL | <- 0 + // +----+----+ + // | LH | HH | <- ny1 + // +----+----+ + // <- ny2 + nx1 = resLevel->bx1[1] - resLevel->bx0[1]; + nx2 = nx1 + resLevel->bx1[0] - resLevel->bx0[0]; + ny1 = resLevel->by1[0] - resLevel->by0[0]; + ny2 = ny1 + resLevel->by1[1] - resLevel->by0[1]; + if (nx2 == 0 || ny2 == 0) { + return; + } + + //----- fixed-point adjustment and dequantization + + for (sb = 0; sb < 3; ++sb) { + + // i-quant parameters + if (qStyle == 0) { + cover(100); + eps = (tileComp->quantSteps[3*r - 2 + sb] >> 3) & 0x1f; + shift = guard + eps - 1; + mu = 0; // make gcc happy + } else { + cover(101); + shift = guard + tileComp->prec; + if (sb == 2) { + cover(102); + ++shift; + } + t = tileComp->quantSteps[qStyle == 1 ? 0 : (3*r - 2 + sb)]; + mu = (double)(0x800 + (t & 0x7ff)) / 2048.0; + } + if (tileComp->transform == 0) { + cover(103); + shift += fracBits - tileComp->prec; + } + + // fixed point adjustment and dequantization + + for (pre = 0; pre < resLevel->nPrecincts; ++pre) { + precinct = &resLevel->precincts[pre]; + 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, touched0 = cb->touched; + y < cb->y1; + ++y, coeff0 += tileComp->w, touched0 += resLevel->cbW) { + for (x = cb->x0, coeff = coeff0, touched = touched0; + x < cb->x1; + ++x, ++coeff, ++touched) { + val = *coeff; + if (val != 0) { + shift2 = shift - (cb->nZeroBitPlanes + cb->len + *touched); + if (shift2 > 0) { + cover(74); + if (val < 0) { + val = (val << shift2) - (1 << (shift2 - 1)); + } else { + val = (val << shift2) + (1 << (shift2 - 1)); + } + } else { + cover(75); + val >>= -shift2; + } + if (qStyle == 0) { + cover(76); + if (tileComp->transform == 0) { + val &= -1 << (fracBits - tileComp->prec); + } + } else { + cover(77); + val = (int)((double)val * mu); + } + } + *coeff = val; + } + } + ++cb; + } + } + } + } + + //----- inverse transform + + // horizontal (row) transforms + offset = 3 + (resLevel->x0 & 1); + for (y = 0, dataPtr = tileComp->data; y < ny2; ++y, dataPtr += tileComp->w) { + if (resLevel->bx0[0] == resLevel->bx0[1]) { + // 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 + offset = 3 + (resLevel->y0 & 1); + for (x = 0, dataPtr = tileComp->data; x < nx2; ++x, ++dataPtr) { + if (resLevel->by0[0] == resLevel->by0[1]) { + // 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 offset, Guint n) { + Guint end, i; + + //----- special case for length = 1 + if (n == 1) { + cover(79); + if (offset == 4) { + cover(104); + *data >>= 1; + } + + } else { + cover(80); + + end = offset + n; + + //----- extend right + data[end] = data[end - 2]; + if (n == 2) { + cover(81); + data[end+1] = data[offset + 1]; + data[end+2] = data[offset]; + data[end+3] = data[offset + 1]; + } else { + cover(82); + data[end+1] = data[end - 3]; + if (n == 3) { + cover(105); + data[end+2] = data[offset + 1]; + data[end+3] = data[offset + 2]; + } else { + cover(106); + data[end+2] = data[end - 4]; + if (n == 4) { + cover(107); + data[end+3] = data[offset + 1]; + } else { + cover(108); + data[end+3] = data[end - 5]; + } + } + } + + //----- extend left + data[offset - 1] = data[offset + 1]; + data[offset - 2] = data[offset + 2]; + data[offset - 3] = data[offset + 3]; + if (offset == 4) { + cover(83); + data[0] = data[offset + 4]; + } + + //----- 9-7 irreversible filter + + if (tileComp->transform == 0) { + cover(84); + // step 1 (even) + for (i = 1; i <= end + 2; i += 2) { + data[i] = (int)(idwtKappa * data[i]); + } + // step 2 (odd) + for (i = 0; i <= end + 3; i += 2) { + data[i] = (int)(idwtIKappa * data[i]); + } + // step 3 (even) + for (i = 1; i <= end + 2; i += 2) { + data[i] = (int)(data[i] - idwtDelta * (data[i-1] + data[i+1])); + } + // step 4 (odd) + for (i = 2; i <= end + 1; i += 2) { + data[i] = (int)(data[i] - idwtGamma * (data[i-1] + data[i+1])); + } + // step 5 (even) + for (i = 3; i <= end; i += 2) { + data[i] = (int)(data[i] - idwtBeta * (data[i-1] + data[i+1])); + } + // step 6 (odd) + for (i = 4; i <= end - 1; i += 2) { + data[i] = (int)(data[i] - idwtAlpha * (data[i-1] + data[i+1])); + } + + //----- 5-3 reversible filter + + } else { + cover(85); + // step 1 (even) + for (i = 3; i <= end; i += 2) { + data[i] -= (data[i-1] + data[i+1] + 2) >> 2; + } + // step 2 (odd) + for (i = 4; i < end; i += 2) { + data[i] += (data[i-1] + data[i+1]) >> 1; + } + } + } +} + +// Inverse multi-component transform and DC level shift. This also +// converts fixed point samples back to integers. +GBool JPXStream::inverseMultiCompAndDC(JPXTile *tile) { + JPXTileComp *tileComp; + int coeff, d0, d1, d2, t, minVal, maxVal, zeroVal; + int *dataPtr; + Guint j, comp, x, y; + + //----- inverse multi-component transform + + if (tile->multiComp == 1) { + cover(86); + if (img.nComps < 3 || + tile->tileComps[0].hSep != tile->tileComps[1].hSep || + tile->tileComps[0].vSep != tile->tileComps[1].vSep || + tile->tileComps[1].hSep != tile->tileComps[2].hSep || + tile->tileComps[1].vSep != tile->tileComps[2].vSep) { + return gFalse; + } + + // inverse irreversible multiple component transform + if (tile->tileComps[0].transform == 0) { + cover(87); + j = 0; + for (y = 0; y < tile->tileComps[0].h; ++y) { + for (x = 0; x < tile->tileComps[0].w; ++x) { + d0 = tile->tileComps[0].data[j]; + d1 = tile->tileComps[1].data[j]; + d2 = tile->tileComps[2].data[j]; + tile->tileComps[0].data[j] = (int)(d0 + 1.402 * d2 + 0.5); + tile->tileComps[1].data[j] = + (int)(d0 - 0.34413 * d1 - 0.71414 * d2 + 0.5); + tile->tileComps[2].data[j] = (int)(d0 + 1.772 * d1 + 0.5); + ++j; + } + } + + // inverse reversible multiple component transform + } else { + cover(88); + j = 0; + for (y = 0; y < tile->tileComps[0].h; ++y) { + for (x = 0; x < tile->tileComps[0].w; ++x) { + d0 = tile->tileComps[0].data[j]; + d1 = tile->tileComps[1].data[j]; + d2 = tile->tileComps[2].data[j]; + tile->tileComps[1].data[j] = t = d0 - ((d2 + d1) >> 2); + tile->tileComps[0].data[j] = d2 + t; + tile->tileComps[2].data[j] = d1 + t; + ++j; + } + } + } + } + + //----- DC level shift + for (comp = 0; comp < img.nComps; ++comp) { + tileComp = &tile->tileComps[comp]; + + // signed: clip + if (tileComp->sgned) { + cover(89); + minVal = -(1 << (tileComp->prec - 1)); + maxVal = (1 << (tileComp->prec - 1)) - 1; + dataPtr = tileComp->data; + for (y = 0; y < tileComp->h; ++y) { + for (x = 0; x < tileComp->w; ++x) { + coeff = *dataPtr; + if (tileComp->transform == 0) { + cover(109); + coeff >>= fracBits - tileComp->prec; + } + if (coeff < minVal) { + cover(110); + coeff = minVal; + } else if (coeff > maxVal) { + cover(111); + coeff = maxVal; + } + *dataPtr++ = coeff; + } + } + + // unsigned: inverse DC level shift and clip + } else { + cover(90); + maxVal = (1 << tileComp->prec) - 1; + zeroVal = 1 << (tileComp->prec - 1); + dataPtr = tileComp->data; + for (y = 0; y < tileComp->h; ++y) { + for (x = 0; x < tileComp->w; ++x) { + coeff = *dataPtr; + if (tileComp->transform == 0) { + cover(112); + coeff >>= fracBits - tileComp->prec; + } + coeff += zeroVal; + if (coeff < 0) { + cover(113); + coeff = 0; + } else if (coeff > maxVal) { + cover(114); + coeff = maxVal; + } + *dataPtr++ = coeff; + } + } + } + } + + return gTrue; +} + +GBool JPXStream::readBoxHdr(Guint *boxType, Guint *boxLen, Guint *dataLen) { + Guint len, lenH; + + if (!readULong(&len) || + !readULong(boxType)) { + return gFalse; + } + if (len == 1) { + if (!readULong(&lenH) || !readULong(&len)) { + return gFalse; + } + if (lenH) { + error(errSyntaxError, getPos(), + "JPX stream contains a box larger than 2^32 bytes"); + return gFalse; + } + *boxLen = len; + *dataLen = len - 16; + } else if (len == 0) { + *boxLen = 0; + *dataLen = 0; + } else { + *boxLen = len; + *dataLen = len - 8; + } + return gTrue; +} + +int JPXStream::readMarkerHdr(int *segType, Guint *segLen) { + int c; + + do { + do { + if ((c = bufStr->getChar()) == EOF) { + return gFalse; + } + } while (c != 0xff); + do { + if ((c = bufStr->getChar()) == EOF) { + return gFalse; + } + } while (c == 0xff); + } while (c == 0x00); + *segType = c; + if ((c >= 0x30 && c <= 0x3f) || + c == 0x4f || c == 0x92 || c == 0x93 || c == 0xd9) { + *segLen = 0; + return gTrue; + } + return readUWord(segLen); +} + +GBool JPXStream::readUByte(Guint *x) { + int c0; + + if ((c0 = bufStr->getChar()) == EOF) { + return gFalse; + } + *x = (Guint)c0; + return gTrue; +} + +GBool JPXStream::readByte(int *x) { + int c0; + + if ((c0 = bufStr->getChar()) == EOF) { + return gFalse; + } + *x = c0; + if (c0 & 0x80) { + *x |= -1 - 0xff; + } + return gTrue; +} + +GBool JPXStream::readUWord(Guint *x) { + int c0, c1; + + if ((c0 = bufStr->getChar()) == EOF || + (c1 = bufStr->getChar()) == EOF) { + return gFalse; + } + *x = (Guint)((c0 << 8) | c1); + return gTrue; +} + +GBool JPXStream::readULong(Guint *x) { + int c0, c1, c2, c3; + + 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); + return gTrue; +} + +GBool JPXStream::readNBytes(int nBytes, GBool signd, int *x) { + int y, c, i; + + y = 0; + for (i = 0; i < nBytes; ++i) { + if ((c = bufStr->getChar()) == EOF) { + return gFalse; + } + y = (y << 8) + c; + } + if (signd) { + if (y & (1 << (8 * nBytes - 1))) { + y |= -1 << (8 * nBytes); + } + } + *x = y; + 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 = bufStr->getChar()) == EOF) { + return gFalse; + } + --byteCount; + if (bitBufSkip) { + bitBuf = (bitBuf << 7) | (c & 0x7f); + bitBufLen += 7; + } else { + bitBuf = (bitBuf << 8) | (c & 0xff); + bitBufLen += 8; + } + bitBufSkip = c == 0xff; + } + *x = (bitBuf >> (bitBufLen - nBits)) & ((1 << nBits) - 1); + bitBufLen -= nBits; + return gTrue; +} + +void JPXStream::skipSOP() { + // 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) { + bufStr->discardChars(6); + byteCount -= 6; + bitBufLen = 0; + bitBufSkip = gFalse; + } +} + +void JPXStream::skipEPH() { + int k; + + k = bitBufSkip ? 1 : 0; + if (byteCount >= (Guint)(k + 2) && + bufStr->lookChar(k) == 0xff && + bufStr->lookChar(k + 1) == 0x92) { + bufStr->discardChars(k + 2); + byteCount -= k + 2; + bitBufLen = 0; + bitBufSkip = gFalse; + } +} + +Guint JPXStream::finishBitBuf() { + if (bitBufSkip) { + bufStr->getChar(); + --byteCount; + } + return byteCount; +} diff --git a/xpdf/JPXStream.h b/xpdf/JPXStream.h new file mode 100644 index 0000000..4b8587b --- /dev/null +++ b/xpdf/JPXStream.h @@ -0,0 +1,364 @@ +//======================================================================== +// +// JPXStream.h +// +// Copyright 2002-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef JPXSTREAM_H +#define JPXSTREAM_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "gtypes.h" +#include "Object.h" +#include "Stream.h" + +class JArithmeticDecoder; +class JArithmeticDecoderStats; + +//------------------------------------------------------------------------ + +enum JPXColorSpaceType { + jpxCSBiLevel = 0, + jpxCSYCbCr1 = 1, + jpxCSYCbCr2 = 3, + jpxCSYCBCr3 = 4, + jpxCSPhotoYCC = 9, + jpxCSCMY = 11, + jpxCSCMYK = 12, + jpxCSYCCK = 13, + jpxCSCIELab = 14, + jpxCSsRGB = 16, + jpxCSGrayscale = 17, + jpxCSBiLevel2 = 18, + jpxCSCIEJab = 19, + jpxCSCISesRGB = 20, + jpxCSROMMRGB = 21, + jpxCSsRGBYCbCr = 22, + jpxCSYPbPr1125 = 23, + jpxCSYPbPr1250 = 24 +}; + +struct JPXColorSpecCIELab { + Guint rl, ol, ra, oa, rb, ob, il; +}; + +struct JPXColorSpecEnumerated { + JPXColorSpaceType type; // color space type + union { + JPXColorSpecCIELab cieLab; + }; +}; + +struct JPXColorSpec { + Guint meth; // method + int prec; // precedence + union { + JPXColorSpecEnumerated enumerated; + }; +}; + +//------------------------------------------------------------------------ + +struct JPXPalette { + Guint nEntries; // number of entries in the palette + Guint nComps; // number of components in each entry + Guint *bpc; // bits per component, for each component + int *c; // color data: + // c[i*nComps+j] = entry i, component j +}; + +//------------------------------------------------------------------------ + +struct JPXCompMap { + Guint nChannels; // number of channels + Guint *comp; // codestream components mapped to each channel + Guint *type; // 0 for direct use, 1 for palette mapping + Guint *pComp; // palette components to use +}; + +//------------------------------------------------------------------------ + +struct JPXChannelDefn { + Guint nChannels; // number of channels + Guint *idx; // channel indexes + Guint *type; // channel types + Guint *assoc; // channel associations +}; + +//------------------------------------------------------------------------ + +struct JPXTagTreeNode { + GBool finished; // true if this node is finished + Guint val; // current value +}; + +//------------------------------------------------------------------------ + +struct JPXCodeBlock { + //----- size + Guint x0, y0, x1, y1; // bounds + + //----- persistent state + GBool seen; // true if this code-block has already + // been seen + Guint lBlock; // base number of bits used for pkt data length + Guint nextPass; // next coding pass + + //---- info from first packet + Guint nZeroBitPlanes; // number of zero bit planes + + //----- info for the current packet + Guint included; // code-block inclusion in this packet: + // 0=not included, 1=included + Guint nCodingPasses; // number of coding passes in this pkt + Guint *dataLen; // data lengths (one per codeword segment) + Guint dataLenSize; // size of the dataLen array + + //----- coefficient data + int *coeffs; + char *touched; // coefficient 'touched' flags + Gushort len; // coefficient length + JArithmeticDecoder // arithmetic decoder + *arithDecoder; + JArithmeticDecoderStats // arithmetic decoder stats + *stats; +}; + +//------------------------------------------------------------------------ + +struct JPXSubband { + //----- computed + Guint nXCBs, nYCBs; // number of code-blocks in the x and y + // directions + + //----- tag trees + Guint maxTTLevel; // max tag tree level + JPXTagTreeNode *inclusion; // inclusion tag tree for each subband + JPXTagTreeNode *zeroBitPlane; // zero-bit plane tag tree for each + // subband + + //----- children + JPXCodeBlock *cbs; // the code-blocks (len = nXCBs * nYCBs) +}; + +//------------------------------------------------------------------------ + +struct JPXPrecinct { + //----- children + JPXSubband *subbands; // the subbands +}; + +//------------------------------------------------------------------------ + +struct JPXResLevel { + //----- from the COD and COC segments (main and tile) + Guint precinctWidth; // log2(precinct width) + Guint precinctHeight; // log2(precinct height) + Guint nPrecincts; + + //----- computed + Guint x0, y0, x1, y1; // bounds of this tile-comp at this res level + Guint bx0[3], by0[3], // subband bounds + bx1[3], by1[3]; + Guint codeBlockW; // log2(code-block width) + Guint codeBlockH; // log2(code-block height) + Guint cbW; // code-block width + Guint cbH; // code-block height + GBool empty; // true if all subbands and precincts are + // zero width or height + + //---- children + JPXPrecinct *precincts; // the precincts +}; + +//------------------------------------------------------------------------ + +struct JPXTileComp { + //----- from the SIZ segment + GBool sgned; // 1 for signed, 0 for unsigned + Guint prec; // precision, in bits + Guint hSep; // horizontal separation of samples + Guint vSep; // vertical separation of samples + + //----- from the COD and COC segments (main and tile) + Guint style; // coding style parameter (Scod / Scoc) + Guint nDecompLevels; // number of decomposition levels + Guint codeBlockW; // log2(code-block width) + Guint codeBlockH; // log2(code-block height) + Guint codeBlockStyle; // code-block style + Guint transform; // wavelet transformation + + //----- from the QCD and QCC segments (main and tile) + Guint quantStyle; // quantization style + Guint *quantSteps; // quantization step size for each subband + Guint nQuantSteps; // number of entries in quantSteps + + //----- computed + Guint x0, y0, x1, y1; // bounds of the tile-comp, in ref coords + Guint x0r, y0r; // x0 >> reduction, y0 >> reduction + Guint w, h; // data size = {x1 - x0, y1 - y0} >> reduction + + //----- image data + int *data; // the decoded image data + int *buf; // intermediate buffer for the inverse + // transform + + //----- children + JPXResLevel *resLevels; // the resolution levels + // (len = nDecompLevels + 1) +}; + +//------------------------------------------------------------------------ + +struct JPXTile { + GBool init; + + //----- from the COD segments (main and tile) + Guint progOrder; // progression order + Guint nLayers; // number of layers + Guint multiComp; // multiple component transformation + + //----- computed + Guint x0, y0, x1, y1; // bounds of the tile, in ref coords + Guint maxNDecompLevels; // max number of decomposition levels used + // in any component in this tile + Guint maxNPrecincts; // max number of precints in any + // component/res level in this tile + + //----- progression order loop counters + Guint comp; // component + Guint res; // resolution level + Guint precinct; // precinct + Guint layer; // layer + GBool done; // set when this tile is done + + //----- tile part info + Guint nextTilePart; // next expected tile-part + + //----- children + JPXTileComp *tileComps; // the tile-components (len = JPXImage.nComps) +}; + +//------------------------------------------------------------------------ + +struct JPXImage { + //----- from the SIZ segment + Guint xSize, ySize; // size of reference grid + Guint xOffset, yOffset; // image offset + Guint xTileSize, yTileSize; // size of tiles + Guint xTileOffset, // offset of first tile + yTileOffset; + Guint xSizeR, ySizeR; // size of reference grid >> reduction + Guint xOffsetR, yOffsetR; // image offset >> reduction + Guint nComps; // number of components + + //----- computed + Guint nXTiles; // number of tiles in x direction + Guint nYTiles; // number of tiles in y direction + + //----- children + JPXTile *tiles; // the tiles (len = nXTiles * nYTiles) +}; + +//------------------------------------------------------------------------ + +enum JPXDecodeResult { + jpxDecodeOk, + jpxDecodeNonFatalError, + jpxDecodeFatalError +}; + +//------------------------------------------------------------------------ + +class JPXStream: public FilterStream { +public: + + JPXStream(Stream *strA); + virtual ~JPXStream(); + virtual Stream *copy(); + virtual StreamKind getKind() { return strJPX; } + virtual void reset(); + virtual void close(); + virtual int getChar(); + virtual int lookChar(); + virtual GString *getPSFilter(int psLevel, const char *indent, + GBool okToReadStream); + virtual GBool isBinary(GBool last = gTrue); + virtual void getImageParams(int *bitsPerComponent, + StreamColorSpaceMode *csMode); + void reduceResolution(int reductionA) { reduction = reductionA; } + +private: + + void decodeImage(); + void fillReadBuf(); + void getImageParams2(int *bitsPerComponent, StreamColorSpaceMode *csMode); + JPXDecodeResult readBoxes(); + GBool readColorSpecBox(Guint dataLen); + JPXDecodeResult readCodestream(Guint len); + GBool readTilePart(); + GBool readTilePartData(Guint tileIdx, + Guint tilePartLen, GBool tilePartToEOC); + GBool readCodeBlockData(JPXTileComp *tileComp, + JPXResLevel *resLevel, + JPXPrecinct *precinct, + JPXSubband *subband, + Guint res, Guint sb, + JPXCodeBlock *cb); + void inverseTransform(JPXTileComp *tileComp); + void inverseTransformLevel(JPXTileComp *tileComp, + 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); + GBool readUByte(Guint *x); + GBool readByte(int *x); + GBool readUWord(Guint *x); + GBool readULong(Guint *x); + GBool readNBytes(int nBytes, GBool signd, int *x); + void startBitBuf(Guint byteCountA); + GBool readBits(int nBits, Guint *x); + void skipSOP(); + void skipEPH(); + Guint finishBitBuf(); + + BufStream *bufStr; // buffered stream (for lookahead) + + GBool decoded; // set when the image has been decoded + Guint nComps; // number of components + Guint *bpc; // bits per component, for each component + Guint width, height; // image size + int reduction; // log2(reduction in resolution) + GBool haveImgHdr; // set if a JP2/JPX image header has been + // found + JPXColorSpec cs; // color specification + GBool haveCS; // set if a color spec has been found + JPXPalette palette; // the palette + GBool havePalette; // set if a palette has been found + JPXCompMap compMap; // the component mapping + GBool haveCompMap; // set if a component mapping has been found + JPXChannelDefn channelDefn; // channel definition + GBool haveChannelDefn; // set if a channel defn has been found + + JPXImage img; // JPEG2000 decoder data + Guint bitBuf; // buffer for bit reads + int bitBufLen; // number of bits in bitBuf + GBool bitBufSkip; // true if next bit should be skipped + // (for bit stuffing) + Guint byteCount; // number of available bytes left + + Guint curX, curY, curComp; // current position for lookChar/getChar + Guint readBuf; // read buffer + Guint readBufLen; // number of valid bits in readBuf +}; + +#endif diff --git a/xpdf/Lexer.cc b/xpdf/Lexer.cc new file mode 100644 index 0000000..0c74dbb --- /dev/null +++ b/xpdf/Lexer.cc @@ -0,0 +1,555 @@ +//======================================================================== +// +// Lexer.cc +// +// Copyright 1996-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include +#include +#include +#include "gmempp.h" +#include "Lexer.h" +#include "Error.h" + +//------------------------------------------------------------------------ + +// A '1' in this array means the character is white space. A '1' or +// '2' means the character ends a name or command. +static char specialChars[256] = { + 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, // 0x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1x + 1, 0, 0, 0, 0, 2, 0, 0, 2, 2, 0, 0, 0, 0, 0, 2, // 2x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, // 3x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 4x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, // 5x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 6x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, // 7x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // ax + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // bx + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // cx + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // dx + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // ex + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // fx +}; + +//------------------------------------------------------------------------ +// Lexer +//------------------------------------------------------------------------ + +Lexer::Lexer(XRef *xref, Stream *str) { + Object obj; + + curStr.initStream(str); + streams = new Array(xref); + streams->add(curStr.copy(&obj)); + strPtr = 0; + freeArray = gTrue; + curStr.streamReset(); +} + +Lexer::Lexer(XRef *xref, Object *obj) { + Object obj2; + + if (obj->isStream()) { + streams = new Array(xref); + freeArray = gTrue; + streams->add(obj->copy(&obj2)); + } else { + streams = obj->getArray(); + freeArray = gFalse; + } + strPtr = 0; + if (streams->getLength() > 0) { + streams->get(strPtr, &curStr); + curStr.streamReset(); + } +} + +Lexer::~Lexer() { + if (!curStr.isNone()) { + curStr.streamClose(); + curStr.free(); + } + if (freeArray) { + delete streams; + } +} + +int Lexer::getChar() { + int c; + + c = EOF; + while (!curStr.isNone() && (c = curStr.streamGetChar()) == EOF) { + curStr.streamClose(); + curStr.free(); + ++strPtr; + if (strPtr < streams->getLength()) { + streams->get(strPtr, &curStr); + curStr.streamReset(); + } + } + return c; +} + +int Lexer::lookChar() { + if (curStr.isNone()) { + return EOF; + } + return curStr.streamLookChar(); +} + +Object *Lexer::getObj(Object *obj) { + char *p; + int c, c2; + GBool comment, neg, doubleMinus, done, invalid; + int numParen; + int xi; + double xf, scale; + GString *s; + int n, m; + + // skip whitespace and comments + comment = gFalse; + while (1) { + if ((c = getChar()) == EOF) { + return obj->initEOF(); + } + if (comment) { + if (c == '\r' || c == '\n') + comment = gFalse; + } else if (c == '%') { + comment = gTrue; + } else if (specialChars[c] != 1) { + break; + } + } + + // start reading token + switch (c) { + + // number + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + case '+': case '-': case '.': + // Adobe's number lexer has some "interesting" behavior: + // "--123" is interpreted as 0 + // "--123.4" is interpreted as -123.4 [I've seen this in the wild] + // "50-100" is interpreted as 50 [I've seen this in the wild] + // "50--100" is interpreted as 50 + // "50-100.0" is an error -- but older versions of Acrobat may + // have interpreted it as 50100.0 (?) + // "50--100.0" is an error -- but older versions of Acrobat may + // have interpreted it as 50100.0 (?) + // "50.0-100" is interpreted as 50.0 (or maybe 50.0100?) + // "50.0--100" is interpreted as 50.0 (or maybe 50.0100?) + // "-50-100" is interpreted as -50 + // "-" is interpreted as 0 + // "-." is interpreted as 0.0 + neg = gFalse; + doubleMinus = gFalse; + xf = xi = 0; + if (c == '+') { + // just ignore it + } else if (c == '-') { + neg = gTrue; + if (lookChar() == '-') { + doubleMinus = gTrue; + do { + getChar(); + } while (lookChar() == '-'); + } + } else if (c == '.') { + goto doReal; + } else { + xf = xi = c - '0'; + } + while (1) { + c = lookChar(); + if (isdigit(c)) { + getChar(); + xi = xi * 10 + (c - '0'); + if (xf < 1e20) { + xf = xf * 10 + (c - '0'); + } + } else if (c == '.') { + getChar(); + goto doReal; + } else { + break; + } + } + while ((c = lookChar()) == '-' || isdigit(c)) { + getChar(); + } + if (neg) { + xi = -xi; + } + if (doubleMinus) { + xi = 0; + } + obj->initInt(xi); + break; + doReal: + scale = 0.1; + while (1) { + c = lookChar(); + if (c == '-') { + error(errSyntaxWarning, getPos(), "Badly formatted number"); + getChar(); + continue; + } + if (!isdigit(c)) { + break; + } + getChar(); + xf = xf + scale * (c - '0'); + scale *= 0.1; + } + while ((c = lookChar()) == '-' || isdigit(c)) { + getChar(); + } + if (neg) { + xf = -xf; + } + obj->initReal(xf); + break; + + // string + case '(': + p = tokBuf; + n = 0; + numParen = 1; + done = gFalse; + s = NULL; + do { + c2 = EOF; + switch (c = getChar()) { + + case EOF: + error(errSyntaxError, getPos(), "Unterminated string"); + done = gTrue; + break; + + case '(': + ++numParen; + c2 = c; + break; + + case ')': + if (--numParen == 0) { + done = gTrue; + } else { + c2 = c; + } + break; + + case '\r': + // The PDF spec says that any literal end-of-line sequence + // (LF, CR, CR+LF) is translated to a single LF char. + c = lookChar(); + if (c == '\n') { + getChar(); + } + c2 = '\n'; + break; + + case '\\': + switch (c = getChar()) { + case 'n': + c2 = '\n'; + break; + case 'r': + c2 = '\r'; + break; + case 't': + c2 = '\t'; + break; + case 'b': + c2 = '\b'; + break; + case 'f': + c2 = '\f'; + break; + case '\\': + case '(': + case ')': + c2 = c; + break; + case '0': case '1': case '2': case '3': + case '4': case '5': case '6': case '7': + c2 = c - '0'; + c = lookChar(); + if (c >= '0' && c <= '7') { + getChar(); + c2 = (c2 << 3) + (c - '0'); + c = lookChar(); + if (c >= '0' && c <= '7') { + getChar(); + c2 = (c2 << 3) + (c - '0'); + } + } + break; + case '\r': + c = lookChar(); + if (c == '\n') { + getChar(); + } + break; + case '\n': + break; + case EOF: + error(errSyntaxError, getPos(), "Unterminated string"); + done = gTrue; + break; + default: + c2 = c; + break; + } + break; + + default: + c2 = c; + break; + } + + if (c2 != EOF) { + if (n == tokBufSize) { + if (!s) + s = new GString(tokBuf, tokBufSize); + else + s->append(tokBuf, tokBufSize); + p = tokBuf; + n = 0; + } + *p++ = (char)c2; + ++n; + } + } while (!done); + if (!s) + s = new GString(tokBuf, n); + else + s->append(tokBuf, n); + obj->initString(s); + break; + + // name + case '/': + p = tokBuf; + n = 0; + s = NULL; + invalid = gFalse; + while ((c = lookChar()) != EOF && !specialChars[c]) { + getChar(); + if (c == '#') { + c2 = lookChar(); + if (c2 >= '0' && c2 <= '9') { + c = c2 - '0'; + } else if (c2 >= 'A' && c2 <= 'F') { + c = c2 - 'A' + 10; + } else if (c2 >= 'a' && c2 <= 'f') { + c = c2 - 'a' + 10; + } else { + error(errSyntaxError, getPos(), "Invalid hex escape in name"); + goto notEscChar; + } + getChar(); + c2 = lookChar(); + if (c2 >= '0' && c2 <= '9') { + c = (c << 4) + (c2 - '0'); + } else if (c2 >= 'A' && c2 <= 'F') { + c = (c << 4) + (c2 - 'A' + 10); + } else if (c2 >= 'a' && c2 <= 'f') { + c = (c << 4) + (c2 - 'a' + 10); + } else { + error(errSyntaxError, getPos(), "Invalid hex escape in name"); + goto notEscChar; + } + getChar(); + if (c == 0) { + invalid = gTrue; + } + } + notEscChar: + // 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++ = (char)c; + } else if (n == tokBufSize) { + *p = (char)c; + s = new GString(tokBuf, n); + } else { + s->append((char)c); + } + } + if (invalid) { + error(errSyntaxError, getPos(), "Null character in name"); + obj->initError(); + if (s) { + delete s; + } + } else if (n < tokBufSize) { + *p = '\0'; + obj->initName(tokBuf); + } else { + obj->initName(s->getCString()); + delete s; + } + break; + + // array punctuation + case '[': + case ']': + tokBuf[0] = (char)c; + tokBuf[1] = '\0'; + obj->initCmd(tokBuf); + break; + + // hex string or dict punctuation + case '<': + c = lookChar(); + + // dict punctuation + if (c == '<') { + getChar(); + tokBuf[0] = tokBuf[1] = '<'; + tokBuf[2] = '\0'; + obj->initCmd(tokBuf); + + // hex string + } else { + p = tokBuf; + m = n = 0; + c2 = 0; + s = NULL; + while (1) { + c = getChar(); + if (c == '>') { + break; + } else if (c == EOF) { + error(errSyntaxError, getPos(), "Unterminated hex string"); + break; + } else if (specialChars[c] != 1) { + c2 = c2 << 4; + if (c >= '0' && c <= '9') + c2 += c - '0'; + else if (c >= 'A' && c <= 'F') + c2 += c - 'A' + 10; + else if (c >= 'a' && c <= 'f') + c2 += c - 'a' + 10; + else + error(errSyntaxError, getPos(), + "Illegal character <{0:02x}> in hex string", c); + if (++m == 2) { + if (n == tokBufSize) { + if (!s) + s = new GString(tokBuf, tokBufSize); + else + s->append(tokBuf, tokBufSize); + p = tokBuf; + n = 0; + } + *p++ = (char)c2; + ++n; + c2 = 0; + m = 0; + } + } + } + if (!s) + s = new GString(tokBuf, n); + else + s->append(tokBuf, n); + if (m == 1) + s->append((char)(c2 << 4)); + obj->initString(s); + } + break; + + // dict punctuation + case '>': + c = lookChar(); + if (c == '>') { + getChar(); + tokBuf[0] = tokBuf[1] = '>'; + tokBuf[2] = '\0'; + obj->initCmd(tokBuf); + } else { + error(errSyntaxError, getPos(), "Illegal character '>'"); + obj->initError(); + } + break; + + // error + case ')': + case '{': + case '}': + error(errSyntaxError, getPos(), "Illegal character '{0:c}'", c); + obj->initError(); + break; + + // command + default: + p = tokBuf; + *p++ = (char)c; + n = 1; + while ((c = lookChar()) != EOF && !specialChars[c]) { + getChar(); + if (++n == tokBufSize) { + error(errSyntaxError, getPos(), "Command token too long"); + break; + } + *p++ = (char)c; + } + *p = '\0'; + if (tokBuf[0] == 't' && !strcmp(tokBuf, "true")) { + obj->initBool(gTrue); + } else if (tokBuf[0] == 'f' && !strcmp(tokBuf, "false")) { + obj->initBool(gFalse); + } else if (tokBuf[0] == 'n' && !strcmp(tokBuf, "null")) { + obj->initNull(); + } else { + obj->initCmd(tokBuf); + } + break; + } + + return obj; +} + +void Lexer::skipToNextLine() { + int c; + + while (1) { + c = getChar(); + if (c == EOF || c == '\n') { + return; + } + if (c == '\r') { + if ((c = lookChar()) == '\n') { + getChar(); + } + return; + } + } +} + +void Lexer::skipToEOF() { + while (getChar() != EOF) ; +} + +GBool Lexer::isSpace(int c) { + return c >= 0 && c <= 0xff && specialChars[c] == 1; +} diff --git a/xpdf/Lexer.h b/xpdf/Lexer.h new file mode 100644 index 0000000..d481c2c --- /dev/null +++ b/xpdf/Lexer.h @@ -0,0 +1,85 @@ +//======================================================================== +// +// Lexer.h +// +// Copyright 1996-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef LEXER_H +#define LEXER_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "Object.h" +#include "Stream.h" + +class XRef; + +#define tokBufSize 128 // size of token buffer + +//------------------------------------------------------------------------ +// Lexer +//------------------------------------------------------------------------ + +class Lexer { +public: + + // Construct a lexer for a single stream. Deletes the stream when + // lexer is deleted. + Lexer(XRef *xref, Stream *str); + + // Construct a lexer for a stream or array of streams (assumes obj + // is either a stream or array of streams). + Lexer(XRef *xref, Object *obj); + + // Destructor. + ~Lexer(); + + // Get the next object from the input stream. + Object *getObj(Object *obj); + + // Skip to the beginning of the next line in the input stream. + void skipToNextLine(); + + // Skip to the end of the input stream. + void skipToEOF(); + + // Skip over one character. + void skipChar() { getChar(); } + + // Get stream index (for arrays of streams). + int getStreamIndex() { return strPtr; } + + // Get stream. + Stream *getStream() + { return curStr.isNone() ? (Stream *)NULL : curStr.getStream(); } + + // Get current position in file. + GFileOffset getPos() + { return curStr.isNone() ? -1 : curStr.streamGetPos(); } + + // Set position in file. + void setPos(GFileOffset pos, int dir = 0) + { if (!curStr.isNone()) curStr.streamSetPos(pos, dir); } + + // Returns true if is a whitespace character. + static GBool isSpace(int c); + +private: + + int getChar(); + int lookChar(); + + Array *streams; // array of input streams + int strPtr; // index of current stream + Object curStr; // current stream + GBool freeArray; // should lexer free the streams array? + char tokBuf[tokBufSize]; // temporary token buffer +}; + +#endif diff --git a/xpdf/Link.cc b/xpdf/Link.cc new file mode 100644 index 0000000..900f79d --- /dev/null +++ b/xpdf/Link.cc @@ -0,0 +1,926 @@ +//======================================================================== +// +// Link.cc +// +// Copyright 1996-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include +#include "gmem.h" +#include "gmempp.h" +#include "GString.h" +#include "Error.h" +#include "Object.h" +#include "Array.h" +#include "Dict.h" +#include "Link.h" + +//------------------------------------------------------------------------ +// LinkAction +//------------------------------------------------------------------------ + +LinkAction *LinkAction::parseDest(Object *obj) { + LinkAction *action; + + action = new LinkGoTo(obj); + if (!action->isOk()) { + delete action; + return NULL; + } + return action; +} + +LinkAction *LinkAction::parseAction(Object *obj, GString *baseURI) { + LinkAction *action; + Object obj2, obj3, obj4, obj5; + + if (!obj->isDict()) { + error(errSyntaxWarning, -1, "Bad annotation action"); + return NULL; + } + + obj->dictLookup("S", &obj2); + + // GoTo action + if (obj2.isName("GoTo")) { + obj->dictLookup("D", &obj3); + action = new LinkGoTo(&obj3); + obj3.free(); + + // GoToR action + } else if (obj2.isName("GoToR")) { + obj->dictLookup("F", &obj3); + obj->dictLookup("D", &obj4); + action = new LinkGoToR(&obj3, &obj4); + obj3.free(); + obj4.free(); + + // Launch action + } else if (obj2.isName("Launch")) { + action = new LinkLaunch(obj); + + // URI action + } else if (obj2.isName("URI")) { + obj->dictLookup("URI", &obj3); + action = new LinkURI(&obj3, baseURI); + obj3.free(); + + // Named action + } else if (obj2.isName("Named")) { + obj->dictLookup("N", &obj3); + action = new LinkNamed(&obj3); + obj3.free(); + + // Movie action + } else if (obj2.isName("Movie")) { + obj->dictLookupNF("Annot", &obj3); + obj->dictLookup("T", &obj4); + action = new LinkMovie(&obj3, &obj4); + obj3.free(); + obj4.free(); + + // JavaScript action + } else if (obj2.isName("JavaScript")) { + obj->dictLookup("JS", &obj3); + action = new LinkJavaScript(&obj3); + obj3.free(); + + // SubmitForm action + } else if (obj2.isName("SubmitForm")) { + obj->dictLookup("F", &obj3); + obj->dictLookup("Fields", &obj4); + obj->dictLookup("Flags", &obj5); + action = new LinkSubmitForm(&obj3, &obj4, &obj5); + obj3.free(); + obj4.free(); + obj5.free(); + + // Hide action + } else if (obj2.isName("Hide")) { + obj->dictLookupNF("T", &obj3); + obj->dictLookup("H", &obj4); + action = new LinkHide(&obj3, &obj4); + obj3.free(); + obj4.free(); + + // unknown action + } else if (obj2.isName()) { + action = new LinkUnknown(obj2.getName()); + + // action is missing or wrong type + } else { + error(errSyntaxWarning, -1, "Bad annotation action"); + action = NULL; + } + + obj2.free(); + + if (action && !action->isOk()) { + delete action; + return NULL; + } + return action; +} + +GString *LinkAction::getFileSpecName(Object *fileSpecObj) { + GString *name; + Object obj1; + + name = NULL; + + // string + if (fileSpecObj->isString()) { + name = fileSpecObj->getString()->copy(); + + // dictionary + } else if (fileSpecObj->isDict()) { +#ifdef _WIN32 + if (!fileSpecObj->dictLookup("DOS", &obj1)->isString()) { +#else + if (!fileSpecObj->dictLookup("Unix", &obj1)->isString()) { +#endif + obj1.free(); + fileSpecObj->dictLookup("F", &obj1); + } + if (obj1.isString()) { + name = obj1.getString()->copy(); + } else { + error(errSyntaxWarning, -1, "Illegal file spec in link"); + } + obj1.free(); + + // error + } else { + error(errSyntaxWarning, -1, "Illegal file spec in link"); + } + + // system-dependent path manipulation + if (name) { +#ifdef _WIN32 + int i, j; + + // "//...." --> "\...." + // "/x/...." --> "x:\...." + // "/server/share/...." --> "\\server\share\...." + // convert escaped slashes to slashes and unescaped slashes to backslashes + i = 0; + if (name->getChar(0) == '/') { + if (name->getLength() >= 2 && name->getChar(1) == '/') { + name->del(0); + i = 0; + } else if (name->getLength() >= 2 && + ((name->getChar(1) >= 'a' && name->getChar(1) <= 'z') || + (name->getChar(1) >= 'A' && name->getChar(1) <= 'Z')) && + (name->getLength() == 2 || name->getChar(2) == '/')) { + name->setChar(0, name->getChar(1)); + name->setChar(1, ':'); + i = 2; + } else { + for (j = 2; j < name->getLength(); ++j) { + if (name->getChar(j-1) != '\\' && + name->getChar(j) == '/') { + break; + } + } + if (j < name->getLength()) { + name->setChar(0, '\\'); + name->insert(0, '\\'); + i = 2; + } + } + } + for (; i < name->getLength(); ++i) { + if (name->getChar(i) == '/') { + name->setChar(i, '\\'); + } else if (name->getChar(i) == '\\' && + i+1 < name->getLength() && + name->getChar(i+1) == '/') { + name->del(i); + } + } +#else + // no manipulation needed for Unix +#endif + } + + return name; +} + +//------------------------------------------------------------------------ +// LinkDest +//------------------------------------------------------------------------ + +LinkDest::LinkDest(Array *a) { + Object obj1, obj2; + + // initialize fields + left = bottom = right = top = zoom = 0; + ok = gFalse; + + // get page + if (a->getLength() < 2) { + error(errSyntaxWarning, -1, "Annotation destination array is too short"); + return; + } + a->getNF(0, &obj1); + if (obj1.isInt()) { + pageNum = obj1.getInt() + 1; + pageIsRef = gFalse; + } else if (obj1.isRef()) { + pageRef.num = obj1.getRefNum(); + pageRef.gen = obj1.getRefGen(); + pageIsRef = gTrue; + } else { + error(errSyntaxWarning, -1, "Bad annotation destination"); + goto err2; + } + obj1.free(); + + // get destination type + a->get(1, &obj1); + + // XYZ link + if (obj1.isName("XYZ")) { + kind = destXYZ; + if (a->getLength() < 3) { + changeLeft = gFalse; + } else { + a->get(2, &obj2); + if (obj2.isNull()) { + changeLeft = gFalse; + } else if (obj2.isNum()) { + changeLeft = gTrue; + left = obj2.getNum(); + } else { + error(errSyntaxWarning, -1, "Bad annotation destination position"); + goto err1; + } + obj2.free(); + } + if (a->getLength() < 4) { + changeTop = gFalse; + } else { + a->get(3, &obj2); + if (obj2.isNull()) { + changeTop = gFalse; + } else if (obj2.isNum()) { + changeTop = gTrue; + top = obj2.getNum(); + } else { + error(errSyntaxWarning, -1, "Bad annotation destination position"); + goto err1; + } + obj2.free(); + } + if (a->getLength() < 5) { + changeZoom = gFalse; + } else { + a->get(4, &obj2); + if (obj2.isNull()) { + changeZoom = gFalse; + } else if (obj2.isNum()) { + changeZoom = gTrue; + zoom = obj2.getNum(); + } else { + error(errSyntaxWarning, -1, "Bad annotation destination position"); + goto err1; + } + obj2.free(); + } + + // Fit link + } else if (obj1.isName("Fit")) { + if (a->getLength() < 2) { + error(errSyntaxWarning, -1, "Annotation destination array is too short"); + goto err2; + } + kind = destFit; + + // FitH link + } else if (obj1.isName("FitH")) { + if (a->getLength() < 3) { + error(errSyntaxWarning, -1, "Annotation destination array is too short"); + goto err2; + } + kind = destFitH; + 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; + } + obj2.free(); + + // FitV link + } else if (obj1.isName("FitV")) { + if (a->getLength() < 3) { + error(errSyntaxWarning, -1, "Annotation destination array is too short"); + goto err2; + } + kind = destFitV; + 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; + } + obj2.free(); + + // FitR link + } else if (obj1.isName("FitR")) { + if (a->getLength() < 6) { + error(errSyntaxWarning, -1, "Annotation destination array is too short"); + goto err2; + } + kind = destFitR; + if (a->get(2, &obj2)->isNum()) { + left = obj2.getNum(); + } else { + error(errSyntaxWarning, -1, "Bad annotation destination position"); + kind = destFit; + } + obj2.free(); + if (!a->get(3, &obj2)->isNum()) { + error(errSyntaxWarning, -1, "Bad annotation destination position"); + kind = destFit; + } + bottom = obj2.getNum(); + obj2.free(); + if (!a->get(4, &obj2)->isNum()) { + error(errSyntaxWarning, -1, "Bad annotation destination position"); + kind = destFit; + } + right = obj2.getNum(); + obj2.free(); + if (!a->get(5, &obj2)->isNum()) { + error(errSyntaxWarning, -1, "Bad annotation destination position"); + kind = destFit; + } + top = obj2.getNum(); + obj2.free(); + + // FitB link + } else if (obj1.isName("FitB")) { + if (a->getLength() < 2) { + error(errSyntaxWarning, -1, "Annotation destination array is too short"); + goto err2; + } + kind = destFitB; + + // FitBH link + } else if (obj1.isName("FitBH")) { + if (a->getLength() < 3) { + error(errSyntaxWarning, -1, "Annotation destination array is too short"); + goto err2; + } + kind = destFitBH; + 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; + } + obj2.free(); + + // FitBV link + } else if (obj1.isName("FitBV")) { + if (a->getLength() < 3) { + error(errSyntaxWarning, -1, "Annotation destination array is too short"); + goto err2; + } + kind = destFitBV; + 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; + } + obj2.free(); + + // unknown link kind + } else { + error(errSyntaxWarning, -1, "Unknown annotation destination type"); + goto err2; + } + + obj1.free(); + ok = gTrue; + return; + + err1: + obj2.free(); + err2: + obj1.free(); +} + +LinkDest::LinkDest(LinkDest *dest) { + kind = dest->kind; + pageIsRef = dest->pageIsRef; + if (pageIsRef) + pageRef = dest->pageRef; + else + pageNum = dest->pageNum; + left = dest->left; + bottom = dest->bottom; + right = dest->right; + top = dest->top; + zoom = dest->zoom; + changeLeft = dest->changeLeft; + changeTop = dest->changeTop; + changeZoom = dest->changeZoom; + ok = gTrue; +} + +//------------------------------------------------------------------------ +// LinkGoTo +//------------------------------------------------------------------------ + +LinkGoTo::LinkGoTo(Object *destObj) { + dest = NULL; + namedDest = NULL; + + // named destination + if (destObj->isName()) { + namedDest = new GString(destObj->getName()); + } else if (destObj->isString()) { + namedDest = destObj->getString()->copy(); + + // destination dictionary + } else if (destObj->isArray()) { + dest = new LinkDest(destObj->getArray()); + if (!dest->isOk()) { + delete dest; + dest = NULL; + } + + // error + } else { + error(errSyntaxWarning, -1, "Illegal annotation destination"); + } +} + +LinkGoTo::~LinkGoTo() { + if (dest) + delete dest; + if (namedDest) + delete namedDest; +} + +//------------------------------------------------------------------------ +// LinkGoToR +//------------------------------------------------------------------------ + +LinkGoToR::LinkGoToR(Object *fileSpecObj, Object *destObj) { + dest = NULL; + namedDest = NULL; + + // get file name + fileName = getFileSpecName(fileSpecObj); + + // named destination + if (destObj->isName()) { + namedDest = new GString(destObj->getName()); + } else if (destObj->isString()) { + namedDest = destObj->getString()->copy(); + + // destination dictionary + } else if (destObj->isArray()) { + dest = new LinkDest(destObj->getArray()); + if (!dest->isOk()) { + delete dest; + dest = NULL; + } + + // error + } else { + error(errSyntaxWarning, -1, "Illegal annotation destination"); + } +} + +LinkGoToR::~LinkGoToR() { + if (fileName) + delete fileName; + if (dest) + delete dest; + if (namedDest) + delete namedDest; +} + + +//------------------------------------------------------------------------ +// LinkLaunch +//------------------------------------------------------------------------ + +LinkLaunch::LinkLaunch(Object *actionObj) { + Object obj1, obj2; + + fileName = NULL; + params = NULL; + + if (actionObj->isDict()) { + if (!actionObj->dictLookup("F", &obj1)->isNull()) { + fileName = getFileSpecName(&obj1); + } else { + obj1.free(); +#ifdef _WIN32 + if (actionObj->dictLookup("Win", &obj1)->isDict()) { + obj1.dictLookup("F", &obj2); + fileName = getFileSpecName(&obj2); + obj2.free(); + if (obj1.dictLookup("P", &obj2)->isString()) { + params = obj2.getString()->copy(); + } + obj2.free(); + } else { + error(errSyntaxWarning, -1, "Bad launch-type link action"); + } +#else + //~ This hasn't been defined by Adobe yet, so assume it looks + //~ just like the Win dictionary until they say otherwise. + if (actionObj->dictLookup("Unix", &obj1)->isDict()) { + obj1.dictLookup("F", &obj2); + fileName = getFileSpecName(&obj2); + obj2.free(); + if (obj1.dictLookup("P", &obj2)->isString()) { + params = obj2.getString()->copy(); + } + obj2.free(); + } else { + error(errSyntaxWarning, -1, "Bad launch-type link action"); + } +#endif + } + obj1.free(); + } +} + +LinkLaunch::~LinkLaunch() { + if (fileName) + delete fileName; + if (params) + delete params; +} + +//------------------------------------------------------------------------ +// LinkURI +//------------------------------------------------------------------------ + +LinkURI::LinkURI(Object *uriObj, GString *baseURI) { + GString *uri2; + int n; + char c; + + uri = NULL; + if (uriObj->isString()) { + 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 != '?') { + uri->append('/'); + } + if (uri2->getChar(0) == '/') { + uri->append(uri2->getCString() + 1, uri2->getLength() - 1); + } else { + uri->append(uri2); + } + } else { + uri = uri2->copy(); + } + } + } else { + error(errSyntaxWarning, -1, "Illegal URI-type link"); + } +} + +LinkURI::~LinkURI() { + if (uri) + delete uri; +} + +//------------------------------------------------------------------------ +// LinkNamed +//------------------------------------------------------------------------ + +LinkNamed::LinkNamed(Object *nameObj) { + name = NULL; + if (nameObj->isName()) { + name = new GString(nameObj->getName()); + } +} + +LinkNamed::~LinkNamed() { + if (name) { + delete name; + } +} + +//------------------------------------------------------------------------ +// LinkMovie +//------------------------------------------------------------------------ + +LinkMovie::LinkMovie(Object *annotObj, Object *titleObj) { + annotRef.num = -1; + title = NULL; + if (annotObj->isRef()) { + annotRef = annotObj->getRef(); + } else if (titleObj->isString()) { + title = titleObj->getString()->copy(); + } else { + error(errSyntaxError, -1, + "Movie action is missing both the Annot and T keys"); + } +} + +LinkMovie::~LinkMovie() { + if (title) { + delete title; + } +} + +//------------------------------------------------------------------------ +// LinkJavaScript +//------------------------------------------------------------------------ + +LinkJavaScript::LinkJavaScript(Object *jsObj) { + char buf[4096]; + int n; + + if (jsObj->isString()) { + js = jsObj->getString()->copy(); + } else if (jsObj->isStream()) { + js = new GString(); + jsObj->streamReset(); + while ((n = jsObj->getStream()->getBlock(buf, sizeof(buf))) > 0) { + js->append(buf, n); + } + jsObj->streamClose(); + } else { + error(errSyntaxError, -1, "JavaScript action JS key is wrong type"); + js = NULL; + } +} + +LinkJavaScript::~LinkJavaScript() { + if (js) { + delete js; + } +} + +//------------------------------------------------------------------------ +// LinkSubmitForm +//------------------------------------------------------------------------ + +LinkSubmitForm::LinkSubmitForm(Object *urlObj, Object *fieldsObj, + Object *flagsObj) { + if (urlObj->isString()) { + url = urlObj->getString()->copy(); + } else { + error(errSyntaxError, -1, "SubmitForm action URL is wrong type"); + url = NULL; + } + + if (fieldsObj->isArray()) { + fieldsObj->copy(&fields); + } else { + if (!fieldsObj->isNull()) { + error(errSyntaxError, -1, "SubmitForm action Fields value is wrong type"); + } + fields.initNull(); + } + + if (flagsObj->isInt()) { + flags = flagsObj->getInt(); + } else { + if (!flagsObj->isNull()) { + error(errSyntaxError, -1, "SubmitForm action Flags value is wrong type"); + } + flags = 0; + } +} + +LinkSubmitForm::~LinkSubmitForm() { + if (url) { + delete url; + } + fields.free(); +} + +//------------------------------------------------------------------------ +// LinkHide +//------------------------------------------------------------------------ + +LinkHide::LinkHide(Object *fieldsObj, Object *hideFlagObj) { + if (fieldsObj->isRef() || fieldsObj->isString() || fieldsObj->isArray()) { + fieldsObj->copy(&fields); + } else { + error(errSyntaxError, -1, "Hide action T value is wrong type"); + fields.initNull(); + } + + if (hideFlagObj->isBool()) { + hideFlag = hideFlagObj->getBool(); + } else { + error(errSyntaxError, -1, "Hide action H value is wrong type"); + hideFlag = gFalse; + } +} + +LinkHide::~LinkHide() { + fields.free(); +} + +//------------------------------------------------------------------------ +// LinkUnknown +//------------------------------------------------------------------------ + +LinkUnknown::LinkUnknown(char *actionA) { + action = new GString(actionA); +} + +LinkUnknown::~LinkUnknown() { + delete action; +} + +//------------------------------------------------------------------------ +// Link +//------------------------------------------------------------------------ + +Link::Link(Dict *dict, GString *baseURI) { + Object obj1, obj2; + double t; + + action = NULL; + ok = gFalse; + + // get rectangle + if (!dict->lookup("Rect", &obj1)->isArray()) { + error(errSyntaxError, -1, "Annotation rectangle is wrong type"); + goto err2; + } + if (!obj1.arrayGet(0, &obj2)->isNum()) { + error(errSyntaxError, -1, "Bad annotation rectangle"); + goto err1; + } + x1 = obj2.getNum(); + obj2.free(); + if (!obj1.arrayGet(1, &obj2)->isNum()) { + error(errSyntaxError, -1, "Bad annotation rectangle"); + goto err1; + } + y1 = obj2.getNum(); + obj2.free(); + if (!obj1.arrayGet(2, &obj2)->isNum()) { + error(errSyntaxError, -1, "Bad annotation rectangle"); + goto err1; + } + x2 = obj2.getNum(); + obj2.free(); + if (!obj1.arrayGet(3, &obj2)->isNum()) { + error(errSyntaxError, -1, "Bad annotation rectangle"); + goto err1; + } + y2 = obj2.getNum(); + obj2.free(); + obj1.free(); + if (x1 > x2) { + t = x1; + x1 = x2; + x2 = t; + } + if (y1 > y2) { + t = y1; + y1 = y2; + y2 = t; + } + + // look for destination + if (!dict->lookup("Dest", &obj1)->isNull()) { + action = LinkAction::parseDest(&obj1); + + // look for action + } else { + obj1.free(); + if (dict->lookup("A", &obj1)->isDict()) { + action = LinkAction::parseAction(&obj1, baseURI); + } + } + obj1.free(); + + // check for bad action + if (action) { + ok = gTrue; + } + + return; + + err1: + obj2.free(); + err2: + obj1.free(); +} + +Link::~Link() { + if (action) { + delete action; + } +} + +//------------------------------------------------------------------------ +// Links +//------------------------------------------------------------------------ + +Links::Links(Object *annots, GString *baseURI) { + Link *link; + Object obj1, obj2, obj3; + int size; + int i; + + links = NULL; + size = 0; + numLinks = 0; + + if (annots->isArray()) { + for (i = 0; i < annots->arrayGetLength(); ++i) { + if (annots->arrayGet(i, &obj1)->isDict()) { + obj1.dictLookup("Subtype", &obj2); + obj1.dictLookup("FT", &obj3); + if (obj2.isName("Link") || + (obj2.isName("Widget") && (obj3.isName("Btn") || obj3.isNull()))) { + link = new Link(obj1.getDict(), baseURI); + if (link->isOk()) { + if (numLinks >= size) { + size += 16; + links = (Link **)greallocn(links, size, sizeof(Link *)); + } + links[numLinks++] = link; + } else { + delete link; + } + } + obj3.free(); + obj2.free(); + } + obj1.free(); + } + } +} + +Links::~Links() { + int i; + + for (i = 0; i < numLinks; ++i) + delete links[i]; + gfree(links); +} + +LinkAction *Links::find(double x, double y) { + int i; + + for (i = numLinks - 1; i >= 0; --i) { + if (links[i]->inRect(x, y)) { + return links[i]->getAction(); + } + } + return NULL; +} + +GBool Links::onLink(double x, double y) { + int i; + + for (i = 0; i < numLinks; ++i) { + if (links[i]->inRect(x, y)) + return gTrue; + } + return gFalse; +} diff --git a/xpdf/Link.h b/xpdf/Link.h new file mode 100644 index 0000000..480496a --- /dev/null +++ b/xpdf/Link.h @@ -0,0 +1,453 @@ +//======================================================================== +// +// Link.h +// +// Copyright 1996-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef LINK_H +#define LINK_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "Object.h" + +class GString; +class Array; +class Dict; + +//------------------------------------------------------------------------ +// LinkAction +//------------------------------------------------------------------------ + +enum LinkActionKind { + actionGoTo, // go to destination + actionGoToR, // go to destination in new file + actionLaunch, // launch app (or open document) + actionURI, // URI + actionNamed, // named action + actionMovie, // movie action + actionJavaScript, // run JavaScript + actionSubmitForm, // submit form + actionHide, // hide annotation + actionUnknown // anything else +}; + +class LinkAction { +public: + + // Destructor. + virtual ~LinkAction() {} + + // Was the LinkAction created successfully? + virtual GBool isOk() = 0; + + // Check link action type. + virtual LinkActionKind getKind() = 0; + + // Parse a destination (old-style action) name, string, or array. + static LinkAction *parseDest(Object *obj); + + // Parse an action dictionary. + static LinkAction *parseAction(Object *obj, GString *baseURI = NULL); + + // Extract a file name from a file specification (string or + // dictionary). + static GString *getFileSpecName(Object *fileSpecObj); +}; + +//------------------------------------------------------------------------ +// LinkDest +//------------------------------------------------------------------------ + +enum LinkDestKind { + destXYZ, + destFit, + destFitH, + destFitV, + destFitR, + destFitB, + destFitBH, + destFitBV +}; + +class LinkDest { +public: + + // Build a LinkDest from the array. + LinkDest(Array *a); + + // Copy a LinkDest. + LinkDest *copy() { return new LinkDest(this); } + + // Was the LinkDest created successfully? + GBool isOk() { return ok; } + + // Accessors. + LinkDestKind getKind() { return kind; } + GBool isPageRef() { return pageIsRef; } + int getPageNum() { return pageNum; } + Ref getPageRef() { return pageRef; } + double getLeft() { return left; } + double getBottom() { return bottom; } + double getRight() { return right; } + double getTop() { return top; } + double getZoom() { return zoom; } + GBool getChangeLeft() { return changeLeft; } + GBool getChangeTop() { return changeTop; } + GBool getChangeZoom() { return changeZoom; } + +private: + + LinkDestKind kind; // destination type + GBool pageIsRef; // is the page a reference or number? + union { + Ref pageRef; // reference to page + int pageNum; // one-relative page number + }; + double left, bottom; // position + double right, top; + double zoom; // zoom factor + 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); +}; + +//------------------------------------------------------------------------ +// LinkGoTo +//------------------------------------------------------------------------ + +class LinkGoTo: public LinkAction { +public: + + // Build a LinkGoTo from a destination (dictionary, name, or string). + LinkGoTo(Object *destObj); + + // Destructor. + virtual ~LinkGoTo(); + + // Was the LinkGoTo created successfully? + virtual GBool isOk() { return dest || namedDest; } + + // Accessors. + virtual LinkActionKind getKind() { return actionGoTo; } + LinkDest *getDest() { return dest; } + GString *getNamedDest() { return namedDest; } + +private: + + LinkDest *dest; // regular destination (NULL for remote + // link with bad destination) + GString *namedDest; // named destination (only one of dest and + // and namedDest may be non-NULL) +}; + +//------------------------------------------------------------------------ +// LinkGoToR +//------------------------------------------------------------------------ + +class LinkGoToR: public LinkAction { +public: + + // Build a LinkGoToR from a file spec (dictionary) and destination + // (dictionary, name, or string). + LinkGoToR(Object *fileSpecObj, Object *destObj); + + // Destructor. + virtual ~LinkGoToR(); + + // Was the LinkGoToR created successfully? + virtual GBool isOk() { return fileName && (dest || namedDest); } + + // Accessors. + virtual LinkActionKind getKind() { return actionGoToR; } + GString *getFileName() { return fileName; } + LinkDest *getDest() { return dest; } + GString *getNamedDest() { return namedDest; } + +private: + + GString *fileName; // file name + LinkDest *dest; // regular destination (NULL for remote + // link with bad destination) + GString *namedDest; // named destination (only one of dest and + // and namedDest may be non-NULL) +}; + +//------------------------------------------------------------------------ +// LinkLaunch +//------------------------------------------------------------------------ + +class LinkLaunch: public LinkAction { +public: + + // Build a LinkLaunch from an action dictionary. + LinkLaunch(Object *actionObj); + + // Destructor. + virtual ~LinkLaunch(); + + // Was the LinkLaunch created successfully? + virtual GBool isOk() { return fileName != NULL; } + + // Accessors. + virtual LinkActionKind getKind() { return actionLaunch; } + GString *getFileName() { return fileName; } + GString *getParams() { return params; } + +private: + + GString *fileName; // file name + GString *params; // parameters +}; + +//------------------------------------------------------------------------ +// LinkURI +//------------------------------------------------------------------------ + +class LinkURI: public LinkAction { +public: + + // Build a LinkURI given the URI (string) and base URI. + LinkURI(Object *uriObj, GString *baseURI); + + // Destructor. + virtual ~LinkURI(); + + // Was the LinkURI created successfully? + virtual GBool isOk() { return uri != NULL; } + + // Accessors. + virtual LinkActionKind getKind() { return actionURI; } + GString *getURI() { return uri; } + +private: + + GString *uri; // the URI +}; + +//------------------------------------------------------------------------ +// LinkNamed +//------------------------------------------------------------------------ + +class LinkNamed: public LinkAction { +public: + + // Build a LinkNamed given the action name. + LinkNamed(Object *nameObj); + + virtual ~LinkNamed(); + + // Was the LinkNamed created successfully? + virtual GBool isOk() { return name != NULL; } + + // Accessors. + virtual LinkActionKind getKind() { return actionNamed; } + GString *getName() { return name; } + +private: + + GString *name; +}; + +//------------------------------------------------------------------------ +// LinkMovie +//------------------------------------------------------------------------ + +class LinkMovie: public LinkAction { +public: + + LinkMovie(Object *annotObj, Object *titleObj); + + virtual ~LinkMovie(); + + // Was the LinkMovie created successfully? + virtual GBool isOk() { return annotRef.num >= 0 || title != NULL; } + + // Accessors. + virtual LinkActionKind getKind() { return actionMovie; } + GBool hasAnnotRef() { return annotRef.num >= 0; } + Ref *getAnnotRef() { return &annotRef; } + GString *getTitle() { return title; } + +private: + + Ref annotRef; + GString *title; +}; + +//------------------------------------------------------------------------ +// LinkJavaScript +//------------------------------------------------------------------------ + +class LinkJavaScript: public LinkAction { +public: + + LinkJavaScript(Object *jsObj); + + virtual ~LinkJavaScript(); + + // Was the LinkJavaScript created successfully? + virtual GBool isOk() { return js != NULL; } + + // Accessors. + virtual LinkActionKind getKind() { return actionJavaScript; } + GString *getJS() { return js; } + +private: + + GString *js; +}; + +//------------------------------------------------------------------------ +// LinkSubmitForm +//------------------------------------------------------------------------ + +class LinkSubmitForm: public LinkAction { +public: + + LinkSubmitForm(Object *urlObj, Object *fieldsObj, Object *flagsObj); + + virtual ~LinkSubmitForm(); + + // Was the LinkSubmitForm created successfully? + virtual GBool isOk() { return url != NULL; } + + // Accessors. + virtual LinkActionKind getKind() { return actionSubmitForm; } + GString *getURL() { return url; } + Object *getFields() { return &fields; } + int getFlags() { return flags; } + +private: + + GString *url; + Object fields; + int flags; +}; + +//------------------------------------------------------------------------ +// LinkHide +//------------------------------------------------------------------------ + +class LinkHide: public LinkAction { +public: + + LinkHide(Object *fieldsObj, Object *hideFlagObj); + + virtual ~LinkHide(); + + // Was the LinkHide created successfully? + virtual GBool isOk() { return !fields.isNull(); } + + // Accessors. + virtual LinkActionKind getKind() { return actionHide; } + Object *getFields() { return &fields; } + GBool getHideFlag() { return hideFlag; } + +private: + + Object fields; + GBool hideFlag; +}; + +//------------------------------------------------------------------------ +// LinkUnknown +//------------------------------------------------------------------------ + +class LinkUnknown: public LinkAction { +public: + + // Build a LinkUnknown with the specified action type. + LinkUnknown(char *actionA); + + // Destructor. + virtual ~LinkUnknown(); + + // Was the LinkUnknown create successfully? + virtual GBool isOk() { return action != NULL; } + + // Accessors. + virtual LinkActionKind getKind() { return actionUnknown; } + GString *getAction() { return action; } + +private: + + GString *action; // action subtype +}; + +//------------------------------------------------------------------------ +// Link +//------------------------------------------------------------------------ + +class Link { +public: + + // Construct a link, given its dictionary. + Link(Dict *dict, GString *baseURI); + + // Destructor. + ~Link(); + + // Was the link created successfully? + GBool isOk() { return ok; } + + // Check if point is inside the link rectangle. + GBool inRect(double x, double y) + { return x1 <= x && x <= x2 && y1 <= y && y <= y2; } + + // Get action. + LinkAction *getAction() { return action; } + + // Get the link rectangle. + void getRect(double *xa1, double *ya1, double *xa2, double *ya2) + { *xa1 = x1; *ya1 = y1; *xa2 = x2; *ya2 = y2; } + +private: + + double x1, y1; // lower left corner + double x2, y2; // upper right corner + LinkAction *action; // action + GBool ok; // is link valid? +}; + +//------------------------------------------------------------------------ +// Links +//------------------------------------------------------------------------ + +class Links { +public: + + // Extract links from array of annotations. + Links(Object *annots, GString *baseURI); + + // Destructor. + ~Links(); + + // Iterate through list of links. + int getNumLinks() { return numLinks; } + Link *getLink(int i) { return links[i]; } + + // If point , is in a link, return the associated action; + // else return NULL. + LinkAction *find(double x, double y); + + // Return true if , is in a link. + GBool onLink(double x, double y); + +private: + + Link **links; + int numLinks; +}; + +#endif diff --git a/xpdf/Makefile b/xpdf/Makefile new file mode 100644 index 0000000..456d871 --- /dev/null +++ b/xpdf/Makefile @@ -0,0 +1,2365 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +# Default target executed when no arguments are given to make. +default_target: all + +.PHONY : default_target + +# Allow only one "make -f Makefile2" at a time, but pass parallelism. +.NOTPARALLEL: + + +#============================================================================= +# Special targets provided by cmake. + +# Disable implicit rules so canonical targets will work. +.SUFFIXES: + + +# Disable VCS-based implicit rules. +% : %,v + + +# Disable VCS-based implicit rules. +% : RCS/% + + +# Disable VCS-based implicit rules. +% : RCS/%,v + + +# Disable VCS-based implicit rules. +% : SCCS/s.% + + +# Disable VCS-based implicit rules. +% : s.% + + +.SUFFIXES: .hpux_make_needs_suffix_list + + +# Command-line flag to silence nested $(MAKE). +$(VERBOSE)MAKESILENT = -s + +#Suppress display of executed commands. +$(VERBOSE).SILENT: + +# A target that is always out of date. +cmake_force: + +.PHONY : cmake_force + +#============================================================================= +# Set environment variables for the build. + +# The shell in which to execute make rules. +SHELL = /bin/sh + +# The CMake executable. +CMAKE_COMMAND = /usr/bin/cmake + +# The command to remove a file. +RM = /usr/bin/cmake -E rm -f + +# Escaping for special characters. +EQUALS = = + +# The top-level source directory on which CMake was run. +CMAKE_SOURCE_DIR = /home/calvin/src/xpdf-4.04 + +# The top-level build directory on which CMake was run. +CMAKE_BINARY_DIR = /home/calvin/src/xpdf-4.04 + +#============================================================================= +# Targets provided globally by CMake. + +# Special rule for the target install/strip +install/strip: preinstall + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing the project stripped..." + /usr/bin/cmake -DCMAKE_INSTALL_DO_STRIP=1 -P cmake_install.cmake +.PHONY : install/strip + +# Special rule for the target install/strip +install/strip/fast: preinstall/fast + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing the project stripped..." + /usr/bin/cmake -DCMAKE_INSTALL_DO_STRIP=1 -P cmake_install.cmake +.PHONY : install/strip/fast + +# Special rule for the target install/local +install/local: preinstall + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing only the local directory..." + /usr/bin/cmake -DCMAKE_INSTALL_LOCAL_ONLY=1 -P cmake_install.cmake +.PHONY : install/local + +# Special rule for the target install/local +install/local/fast: preinstall/fast + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing only the local directory..." + /usr/bin/cmake -DCMAKE_INSTALL_LOCAL_ONLY=1 -P cmake_install.cmake +.PHONY : install/local/fast + +# Special rule for the target list_install_components +list_install_components: + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Available install components are: \"Unspecified\"" +.PHONY : list_install_components + +# Special rule for the target list_install_components +list_install_components/fast: list_install_components + +.PHONY : list_install_components/fast + +# Special rule for the target install +install: preinstall + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Install the project..." + /usr/bin/cmake -P cmake_install.cmake +.PHONY : install + +# Special rule for the target install +install/fast: preinstall/fast + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Install the project..." + /usr/bin/cmake -P cmake_install.cmake +.PHONY : install/fast + +# Special rule for the target rebuild_cache +rebuild_cache: + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake to regenerate build system..." + /usr/bin/cmake --regenerate-during-build -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) +.PHONY : rebuild_cache + +# Special rule for the target rebuild_cache +rebuild_cache/fast: rebuild_cache + +.PHONY : rebuild_cache/fast + +# Special rule for the target edit_cache +edit_cache: + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "No interactive CMake dialog available..." + /usr/bin/cmake -E echo No\ interactive\ CMake\ dialog\ available. +.PHONY : edit_cache + +# Special rule for the target edit_cache +edit_cache/fast: edit_cache + +.PHONY : edit_cache/fast + +# The main all target +all: cmake_check_build_system + cd /home/calvin/src/xpdf-4.04 && $(CMAKE_COMMAND) -E cmake_progress_start /home/calvin/src/xpdf-4.04/CMakeFiles /home/calvin/src/xpdf-4.04/xpdf//CMakeFiles/progress.marks + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 xpdf/all + $(CMAKE_COMMAND) -E cmake_progress_start /home/calvin/src/xpdf-4.04/CMakeFiles 0 +.PHONY : all + +# The main clean target +clean: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 xpdf/clean +.PHONY : clean + +# The main clean target +clean/fast: clean + +.PHONY : clean/fast + +# Prepare targets for installation. +preinstall: all + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 xpdf/preinstall +.PHONY : preinstall + +# Prepare targets for installation. +preinstall/fast: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 xpdf/preinstall +.PHONY : preinstall/fast + +# clear depends +depend: + cd /home/calvin/src/xpdf-4.04 && $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 1 +.PHONY : depend + +# Convenience name for target. +xpdf/CMakeFiles/xpdf_objs.dir/rule: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 xpdf/CMakeFiles/xpdf_objs.dir/rule +.PHONY : xpdf/CMakeFiles/xpdf_objs.dir/rule + +# Convenience name for target. +xpdf_objs: xpdf/CMakeFiles/xpdf_objs.dir/rule + +.PHONY : xpdf_objs + +# fast build rule for target. +xpdf_objs/fast: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/build +.PHONY : xpdf_objs/fast + +# Convenience name for target. +xpdf/CMakeFiles/pdftohtml.dir/rule: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 xpdf/CMakeFiles/pdftohtml.dir/rule +.PHONY : xpdf/CMakeFiles/pdftohtml.dir/rule + +# Convenience name for target. +pdftohtml: xpdf/CMakeFiles/pdftohtml.dir/rule + +.PHONY : pdftohtml + +# fast build rule for target. +pdftohtml/fast: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftohtml.dir/build.make xpdf/CMakeFiles/pdftohtml.dir/build +.PHONY : pdftohtml/fast + +# Convenience name for target. +xpdf/CMakeFiles/pdftoppm.dir/rule: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 xpdf/CMakeFiles/pdftoppm.dir/rule +.PHONY : xpdf/CMakeFiles/pdftoppm.dir/rule + +# Convenience name for target. +pdftoppm: xpdf/CMakeFiles/pdftoppm.dir/rule + +.PHONY : pdftoppm + +# fast build rule for target. +pdftoppm/fast: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftoppm.dir/build.make xpdf/CMakeFiles/pdftoppm.dir/build +.PHONY : pdftoppm/fast + +# Convenience name for target. +xpdf/CMakeFiles/pdftopng.dir/rule: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 xpdf/CMakeFiles/pdftopng.dir/rule +.PHONY : xpdf/CMakeFiles/pdftopng.dir/rule + +# Convenience name for target. +pdftopng: xpdf/CMakeFiles/pdftopng.dir/rule + +.PHONY : pdftopng + +# fast build rule for target. +pdftopng/fast: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftopng.dir/build.make xpdf/CMakeFiles/pdftopng.dir/build +.PHONY : pdftopng/fast + +# Convenience name for target. +xpdf/CMakeFiles/pdftotext.dir/rule: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 xpdf/CMakeFiles/pdftotext.dir/rule +.PHONY : xpdf/CMakeFiles/pdftotext.dir/rule + +# Convenience name for target. +pdftotext: xpdf/CMakeFiles/pdftotext.dir/rule + +.PHONY : pdftotext + +# fast build rule for target. +pdftotext/fast: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftotext.dir/build.make xpdf/CMakeFiles/pdftotext.dir/build +.PHONY : pdftotext/fast + +# Convenience name for target. +xpdf/CMakeFiles/xpdf_widget_objs.dir/rule: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 xpdf/CMakeFiles/xpdf_widget_objs.dir/rule +.PHONY : xpdf/CMakeFiles/xpdf_widget_objs.dir/rule + +# Convenience name for target. +xpdf_widget_objs: xpdf/CMakeFiles/xpdf_widget_objs.dir/rule + +.PHONY : xpdf_widget_objs + +# fast build rule for target. +xpdf_widget_objs/fast: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_widget_objs.dir/build.make xpdf/CMakeFiles/xpdf_widget_objs.dir/build +.PHONY : xpdf_widget_objs/fast + +# Convenience name for target. +xpdf/CMakeFiles/pdfinfo.dir/rule: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 xpdf/CMakeFiles/pdfinfo.dir/rule +.PHONY : xpdf/CMakeFiles/pdfinfo.dir/rule + +# Convenience name for target. +pdfinfo: xpdf/CMakeFiles/pdfinfo.dir/rule + +.PHONY : pdfinfo + +# fast build rule for target. +pdfinfo/fast: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdfinfo.dir/build.make xpdf/CMakeFiles/pdfinfo.dir/build +.PHONY : pdfinfo/fast + +# Convenience name for target. +xpdf/CMakeFiles/pdfdetach.dir/rule: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 xpdf/CMakeFiles/pdfdetach.dir/rule +.PHONY : xpdf/CMakeFiles/pdfdetach.dir/rule + +# Convenience name for target. +pdfdetach: xpdf/CMakeFiles/pdfdetach.dir/rule + +.PHONY : pdfdetach + +# fast build rule for target. +pdfdetach/fast: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdfdetach.dir/build.make xpdf/CMakeFiles/pdfdetach.dir/build +.PHONY : pdfdetach/fast + +# Convenience name for target. +xpdf/CMakeFiles/pdftops.dir/rule: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 xpdf/CMakeFiles/pdftops.dir/rule +.PHONY : xpdf/CMakeFiles/pdftops.dir/rule + +# Convenience name for target. +pdftops: xpdf/CMakeFiles/pdftops.dir/rule + +.PHONY : pdftops + +# fast build rule for target. +pdftops/fast: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftops.dir/build.make xpdf/CMakeFiles/pdftops.dir/build +.PHONY : pdftops/fast + +# Convenience name for target. +xpdf/CMakeFiles/pdffonts.dir/rule: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 xpdf/CMakeFiles/pdffonts.dir/rule +.PHONY : xpdf/CMakeFiles/pdffonts.dir/rule + +# Convenience name for target. +pdffonts: xpdf/CMakeFiles/pdffonts.dir/rule + +.PHONY : pdffonts + +# fast build rule for target. +pdffonts/fast: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdffonts.dir/build.make xpdf/CMakeFiles/pdffonts.dir/build +.PHONY : pdffonts/fast + +# Convenience name for target. +xpdf/CMakeFiles/pdfimages.dir/rule: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 xpdf/CMakeFiles/pdfimages.dir/rule +.PHONY : xpdf/CMakeFiles/pdfimages.dir/rule + +# Convenience name for target. +pdfimages: xpdf/CMakeFiles/pdfimages.dir/rule + +.PHONY : pdfimages + +# fast build rule for target. +pdfimages/fast: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdfimages.dir/build.make xpdf/CMakeFiles/pdfimages.dir/build +.PHONY : pdfimages/fast + +AcroForm.o: AcroForm.cc.o + +.PHONY : AcroForm.o + +# target to build an object file +AcroForm.cc.o: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/AcroForm.cc.o +.PHONY : AcroForm.cc.o + +AcroForm.i: AcroForm.cc.i + +.PHONY : AcroForm.i + +# target to preprocess a source file +AcroForm.cc.i: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/AcroForm.cc.i +.PHONY : AcroForm.cc.i + +AcroForm.s: AcroForm.cc.s + +.PHONY : AcroForm.s + +# target to generate assembly for a file +AcroForm.cc.s: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/AcroForm.cc.s +.PHONY : AcroForm.cc.s + +Annot.o: Annot.cc.o + +.PHONY : Annot.o + +# target to build an object file +Annot.cc.o: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/Annot.cc.o +.PHONY : Annot.cc.o + +Annot.i: Annot.cc.i + +.PHONY : Annot.i + +# target to preprocess a source file +Annot.cc.i: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/Annot.cc.i +.PHONY : Annot.cc.i + +Annot.s: Annot.cc.s + +.PHONY : Annot.s + +# target to generate assembly for a file +Annot.cc.s: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/Annot.cc.s +.PHONY : Annot.cc.s + +Array.o: Array.cc.o + +.PHONY : Array.o + +# target to build an object file +Array.cc.o: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/Array.cc.o +.PHONY : Array.cc.o + +Array.i: Array.cc.i + +.PHONY : Array.i + +# target to preprocess a source file +Array.cc.i: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/Array.cc.i +.PHONY : Array.cc.i + +Array.s: Array.cc.s + +.PHONY : Array.s + +# target to generate assembly for a file +Array.cc.s: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/Array.cc.s +.PHONY : Array.cc.s + +BuiltinFont.o: BuiltinFont.cc.o + +.PHONY : BuiltinFont.o + +# target to build an object file +BuiltinFont.cc.o: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFont.cc.o +.PHONY : BuiltinFont.cc.o + +BuiltinFont.i: BuiltinFont.cc.i + +.PHONY : BuiltinFont.i + +# target to preprocess a source file +BuiltinFont.cc.i: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFont.cc.i +.PHONY : BuiltinFont.cc.i + +BuiltinFont.s: BuiltinFont.cc.s + +.PHONY : BuiltinFont.s + +# target to generate assembly for a file +BuiltinFont.cc.s: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFont.cc.s +.PHONY : BuiltinFont.cc.s + +BuiltinFontTables.o: BuiltinFontTables.cc.o + +.PHONY : BuiltinFontTables.o + +# target to build an object file +BuiltinFontTables.cc.o: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFontTables.cc.o +.PHONY : BuiltinFontTables.cc.o + +BuiltinFontTables.i: BuiltinFontTables.cc.i + +.PHONY : BuiltinFontTables.i + +# target to preprocess a source file +BuiltinFontTables.cc.i: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFontTables.cc.i +.PHONY : BuiltinFontTables.cc.i + +BuiltinFontTables.s: BuiltinFontTables.cc.s + +.PHONY : BuiltinFontTables.s + +# target to generate assembly for a file +BuiltinFontTables.cc.s: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFontTables.cc.s +.PHONY : BuiltinFontTables.cc.s + +CMap.o: CMap.cc.o + +.PHONY : CMap.o + +# target to build an object file +CMap.cc.o: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/CMap.cc.o +.PHONY : CMap.cc.o + +CMap.i: CMap.cc.i + +.PHONY : CMap.i + +# target to preprocess a source file +CMap.cc.i: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/CMap.cc.i +.PHONY : CMap.cc.i + +CMap.s: CMap.cc.s + +.PHONY : CMap.s + +# target to generate assembly for a file +CMap.cc.s: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/CMap.cc.s +.PHONY : CMap.cc.s + +Catalog.o: Catalog.cc.o + +.PHONY : Catalog.o + +# target to build an object file +Catalog.cc.o: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/Catalog.cc.o +.PHONY : Catalog.cc.o + +Catalog.i: Catalog.cc.i + +.PHONY : Catalog.i + +# target to preprocess a source file +Catalog.cc.i: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/Catalog.cc.i +.PHONY : Catalog.cc.i + +Catalog.s: Catalog.cc.s + +.PHONY : Catalog.s + +# target to generate assembly for a file +Catalog.cc.s: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/Catalog.cc.s +.PHONY : Catalog.cc.s + +CharCodeToUnicode.o: CharCodeToUnicode.cc.o + +.PHONY : CharCodeToUnicode.o + +# target to build an object file +CharCodeToUnicode.cc.o: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/CharCodeToUnicode.cc.o +.PHONY : CharCodeToUnicode.cc.o + +CharCodeToUnicode.i: CharCodeToUnicode.cc.i + +.PHONY : CharCodeToUnicode.i + +# target to preprocess a source file +CharCodeToUnicode.cc.i: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/CharCodeToUnicode.cc.i +.PHONY : CharCodeToUnicode.cc.i + +CharCodeToUnicode.s: CharCodeToUnicode.cc.s + +.PHONY : CharCodeToUnicode.s + +# target to generate assembly for a file +CharCodeToUnicode.cc.s: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/CharCodeToUnicode.cc.s +.PHONY : CharCodeToUnicode.cc.s + +Decrypt.o: Decrypt.cc.o + +.PHONY : Decrypt.o + +# target to build an object file +Decrypt.cc.o: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/Decrypt.cc.o +.PHONY : Decrypt.cc.o + +Decrypt.i: Decrypt.cc.i + +.PHONY : Decrypt.i + +# target to preprocess a source file +Decrypt.cc.i: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/Decrypt.cc.i +.PHONY : Decrypt.cc.i + +Decrypt.s: Decrypt.cc.s + +.PHONY : Decrypt.s + +# target to generate assembly for a file +Decrypt.cc.s: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/Decrypt.cc.s +.PHONY : Decrypt.cc.s + +Dict.o: Dict.cc.o + +.PHONY : Dict.o + +# target to build an object file +Dict.cc.o: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/Dict.cc.o +.PHONY : Dict.cc.o + +Dict.i: Dict.cc.i + +.PHONY : Dict.i + +# target to preprocess a source file +Dict.cc.i: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/Dict.cc.i +.PHONY : Dict.cc.i + +Dict.s: Dict.cc.s + +.PHONY : Dict.s + +# target to generate assembly for a file +Dict.cc.s: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/Dict.cc.s +.PHONY : Dict.cc.s + +DisplayState.o: DisplayState.cc.o + +.PHONY : DisplayState.o + +# target to build an object file +DisplayState.cc.o: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_widget_objs.dir/build.make xpdf/CMakeFiles/xpdf_widget_objs.dir/DisplayState.cc.o +.PHONY : DisplayState.cc.o + +DisplayState.i: DisplayState.cc.i + +.PHONY : DisplayState.i + +# target to preprocess a source file +DisplayState.cc.i: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_widget_objs.dir/build.make xpdf/CMakeFiles/xpdf_widget_objs.dir/DisplayState.cc.i +.PHONY : DisplayState.cc.i + +DisplayState.s: DisplayState.cc.s + +.PHONY : DisplayState.s + +# target to generate assembly for a file +DisplayState.cc.s: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_widget_objs.dir/build.make xpdf/CMakeFiles/xpdf_widget_objs.dir/DisplayState.cc.s +.PHONY : DisplayState.cc.s + +Error.o: Error.cc.o + +.PHONY : Error.o + +# target to build an object file +Error.cc.o: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/Error.cc.o +.PHONY : Error.cc.o + +Error.i: Error.cc.i + +.PHONY : Error.i + +# target to preprocess a source file +Error.cc.i: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/Error.cc.i +.PHONY : Error.cc.i + +Error.s: Error.cc.s + +.PHONY : Error.s + +# target to generate assembly for a file +Error.cc.s: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/Error.cc.s +.PHONY : Error.cc.s + +FontEncodingTables.o: FontEncodingTables.cc.o + +.PHONY : FontEncodingTables.o + +# target to build an object file +FontEncodingTables.cc.o: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/FontEncodingTables.cc.o +.PHONY : FontEncodingTables.cc.o + +FontEncodingTables.i: FontEncodingTables.cc.i + +.PHONY : FontEncodingTables.i + +# target to preprocess a source file +FontEncodingTables.cc.i: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/FontEncodingTables.cc.i +.PHONY : FontEncodingTables.cc.i + +FontEncodingTables.s: FontEncodingTables.cc.s + +.PHONY : FontEncodingTables.s + +# target to generate assembly for a file +FontEncodingTables.cc.s: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/FontEncodingTables.cc.s +.PHONY : FontEncodingTables.cc.s + +Function.o: Function.cc.o + +.PHONY : Function.o + +# target to build an object file +Function.cc.o: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/Function.cc.o +.PHONY : Function.cc.o + +Function.i: Function.cc.i + +.PHONY : Function.i + +# target to preprocess a source file +Function.cc.i: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/Function.cc.i +.PHONY : Function.cc.i + +Function.s: Function.cc.s + +.PHONY : Function.s + +# target to generate assembly for a file +Function.cc.s: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/Function.cc.s +.PHONY : Function.cc.s + +Gfx.o: Gfx.cc.o + +.PHONY : Gfx.o + +# target to build an object file +Gfx.cc.o: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/Gfx.cc.o +.PHONY : Gfx.cc.o + +Gfx.i: Gfx.cc.i + +.PHONY : Gfx.i + +# target to preprocess a source file +Gfx.cc.i: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/Gfx.cc.i +.PHONY : Gfx.cc.i + +Gfx.s: Gfx.cc.s + +.PHONY : Gfx.s + +# target to generate assembly for a file +Gfx.cc.s: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/Gfx.cc.s +.PHONY : Gfx.cc.s + +GfxFont.o: GfxFont.cc.o + +.PHONY : GfxFont.o + +# target to build an object file +GfxFont.cc.o: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/GfxFont.cc.o +.PHONY : GfxFont.cc.o + +GfxFont.i: GfxFont.cc.i + +.PHONY : GfxFont.i + +# target to preprocess a source file +GfxFont.cc.i: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/GfxFont.cc.i +.PHONY : GfxFont.cc.i + +GfxFont.s: GfxFont.cc.s + +.PHONY : GfxFont.s + +# target to generate assembly for a file +GfxFont.cc.s: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/GfxFont.cc.s +.PHONY : GfxFont.cc.s + +GfxState.o: GfxState.cc.o + +.PHONY : GfxState.o + +# target to build an object file +GfxState.cc.o: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/GfxState.cc.o +.PHONY : GfxState.cc.o + +GfxState.i: GfxState.cc.i + +.PHONY : GfxState.i + +# target to preprocess a source file +GfxState.cc.i: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/GfxState.cc.i +.PHONY : GfxState.cc.i + +GfxState.s: GfxState.cc.s + +.PHONY : GfxState.s + +# target to generate assembly for a file +GfxState.cc.s: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/GfxState.cc.s +.PHONY : GfxState.cc.s + +GlobalParams.o: GlobalParams.cc.o + +.PHONY : GlobalParams.o + +# target to build an object file +GlobalParams.cc.o: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/GlobalParams.cc.o +.PHONY : GlobalParams.cc.o + +GlobalParams.i: GlobalParams.cc.i + +.PHONY : GlobalParams.i + +# target to preprocess a source file +GlobalParams.cc.i: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/GlobalParams.cc.i +.PHONY : GlobalParams.cc.i + +GlobalParams.s: GlobalParams.cc.s + +.PHONY : GlobalParams.s + +# target to generate assembly for a file +GlobalParams.cc.s: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/GlobalParams.cc.s +.PHONY : GlobalParams.cc.s + +HTMLGen.o: HTMLGen.cc.o + +.PHONY : HTMLGen.o + +# target to build an object file +HTMLGen.cc.o: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftohtml.dir/build.make xpdf/CMakeFiles/pdftohtml.dir/HTMLGen.cc.o +.PHONY : HTMLGen.cc.o + +HTMLGen.i: HTMLGen.cc.i + +.PHONY : HTMLGen.i + +# target to preprocess a source file +HTMLGen.cc.i: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftohtml.dir/build.make xpdf/CMakeFiles/pdftohtml.dir/HTMLGen.cc.i +.PHONY : HTMLGen.cc.i + +HTMLGen.s: HTMLGen.cc.s + +.PHONY : HTMLGen.s + +# target to generate assembly for a file +HTMLGen.cc.s: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftohtml.dir/build.make xpdf/CMakeFiles/pdftohtml.dir/HTMLGen.cc.s +.PHONY : HTMLGen.cc.s + +ImageOutputDev.o: ImageOutputDev.cc.o + +.PHONY : ImageOutputDev.o + +# target to build an object file +ImageOutputDev.cc.o: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdfimages.dir/build.make xpdf/CMakeFiles/pdfimages.dir/ImageOutputDev.cc.o +.PHONY : ImageOutputDev.cc.o + +ImageOutputDev.i: ImageOutputDev.cc.i + +.PHONY : ImageOutputDev.i + +# target to preprocess a source file +ImageOutputDev.cc.i: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdfimages.dir/build.make xpdf/CMakeFiles/pdfimages.dir/ImageOutputDev.cc.i +.PHONY : ImageOutputDev.cc.i + +ImageOutputDev.s: ImageOutputDev.cc.s + +.PHONY : ImageOutputDev.s + +# target to generate assembly for a file +ImageOutputDev.cc.s: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdfimages.dir/build.make xpdf/CMakeFiles/pdfimages.dir/ImageOutputDev.cc.s +.PHONY : ImageOutputDev.cc.s + +JArithmeticDecoder.o: JArithmeticDecoder.cc.o + +.PHONY : JArithmeticDecoder.o + +# target to build an object file +JArithmeticDecoder.cc.o: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/JArithmeticDecoder.cc.o +.PHONY : JArithmeticDecoder.cc.o + +JArithmeticDecoder.i: JArithmeticDecoder.cc.i + +.PHONY : JArithmeticDecoder.i + +# target to preprocess a source file +JArithmeticDecoder.cc.i: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/JArithmeticDecoder.cc.i +.PHONY : JArithmeticDecoder.cc.i + +JArithmeticDecoder.s: JArithmeticDecoder.cc.s + +.PHONY : JArithmeticDecoder.s + +# target to generate assembly for a file +JArithmeticDecoder.cc.s: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/JArithmeticDecoder.cc.s +.PHONY : JArithmeticDecoder.cc.s + +JBIG2Stream.o: JBIG2Stream.cc.o + +.PHONY : JBIG2Stream.o + +# target to build an object file +JBIG2Stream.cc.o: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/JBIG2Stream.cc.o +.PHONY : JBIG2Stream.cc.o + +JBIG2Stream.i: JBIG2Stream.cc.i + +.PHONY : JBIG2Stream.i + +# target to preprocess a source file +JBIG2Stream.cc.i: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/JBIG2Stream.cc.i +.PHONY : JBIG2Stream.cc.i + +JBIG2Stream.s: JBIG2Stream.cc.s + +.PHONY : JBIG2Stream.s + +# target to generate assembly for a file +JBIG2Stream.cc.s: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/JBIG2Stream.cc.s +.PHONY : JBIG2Stream.cc.s + +JPXStream.o: JPXStream.cc.o + +.PHONY : JPXStream.o + +# target to build an object file +JPXStream.cc.o: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/JPXStream.cc.o +.PHONY : JPXStream.cc.o + +JPXStream.i: JPXStream.cc.i + +.PHONY : JPXStream.i + +# target to preprocess a source file +JPXStream.cc.i: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/JPXStream.cc.i +.PHONY : JPXStream.cc.i + +JPXStream.s: JPXStream.cc.s + +.PHONY : JPXStream.s + +# target to generate assembly for a file +JPXStream.cc.s: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/JPXStream.cc.s +.PHONY : JPXStream.cc.s + +Lexer.o: Lexer.cc.o + +.PHONY : Lexer.o + +# target to build an object file +Lexer.cc.o: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/Lexer.cc.o +.PHONY : Lexer.cc.o + +Lexer.i: Lexer.cc.i + +.PHONY : Lexer.i + +# target to preprocess a source file +Lexer.cc.i: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/Lexer.cc.i +.PHONY : Lexer.cc.i + +Lexer.s: Lexer.cc.s + +.PHONY : Lexer.s + +# target to generate assembly for a file +Lexer.cc.s: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/Lexer.cc.s +.PHONY : Lexer.cc.s + +Link.o: Link.cc.o + +.PHONY : Link.o + +# target to build an object file +Link.cc.o: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/Link.cc.o +.PHONY : Link.cc.o + +Link.i: Link.cc.i + +.PHONY : Link.i + +# target to preprocess a source file +Link.cc.i: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/Link.cc.i +.PHONY : Link.cc.i + +Link.s: Link.cc.s + +.PHONY : Link.s + +# target to generate assembly for a file +Link.cc.s: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/Link.cc.s +.PHONY : Link.cc.s + +NameToCharCode.o: NameToCharCode.cc.o + +.PHONY : NameToCharCode.o + +# target to build an object file +NameToCharCode.cc.o: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/NameToCharCode.cc.o +.PHONY : NameToCharCode.cc.o + +NameToCharCode.i: NameToCharCode.cc.i + +.PHONY : NameToCharCode.i + +# target to preprocess a source file +NameToCharCode.cc.i: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/NameToCharCode.cc.i +.PHONY : NameToCharCode.cc.i + +NameToCharCode.s: NameToCharCode.cc.s + +.PHONY : NameToCharCode.s + +# target to generate assembly for a file +NameToCharCode.cc.s: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/NameToCharCode.cc.s +.PHONY : NameToCharCode.cc.s + +Object.o: Object.cc.o + +.PHONY : Object.o + +# target to build an object file +Object.cc.o: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/Object.cc.o +.PHONY : Object.cc.o + +Object.i: Object.cc.i + +.PHONY : Object.i + +# target to preprocess a source file +Object.cc.i: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/Object.cc.i +.PHONY : Object.cc.i + +Object.s: Object.cc.s + +.PHONY : Object.s + +# target to generate assembly for a file +Object.cc.s: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/Object.cc.s +.PHONY : Object.cc.s + +OptionalContent.o: OptionalContent.cc.o + +.PHONY : OptionalContent.o + +# target to build an object file +OptionalContent.cc.o: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/OptionalContent.cc.o +.PHONY : OptionalContent.cc.o + +OptionalContent.i: OptionalContent.cc.i + +.PHONY : OptionalContent.i + +# target to preprocess a source file +OptionalContent.cc.i: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/OptionalContent.cc.i +.PHONY : OptionalContent.cc.i + +OptionalContent.s: OptionalContent.cc.s + +.PHONY : OptionalContent.s + +# target to generate assembly for a file +OptionalContent.cc.s: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/OptionalContent.cc.s +.PHONY : OptionalContent.cc.s + +Outline.o: Outline.cc.o + +.PHONY : Outline.o + +# target to build an object file +Outline.cc.o: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/Outline.cc.o +.PHONY : Outline.cc.o + +Outline.i: Outline.cc.i + +.PHONY : Outline.i + +# target to preprocess a source file +Outline.cc.i: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/Outline.cc.i +.PHONY : Outline.cc.i + +Outline.s: Outline.cc.s + +.PHONY : Outline.s + +# target to generate assembly for a file +Outline.cc.s: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/Outline.cc.s +.PHONY : Outline.cc.s + +OutputDev.o: OutputDev.cc.o + +.PHONY : OutputDev.o + +# target to build an object file +OutputDev.cc.o: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/OutputDev.cc.o +.PHONY : OutputDev.cc.o + +OutputDev.i: OutputDev.cc.i + +.PHONY : OutputDev.i + +# target to preprocess a source file +OutputDev.cc.i: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/OutputDev.cc.i +.PHONY : OutputDev.cc.i + +OutputDev.s: OutputDev.cc.s + +.PHONY : OutputDev.s + +# target to generate assembly for a file +OutputDev.cc.s: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/OutputDev.cc.s +.PHONY : OutputDev.cc.s + +PDF417Barcode.o: PDF417Barcode.cc.o + +.PHONY : PDF417Barcode.o + +# target to build an object file +PDF417Barcode.cc.o: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/PDF417Barcode.cc.o +.PHONY : PDF417Barcode.cc.o + +PDF417Barcode.i: PDF417Barcode.cc.i + +.PHONY : PDF417Barcode.i + +# target to preprocess a source file +PDF417Barcode.cc.i: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/PDF417Barcode.cc.i +.PHONY : PDF417Barcode.cc.i + +PDF417Barcode.s: PDF417Barcode.cc.s + +.PHONY : PDF417Barcode.s + +# target to generate assembly for a file +PDF417Barcode.cc.s: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/PDF417Barcode.cc.s +.PHONY : PDF417Barcode.cc.s + +PDFCore.o: PDFCore.cc.o + +.PHONY : PDFCore.o + +# target to build an object file +PDFCore.cc.o: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_widget_objs.dir/build.make xpdf/CMakeFiles/xpdf_widget_objs.dir/PDFCore.cc.o +.PHONY : PDFCore.cc.o + +PDFCore.i: PDFCore.cc.i + +.PHONY : PDFCore.i + +# target to preprocess a source file +PDFCore.cc.i: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_widget_objs.dir/build.make xpdf/CMakeFiles/xpdf_widget_objs.dir/PDFCore.cc.i +.PHONY : PDFCore.cc.i + +PDFCore.s: PDFCore.cc.s + +.PHONY : PDFCore.s + +# target to generate assembly for a file +PDFCore.cc.s: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_widget_objs.dir/build.make xpdf/CMakeFiles/xpdf_widget_objs.dir/PDFCore.cc.s +.PHONY : PDFCore.cc.s + +PDFDoc.o: PDFDoc.cc.o + +.PHONY : PDFDoc.o + +# target to build an object file +PDFDoc.cc.o: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/PDFDoc.cc.o +.PHONY : PDFDoc.cc.o + +PDFDoc.i: PDFDoc.cc.i + +.PHONY : PDFDoc.i + +# target to preprocess a source file +PDFDoc.cc.i: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/PDFDoc.cc.i +.PHONY : PDFDoc.cc.i + +PDFDoc.s: PDFDoc.cc.s + +.PHONY : PDFDoc.s + +# target to generate assembly for a file +PDFDoc.cc.s: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/PDFDoc.cc.s +.PHONY : PDFDoc.cc.s + +PDFDocEncoding.o: PDFDocEncoding.cc.o + +.PHONY : PDFDocEncoding.o + +# target to build an object file +PDFDocEncoding.cc.o: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/PDFDocEncoding.cc.o +.PHONY : PDFDocEncoding.cc.o + +PDFDocEncoding.i: PDFDocEncoding.cc.i + +.PHONY : PDFDocEncoding.i + +# target to preprocess a source file +PDFDocEncoding.cc.i: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/PDFDocEncoding.cc.i +.PHONY : PDFDocEncoding.cc.i + +PDFDocEncoding.s: PDFDocEncoding.cc.s + +.PHONY : PDFDocEncoding.s + +# target to generate assembly for a file +PDFDocEncoding.cc.s: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/PDFDocEncoding.cc.s +.PHONY : PDFDocEncoding.cc.s + +PSOutputDev.o: PSOutputDev.cc.o + +.PHONY : PSOutputDev.o + +# target to build an object file +PSOutputDev.cc.o: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_widget_objs.dir/build.make xpdf/CMakeFiles/xpdf_widget_objs.dir/PSOutputDev.cc.o + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftops.dir/build.make xpdf/CMakeFiles/pdftops.dir/PSOutputDev.cc.o +.PHONY : PSOutputDev.cc.o + +PSOutputDev.i: PSOutputDev.cc.i + +.PHONY : PSOutputDev.i + +# target to preprocess a source file +PSOutputDev.cc.i: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_widget_objs.dir/build.make xpdf/CMakeFiles/xpdf_widget_objs.dir/PSOutputDev.cc.i + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftops.dir/build.make xpdf/CMakeFiles/pdftops.dir/PSOutputDev.cc.i +.PHONY : PSOutputDev.cc.i + +PSOutputDev.s: PSOutputDev.cc.s + +.PHONY : PSOutputDev.s + +# target to generate assembly for a file +PSOutputDev.cc.s: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_widget_objs.dir/build.make xpdf/CMakeFiles/xpdf_widget_objs.dir/PSOutputDev.cc.s + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftops.dir/build.make xpdf/CMakeFiles/pdftops.dir/PSOutputDev.cc.s +.PHONY : PSOutputDev.cc.s + +PSTokenizer.o: PSTokenizer.cc.o + +.PHONY : PSTokenizer.o + +# target to build an object file +PSTokenizer.cc.o: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/PSTokenizer.cc.o +.PHONY : PSTokenizer.cc.o + +PSTokenizer.i: PSTokenizer.cc.i + +.PHONY : PSTokenizer.i + +# target to preprocess a source file +PSTokenizer.cc.i: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/PSTokenizer.cc.i +.PHONY : PSTokenizer.cc.i + +PSTokenizer.s: PSTokenizer.cc.s + +.PHONY : PSTokenizer.s + +# target to generate assembly for a file +PSTokenizer.cc.s: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/PSTokenizer.cc.s +.PHONY : PSTokenizer.cc.s + +Page.o: Page.cc.o + +.PHONY : Page.o + +# target to build an object file +Page.cc.o: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/Page.cc.o +.PHONY : Page.cc.o + +Page.i: Page.cc.i + +.PHONY : Page.i + +# target to preprocess a source file +Page.cc.i: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/Page.cc.i +.PHONY : Page.cc.i + +Page.s: Page.cc.s + +.PHONY : Page.s + +# target to generate assembly for a file +Page.cc.s: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/Page.cc.s +.PHONY : Page.cc.s + +Parser.o: Parser.cc.o + +.PHONY : Parser.o + +# target to build an object file +Parser.cc.o: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/Parser.cc.o +.PHONY : Parser.cc.o + +Parser.i: Parser.cc.i + +.PHONY : Parser.i + +# target to preprocess a source file +Parser.cc.i: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/Parser.cc.i +.PHONY : Parser.cc.i + +Parser.s: Parser.cc.s + +.PHONY : Parser.s + +# target to generate assembly for a file +Parser.cc.s: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/Parser.cc.s +.PHONY : Parser.cc.s + +PreScanOutputDev.o: PreScanOutputDev.cc.o + +.PHONY : PreScanOutputDev.o + +# target to build an object file +PreScanOutputDev.cc.o: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_widget_objs.dir/build.make xpdf/CMakeFiles/xpdf_widget_objs.dir/PreScanOutputDev.cc.o + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftops.dir/build.make xpdf/CMakeFiles/pdftops.dir/PreScanOutputDev.cc.o +.PHONY : PreScanOutputDev.cc.o + +PreScanOutputDev.i: PreScanOutputDev.cc.i + +.PHONY : PreScanOutputDev.i + +# target to preprocess a source file +PreScanOutputDev.cc.i: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_widget_objs.dir/build.make xpdf/CMakeFiles/xpdf_widget_objs.dir/PreScanOutputDev.cc.i + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftops.dir/build.make xpdf/CMakeFiles/pdftops.dir/PreScanOutputDev.cc.i +.PHONY : PreScanOutputDev.cc.i + +PreScanOutputDev.s: PreScanOutputDev.cc.s + +.PHONY : PreScanOutputDev.s + +# target to generate assembly for a file +PreScanOutputDev.cc.s: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_widget_objs.dir/build.make xpdf/CMakeFiles/xpdf_widget_objs.dir/PreScanOutputDev.cc.s + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftops.dir/build.make xpdf/CMakeFiles/pdftops.dir/PreScanOutputDev.cc.s +.PHONY : PreScanOutputDev.cc.s + +SecurityHandler.o: SecurityHandler.cc.o + +.PHONY : SecurityHandler.o + +# target to build an object file +SecurityHandler.cc.o: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.o +.PHONY : SecurityHandler.cc.o + +SecurityHandler.i: SecurityHandler.cc.i + +.PHONY : SecurityHandler.i + +# target to preprocess a source file +SecurityHandler.cc.i: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.i +.PHONY : SecurityHandler.cc.i + +SecurityHandler.s: SecurityHandler.cc.s + +.PHONY : SecurityHandler.s + +# target to generate assembly for a file +SecurityHandler.cc.s: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.s +.PHONY : SecurityHandler.cc.s + +ShadingImage.o: ShadingImage.cc.o + +.PHONY : ShadingImage.o + +# target to build an object file +ShadingImage.cc.o: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftohtml.dir/build.make xpdf/CMakeFiles/pdftohtml.dir/ShadingImage.cc.o + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftoppm.dir/build.make xpdf/CMakeFiles/pdftoppm.dir/ShadingImage.cc.o + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftopng.dir/build.make xpdf/CMakeFiles/pdftopng.dir/ShadingImage.cc.o + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_widget_objs.dir/build.make xpdf/CMakeFiles/xpdf_widget_objs.dir/ShadingImage.cc.o + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftops.dir/build.make xpdf/CMakeFiles/pdftops.dir/ShadingImage.cc.o +.PHONY : ShadingImage.cc.o + +ShadingImage.i: ShadingImage.cc.i + +.PHONY : ShadingImage.i + +# target to preprocess a source file +ShadingImage.cc.i: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftohtml.dir/build.make xpdf/CMakeFiles/pdftohtml.dir/ShadingImage.cc.i + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftoppm.dir/build.make xpdf/CMakeFiles/pdftoppm.dir/ShadingImage.cc.i + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftopng.dir/build.make xpdf/CMakeFiles/pdftopng.dir/ShadingImage.cc.i + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_widget_objs.dir/build.make xpdf/CMakeFiles/xpdf_widget_objs.dir/ShadingImage.cc.i + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftops.dir/build.make xpdf/CMakeFiles/pdftops.dir/ShadingImage.cc.i +.PHONY : ShadingImage.cc.i + +ShadingImage.s: ShadingImage.cc.s + +.PHONY : ShadingImage.s + +# target to generate assembly for a file +ShadingImage.cc.s: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftohtml.dir/build.make xpdf/CMakeFiles/pdftohtml.dir/ShadingImage.cc.s + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftoppm.dir/build.make xpdf/CMakeFiles/pdftoppm.dir/ShadingImage.cc.s + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftopng.dir/build.make xpdf/CMakeFiles/pdftopng.dir/ShadingImage.cc.s + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_widget_objs.dir/build.make xpdf/CMakeFiles/xpdf_widget_objs.dir/ShadingImage.cc.s + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftops.dir/build.make xpdf/CMakeFiles/pdftops.dir/ShadingImage.cc.s +.PHONY : ShadingImage.cc.s + +SplashOutputDev.o: SplashOutputDev.cc.o + +.PHONY : SplashOutputDev.o + +# target to build an object file +SplashOutputDev.cc.o: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftohtml.dir/build.make xpdf/CMakeFiles/pdftohtml.dir/SplashOutputDev.cc.o + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftoppm.dir/build.make xpdf/CMakeFiles/pdftoppm.dir/SplashOutputDev.cc.o + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftopng.dir/build.make xpdf/CMakeFiles/pdftopng.dir/SplashOutputDev.cc.o + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_widget_objs.dir/build.make xpdf/CMakeFiles/xpdf_widget_objs.dir/SplashOutputDev.cc.o + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftops.dir/build.make xpdf/CMakeFiles/pdftops.dir/SplashOutputDev.cc.o +.PHONY : SplashOutputDev.cc.o + +SplashOutputDev.i: SplashOutputDev.cc.i + +.PHONY : SplashOutputDev.i + +# target to preprocess a source file +SplashOutputDev.cc.i: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftohtml.dir/build.make xpdf/CMakeFiles/pdftohtml.dir/SplashOutputDev.cc.i + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftoppm.dir/build.make xpdf/CMakeFiles/pdftoppm.dir/SplashOutputDev.cc.i + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftopng.dir/build.make xpdf/CMakeFiles/pdftopng.dir/SplashOutputDev.cc.i + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_widget_objs.dir/build.make xpdf/CMakeFiles/xpdf_widget_objs.dir/SplashOutputDev.cc.i + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftops.dir/build.make xpdf/CMakeFiles/pdftops.dir/SplashOutputDev.cc.i +.PHONY : SplashOutputDev.cc.i + +SplashOutputDev.s: SplashOutputDev.cc.s + +.PHONY : SplashOutputDev.s + +# target to generate assembly for a file +SplashOutputDev.cc.s: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftohtml.dir/build.make xpdf/CMakeFiles/pdftohtml.dir/SplashOutputDev.cc.s + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftoppm.dir/build.make xpdf/CMakeFiles/pdftoppm.dir/SplashOutputDev.cc.s + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftopng.dir/build.make xpdf/CMakeFiles/pdftopng.dir/SplashOutputDev.cc.s + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_widget_objs.dir/build.make xpdf/CMakeFiles/xpdf_widget_objs.dir/SplashOutputDev.cc.s + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftops.dir/build.make xpdf/CMakeFiles/pdftops.dir/SplashOutputDev.cc.s +.PHONY : SplashOutputDev.cc.s + +Stream.o: Stream.cc.o + +.PHONY : Stream.o + +# target to build an object file +Stream.cc.o: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/Stream.cc.o +.PHONY : Stream.cc.o + +Stream.i: Stream.cc.i + +.PHONY : Stream.i + +# target to preprocess a source file +Stream.cc.i: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/Stream.cc.i +.PHONY : Stream.cc.i + +Stream.s: Stream.cc.s + +.PHONY : Stream.s + +# target to generate assembly for a file +Stream.cc.s: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/Stream.cc.s +.PHONY : Stream.cc.s + +TextOutputDev.o: TextOutputDev.cc.o + +.PHONY : TextOutputDev.o + +# target to build an object file +TextOutputDev.cc.o: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftohtml.dir/build.make xpdf/CMakeFiles/pdftohtml.dir/TextOutputDev.cc.o + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftotext.dir/build.make xpdf/CMakeFiles/pdftotext.dir/TextOutputDev.cc.o + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_widget_objs.dir/build.make xpdf/CMakeFiles/xpdf_widget_objs.dir/TextOutputDev.cc.o +.PHONY : TextOutputDev.cc.o + +TextOutputDev.i: TextOutputDev.cc.i + +.PHONY : TextOutputDev.i + +# target to preprocess a source file +TextOutputDev.cc.i: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftohtml.dir/build.make xpdf/CMakeFiles/pdftohtml.dir/TextOutputDev.cc.i + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftotext.dir/build.make xpdf/CMakeFiles/pdftotext.dir/TextOutputDev.cc.i + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_widget_objs.dir/build.make xpdf/CMakeFiles/xpdf_widget_objs.dir/TextOutputDev.cc.i +.PHONY : TextOutputDev.cc.i + +TextOutputDev.s: TextOutputDev.cc.s + +.PHONY : TextOutputDev.s + +# target to generate assembly for a file +TextOutputDev.cc.s: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftohtml.dir/build.make xpdf/CMakeFiles/pdftohtml.dir/TextOutputDev.cc.s + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftotext.dir/build.make xpdf/CMakeFiles/pdftotext.dir/TextOutputDev.cc.s + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_widget_objs.dir/build.make xpdf/CMakeFiles/xpdf_widget_objs.dir/TextOutputDev.cc.s +.PHONY : TextOutputDev.cc.s + +TextString.o: TextString.cc.o + +.PHONY : TextString.o + +# target to build an object file +TextString.cc.o: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/TextString.cc.o +.PHONY : TextString.cc.o + +TextString.i: TextString.cc.i + +.PHONY : TextString.i + +# target to preprocess a source file +TextString.cc.i: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/TextString.cc.i +.PHONY : TextString.cc.i + +TextString.s: TextString.cc.s + +.PHONY : TextString.s + +# target to generate assembly for a file +TextString.cc.s: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/TextString.cc.s +.PHONY : TextString.cc.s + +TileCache.o: TileCache.cc.o + +.PHONY : TileCache.o + +# target to build an object file +TileCache.cc.o: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_widget_objs.dir/build.make xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCache.cc.o +.PHONY : TileCache.cc.o + +TileCache.i: TileCache.cc.i + +.PHONY : TileCache.i + +# target to preprocess a source file +TileCache.cc.i: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_widget_objs.dir/build.make xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCache.cc.i +.PHONY : TileCache.cc.i + +TileCache.s: TileCache.cc.s + +.PHONY : TileCache.s + +# target to generate assembly for a file +TileCache.cc.s: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_widget_objs.dir/build.make xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCache.cc.s +.PHONY : TileCache.cc.s + +TileCompositor.o: TileCompositor.cc.o + +.PHONY : TileCompositor.o + +# target to build an object file +TileCompositor.cc.o: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_widget_objs.dir/build.make xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCompositor.cc.o +.PHONY : TileCompositor.cc.o + +TileCompositor.i: TileCompositor.cc.i + +.PHONY : TileCompositor.i + +# target to preprocess a source file +TileCompositor.cc.i: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_widget_objs.dir/build.make xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCompositor.cc.i +.PHONY : TileCompositor.cc.i + +TileCompositor.s: TileCompositor.cc.s + +.PHONY : TileCompositor.s + +# target to generate assembly for a file +TileCompositor.cc.s: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_widget_objs.dir/build.make xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCompositor.cc.s +.PHONY : TileCompositor.cc.s + +TileMap.o: TileMap.cc.o + +.PHONY : TileMap.o + +# target to build an object file +TileMap.cc.o: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_widget_objs.dir/build.make xpdf/CMakeFiles/xpdf_widget_objs.dir/TileMap.cc.o +.PHONY : TileMap.cc.o + +TileMap.i: TileMap.cc.i + +.PHONY : TileMap.i + +# target to preprocess a source file +TileMap.cc.i: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_widget_objs.dir/build.make xpdf/CMakeFiles/xpdf_widget_objs.dir/TileMap.cc.i +.PHONY : TileMap.cc.i + +TileMap.s: TileMap.cc.s + +.PHONY : TileMap.s + +# target to generate assembly for a file +TileMap.cc.s: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_widget_objs.dir/build.make xpdf/CMakeFiles/xpdf_widget_objs.dir/TileMap.cc.s +.PHONY : TileMap.cc.s + +UTF8.o: UTF8.cc.o + +.PHONY : UTF8.o + +# target to build an object file +UTF8.cc.o: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/UTF8.cc.o +.PHONY : UTF8.cc.o + +UTF8.i: UTF8.cc.i + +.PHONY : UTF8.i + +# target to preprocess a source file +UTF8.cc.i: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/UTF8.cc.i +.PHONY : UTF8.cc.i + +UTF8.s: UTF8.cc.s + +.PHONY : UTF8.s + +# target to generate assembly for a file +UTF8.cc.s: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/UTF8.cc.s +.PHONY : UTF8.cc.s + +UnicodeMap.o: UnicodeMap.cc.o + +.PHONY : UnicodeMap.o + +# target to build an object file +UnicodeMap.cc.o: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/UnicodeMap.cc.o +.PHONY : UnicodeMap.cc.o + +UnicodeMap.i: UnicodeMap.cc.i + +.PHONY : UnicodeMap.i + +# target to preprocess a source file +UnicodeMap.cc.i: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/UnicodeMap.cc.i +.PHONY : UnicodeMap.cc.i + +UnicodeMap.s: UnicodeMap.cc.s + +.PHONY : UnicodeMap.s + +# target to generate assembly for a file +UnicodeMap.cc.s: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/UnicodeMap.cc.s +.PHONY : UnicodeMap.cc.s + +UnicodeRemapping.o: UnicodeRemapping.cc.o + +.PHONY : UnicodeRemapping.o + +# target to build an object file +UnicodeRemapping.cc.o: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/UnicodeRemapping.cc.o +.PHONY : UnicodeRemapping.cc.o + +UnicodeRemapping.i: UnicodeRemapping.cc.i + +.PHONY : UnicodeRemapping.i + +# target to preprocess a source file +UnicodeRemapping.cc.i: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/UnicodeRemapping.cc.i +.PHONY : UnicodeRemapping.cc.i + +UnicodeRemapping.s: UnicodeRemapping.cc.s + +.PHONY : UnicodeRemapping.s + +# target to generate assembly for a file +UnicodeRemapping.cc.s: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/UnicodeRemapping.cc.s +.PHONY : UnicodeRemapping.cc.s + +UnicodeTypeTable.o: UnicodeTypeTable.cc.o + +.PHONY : UnicodeTypeTable.o + +# target to build an object file +UnicodeTypeTable.cc.o: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/UnicodeTypeTable.cc.o +.PHONY : UnicodeTypeTable.cc.o + +UnicodeTypeTable.i: UnicodeTypeTable.cc.i + +.PHONY : UnicodeTypeTable.i + +# target to preprocess a source file +UnicodeTypeTable.cc.i: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/UnicodeTypeTable.cc.i +.PHONY : UnicodeTypeTable.cc.i + +UnicodeTypeTable.s: UnicodeTypeTable.cc.s + +.PHONY : UnicodeTypeTable.s + +# target to generate assembly for a file +UnicodeTypeTable.cc.s: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/UnicodeTypeTable.cc.s +.PHONY : UnicodeTypeTable.cc.s + +WebFont.o: WebFont.cc.o + +.PHONY : WebFont.o + +# target to build an object file +WebFont.cc.o: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftohtml.dir/build.make xpdf/CMakeFiles/pdftohtml.dir/WebFont.cc.o +.PHONY : WebFont.cc.o + +WebFont.i: WebFont.cc.i + +.PHONY : WebFont.i + +# target to preprocess a source file +WebFont.cc.i: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftohtml.dir/build.make xpdf/CMakeFiles/pdftohtml.dir/WebFont.cc.i +.PHONY : WebFont.cc.i + +WebFont.s: WebFont.cc.s + +.PHONY : WebFont.s + +# target to generate assembly for a file +WebFont.cc.s: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftohtml.dir/build.make xpdf/CMakeFiles/pdftohtml.dir/WebFont.cc.s +.PHONY : WebFont.cc.s + +XFAScanner.o: XFAScanner.cc.o + +.PHONY : XFAScanner.o + +# target to build an object file +XFAScanner.cc.o: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/XFAScanner.cc.o +.PHONY : XFAScanner.cc.o + +XFAScanner.i: XFAScanner.cc.i + +.PHONY : XFAScanner.i + +# target to preprocess a source file +XFAScanner.cc.i: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/XFAScanner.cc.i +.PHONY : XFAScanner.cc.i + +XFAScanner.s: XFAScanner.cc.s + +.PHONY : XFAScanner.s + +# target to generate assembly for a file +XFAScanner.cc.s: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/XFAScanner.cc.s +.PHONY : XFAScanner.cc.s + +XRef.o: XRef.cc.o + +.PHONY : XRef.o + +# target to build an object file +XRef.cc.o: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/XRef.cc.o +.PHONY : XRef.cc.o + +XRef.i: XRef.cc.i + +.PHONY : XRef.i + +# target to preprocess a source file +XRef.cc.i: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/XRef.cc.i +.PHONY : XRef.cc.i + +XRef.s: XRef.cc.s + +.PHONY : XRef.s + +# target to generate assembly for a file +XRef.cc.s: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/XRef.cc.s +.PHONY : XRef.cc.s + +Zoox.o: Zoox.cc.o + +.PHONY : Zoox.o + +# target to build an object file +Zoox.cc.o: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/Zoox.cc.o +.PHONY : Zoox.cc.o + +Zoox.i: Zoox.cc.i + +.PHONY : Zoox.i + +# target to preprocess a source file +Zoox.cc.i: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/Zoox.cc.i +.PHONY : Zoox.cc.i + +Zoox.s: Zoox.cc.s + +.PHONY : Zoox.s + +# target to generate assembly for a file +Zoox.cc.s: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/Zoox.cc.s +.PHONY : Zoox.cc.s + +pdfdetach.o: pdfdetach.cc.o + +.PHONY : pdfdetach.o + +# target to build an object file +pdfdetach.cc.o: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdfdetach.dir/build.make xpdf/CMakeFiles/pdfdetach.dir/pdfdetach.cc.o +.PHONY : pdfdetach.cc.o + +pdfdetach.i: pdfdetach.cc.i + +.PHONY : pdfdetach.i + +# target to preprocess a source file +pdfdetach.cc.i: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdfdetach.dir/build.make xpdf/CMakeFiles/pdfdetach.dir/pdfdetach.cc.i +.PHONY : pdfdetach.cc.i + +pdfdetach.s: pdfdetach.cc.s + +.PHONY : pdfdetach.s + +# target to generate assembly for a file +pdfdetach.cc.s: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdfdetach.dir/build.make xpdf/CMakeFiles/pdfdetach.dir/pdfdetach.cc.s +.PHONY : pdfdetach.cc.s + +pdffonts.o: pdffonts.cc.o + +.PHONY : pdffonts.o + +# target to build an object file +pdffonts.cc.o: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdffonts.dir/build.make xpdf/CMakeFiles/pdffonts.dir/pdffonts.cc.o +.PHONY : pdffonts.cc.o + +pdffonts.i: pdffonts.cc.i + +.PHONY : pdffonts.i + +# target to preprocess a source file +pdffonts.cc.i: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdffonts.dir/build.make xpdf/CMakeFiles/pdffonts.dir/pdffonts.cc.i +.PHONY : pdffonts.cc.i + +pdffonts.s: pdffonts.cc.s + +.PHONY : pdffonts.s + +# target to generate assembly for a file +pdffonts.cc.s: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdffonts.dir/build.make xpdf/CMakeFiles/pdffonts.dir/pdffonts.cc.s +.PHONY : pdffonts.cc.s + +pdfimages.o: pdfimages.cc.o + +.PHONY : pdfimages.o + +# target to build an object file +pdfimages.cc.o: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdfimages.dir/build.make xpdf/CMakeFiles/pdfimages.dir/pdfimages.cc.o +.PHONY : pdfimages.cc.o + +pdfimages.i: pdfimages.cc.i + +.PHONY : pdfimages.i + +# target to preprocess a source file +pdfimages.cc.i: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdfimages.dir/build.make xpdf/CMakeFiles/pdfimages.dir/pdfimages.cc.i +.PHONY : pdfimages.cc.i + +pdfimages.s: pdfimages.cc.s + +.PHONY : pdfimages.s + +# target to generate assembly for a file +pdfimages.cc.s: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdfimages.dir/build.make xpdf/CMakeFiles/pdfimages.dir/pdfimages.cc.s +.PHONY : pdfimages.cc.s + +pdfinfo.o: pdfinfo.cc.o + +.PHONY : pdfinfo.o + +# target to build an object file +pdfinfo.cc.o: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdfinfo.dir/build.make xpdf/CMakeFiles/pdfinfo.dir/pdfinfo.cc.o +.PHONY : pdfinfo.cc.o + +pdfinfo.i: pdfinfo.cc.i + +.PHONY : pdfinfo.i + +# target to preprocess a source file +pdfinfo.cc.i: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdfinfo.dir/build.make xpdf/CMakeFiles/pdfinfo.dir/pdfinfo.cc.i +.PHONY : pdfinfo.cc.i + +pdfinfo.s: pdfinfo.cc.s + +.PHONY : pdfinfo.s + +# target to generate assembly for a file +pdfinfo.cc.s: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdfinfo.dir/build.make xpdf/CMakeFiles/pdfinfo.dir/pdfinfo.cc.s +.PHONY : pdfinfo.cc.s + +pdftohtml.o: pdftohtml.cc.o + +.PHONY : pdftohtml.o + +# target to build an object file +pdftohtml.cc.o: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftohtml.dir/build.make xpdf/CMakeFiles/pdftohtml.dir/pdftohtml.cc.o +.PHONY : pdftohtml.cc.o + +pdftohtml.i: pdftohtml.cc.i + +.PHONY : pdftohtml.i + +# target to preprocess a source file +pdftohtml.cc.i: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftohtml.dir/build.make xpdf/CMakeFiles/pdftohtml.dir/pdftohtml.cc.i +.PHONY : pdftohtml.cc.i + +pdftohtml.s: pdftohtml.cc.s + +.PHONY : pdftohtml.s + +# target to generate assembly for a file +pdftohtml.cc.s: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftohtml.dir/build.make xpdf/CMakeFiles/pdftohtml.dir/pdftohtml.cc.s +.PHONY : pdftohtml.cc.s + +pdftopng.o: pdftopng.cc.o + +.PHONY : pdftopng.o + +# target to build an object file +pdftopng.cc.o: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftopng.dir/build.make xpdf/CMakeFiles/pdftopng.dir/pdftopng.cc.o +.PHONY : pdftopng.cc.o + +pdftopng.i: pdftopng.cc.i + +.PHONY : pdftopng.i + +# target to preprocess a source file +pdftopng.cc.i: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftopng.dir/build.make xpdf/CMakeFiles/pdftopng.dir/pdftopng.cc.i +.PHONY : pdftopng.cc.i + +pdftopng.s: pdftopng.cc.s + +.PHONY : pdftopng.s + +# target to generate assembly for a file +pdftopng.cc.s: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftopng.dir/build.make xpdf/CMakeFiles/pdftopng.dir/pdftopng.cc.s +.PHONY : pdftopng.cc.s + +pdftoppm.o: pdftoppm.cc.o + +.PHONY : pdftoppm.o + +# target to build an object file +pdftoppm.cc.o: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftoppm.dir/build.make xpdf/CMakeFiles/pdftoppm.dir/pdftoppm.cc.o +.PHONY : pdftoppm.cc.o + +pdftoppm.i: pdftoppm.cc.i + +.PHONY : pdftoppm.i + +# target to preprocess a source file +pdftoppm.cc.i: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftoppm.dir/build.make xpdf/CMakeFiles/pdftoppm.dir/pdftoppm.cc.i +.PHONY : pdftoppm.cc.i + +pdftoppm.s: pdftoppm.cc.s + +.PHONY : pdftoppm.s + +# target to generate assembly for a file +pdftoppm.cc.s: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftoppm.dir/build.make xpdf/CMakeFiles/pdftoppm.dir/pdftoppm.cc.s +.PHONY : pdftoppm.cc.s + +pdftops.o: pdftops.cc.o + +.PHONY : pdftops.o + +# target to build an object file +pdftops.cc.o: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftops.dir/build.make xpdf/CMakeFiles/pdftops.dir/pdftops.cc.o +.PHONY : pdftops.cc.o + +pdftops.i: pdftops.cc.i + +.PHONY : pdftops.i + +# target to preprocess a source file +pdftops.cc.i: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftops.dir/build.make xpdf/CMakeFiles/pdftops.dir/pdftops.cc.i +.PHONY : pdftops.cc.i + +pdftops.s: pdftops.cc.s + +.PHONY : pdftops.s + +# target to generate assembly for a file +pdftops.cc.s: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftops.dir/build.make xpdf/CMakeFiles/pdftops.dir/pdftops.cc.s +.PHONY : pdftops.cc.s + +pdftotext.o: pdftotext.cc.o + +.PHONY : pdftotext.o + +# target to build an object file +pdftotext.cc.o: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftotext.dir/build.make xpdf/CMakeFiles/pdftotext.dir/pdftotext.cc.o +.PHONY : pdftotext.cc.o + +pdftotext.i: pdftotext.cc.i + +.PHONY : pdftotext.i + +# target to preprocess a source file +pdftotext.cc.i: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftotext.dir/build.make xpdf/CMakeFiles/pdftotext.dir/pdftotext.cc.i +.PHONY : pdftotext.cc.i + +pdftotext.s: pdftotext.cc.s + +.PHONY : pdftotext.s + +# target to generate assembly for a file +pdftotext.cc.s: + cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftotext.dir/build.make xpdf/CMakeFiles/pdftotext.dir/pdftotext.cc.s +.PHONY : pdftotext.cc.s + +# Help Target +help: + @echo "The following are some of the valid targets for this Makefile:" + @echo "... all (the default if no target is provided)" + @echo "... clean" + @echo "... depend" + @echo "... edit_cache" + @echo "... install" + @echo "... install/local" + @echo "... install/strip" + @echo "... list_install_components" + @echo "... rebuild_cache" + @echo "... pdfdetach" + @echo "... pdffonts" + @echo "... pdfimages" + @echo "... pdfinfo" + @echo "... pdftohtml" + @echo "... pdftopng" + @echo "... pdftoppm" + @echo "... pdftops" + @echo "... pdftotext" + @echo "... xpdf_objs" + @echo "... xpdf_widget_objs" + @echo "... AcroForm.o" + @echo "... AcroForm.i" + @echo "... AcroForm.s" + @echo "... Annot.o" + @echo "... Annot.i" + @echo "... Annot.s" + @echo "... Array.o" + @echo "... Array.i" + @echo "... Array.s" + @echo "... BuiltinFont.o" + @echo "... BuiltinFont.i" + @echo "... BuiltinFont.s" + @echo "... BuiltinFontTables.o" + @echo "... BuiltinFontTables.i" + @echo "... BuiltinFontTables.s" + @echo "... CMap.o" + @echo "... CMap.i" + @echo "... CMap.s" + @echo "... Catalog.o" + @echo "... Catalog.i" + @echo "... Catalog.s" + @echo "... CharCodeToUnicode.o" + @echo "... CharCodeToUnicode.i" + @echo "... CharCodeToUnicode.s" + @echo "... Decrypt.o" + @echo "... Decrypt.i" + @echo "... Decrypt.s" + @echo "... Dict.o" + @echo "... Dict.i" + @echo "... Dict.s" + @echo "... DisplayState.o" + @echo "... DisplayState.i" + @echo "... DisplayState.s" + @echo "... Error.o" + @echo "... Error.i" + @echo "... Error.s" + @echo "... FontEncodingTables.o" + @echo "... FontEncodingTables.i" + @echo "... FontEncodingTables.s" + @echo "... Function.o" + @echo "... Function.i" + @echo "... Function.s" + @echo "... Gfx.o" + @echo "... Gfx.i" + @echo "... Gfx.s" + @echo "... GfxFont.o" + @echo "... GfxFont.i" + @echo "... GfxFont.s" + @echo "... GfxState.o" + @echo "... GfxState.i" + @echo "... GfxState.s" + @echo "... GlobalParams.o" + @echo "... GlobalParams.i" + @echo "... GlobalParams.s" + @echo "... HTMLGen.o" + @echo "... HTMLGen.i" + @echo "... HTMLGen.s" + @echo "... ImageOutputDev.o" + @echo "... ImageOutputDev.i" + @echo "... ImageOutputDev.s" + @echo "... JArithmeticDecoder.o" + @echo "... JArithmeticDecoder.i" + @echo "... JArithmeticDecoder.s" + @echo "... JBIG2Stream.o" + @echo "... JBIG2Stream.i" + @echo "... JBIG2Stream.s" + @echo "... JPXStream.o" + @echo "... JPXStream.i" + @echo "... JPXStream.s" + @echo "... Lexer.o" + @echo "... Lexer.i" + @echo "... Lexer.s" + @echo "... Link.o" + @echo "... Link.i" + @echo "... Link.s" + @echo "... NameToCharCode.o" + @echo "... NameToCharCode.i" + @echo "... NameToCharCode.s" + @echo "... Object.o" + @echo "... Object.i" + @echo "... Object.s" + @echo "... OptionalContent.o" + @echo "... OptionalContent.i" + @echo "... OptionalContent.s" + @echo "... Outline.o" + @echo "... Outline.i" + @echo "... Outline.s" + @echo "... OutputDev.o" + @echo "... OutputDev.i" + @echo "... OutputDev.s" + @echo "... PDF417Barcode.o" + @echo "... PDF417Barcode.i" + @echo "... PDF417Barcode.s" + @echo "... PDFCore.o" + @echo "... PDFCore.i" + @echo "... PDFCore.s" + @echo "... PDFDoc.o" + @echo "... PDFDoc.i" + @echo "... PDFDoc.s" + @echo "... PDFDocEncoding.o" + @echo "... PDFDocEncoding.i" + @echo "... PDFDocEncoding.s" + @echo "... PSOutputDev.o" + @echo "... PSOutputDev.i" + @echo "... PSOutputDev.s" + @echo "... PSTokenizer.o" + @echo "... PSTokenizer.i" + @echo "... PSTokenizer.s" + @echo "... Page.o" + @echo "... Page.i" + @echo "... Page.s" + @echo "... Parser.o" + @echo "... Parser.i" + @echo "... Parser.s" + @echo "... PreScanOutputDev.o" + @echo "... PreScanOutputDev.i" + @echo "... PreScanOutputDev.s" + @echo "... SecurityHandler.o" + @echo "... SecurityHandler.i" + @echo "... SecurityHandler.s" + @echo "... ShadingImage.o" + @echo "... ShadingImage.i" + @echo "... ShadingImage.s" + @echo "... SplashOutputDev.o" + @echo "... SplashOutputDev.i" + @echo "... SplashOutputDev.s" + @echo "... Stream.o" + @echo "... Stream.i" + @echo "... Stream.s" + @echo "... TextOutputDev.o" + @echo "... TextOutputDev.i" + @echo "... TextOutputDev.s" + @echo "... TextString.o" + @echo "... TextString.i" + @echo "... TextString.s" + @echo "... TileCache.o" + @echo "... TileCache.i" + @echo "... TileCache.s" + @echo "... TileCompositor.o" + @echo "... TileCompositor.i" + @echo "... TileCompositor.s" + @echo "... TileMap.o" + @echo "... TileMap.i" + @echo "... TileMap.s" + @echo "... UTF8.o" + @echo "... UTF8.i" + @echo "... UTF8.s" + @echo "... UnicodeMap.o" + @echo "... UnicodeMap.i" + @echo "... UnicodeMap.s" + @echo "... UnicodeRemapping.o" + @echo "... UnicodeRemapping.i" + @echo "... UnicodeRemapping.s" + @echo "... UnicodeTypeTable.o" + @echo "... UnicodeTypeTable.i" + @echo "... UnicodeTypeTable.s" + @echo "... WebFont.o" + @echo "... WebFont.i" + @echo "... WebFont.s" + @echo "... XFAScanner.o" + @echo "... XFAScanner.i" + @echo "... XFAScanner.s" + @echo "... XRef.o" + @echo "... XRef.i" + @echo "... XRef.s" + @echo "... Zoox.o" + @echo "... Zoox.i" + @echo "... Zoox.s" + @echo "... pdfdetach.o" + @echo "... pdfdetach.i" + @echo "... pdfdetach.s" + @echo "... pdffonts.o" + @echo "... pdffonts.i" + @echo "... pdffonts.s" + @echo "... pdfimages.o" + @echo "... pdfimages.i" + @echo "... pdfimages.s" + @echo "... pdfinfo.o" + @echo "... pdfinfo.i" + @echo "... pdfinfo.s" + @echo "... pdftohtml.o" + @echo "... pdftohtml.i" + @echo "... pdftohtml.s" + @echo "... pdftopng.o" + @echo "... pdftopng.i" + @echo "... pdftopng.s" + @echo "... pdftoppm.o" + @echo "... pdftoppm.i" + @echo "... pdftoppm.s" + @echo "... pdftops.o" + @echo "... pdftops.i" + @echo "... pdftops.s" + @echo "... pdftotext.o" + @echo "... pdftotext.i" + @echo "... pdftotext.s" +.PHONY : help + + + +#============================================================================= +# Special targets to cleanup operation of make. + +# Special rule to run CMake to check the build system integrity. +# No rule that depends on this can have commands that come from listfiles +# because they might be regenerated. +cmake_check_build_system: + cd /home/calvin/src/xpdf-4.04 && $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0 +.PHONY : cmake_check_build_system + diff --git a/xpdf/NameToCharCode.cc b/xpdf/NameToCharCode.cc new file mode 100644 index 0000000..f846d8e --- /dev/null +++ b/xpdf/NameToCharCode.cc @@ -0,0 +1,117 @@ +//======================================================================== +// +// NameToCharCode.cc +// +// Copyright 2001-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include "gmem.h" +#include "gmempp.h" +#include "NameToCharCode.h" + +//------------------------------------------------------------------------ + +struct NameToCharCodeEntry { + char *name; + CharCode c; +}; + +//------------------------------------------------------------------------ + +NameToCharCode::NameToCharCode() { + int i; + + size = 31; + len = 0; + tab = (NameToCharCodeEntry *)gmallocn(size, sizeof(NameToCharCodeEntry)); + for (i = 0; i < size; ++i) { + tab[i].name = NULL; + } +} + +NameToCharCode::~NameToCharCode() { + int i; + + for (i = 0; i < size; ++i) { + if (tab[i].name) { + gfree(tab[i].name); + } + } + gfree(tab); +} + +void NameToCharCode::add(const char *name, CharCode c) { + NameToCharCodeEntry *oldTab; + int h, i, oldSize; + + // expand the table if necessary + if (len >= size / 2) { + oldSize = size; + oldTab = tab; + size = 2*size + 1; + tab = (NameToCharCodeEntry *)gmallocn(size, sizeof(NameToCharCodeEntry)); + for (h = 0; h < size; ++h) { + tab[h].name = NULL; + } + for (i = 0; i < oldSize; ++i) { + if (oldTab[i].name) { + h = hash(oldTab[i].name); + while (tab[h].name) { + if (++h == size) { + h = 0; + } + } + tab[h] = oldTab[i]; + } + } + gfree(oldTab); + } + + // add the new name + h = hash(name); + while (tab[h].name && strcmp(tab[h].name, name)) { + if (++h == size) { + h = 0; + } + } + if (!tab[h].name) { + tab[h].name = copyString(name); + } + tab[h].c = c; + + ++len; +} + +CharCode NameToCharCode::lookup(const char *name) { + int h; + + h = hash(name); + while (tab[h].name) { + if (!strcmp(tab[h].name, name)) { + return tab[h].c; + } + if (++h == size) { + h = 0; + } + } + return 0; +} + +int NameToCharCode::hash(const char *name) { + const char *p; + unsigned int h; + + h = 0; + for (p = name; *p; ++p) { + h = 17 * h + (int)(*p & 0xff); + } + return (int)(h % size); +} diff --git a/xpdf/NameToCharCode.h b/xpdf/NameToCharCode.h new file mode 100644 index 0000000..6548133 --- /dev/null +++ b/xpdf/NameToCharCode.h @@ -0,0 +1,42 @@ +//======================================================================== +// +// NameToCharCode.h +// +// Copyright 2001-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef NAMETOCHARCODE_H +#define NAMETOCHARCODE_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "CharTypes.h" + +struct NameToCharCodeEntry; + +//------------------------------------------------------------------------ + +class NameToCharCode { +public: + + NameToCharCode(); + ~NameToCharCode(); + + void add(const char *name, CharCode c); + CharCode lookup(const char *name); + +private: + + int hash(const char *name); + + NameToCharCodeEntry *tab; + int size; + int len; +}; + +#endif diff --git a/xpdf/NameToUnicodeTable.h b/xpdf/NameToUnicodeTable.h new file mode 100644 index 0000000..5000bd3 --- /dev/null +++ b/xpdf/NameToUnicodeTable.h @@ -0,0 +1,4257 @@ +//======================================================================== +// +// NameToUnicodeTable.h +// +// Copyright 2001-2004 Glyph & Cog, LLC +// +//======================================================================== + +static struct { + Unicode u; + const char *name; +} nameToUnicodeTab[] = { + {0x0021, "!"}, + {0x0023, "#"}, + {0x0024, "$"}, + {0x0025, "%"}, + {0x0026, "&"}, + {0x0027, "'"}, + {0x0028, "("}, + {0x0029, ")"}, + {0x002a, "*"}, + {0x002b, "+"}, + {0x002c, ","}, + {0x002d, "-"}, + {0x002e, "."}, + {0x002f, "/"}, + {0x0030, "0"}, + {0x0031, "1"}, + {0x0032, "2"}, + {0x0033, "3"}, + {0x0034, "4"}, + {0x0035, "5"}, + {0x0036, "6"}, + {0x0037, "7"}, + {0x0038, "8"}, + {0x0039, "9"}, + {0x003a, ":"}, + {0x003b, ";"}, + {0x003c, "<"}, + {0x003d, "="}, + {0x003e, ">"}, + {0x003f, "?"}, + {0x0040, "@"}, + {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"}, + {0x039d, "Nu"}, + {0x004f, "O"}, + {0x0152, "OE"}, + {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"}, + {0x2510, "SF030000"}, + {0x2518, "SF040000"}, + {0x253c, "SF050000"}, + {0x252c, "SF060000"}, + {0x2534, "SF070000"}, + {0x251c, "SF080000"}, + {0x2524, "SF090000"}, + {0x2500, "SF100000"}, + {0x2502, "SF110000"}, + {0x2561, "SF190000"}, + {0x2562, "SF200000"}, + {0x2556, "SF210000"}, + {0x2555, "SF220000"}, + {0x2563, "SF230000"}, + {0x2551, "SF240000"}, + {0x2557, "SF250000"}, + {0x255d, "SF260000"}, + {0x255c, "SF270000"}, + {0x255b, "SF280000"}, + {0x255e, "SF360000"}, + {0x255f, "SF370000"}, + {0x255a, "SF380000"}, + {0x2554, "SF390000"}, + {0x2569, "SF400000"}, + {0x2566, "SF410000"}, + {0x2560, "SF420000"}, + {0x2550, "SF430000"}, + {0x256c, "SF440000"}, + {0x2567, "SF450000"}, + {0x2568, "SF460000"}, + {0x2564, "SF470000"}, + {0x2565, "SF480000"}, + {0x2559, "SF490000"}, + {0x2558, "SF500000"}, + {0x2552, "SF510000"}, + {0x2553, "SF520000"}, + {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, "]"}, + {0x005e, "^"}, + {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"}, + {0x0413, "afii10020"}, + {0x0414, "afii10021"}, + {0x0415, "afii10022"}, + {0x0401, "afii10023"}, + {0x0416, "afii10024"}, + {0x0417, "afii10025"}, + {0x0418, "afii10026"}, + {0x0419, "afii10027"}, + {0x041a, "afii10028"}, + {0x041b, "afii10029"}, + {0x041c, "afii10030"}, + {0x041d, "afii10031"}, + {0x041e, "afii10032"}, + {0x041f, "afii10033"}, + {0x0420, "afii10034"}, + {0x0421, "afii10035"}, + {0x0422, "afii10036"}, + {0x0423, "afii10037"}, + {0x0424, "afii10038"}, + {0x0425, "afii10039"}, + {0x0426, "afii10040"}, + {0x0427, "afii10041"}, + {0x0428, "afii10042"}, + {0x0429, "afii10043"}, + {0x042a, "afii10044"}, + {0x042b, "afii10045"}, + {0x042c, "afii10046"}, + {0x042d, "afii10047"}, + {0x042e, "afii10048"}, + {0x042f, "afii10049"}, + {0x0490, "afii10050"}, + {0x0402, "afii10051"}, + {0x0403, "afii10052"}, + {0x0404, "afii10053"}, + {0x0405, "afii10054"}, + {0x0406, "afii10055"}, + {0x0407, "afii10056"}, + {0x0408, "afii10057"}, + {0x0409, "afii10058"}, + {0x040a, "afii10059"}, + {0x040b, "afii10060"}, + {0x040c, "afii10061"}, + {0x040e, "afii10062"}, + {0xf6c4, "afii10063"}, + {0xf6c5, "afii10064"}, + {0x0430, "afii10065"}, + {0x0431, "afii10066"}, + {0x0432, "afii10067"}, + {0x0433, "afii10068"}, + {0x0434, "afii10069"}, + {0x0435, "afii10070"}, + {0x0451, "afii10071"}, + {0x0436, "afii10072"}, + {0x0437, "afii10073"}, + {0x0438, "afii10074"}, + {0x0439, "afii10075"}, + {0x043a, "afii10076"}, + {0x043b, "afii10077"}, + {0x043c, "afii10078"}, + {0x043d, "afii10079"}, + {0x043e, "afii10080"}, + {0x043f, "afii10081"}, + {0x0440, "afii10082"}, + {0x0441, "afii10083"}, + {0x0442, "afii10084"}, + {0x0443, "afii10085"}, + {0x0444, "afii10086"}, + {0x0445, "afii10087"}, + {0x0446, "afii10088"}, + {0x0447, "afii10089"}, + {0x0448, "afii10090"}, + {0x0449, "afii10091"}, + {0x044a, "afii10092"}, + {0x044b, "afii10093"}, + {0x044c, "afii10094"}, + {0x044d, "afii10095"}, + {0x044e, "afii10096"}, + {0x044f, "afii10097"}, + {0x0491, "afii10098"}, + {0x0452, "afii10099"}, + {0x0453, "afii10100"}, + {0x0454, "afii10101"}, + {0x0455, "afii10102"}, + {0x0456, "afii10103"}, + {0x0457, "afii10104"}, + {0x0458, "afii10105"}, + {0x0459, "afii10106"}, + {0x045a, "afii10107"}, + {0x045b, "afii10108"}, + {0x045c, "afii10109"}, + {0x045e, "afii10110"}, + {0x040f, "afii10145"}, + {0x0462, "afii10146"}, + {0x0472, "afii10147"}, + {0x0474, "afii10148"}, + {0xf6c6, "afii10192"}, + {0x045f, "afii10193"}, + {0x0463, "afii10194"}, + {0x0473, "afii10195"}, + {0x0475, "afii10196"}, + {0xf6c7, "afii10831"}, + {0xf6c8, "afii10832"}, + {0x04d9, "afii10846"}, + {0x200e, "afii299"}, + {0x200f, "afii300"}, + {0x200d, "afii301"}, + {0x066a, "afii57381"}, + {0x060c, "afii57388"}, + {0x0660, "afii57392"}, + {0x0661, "afii57393"}, + {0x0662, "afii57394"}, + {0x0663, "afii57395"}, + {0x0664, "afii57396"}, + {0x0665, "afii57397"}, + {0x0666, "afii57398"}, + {0x0667, "afii57399"}, + {0x0668, "afii57400"}, + {0x0669, "afii57401"}, + {0x061b, "afii57403"}, + {0x061f, "afii57407"}, + {0x0621, "afii57409"}, + {0x0622, "afii57410"}, + {0x0623, "afii57411"}, + {0x0624, "afii57412"}, + {0x0625, "afii57413"}, + {0x0626, "afii57414"}, + {0x0627, "afii57415"}, + {0x0628, "afii57416"}, + {0x0629, "afii57417"}, + {0x062a, "afii57418"}, + {0x062b, "afii57419"}, + {0x062c, "afii57420"}, + {0x062d, "afii57421"}, + {0x062e, "afii57422"}, + {0x062f, "afii57423"}, + {0x0630, "afii57424"}, + {0x0631, "afii57425"}, + {0x0632, "afii57426"}, + {0x0633, "afii57427"}, + {0x0634, "afii57428"}, + {0x0635, "afii57429"}, + {0x0636, "afii57430"}, + {0x0637, "afii57431"}, + {0x0638, "afii57432"}, + {0x0639, "afii57433"}, + {0x063a, "afii57434"}, + {0x0640, "afii57440"}, + {0x0641, "afii57441"}, + {0x0642, "afii57442"}, + {0x0643, "afii57443"}, + {0x0644, "afii57444"}, + {0x0645, "afii57445"}, + {0x0646, "afii57446"}, + {0x0648, "afii57448"}, + {0x0649, "afii57449"}, + {0x064a, "afii57450"}, + {0x064b, "afii57451"}, + {0x064c, "afii57452"}, + {0x064d, "afii57453"}, + {0x064e, "afii57454"}, + {0x064f, "afii57455"}, + {0x0650, "afii57456"}, + {0x0651, "afii57457"}, + {0x0652, "afii57458"}, + {0x0647, "afii57470"}, + {0x06a4, "afii57505"}, + {0x067e, "afii57506"}, + {0x0686, "afii57507"}, + {0x0698, "afii57508"}, + {0x06af, "afii57509"}, + {0x0679, "afii57511"}, + {0x0688, "afii57512"}, + {0x0691, "afii57513"}, + {0x06ba, "afii57514"}, + {0x06d2, "afii57519"}, + {0x06d5, "afii57534"}, + {0x20aa, "afii57636"}, + {0x05be, "afii57645"}, + {0x05c3, "afii57658"}, + {0x05d0, "afii57664"}, + {0x05d1, "afii57665"}, + {0x05d2, "afii57666"}, + {0x05d3, "afii57667"}, + {0x05d4, "afii57668"}, + {0x05d5, "afii57669"}, + {0x05d6, "afii57670"}, + {0x05d7, "afii57671"}, + {0x05d8, "afii57672"}, + {0x05d9, "afii57673"}, + {0x05da, "afii57674"}, + {0x05db, "afii57675"}, + {0x05dc, "afii57676"}, + {0x05dd, "afii57677"}, + {0x05de, "afii57678"}, + {0x05df, "afii57679"}, + {0x05e0, "afii57680"}, + {0x05e1, "afii57681"}, + {0x05e2, "afii57682"}, + {0x05e3, "afii57683"}, + {0x05e4, "afii57684"}, + {0x05e5, "afii57685"}, + {0x05e6, "afii57686"}, + {0x05e7, "afii57687"}, + {0x05e8, "afii57688"}, + {0x05e9, "afii57689"}, + {0x05ea, "afii57690"}, + {0xfb2a, "afii57694"}, + {0xfb2b, "afii57695"}, + {0xfb4b, "afii57700"}, + {0xfb1f, "afii57705"}, + {0x05f0, "afii57716"}, + {0x05f1, "afii57717"}, + {0x05f2, "afii57718"}, + {0xfb35, "afii57723"}, + {0x05b4, "afii57793"}, + {0x05b5, "afii57794"}, + {0x05b6, "afii57795"}, + {0x05bb, "afii57796"}, + {0x05b8, "afii57797"}, + {0x05b7, "afii57798"}, + {0x05b0, "afii57799"}, + {0x05b2, "afii57800"}, + {0x05b1, "afii57801"}, + {0x05b3, "afii57802"}, + {0x05c2, "afii57803"}, + {0x05c1, "afii57804"}, + {0x05b9, "afii57806"}, + {0x05bc, "afii57807"}, + {0x05bd, "afii57839"}, + {0x05bf, "afii57841"}, + {0x05c0, "afii57842"}, + {0x02bc, "afii57929"}, + {0x2105, "afii61248"}, + {0x2113, "afii61289"}, + {0x2116, "afii61352"}, + {0x202c, "afii61573"}, + {0x202d, "afii61574"}, + {0x202e, "afii61575"}, + {0x200c, "afii61664"}, + {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"}, + {0x00a0, "nobreakspace"}, + {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, "}"}, + {0x007e, "~"}, + { 0, NULL } +}; diff --git a/xpdf/Object.cc b/xpdf/Object.cc new file mode 100644 index 0000000..898fbc9 --- /dev/null +++ b/xpdf/Object.cc @@ -0,0 +1,245 @@ +//======================================================================== +// +// Object.cc +// +// Copyright 1996-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include "gmempp.h" +#include "Object.h" +#include "Array.h" +#include "Dict.h" +#include "Error.h" +#include "Stream.h" +#include "XRef.h" + +//------------------------------------------------------------------------ +// Object +//------------------------------------------------------------------------ + +const char *objTypeNames[numObjTypes] = { + "boolean", + "integer", + "real", + "string", + "name", + "null", + "array", + "dictionary", + "stream", + "ref", + "cmd", + "error", + "eof", + "none" +}; + +#ifdef DEBUG_MEM +#if MULTITHREADED +GAtomicCounter Object::numAlloc[numObjTypes] = + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +#else +long Object::numAlloc[numObjTypes] = + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +#endif +#endif // DEBUG_MEM + +Object *Object::initArray(XRef *xref) { + initObj(objArray); + array = new Array(xref); + return this; +} + +Object *Object::initDict(XRef *xref) { + initObj(objDict); + dict = new Dict(xref); + return this; +} + +Object *Object::initDict(Dict *dictA) { + initObj(objDict); + dict = dictA; + dict->incRef(); + return this; +} + +Object *Object::initStream(Stream *streamA) { + initObj(objStream); + stream = streamA; + return this; +} + +Object *Object::copy(Object *obj) { + *obj = *this; + switch (type) { + case objString: + obj->string = string->copy(); + break; + case objName: + obj->name = copyString(name); + break; + case objArray: + array->incRef(); + break; + case objDict: + dict->incRef(); + break; + case objStream: + obj->stream = stream->copy(); + break; + case objCmd: + obj->cmd = copyString(cmd); + break; + default: + break; + } +#ifdef DEBUG_MEM +#if MULTITHREADED + gAtomicIncrement(&numAlloc[type]); +#else + ++numAlloc[type]; +#endif +#endif + return obj; +} + +Object *Object::fetch(XRef *xref, Object *obj, int recursion) { + return (type == objRef && xref) ? + xref->fetch(ref.num, ref.gen, obj, recursion) : copy(obj); +} + +void Object::free() { + switch (type) { + case objString: + delete string; + break; + case objName: + gfree(name); + break; + case objArray: + if (!array->decRef()) { + delete array; + } + break; + case objDict: + if (!dict->decRef()) { + delete dict; + } + break; + case objStream: + delete stream; + break; + case objCmd: + gfree(cmd); + break; + default: + break; + } +#ifdef DEBUG_MEM +#if MULTITHREADED + gAtomicDecrement(&numAlloc[type]); +#else + --numAlloc[type]; +#endif +#endif + type = objNone; +} + +const char *Object::getTypeName() { + return objTypeNames[type]; +} + +void Object::print(FILE *f) { + Object obj; + int i; + + switch (type) { + case objBool: + fprintf(f, "%s", booln ? "true" : "false"); + break; + case objInt: + fprintf(f, "%d", intg); + break; + case objReal: + fprintf(f, "%g", real); + break; + case objString: + fprintf(f, "("); + fwrite(string->getCString(), 1, string->getLength(), f); + fprintf(f, ")"); + break; + case objName: + fprintf(f, "/%s", name); + break; + case objNull: + fprintf(f, "null"); + break; + case objArray: + fprintf(f, "["); + for (i = 0; i < arrayGetLength(); ++i) { + if (i > 0) + fprintf(f, " "); + arrayGetNF(i, &obj); + obj.print(f); + obj.free(); + } + fprintf(f, "]"); + break; + case objDict: + fprintf(f, "<<"); + for (i = 0; i < dictGetLength(); ++i) { + fprintf(f, " /%s ", dictGetKey(i)); + dictGetValNF(i, &obj); + obj.print(f); + obj.free(); + } + fprintf(f, " >>"); + break; + case objStream: + fprintf(f, ""); + break; + case objRef: + fprintf(f, "%d %d R", ref.num, ref.gen); + break; + case objCmd: + fprintf(f, "%s", cmd); + break; + case objError: + fprintf(f, ""); + break; + case objEOF: + fprintf(f, ""); + break; + case objNone: + fprintf(f, ""); + break; + } +} + +void Object::memCheck(FILE *f) { +#ifdef DEBUG_MEM + int i; + long t; + + t = 0; + for (i = 0; i < numObjTypes; ++i) { + t += numAlloc[i]; + } + if (t > 0) { + fprintf(f, "Allocated objects:\n"); + for (i = 0; i < numObjTypes; ++i) { + if (numAlloc[i] > 0) { + fprintf(f, " %-20s: %6ld\n", objTypeNames[i], numAlloc[i]); + } + } + } +#endif +} diff --git a/xpdf/Object.h b/xpdf/Object.h new file mode 100644 index 0000000..cb63651 --- /dev/null +++ b/xpdf/Object.h @@ -0,0 +1,320 @@ +//======================================================================== +// +// Object.h +// +// Copyright 1996-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef OBJECT_H +#define OBJECT_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include +#include +#include "gtypes.h" +#include "gmem.h" +#include "gfile.h" +#include "GString.h" +#if MULTITHREADED +#include "GMutex.h" +#endif + +class XRef; +class Array; +class Dict; +class Stream; + +//------------------------------------------------------------------------ +// Ref +//------------------------------------------------------------------------ + +struct Ref { + int num; // object number + int gen; // generation number +}; + +//------------------------------------------------------------------------ +// object types +//------------------------------------------------------------------------ + +enum ObjType { + // simple objects + objBool, // boolean + objInt, // integer + objReal, // real + objString, // string + objName, // name + objNull, // null + + // complex objects + objArray, // array + objDict, // dictionary + objStream, // stream + objRef, // indirect reference + + // special objects + objCmd, // command name + objError, // error return from Lexer + objEOF, // end of file return from Lexer + objNone // uninitialized object +}; + +#define numObjTypes 14 // total number of object types + +//------------------------------------------------------------------------ +// Object +//------------------------------------------------------------------------ + +#ifdef DEBUG_MEM +# if MULTITHREADED +# define initObj(t) gAtomicIncrement(&numAlloc[type = t]) +# else +# define initObj(t) ++numAlloc[type = t] +# endif +#else +#define initObj(t) type = t +#endif + +class Object { +public: + + // Default constructor. + Object(): + type(objNone) {} + + // Initialize an object. + Object *initBool(GBool boolnA) + { initObj(objBool); booln = boolnA; return this; } + Object *initInt(int intgA) + { initObj(objInt); intg = intgA; return this; } + Object *initReal(double realA) + { initObj(objReal); real = realA; return this; } + Object *initString(GString *stringA) + { initObj(objString); string = stringA; return this; } + Object *initName(const char *nameA) + { initObj(objName); name = copyString(nameA); return this; } + Object *initNull() + { initObj(objNull); return this; } + Object *initArray(XRef *xref); + Object *initDict(XRef *xref); + Object *initDict(Dict *dictA); + Object *initStream(Stream *streamA); + Object *initRef(int numA, int genA) + { initObj(objRef); ref.num = numA; ref.gen = genA; return this; } + Object *initCmd(char *cmdA) + { initObj(objCmd); cmd = copyString(cmdA); return this; } + Object *initError() + { initObj(objError); return this; } + Object *initEOF() + { initObj(objEOF); return this; } + + // Copy an object. + Object *copy(Object *obj); + + // If object is a Ref, fetch and return the referenced object. + // Otherwise, return a copy of the object. + Object *fetch(XRef *xref, Object *obj, int recursion = 0); + + // Free object contents. + void free(); + + // Type checking. + ObjType getType() { return type; } + GBool isBool() { return type == objBool; } + GBool isInt() { return type == objInt; } + GBool isReal() { return type == objReal; } + GBool isNum() { return type == objInt || type == objReal; } + GBool isString() { return type == objString; } + GBool isName() { return type == objName; } + GBool isNull() { return type == objNull; } + GBool isArray() { return type == objArray; } + GBool isDict() { return type == objDict; } + GBool isStream() { return type == objStream; } + GBool isRef() { return type == objRef; } + GBool isCmd() { return type == objCmd; } + GBool isError() { return type == objError; } + GBool isEOF() { return type == objEOF; } + GBool isNone() { return type == objNone; } + + // Special type checking. + GBool isName(const char *nameA) + { return type == objName && !strcmp(name, nameA); } + GBool isDict(const char *dictType); + GBool isStream(char *dictType); + GBool isCmd(const char *cmdA) + { return type == objCmd && !strcmp(cmd, cmdA); } + + // Accessors. NB: these assume object is of correct type. + GBool getBool() { return booln; } + int getInt() { return intg; } + double getReal() { return real; } + double getNum() { return type == objInt ? (double)intg : real; } + GString *getString() { return string; } + char *getName() { return name; } + Array *getArray() { return array; } + Dict *getDict() { return dict; } + Stream *getStream() { return stream; } + Ref getRef() { return ref; } + int getRefNum() { return ref.num; } + int getRefGen() { return ref.gen; } + char *getCmd() { return cmd; } + + // Array accessors. + int arrayGetLength(); + void arrayAdd(Object *elem); + Object *arrayGet(int i, Object *obj, int recursion = 0); + Object *arrayGetNF(int i, Object *obj); + + // Dict accessors. + int dictGetLength(); + void dictAdd(char *key, Object *val); + 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); + + // Stream accessors. + GBool streamIs(char *dictType); + void streamReset(); + void streamClose(); + int streamGetChar(); + int streamLookChar(); + int streamGetBlock(char *blk, int size); + char *streamGetLine(char *buf, int size); + GFileOffset streamGetPos(); + void streamSetPos(GFileOffset pos, int dir = 0); + Dict *streamGetDict(); + + // Output. + const char *getTypeName(); + void print(FILE *f = stdout); + + // Memory testing. + static void memCheck(FILE *f); + +private: + + ObjType type; // object type + union { // value for each type: + GBool booln; // boolean + int intg; // integer + double real; // real + GString *string; // string + char *name; // name + Array *array; // array + Dict *dict; // dictionary + Stream *stream; // stream + Ref ref; // indirect reference + char *cmd; // command + }; + +#ifdef DEBUG_MEM +#if MULTITHREADED + static GAtomicCounter // number of each type of object + numAlloc[numObjTypes]; // currently allocated +#else + static int // number of each type of object + numAlloc[numObjTypes]; // currently allocated +#endif +#endif +}; + +//------------------------------------------------------------------------ +// Array accessors. +//------------------------------------------------------------------------ + +#include "Array.h" + +inline int Object::arrayGetLength() + { return array->getLength(); } + +inline void Object::arrayAdd(Object *elem) + { array->add(elem); } + +inline Object *Object::arrayGet(int i, Object *obj, int recursion) + { return array->get(i, obj, recursion); } + +inline Object *Object::arrayGetNF(int i, Object *obj) + { return array->getNF(i, obj); } + +//------------------------------------------------------------------------ +// Dict accessors. +//------------------------------------------------------------------------ + +#include "Dict.h" + +inline int Object::dictGetLength() + { return dict->getLength(); } + +inline void Object::dictAdd(char *key, Object *val) + { dict->add(key, val); } + +inline GBool Object::dictIs(const char *dictType) + { return dict->is(dictType); } + +inline GBool Object::isDict(const char *dictType) + { return type == objDict && dictIs(dictType); } + +inline Object *Object::dictLookup(const char *key, Object *obj, int recursion) + { return dict->lookup(key, obj, recursion); } + +inline Object *Object::dictLookupNF(const char *key, Object *obj) + { return dict->lookupNF(key, obj); } + +inline char *Object::dictGetKey(int i) + { return dict->getKey(i); } + +inline Object *Object::dictGetVal(int i, Object *obj) + { return dict->getVal(i, obj); } + +inline Object *Object::dictGetValNF(int i, Object *obj) + { return dict->getValNF(i, obj); } + +//------------------------------------------------------------------------ +// Stream accessors. +//------------------------------------------------------------------------ + +#include "Stream.h" + +inline GBool Object::streamIs(char *dictType) + { return stream->getDict()->is(dictType); } + +inline GBool Object::isStream(char *dictType) + { return type == objStream && streamIs(dictType); } + +inline void Object::streamReset() + { stream->reset(); } + +inline void Object::streamClose() + { stream->close(); } + +inline int Object::streamGetChar() + { return stream->getChar(); } + +inline int Object::streamLookChar() + { return stream->lookChar(); } + +inline int Object::streamGetBlock(char *blk, int size) + { return stream->getBlock(blk, size); } + +inline char *Object::streamGetLine(char *buf, int size) + { return stream->getLine(buf, size); } + +inline GFileOffset Object::streamGetPos() + { return stream->getPos(); } + +inline void Object::streamSetPos(GFileOffset pos, int dir) + { stream->setPos(pos, dir); } + +inline Dict *Object::streamGetDict() + { return stream->getDict(); } + +#endif diff --git a/xpdf/OptionalContent.cc b/xpdf/OptionalContent.cc new file mode 100644 index 0000000..a0fbb1b --- /dev/null +++ b/xpdf/OptionalContent.cc @@ -0,0 +1,537 @@ +//======================================================================== +// +// OptionalContent.cc +// +// Copyright 2008-2013 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include "gmempp.h" +#include "GString.h" +#include "GList.h" +#include "Error.h" +#include "Object.h" +#include "PDFDoc.h" +#include "TextString.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, uad, obj1, obj2, obj3, obj4; + Ref ref1; + OptionalContentGroup *ocg; + int i, j; + + 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()) { + + //----- read the usage app dicts + if (defView.dictLookup("AS", &obj1)->isArray()) { + for (i = 0; i < obj1.arrayGetLength(); ++i) { + if (obj1.arrayGet(i, &uad)->isDict()) { + if (uad.dictLookup("Event", &obj2)->isName("View")) { + if (uad.dictLookup("OCGs", &obj3)->isArray()) { + for (j = 0; j < obj3.arrayGetLength(); ++j) { + if (obj3.arrayGetNF(j, &obj4)->isRef()) { + ref1 = obj4.getRef(); + if ((ocg = findOCG(&ref1))) { + ocg->setInViewUsageAppDict(); + } + } + obj4.free(); + } + } + obj3.free(); + } + obj2.free(); + } + uad.free(); + } + } + obj1.free(); + + //----- initial state from OCCD + 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(); + + //----- initial state from OCG usage dict + for (i = 0; i < ocgs->getLength(); ++i) { + ocg = (OptionalContentGroup *)ocgs->get(i); + if (ocg->getInViewUsageAppDict() && + ocg->getViewState() != ocUsageUnset) { + ocg->setState(ocg->getViewState() == ocUsageOn); + } + } + + //----- 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; + GBool gotOCG; + 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")) { + obj2.free(); + return gFalse; + } + if (obj2.dictLookup("VE", &obj3)->isArray()) { + *visible = evalOCVisibilityExpr(&obj3, 0); + obj3.free(); + } else { + obj3.free(); + policy = ocPolicyAnyOn; + if (obj2.dictLookup("P", &obj3)->isName()) { + if (obj3.isName("AllOn")) { + policy = ocPolicyAllOn; + } else if (obj3.isName("AnyOn")) { + policy = ocPolicyAnyOn; + } else if (obj3.isName("AnyOff")) { + policy = ocPolicyAnyOff; + } else if (obj3.isName("AllOff")) { + policy = ocPolicyAllOff; + } + } + obj3.free(); + obj2.dictLookupNF("OCGs", &obj3); + ocg = NULL; + if (obj3.isRef()) { + ref = obj3.getRef(); + ocg = findOCG(&ref); + } + if (ocg) { + *visible = (policy == ocPolicyAllOn || policy == ocPolicyAnyOn) ? + ocg->getState() : !ocg->getState(); + } else { + *visible = policy == ocPolicyAllOn || policy == ocPolicyAllOff; + if (!obj3.fetch(xref, &obj4)->isArray()) { + obj4.free(); + obj3.free(); + obj2.free(); + return gFalse; + } + gotOCG = gFalse; + for (i = 0; i < obj4.arrayGetLength(); ++i) { + obj4.arrayGetNF(i, &obj5); + if (obj5.isRef()) { + ref = obj5.getRef(); + if ((ocg = findOCG(&ref))) { + gotOCG = gTrue; + 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(); + } + if (!gotOCG) { + // if the "OCGs" array is "empty or contains references only + // to null or deleted objects", this OCMD doesn't have any + // effect + obj4.free(); + obj3.free(); + obj2.free(); + return gFalse; + } + obj4.free(); + } + obj3.free(); + } + obj2.free(); + return gTrue; +} + +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) { + TextString *nameA; + Object obj1, obj2, obj3; + OCUsageState viewStateA, printStateA; + + if (!obj->isDict()) { + return NULL; + } + if (!obj->dictLookup("Name", &obj1)->isString()) { + error(errSyntaxError, -1, "Missing or invalid Name in OCG"); + obj1.free(); + return NULL; + } + nameA = new TextString(obj1.getString()); + 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, viewStateA, printStateA); +} + +OptionalContentGroup::OptionalContentGroup(Ref *refA, TextString *nameA, + OCUsageState viewStateA, + OCUsageState printStateA) { + ref = *refA; + name = nameA; + viewState = viewStateA; + printState = printStateA; + state = gTrue; + inViewUsageAppDict = gFalse; +} + +OptionalContentGroup::~OptionalContentGroup() { + delete name; +} + +GBool OptionalContentGroup::matches(Ref *refA) { + return refA->num == ref.num && refA->gen == ref.gen; +} + +Unicode *OptionalContentGroup::getName() { + return name->getUnicode(); +} + +int OptionalContentGroup::getNameLength() { + return name->getLength(); +} + +//------------------------------------------------------------------------ + +OCDisplayNode *OCDisplayNode::parse(Object *obj, OptionalContent *oc, + 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) { + if (child->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 = new TextString(); + ocg = NULL; + parent = NULL; + children = NULL; +} + +OCDisplayNode::OCDisplayNode(GString *nameA) { + name = new TextString(nameA); + ocg = NULL; + children = NULL; +} + +OCDisplayNode::OCDisplayNode(OptionalContentGroup *ocgA) { + name = new TextString(ocgA->name); + ocg = ocgA; + children = NULL; +} + +void OCDisplayNode::addChild(OCDisplayNode *child) { + if (!children) { + children = new GList(); + } + children->append(child); + child->parent = this; +} + +void OCDisplayNode::addChildren(GList *childrenA) { + int i; + + if (!children) { + children = new GList(); + } + children->append(childrenA); + for (i = 0; i < childrenA->getLength(); ++i) { + ((OCDisplayNode *)childrenA->get(i))->parent = this; + } + delete childrenA; +} + +GList *OCDisplayNode::takeChildren() { + GList *childrenA; + int i; + + childrenA = children; + children = NULL; + for (i = 0; i < childrenA->getLength(); ++i) { + ((OCDisplayNode *)childrenA->get(i))->parent = NULL; + } + return childrenA; +} + +OCDisplayNode::~OCDisplayNode() { + delete name; + if (children) { + deleteGList(children, OCDisplayNode); + } +} + +Unicode *OCDisplayNode::getName() { + return name->getUnicode(); +} + +int OCDisplayNode::getNameLength() { + return name->getLength(); +} + +int OCDisplayNode::getNumChildren() { + if (!children) { + return 0; + } + 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..f00ef29 --- /dev/null +++ b/xpdf/OptionalContent.h @@ -0,0 +1,139 @@ +//======================================================================== +// +// OptionalContent.h +// +// Copyright 2008-2013 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef OPTIONALCONTENT_H +#define OPTIONALCONTENT_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "gtypes.h" +#include "Object.h" +#include "CharTypes.h" + +class GString; +class GList; +class PDFDoc; +class TextString; +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 is a valid OCG or OCMD, sets * 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(); + int getNameLength(); + OCUsageState getViewState() { return viewState; } + OCUsageState getPrintState() { return printState; } + GBool getState() { return state; } + void setState(GBool stateA) { state = stateA; } + GBool getInViewUsageAppDict() { return inViewUsageAppDict; } + void setInViewUsageAppDict() { inViewUsageAppDict = gTrue; } + +private: + + OptionalContentGroup(Ref *refA, TextString *nameA, + OCUsageState viewStateA, OCUsageState printStateA); + + Ref ref; + TextString *name; + OCUsageState viewState, // suggested state when viewing + printState; // suggested state when printing + GBool state; // current state (on/off) + GBool inViewUsageAppDict; // true if this OCG is listed in a + // usage app dict with Event=View + + friend class OCDisplayNode; +}; + +//------------------------------------------------------------------------ + +class OCDisplayNode { +public: + + static OCDisplayNode *parse(Object *obj, OptionalContent *oc, XRef *xref, + int recursion = 0); + OCDisplayNode(); + ~OCDisplayNode(); + + Unicode *getName(); + int getNameLength(); + OptionalContentGroup *getOCG() { return ocg; } + int getNumChildren(); + OCDisplayNode *getChild(int idx); + OCDisplayNode *getParent() { return parent; } + +private: + + OCDisplayNode(GString *nameA); + OCDisplayNode(OptionalContentGroup *ocgA); + void addChild(OCDisplayNode *child); + void addChildren(GList *childrenA); + GList *takeChildren(); + + TextString *name; // display name + OptionalContentGroup *ocg; // NULL for display labels + OCDisplayNode *parent; // parent node; NULL at root + GList *children; // NULL if there are no children + // [OCDisplayNode] +}; + +#endif diff --git a/xpdf/Outline.cc b/xpdf/Outline.cc new file mode 100644 index 0000000..9593956 --- /dev/null +++ b/xpdf/Outline.cc @@ -0,0 +1,186 @@ +//======================================================================== +// +// Outline.cc +// +// Copyright 2002-2013 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include "gmem.h" +#include "gmempp.h" +#include "GString.h" +#include "GList.h" +#include "Error.h" +#include "Link.h" +#include "TextString.h" +#include "Outline.h" + +//------------------------------------------------------------------------ + +Outline::Outline(Object *outlineObj, XRef *xref) { + Object first, last; + + items = NULL; + if (!outlineObj->isDict()) { + return; + } + outlineObj->dictLookupNF("First", &first); + outlineObj->dictLookupNF("Last", &last); + if (first.isRef() && last.isRef()) { + items = OutlineItem::readItemList(&first, &last, NULL, xref); + } + first.free(); + last.free(); +} + +Outline::~Outline() { + if (items) { + deleteGList(items, OutlineItem); + } +} + +//------------------------------------------------------------------------ + +OutlineItem::OutlineItem(Object *itemRefA, Dict *dict, + OutlineItem *parentA, XRef *xrefA) { + Object obj1; + + xref = xrefA; + title = NULL; + action = NULL; + kids = NULL; + parent = parentA; + + if (dict->lookup("Title", &obj1)->isString()) { + title = new TextString(obj1.getString()); + } + obj1.free(); + + if (!dict->lookup("Dest", &obj1)->isNull()) { + action = LinkAction::parseDest(&obj1); + } else { + obj1.free(); + if (!dict->lookup("A", &obj1)->isNull()) { + action = LinkAction::parseAction(&obj1); + } + } + obj1.free(); + + itemRefA->copy(&itemRef); + dict->lookupNF("First", &firstRef); + dict->lookupNF("Last", &lastRef); + dict->lookupNF("Next", &nextRef); + + startsOpen = gFalse; + if (dict->lookup("Count", &obj1)->isInt()) { + if (obj1.getInt() > 0) { + startsOpen = gTrue; + } + } + obj1.free(); + + pageNum = -1; +} + +OutlineItem::~OutlineItem() { + close(); + if (title) { + delete title; + } + if (action) { + delete action; + } + itemRef.free(); + firstRef.free(); + lastRef.free(); + nextRef.free(); +} + +GList *OutlineItem::readItemList(Object *firstItemRef, Object *lastItemRef, + OutlineItem *parentA, XRef *xrefA) { + GList *items; + OutlineItem *item, *sibling; + Object obj; + Object *p; + OutlineItem *ancestor; + int i; + + items = new GList(); + if (!firstItemRef->isRef() || !lastItemRef->isRef()) { + return items; + } + p = firstItemRef; + do { + if (!p->fetch(xrefA, &obj)->isDict()) { + obj.free(); + break; + } + item = new OutlineItem(p, obj.getDict(), parentA, xrefA); + obj.free(); + + // check for loops with parents + for (ancestor = parentA; ancestor; ancestor = ancestor->parent) { + if (p->getRefNum() == ancestor->itemRef.getRefNum() && + p->getRefGen() == ancestor->itemRef.getRefGen()) { + error(errSyntaxError, -1, "Loop detected in outline"); + break; + } + } + if (ancestor) { + delete item; + break; + } + + // check for loops with siblings + for (i = 0; i < items->getLength(); ++i) { + sibling = (OutlineItem *)items->get(i); + if (p->getRefNum() == sibling->itemRef.getRefNum() && + p->getRefGen() == sibling->itemRef.getRefGen()) { + error(errSyntaxError, -1, "Loop detected in outline"); + break; + } + } + if (i < items->getLength()) { + delete item; + break; + } + + items->append(item); + if (p->getRefNum() == lastItemRef->getRef().num && + p->getRefGen() == lastItemRef->getRef().gen) { + break; + } + p = &item->nextRef; + if (!p->isRef()) { + break; + } + } while (p); + return items; +} + +void OutlineItem::open() { + if (!kids) { + kids = readItemList(&firstRef, &lastRef, this, xref); + } +} + +void OutlineItem::close() { + if (kids) { + deleteGList(kids, OutlineItem); + kids = NULL; + } +} + +Unicode *OutlineItem::getTitle() { + return title ? title->getUnicode() : (Unicode *)NULL; +} + +int OutlineItem::getTitleLength() { + return title ? title->getLength() : 0; +} diff --git a/xpdf/Outline.h b/xpdf/Outline.h new file mode 100644 index 0000000..e9bce83 --- /dev/null +++ b/xpdf/Outline.h @@ -0,0 +1,84 @@ +//======================================================================== +// +// Outline.h +// +// Copyright 2002-2013 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef OUTLINE_H +#define OUTLINE_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "Object.h" +#include "CharTypes.h" + +class GString; +class GList; +class XRef; +class LinkAction; +class TextString; + +//------------------------------------------------------------------------ + +class Outline { +public: + + Outline(Object *outlineObj, XRef *xref); + ~Outline(); + + GList *getItems() { return items; } + +private: + + GList *items; // NULL if document has no outline + // [OutlineItem] +}; + +//------------------------------------------------------------------------ + +class OutlineItem { +public: + + OutlineItem(Object *itemRefA, Dict *dict, OutlineItem *parentA, XRef *xrefA); + ~OutlineItem(); + + static GList *readItemList(Object *firstItemRef, Object *lastItemRef, + OutlineItem *parentA, XRef *xrefA); + + void open(); + void close(); + + Unicode *getTitle(); + int getTitleLength(); + TextString *getTitleTextString() { return title; } + LinkAction *getAction() { return action; } + GBool isOpen() { return startsOpen; } + GBool hasKids() { return firstRef.isRef(); } + GList *getKids() { return kids; } + OutlineItem *getParent() { return parent; } + +private: + + friend class PDFDoc; + + XRef *xref; + TextString *title; // may be NULL + LinkAction *action; + Object itemRef; + Object firstRef; + Object lastRef; + Object nextRef; + GBool startsOpen; + int pageNum; // page number (used by + // PDFDoc::getOutlineTargetPage) + GList *kids; // NULL unless this item is open [OutlineItem] + OutlineItem *parent; +}; + +#endif diff --git a/xpdf/OutputDev.cc b/xpdf/OutputDev.cc new file mode 100644 index 0000000..f2be88e --- /dev/null +++ b/xpdf/OutputDev.cc @@ -0,0 +1,140 @@ +//======================================================================== +// +// OutputDev.cc +// +// Copyright 1996-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include "gmempp.h" +#include "Object.h" +#include "Stream.h" +#include "GfxState.h" +#include "OutputDev.h" + +//------------------------------------------------------------------------ +// OutputDev +//------------------------------------------------------------------------ + +void OutputDev::setDefaultCTM(double *ctm) { + int i; + double det; + + for (i = 0; i < 6; ++i) { + defCTM[i] = ctm[i]; + } + det = 1 / (defCTM[0] * defCTM[3] - defCTM[1] * defCTM[2]); + defICTM[0] = defCTM[3] * det; + defICTM[1] = -defCTM[1] * det; + defICTM[2] = -defCTM[2] * det; + defICTM[3] = defCTM[0] * det; + defICTM[4] = (defCTM[2] * defCTM[5] - defCTM[3] * defCTM[4]) * det; + defICTM[5] = (defCTM[1] * defCTM[4] - defCTM[0] * defCTM[5]) * det; +} + +void OutputDev::cvtDevToUser(double dx, double dy, double *ux, double *uy) { + *ux = defICTM[0] * dx + defICTM[2] * dy + defICTM[4]; + *uy = defICTM[1] * dx + defICTM[3] * dy + defICTM[5]; +} + +void OutputDev::cvtUserToDev(double ux, double uy, double *dx, double *dy) { + *dx = defCTM[0] * ux + defCTM[2] * uy + defCTM[4]; + *dy = defCTM[1] * ux + defCTM[3] * uy + defCTM[5]; +} + +void OutputDev::cvtUserToDev(double ux, double uy, int *dx, int *dy) { + *dx = (int)(defCTM[0] * ux + defCTM[2] * uy + defCTM[4] + 0.5); + *dy = (int)(defCTM[1] * ux + defCTM[3] * uy + defCTM[5] + 0.5); +} + +void OutputDev::updateAll(GfxState *state) { + updateLineDash(state); + updateFlatness(state); + updateLineJoin(state); + updateLineCap(state); + updateMiterLimit(state); + updateLineWidth(state); + updateStrokeAdjust(state); + updateFillColorSpace(state); + updateFillColor(state); + updateStrokeColorSpace(state); + updateStrokeColor(state); + updateBlendMode(state); + updateFillOpacity(state); + updateStrokeOpacity(state); + updateFillOverprint(state); + updateStrokeOverprint(state); + updateOverprintMode(state); + updateTransfer(state); + updateFont(state); +} + +GBool OutputDev::beginType3Char(GfxState *state, double x, double y, + double dx, double dy, + CharCode code, Unicode *u, int uLen) { + return gFalse; +} + +void OutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str, + int width, int height, GBool invert, + GBool inlineImg, GBool interpolate) { + if (inlineImg) { + str->reset(); + str->discardChars(height * ((width + 7) / 8)); + str->close(); + } +} + +void OutputDev::setSoftMaskFromImageMask(GfxState *state, + Object *ref, Stream *str, + int width, int height, GBool invert, + GBool inlineImg, GBool interpolate) { + drawImageMask(state, ref, str, width, height, invert, inlineImg, interpolate); +} + +void OutputDev::drawImage(GfxState *state, Object *ref, Stream *str, + int width, int height, GfxImageColorMap *colorMap, + int *maskColors, GBool inlineImg, GBool interpolate) { + if (inlineImg) { + str->reset(); + str->discardChars(height * ((width * colorMap->getNumPixelComps() * + colorMap->getBits() + 7) / 8)); + str->close(); + } +} + +void OutputDev::drawMaskedImage(GfxState *state, Object *ref, Stream *str, + int width, int height, + GfxImageColorMap *colorMap, + Object *maskRef, Stream *maskStr, + int maskWidth, int maskHeight, + GBool maskInvert, GBool interpolate) { + drawImage(state, ref, str, width, height, colorMap, NULL, gFalse, + interpolate); +} + +void OutputDev::drawSoftMaskedImage(GfxState *state, Object *ref, Stream *str, + int width, int height, + GfxImageColorMap *colorMap, + Object *maskRef, Stream *maskStr, + int maskWidth, int maskHeight, + GfxImageColorMap *maskColorMap, + double *matte, GBool interpolate) { + drawImage(state, ref, str, width, height, colorMap, NULL, gFalse, + interpolate); +} + +#if OPI_SUPPORT +void OutputDev::opiBegin(GfxState *state, Dict *opiDict) { +} + +void OutputDev::opiEnd(GfxState *state, Dict *opiDict) { +} +#endif diff --git a/xpdf/OutputDev.h b/xpdf/OutputDev.h new file mode 100644 index 0000000..54483cf --- /dev/null +++ b/xpdf/OutputDev.h @@ -0,0 +1,251 @@ +//======================================================================== +// +// OutputDev.h +// +// Copyright 1996-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef OUTPUTDEV_H +#define OUTPUTDEV_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "gtypes.h" +#include "CharTypes.h" + +class GString; +class Gfx; +class GfxState; +struct GfxColor; +class GfxColorSpace; +class GfxImageColorMap; +class GfxShading; +class Stream; +class Links; +class Link; +class Catalog; +class Page; +class Function; + +//------------------------------------------------------------------------ +// OutputDev +//------------------------------------------------------------------------ + +class OutputDev { +public: + + // Constructor. + OutputDev() {} + + // Destructor. + virtual ~OutputDev() {} + + //----- get info about output device + + // Does this device use upside-down coordinates? + // (Upside-down means (0,0) is the top left corner of the page.) + virtual GBool upsideDown() = 0; + + // Does this device use drawChar() or drawString()? + virtual GBool useDrawChar() = 0; + + // 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 gFalse; } + + // Does this device use drawForm()? If this returns false, + // form-type XObjects will be interpreted (i.e., unrolled). + virtual GBool useDrawForm() { return gFalse; } + + // Does this device use beginType3Char/endType3Char? Otherwise, + // text in Type 3 fonts will be drawn with drawChar/drawString. + virtual GBool interpretType3Chars() = 0; + + // 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. + virtual void setDefaultCTM(double *ctm); + + // Check to see if a page slice should be displayed. If this + // returns false, the page display is aborted. Typically, an + // OutputDev will use some alternate means to display the page + // before returning false. + virtual GBool checkPageSlice(Page *page, double hDPI, double vDPI, + int rotate, GBool useMediaBox, GBool crop, + int sliceX, int sliceY, int sliceW, int sliceH, + GBool printing, + GBool (*abortCheckCbk)(void *data) = NULL, + void *abortCheckCbkData = NULL) + { return gTrue; } + + // Start a page. + virtual void startPage(int pageNum, GfxState *state) {} + + // End a page. + virtual void endPage() {} + + //----- coordinate conversion + + // Convert between device and user coordinates. + virtual void cvtDevToUser(double dx, double dy, double *ux, double *uy); + virtual void cvtUserToDev(double ux, double uy, double *dx, double *dy); + virtual void cvtUserToDev(double ux, double uy, int *dx, int *dy); + + double *getDefCTM() { return defCTM; } + double *getDefICTM() { return defICTM; } + + //----- save/restore graphics state + virtual void saveState(GfxState *state) {} + virtual void restoreState(GfxState *state) {} + + //----- update graphics state + virtual void updateAll(GfxState *state); + virtual void updateCTM(GfxState *state, double m11, double m12, + double m21, double m22, double m31, double m32) {} + virtual void updateLineDash(GfxState *state) {} + virtual void updateFlatness(GfxState *state) {} + virtual void updateLineJoin(GfxState *state) {} + virtual void updateLineCap(GfxState *state) {} + virtual void updateMiterLimit(GfxState *state) {} + virtual void updateLineWidth(GfxState *state) {} + virtual void updateStrokeAdjust(GfxState *state) {} + virtual void updateFillColorSpace(GfxState *state) {} + virtual void updateStrokeColorSpace(GfxState *state) {} + virtual void updateFillColor(GfxState *state) {} + virtual void updateStrokeColor(GfxState *state) {} + virtual void updateBlendMode(GfxState *state) {} + virtual void updateFillOpacity(GfxState *state) {} + virtual void updateStrokeOpacity(GfxState *state) {} + virtual void updateFillOverprint(GfxState *state) {} + virtual void updateStrokeOverprint(GfxState *state) {} + virtual void updateOverprintMode(GfxState *state) {} + virtual void updateRenderingIntent(GfxState *state) {} + virtual void updateTransfer(GfxState *state) {} + + //----- update text state + virtual void updateFont(GfxState *state) {} + virtual void updateTextMat(GfxState *state) {} + virtual void updateCharSpace(GfxState *state) {} + virtual void updateRender(GfxState *state) {} + virtual void updateRise(GfxState *state) {} + virtual void updateWordSpace(GfxState *state) {} + 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, Gfx *gfx, Object *strRef, + int paintType, int tilingType, Dict *resDict, + double *mat, double *bbox, + int x0, int y0, int x1, int y1, + double xStep, double yStep) {} + virtual GBool shadedFill(GfxState *state, GfxShading *shading) + { return gFalse; } + + //----- path clipping + virtual void clip(GfxState *state) {} + virtual void eoClip(GfxState *state) {} + virtual void clipToStrokePath(GfxState *state) {} + + //----- text drawing + virtual void beginStringOp(GfxState *state) {} + virtual void endStringOp(GfxState *state) {} + virtual void beginString(GfxState *state, GString *s) {} + virtual void endString(GfxState *state) {} + virtual void drawChar(GfxState *state, double x, double y, + double dx, double dy, + double originX, double originY, + CharCode code, int nBytes, Unicode *u, int uLen) {} + virtual void drawString(GfxState *state, GString *s) {} + virtual GBool beginType3Char(GfxState *state, double x, double y, + double dx, double dy, + 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, GBool interpolate); + virtual void setSoftMaskFromImageMask(GfxState *state, + Object *ref, Stream *str, + int width, int height, GBool invert, + GBool inlineImg, GBool interpolate); + virtual void drawImage(GfxState *state, Object *ref, Stream *str, + int width, int height, GfxImageColorMap *colorMap, + int *maskColors, GBool inlineImg, GBool interpolate); + virtual void drawMaskedImage(GfxState *state, Object *ref, Stream *str, + int width, int height, + GfxImageColorMap *colorMap, + Object *maskRef, Stream *maskStr, + int maskWidth, int maskHeight, + GBool maskInvert, GBool interpolate); + virtual void drawSoftMaskedImage(GfxState *state, Object *ref, Stream *str, + int width, int height, + GfxImageColorMap *colorMap, + Object *maskRef, Stream *maskStr, + int maskWidth, int maskHeight, + GfxImageColorMap *maskColorMap, + double *matte, GBool interpolate); + +#if OPI_SUPPORT + //----- OPI functions + virtual void opiBegin(GfxState *state, Dict *opiDict); + virtual void opiEnd(GfxState *state, Dict *opiDict); +#endif + + //----- Type 3 font operators + virtual void type3D0(GfxState *state, double wx, double wy) {} + virtual void type3D1(GfxState *state, double wx, double wy, + double llx, double lly, double urx, double ury) {} + + //----- form XObjects + virtual void drawForm(Ref id) {} + + //----- PostScript XObjects + virtual void psXObject(Stream *psStream, Stream *level1Stream) {} + + //----- transparency groups and soft masks + virtual GBool beginTransparencyGroup(GfxState *state, double *bbox, + GfxColorSpace *blendingColorSpace, + GBool isolated, GBool knockout, + GBool forSoftMask) { return gTrue; } + virtual void endTransparencyGroup(GfxState *state) {} + virtual void paintTransparencyGroup(GfxState *state, double *bbox) {} + virtual void setSoftMask(GfxState *state, double *bbox, GBool alpha, + Function *transferFunc, GfxColor *backdropColor) {} + virtual void clearSoftMask(GfxState *state) {} + + //----- links + virtual void processLink(Link *link) {} + +private: + + double defCTM[6]; // default coordinate transform matrix + double defICTM[6]; // inverse of default CTM +}; + +#endif diff --git a/xpdf/PDF417Barcode.cc b/xpdf/PDF417Barcode.cc new file mode 100644 index 0000000..0dd35ee --- /dev/null +++ b/xpdf/PDF417Barcode.cc @@ -0,0 +1,1916 @@ +//======================================================================== +// +// PDF417Barcode.cc +// +// Copyright 2018 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include "gtypes.h" +#include "GString.h" +#include "GList.h" +#include "Error.h" +#include "PDF417Barcode.h" + +//------------------------------------------------------------------------ + +#define maxDataCodewords 928 +#define maxErrorCorrectionLevel 8 +#define maxErrorCorrectionCodewords (1 << (maxErrorCorrectionLevel + 1)) + +// mode latches +#define textModeLatch 900 +#define byteModeLatchMult6 924 +#define byteModeLatchNonMult6 901 +#define byteModeShift 913 +#define numericModeLatch 902 + +// text submode latches and shifts +#define textAlphaLowerLatch 27 +#define textAlphaMixedLatch 28 +#define textAlphaPuncShift 29 +#define textLowerAlphaShift 27 +#define textLowerMixedLatch 28 +#define textLowerPuncShift 29 +#define textMixedPuncLatch 25 +#define textMixedLowerLatch 27 +#define textMixedAlphaLatch 28 +#define textMixedPuncShift 29 +#define textPuncAlphaLatch 29 + +#define textSubmodeAlpha 0 +#define textSubmodeLower 1 +#define textSubmodeMixed 2 +#define textSubmodePunc 3 +#define textSubmodeAlphaShift 4 +#define textSubmodePuncShift 5 + +// textCompaction[char][submode] = base-30 value +// or 30 if char isn't available +static char textCompaction[128][4] = { + { 30, 30, 30, 30 }, // 0 + { 30, 30, 30, 30 }, // 1 + { 30, 30, 30, 30 }, // 2 + { 30, 30, 30, 30 }, // 3 + { 30, 30, 30, 30 }, // 4 + { 30, 30, 30, 30 }, // 5 + { 30, 30, 30, 30 }, // 6 + { 30, 30, 30, 30 }, // 7 + { 30, 30, 30, 30 }, // 8 + { 30, 30, 12, 12 }, // 9 + { 30, 30, 30, 15 }, // 10 + { 30, 30, 30, 30 }, // 11 + { 30, 30, 30, 30 }, // 12 + { 30, 30, 11, 11 }, // 13 + { 30, 30, 30, 30 }, // 14 + { 30, 30, 30, 30 }, // 15 + { 30, 30, 30, 30 }, // 16 + { 30, 30, 30, 30 }, // 17 + { 30, 30, 30, 30 }, // 18 + { 30, 30, 30, 30 }, // 19 + { 30, 30, 30, 30 }, // 20 + { 30, 30, 30, 30 }, // 21 + { 30, 30, 30, 30 }, // 22 + { 30, 30, 30, 30 }, // 23 + { 30, 30, 30, 30 }, // 24 + { 30, 30, 30, 30 }, // 25 + { 30, 30, 30, 30 }, // 26 + { 30, 30, 30, 30 }, // 27 + { 30, 30, 30, 30 }, // 28 + { 30, 30, 30, 30 }, // 29 + { 30, 30, 30, 30 }, // 30 + { 30, 30, 30, 30 }, // 31 + { 26, 26, 26, 30 }, // 32 + { 30, 30, 30, 10 }, // 33 + { 30, 30, 30, 20 }, // 34 + { 30, 30, 15, 30 }, // 35 + { 30, 30, 18, 18 }, // 36 + { 30, 30, 21, 30 }, // 37 + { 30, 30, 10, 30 }, // 38 + { 30, 30, 30, 28 }, // 39 + { 30, 30, 30, 23 }, // 40 + { 30, 30, 30, 24 }, // 41 + { 30, 30, 22, 22 }, // 42 + { 30, 30, 20, 30 }, // 43 + { 30, 30, 13, 13 }, // 44 + { 30, 30, 16, 16 }, // 45 + { 30, 30, 17, 17 }, // 46 + { 30, 30, 19, 19 }, // 47 + { 30, 30, 0, 30 }, // 48 + { 30, 30, 1, 30 }, // 49 + { 30, 30, 2, 30 }, // 50 + { 30, 30, 3, 30 }, // 51 + { 30, 30, 4, 30 }, // 52 + { 30, 30, 5, 30 }, // 53 + { 30, 30, 6, 30 }, // 54 + { 30, 30, 7, 30 }, // 55 + { 30, 30, 8, 30 }, // 56 + { 30, 30, 9, 30 }, // 57 + { 30, 30, 14, 14 }, // 58 + { 30, 30, 30, 0 }, // 59 + { 30, 30, 30, 1 }, // 60 + { 30, 30, 23, 30 }, // 61 + { 30, 30, 30, 2 }, // 62 + { 30, 30, 30, 25 }, // 63 + { 30, 30, 30, 3 }, // 64 + { 0, 30, 30, 30 }, // 65 + { 1, 30, 30, 30 }, // 66 + { 2, 30, 30, 30 }, // 67 + { 3, 30, 30, 30 }, // 68 + { 4, 30, 30, 30 }, // 69 + { 5, 30, 30, 30 }, // 70 + { 6, 30, 30, 30 }, // 71 + { 7, 30, 30, 30 }, // 72 + { 8, 30, 30, 30 }, // 73 + { 9, 30, 30, 30 }, // 74 + { 10, 30, 30, 30 }, // 75 + { 11, 30, 30, 30 }, // 76 + { 12, 30, 30, 30 }, // 77 + { 13, 30, 30, 30 }, // 78 + { 14, 30, 30, 30 }, // 79 + { 15, 30, 30, 30 }, // 80 + { 16, 30, 30, 30 }, // 81 + { 17, 30, 30, 30 }, // 82 + { 18, 30, 30, 30 }, // 83 + { 19, 30, 30, 30 }, // 84 + { 20, 30, 30, 30 }, // 85 + { 21, 30, 30, 30 }, // 86 + { 22, 30, 30, 30 }, // 87 + { 23, 30, 30, 30 }, // 88 + { 24, 30, 30, 30 }, // 89 + { 25, 30, 30, 30 }, // 90 + { 30, 30, 30, 4 }, // 91 + { 30, 30, 30, 5 }, // 92 + { 30, 30, 30, 6 }, // 93 + { 30, 30, 24, 30 }, // 94 + { 30, 30, 30, 7 }, // 95 + { 30, 30, 30, 8 }, // 96 + { 30, 0, 30, 30 }, // 97 + { 30, 1, 30, 30 }, // 98 + { 30, 2, 30, 30 }, // 30 + { 30, 3, 30, 30 }, // 100 + { 30, 4, 30, 30 }, // 101 + { 30, 5, 30, 30 }, // 102 + { 30, 6, 30, 30 }, // 103 + { 30, 7, 30, 30 }, // 104 + { 30, 8, 30, 30 }, // 105 + { 30, 9, 30, 30 }, // 106 + { 30, 10, 30, 30 }, // 107 + { 30, 11, 30, 30 }, // 108 + { 30, 12, 30, 30 }, // 109 + { 30, 13, 30, 30 }, // 110 + { 30, 14, 30, 30 }, // 111 + { 30, 15, 30, 30 }, // 112 + { 30, 16, 30, 30 }, // 113 + { 30, 17, 30, 30 }, // 114 + { 30, 18, 30, 30 }, // 115 + { 30, 19, 30, 30 }, // 116 + { 30, 20, 30, 30 }, // 117 + { 30, 21, 30, 30 }, // 118 + { 30, 22, 30, 30 }, // 119 + { 30, 23, 30, 30 }, // 120 + { 30, 24, 30, 30 }, // 121 + { 30, 25, 30, 30 }, // 122 + { 30, 30, 30, 26 }, // 123 + { 30, 30, 30, 21 }, // 124 + { 30, 30, 30, 27 }, // 125 + { 30, 30, 30, 9 }, // 126 + { 30, 30, 30, 30 } // 127 +}; + +static int errorCorrectionCoeffLevel0[2] = { + 27, 917 +}; + +static int errorCorrectionCoeffLevel1[4] = { + 522, 568, 723, 809 +}; + +static int errorCorrectionCoeffLevel2[8] = { + 237, 308, 436, 284, 646, 653, 428, 379 +}; + +static int errorCorrectionCoeffLevel3[16] = { + 274, 562, 232, 755, 599, 524, 801, 132, + 295, 116, 442, 428, 295, 42, 176, 65 +}; + +static int errorCorrectionCoeffLevel4[32] = { + 361, 575, 922, 525, 176, 586, 640, 321, + 536, 742, 677, 742, 687, 284, 193, 517, + 273, 494, 263, 147, 593, 800, 571, 320, + 803, 133, 231, 390, 685, 330, 63, 410 +}; + +static int errorCorrectionCoeffLevel5[64] = { + 539, 422, 6, 93, 862, 771, 453, 106, + 610, 287, 107, 505, 733, 877, 381, 612, + 723, 476, 462, 172, 430, 609, 858, 822, + 543, 376, 511, 400, 672, 762, 283, 184, + 440, 35, 519, 31, 460, 594, 225, 535, + 517, 352, 605, 158, 651, 201, 488, 502, + 648, 733, 717, 83, 404, 97, 280, 771, + 840, 629, 4, 381, 843, 623, 264, 543 +}; + +static int errorCorrectionCoeffLevel6[128] = { + 521, 310, 864, 547, 858, 580, 296, 379, + 53, 779, 897, 444, 400, 925, 749, 415, + 822, 93, 217, 208, 928, 244, 583, 620, + 246, 148, 447, 631, 292, 908, 490, 704, + 516, 258, 457, 907, 594, 723, 674, 292, + 272, 96, 684, 432, 686, 606, 860, 569, + 193, 219, 129, 186, 236, 287, 192, 775, + 278, 173, 40, 379, 712, 463, 646, 776, + 171, 491, 297, 763, 156, 732, 95, 270, + 447, 90, 507, 48, 228, 821, 808, 898, + 784, 663, 627, 378, 382, 262, 380, 602, + 754, 336, 89, 614, 87, 432, 670, 616, + 157, 374, 242, 726, 600, 269, 375, 898, + 845, 454, 354, 130, 814, 587, 804, 34, + 211, 330, 539, 297, 827, 865, 37, 517, + 834, 315, 550, 86, 801, 4, 108, 539 +}; + +static int errorCorrectionCoeffLevel7[256] = { + 524, 894, 75, 766, 882, 857, 74, 204, + 82, 586, 708, 250, 905, 786, 138, 720, + 858, 194, 311, 913, 275, 190, 375, 850, + 438, 733, 194, 280, 201, 280, 828, 757, + 710, 814, 919, 89, 68, 569, 11, 204, + 796, 605, 540, 913, 801, 700, 799, 137, + 439, 418, 592, 668, 353, 859, 370, 694, + 325, 240, 216, 257, 284, 549, 209, 884, + 315, 70, 329, 793, 490, 274, 877, 162, + 749, 812, 684, 461, 334, 376, 849, 521, + 307, 291, 803, 712, 19, 358, 399, 908, + 103, 511, 51, 8, 517, 225, 289, 470, + 637, 731, 66, 255, 917, 269, 463, 830, + 730, 433, 848, 585, 136, 538, 906, 90, + 2, 290, 743, 199, 655, 903, 329, 49, + 802, 580, 355, 588, 188, 462, 10, 134, + 628, 320, 479, 130, 739, 71, 263, 318, + 374, 601, 192, 605, 142, 673, 687, 234, + 722, 384, 177, 752, 607, 640, 455, 193, + 689, 707, 805, 641, 48, 60, 732, 621, + 895, 544, 261, 852, 655, 309, 697, 755, + 756, 60, 231, 773, 434, 421, 726, 528, + 503, 118, 49, 795, 32, 144, 500, 238, + 836, 394, 280, 566, 319, 9, 647, 550, + 73, 914, 342, 126, 32, 681, 331, 792, + 620, 60, 609, 441, 180, 791, 893, 754, + 605, 383, 228, 749, 760, 213, 54, 297, + 134, 54, 834, 299, 922, 191, 910, 532, + 609, 829, 189, 20, 167, 29, 872, 449, + 83, 402, 41, 656, 505, 579, 481, 173, + 404, 251, 688, 95, 497, 555, 642, 543, + 307, 159, 924, 558, 648, 55, 497, 10 +}; + +static int errorCorrectionCoeffLevel8[512] = { + 352, 77, 373, 504, 35, 599, 428, 207, + 409, 574, 118, 498, 285, 380, 350, 492, + 197, 265, 920, 155, 914, 299, 229, 643, + 294, 871, 306, 88, 87, 193, 352, 781, + 846, 75, 327, 520, 435, 543, 203, 666, + 249, 346, 781, 621, 640, 268, 794, 534, + 539, 781, 408, 390, 644, 102, 476, 499, + 290, 632, 545, 37, 858, 916, 552, 41, + 542, 289, 122, 272, 383, 800, 485, 98, + 752, 472, 761, 107, 784, 860, 658, 741, + 290, 204, 681, 407, 855, 85, 99, 62, + 482, 180, 20, 297, 451, 593, 913, 142, + 808, 684, 287, 536, 561, 76, 653, 899, + 729, 567, 744, 390, 513, 192, 516, 258, + 240, 518, 794, 395, 768, 848, 51, 610, + 384, 168, 190, 826, 328, 596, 786, 303, + 570, 381, 415, 641, 156, 237, 151, 429, + 531, 207, 676, 710, 89, 168, 304, 402, + 40, 708, 575, 162, 864, 229, 65, 861, + 841, 512, 164, 477, 221, 92, 358, 785, + 288, 357, 850, 836, 827, 736, 707, 94, + 8, 494, 114, 521, 2, 499, 851, 543, + 152, 729, 771, 95, 248, 361, 578, 323, + 856, 797, 289, 51, 684, 466, 533, 820, + 669, 45, 902, 452, 167, 342, 244, 173, + 35, 463, 651, 51, 699, 591, 452, 578, + 37, 124, 298, 332, 552, 43, 427, 119, + 662, 777, 475, 850, 764, 364, 578, 911, + 283, 711, 472, 420, 245, 288, 594, 394, + 511, 327, 589, 777, 699, 688, 43, 408, + 842, 383, 721, 521, 560, 644, 714, 559, + 62, 145, 873, 663, 713, 159, 672, 729, + 624, 59, 193, 417, 158, 209, 563, 564, + 343, 693, 109, 608, 563, 365, 181, 772, + 677, 310, 248, 353, 708, 410, 579, 870, + 617, 841, 632, 860, 289, 536, 35, 777, + 618, 586, 424, 833, 77, 597, 346, 269, + 757, 632, 695, 751, 331, 247, 184, 45, + 787, 680, 18, 66, 407, 369, 54, 492, + 228, 613, 830, 922, 437, 519, 644, 905, + 789, 420, 305, 441, 207, 300, 892, 827, + 141, 537, 381, 662, 513, 56, 252, 341, + 242, 797, 838, 837, 720, 224, 307, 631, + 61, 87, 560, 310, 756, 665, 397, 808, + 851, 309, 473, 795, 378, 31, 647, 915, + 459, 806, 590, 731, 425, 216, 548, 249, + 321, 881, 699, 535, 673, 782, 210, 815, + 905, 303, 843, 922, 281, 73, 469, 791, + 660, 162, 498, 308, 155, 422, 907, 817, + 187, 62, 16, 425, 535, 336, 286, 437, + 375, 273, 610, 296, 183, 923, 116, 667, + 751, 353, 62, 366, 691, 379, 687, 842, + 37, 357, 720, 742, 330, 5, 39, 923, + 311, 424, 242, 749, 321, 54, 669, 316, + 342, 299, 534, 105, 667, 488, 640, 672, + 576, 540, 316, 486, 721, 610, 46, 656, + 447, 171, 616, 464, 190, 531, 297, 321, + 762, 752, 533, 175, 134, 14, 381, 433, + 717, 45, 111, 20, 596, 284, 736, 138, + 646, 411, 877, 669, 141, 919, 45, 780, + 407, 164, 332, 899, 165, 726, 600, 325, + 498, 655, 357, 752, 768, 223, 849, 647, + 63, 310, 863, 251, 366, 304, 282, 738, + 675, 410, 389, 244, 31, 121, 303, 263 +}; + +static int *errorCorrectionCoeff[maxErrorCorrectionLevel + 1] = { + errorCorrectionCoeffLevel0, + errorCorrectionCoeffLevel1, + errorCorrectionCoeffLevel2, + errorCorrectionCoeffLevel3, + errorCorrectionCoeffLevel4, + errorCorrectionCoeffLevel5, + errorCorrectionCoeffLevel6, + errorCorrectionCoeffLevel7, + errorCorrectionCoeffLevel8 +}; + +#define startPatternLength 8 +static char startPattern[startPatternLength] = {8,1,1,1,1,1,1,3}; + +#define stopPatternLength 9 +static char stopPattern[stopPatternLength] = {7,1,1,3,1,1,1,2,1}; + +#define patternLength 8 + +// patterns[codeword][cluster][element] = element (bar or space) width +static char patterns[929][3][patternLength] = { + {{3,1,1,1,1,1,3,6}, {5,1,1,1,1,1,2,5}, {2,1,1,1,1,1,5,5}}, + {{4,1,1,1,1,1,4,4}, {6,1,1,1,1,1,3,3}, {3,1,1,1,1,1,6,3}}, + {{5,1,1,1,1,1,5,2}, {4,1,1,1,1,2,1,6}, {1,1,1,1,1,2,4,6}}, + {{3,1,1,1,1,2,3,5}, {5,1,1,1,1,2,2,4}, {2,1,1,1,1,2,5,4}}, + {{4,1,1,1,1,2,4,3}, {6,1,1,1,1,2,3,2}, {3,1,1,1,1,2,6,2}}, + {{5,1,1,1,1,2,5,1}, {4,1,1,1,1,3,1,5}, {1,1,1,1,1,3,4,5}}, + {{2,1,1,1,1,3,2,6}, {5,1,1,1,1,3,2,3}, {2,1,1,1,1,3,5,3}}, + {{3,1,1,1,1,3,3,4}, {6,1,1,1,1,3,3,1}, {3,1,1,1,1,3,6,1}}, + {{2,1,1,1,1,4,2,5}, {4,1,1,1,1,4,1,4}, {1,1,1,1,1,4,4,4}}, + {{1,1,1,1,1,5,1,6}, {5,1,1,1,1,4,2,2}, {2,1,1,1,1,4,5,2}}, + {{2,1,1,1,1,5,2,4}, {4,1,1,1,1,5,1,3}, {1,1,1,1,1,5,4,3}}, + {{1,1,1,1,1,6,1,5}, {5,1,1,1,1,5,2,1}, {6,1,1,1,2,1,1,4}}, + {{2,1,1,1,2,1,3,6}, {4,1,1,1,1,6,1,2}, {1,1,1,1,2,1,5,5}}, + {{3,1,1,1,2,1,4,4}, {4,1,1,1,2,1,2,5}, {2,1,1,1,2,1,6,3}}, + {{4,1,1,1,2,1,5,2}, {5,1,1,1,2,1,3,3}, {6,1,1,1,2,2,1,3}}, + {{2,1,1,1,2,2,3,5}, {6,1,1,1,2,1,4,1}, {1,1,1,1,2,2,5,4}}, + {{3,1,1,1,2,2,4,3}, {3,1,1,1,2,2,1,6}, {2,1,1,1,2,2,6,2}}, + {{4,1,1,1,2,2,5,1}, {4,1,1,1,2,2,2,4}, {6,1,1,1,2,3,1,2}}, + {{1,1,1,1,2,3,2,6}, {5,1,1,1,2,2,3,2}, {1,1,1,1,2,3,5,3}}, + {{2,1,1,1,2,3,3,4}, {3,1,1,1,2,3,1,5}, {2,1,1,1,2,3,6,1}}, + {{1,1,1,1,2,4,2,5}, {4,1,1,1,2,3,2,3}, {6,1,1,1,2,4,1,1}}, + {{1,1,1,1,3,1,3,6}, {5,1,1,1,2,3,3,1}, {1,1,1,1,2,4,5,2}}, + {{2,1,1,1,3,1,4,4}, {3,1,1,1,2,4,1,4}, {5,1,1,1,3,1,1,4}}, + {{3,1,1,1,3,1,5,2}, {4,1,1,1,2,4,2,2}, {6,1,1,1,3,1,2,2}}, + {{1,1,1,1,3,2,3,5}, {3,1,1,1,2,5,1,3}, {1,1,1,1,3,1,6,3}}, + {{2,1,1,1,3,2,4,3}, {4,1,1,1,2,5,2,1}, {5,1,1,1,3,2,1,3}}, + {{3,1,1,1,3,2,5,1}, {3,1,1,1,2,6,1,2}, {6,1,1,1,3,2,2,1}}, + {{1,1,1,1,3,3,3,4}, {3,1,1,1,3,1,2,5}, {1,1,1,1,3,2,6,2}}, + {{2,1,1,1,3,3,4,2}, {4,1,1,1,3,1,3,3}, {5,1,1,1,3,3,1,2}}, + {{1,1,1,1,4,1,4,4}, {5,1,1,1,3,1,4,1}, {1,1,1,1,3,3,6,1}}, + {{2,1,1,1,4,1,5,2}, {2,1,1,1,3,2,1,6}, {5,1,1,1,3,4,1,1}}, + {{1,1,1,1,4,2,4,3}, {3,1,1,1,3,2,2,4}, {4,1,1,1,4,1,1,4}}, + {{2,1,1,1,4,2,5,1}, {4,1,1,1,3,2,3,2}, {5,1,1,1,4,1,2,2}}, + {{1,1,1,1,5,1,5,2}, {2,1,1,1,3,3,1,5}, {4,1,1,1,4,2,1,3}}, + {{5,1,1,1,6,1,1,1}, {3,1,1,1,3,3,2,3}, {5,1,1,1,4,2,2,1}}, + {{3,1,1,2,1,1,3,5}, {4,1,1,1,3,3,3,1}, {4,1,1,1,4,3,1,2}}, + {{4,1,1,2,1,1,4,3}, {2,1,1,1,3,4,1,4}, {4,1,1,1,4,4,1,1}}, + {{5,1,1,2,1,1,5,1}, {3,1,1,1,3,4,2,2}, {3,1,1,1,5,1,1,4}}, + {{2,1,1,2,1,2,2,6}, {2,1,1,1,3,5,1,3}, {4,1,1,1,5,1,2,2}}, + {{3,1,1,2,1,2,3,4}, {3,1,1,1,3,5,2,1}, {3,1,1,1,5,2,1,3}}, + {{4,1,1,2,1,2,4,2}, {2,1,1,1,3,6,1,2}, {4,1,1,1,5,2,2,1}}, + {{2,1,1,2,1,3,2,5}, {2,1,1,1,4,1,2,5}, {3,1,1,1,5,3,1,2}}, + {{3,1,1,2,1,3,3,3}, {3,1,1,1,4,1,3,3}, {3,1,1,1,5,4,1,1}}, + {{1,1,1,2,1,4,1,6}, {4,1,1,1,4,1,4,1}, {2,1,1,1,6,1,1,4}}, + {{2,1,1,2,1,4,2,4}, {1,1,1,1,4,2,1,6}, {3,1,1,1,6,1,2,2}}, + {{3,1,1,2,1,4,3,2}, {2,1,1,1,4,2,2,4}, {2,1,1,1,6,2,1,3}}, + {{1,1,1,2,1,5,1,5}, {3,1,1,1,4,2,3,2}, {3,1,1,1,6,2,2,1}}, + {{2,1,1,2,1,5,2,3}, {1,1,1,1,4,3,1,5}, {2,1,1,1,6,3,1,2}}, + {{1,1,1,2,1,6,1,4}, {2,1,1,1,4,3,2,3}, {1,1,1,2,1,1,4,6}}, + {{2,1,1,2,2,1,3,5}, {3,1,1,1,4,3,3,1}, {2,1,1,2,1,1,5,4}}, + {{3,1,1,2,2,1,4,3}, {1,1,1,1,4,4,1,4}, {3,1,1,2,1,1,6,2}}, + {{4,1,1,2,2,1,5,1}, {2,1,1,1,4,4,2,2}, {1,1,1,2,1,2,4,5}}, + {{1,1,1,2,2,2,2,6}, {1,1,1,1,4,5,1,3}, {2,1,1,2,1,2,5,3}}, + {{2,1,1,2,2,2,3,4}, {2,1,1,1,4,5,2,1}, {3,1,1,2,1,2,6,1}}, + {{3,1,1,2,2,2,4,2}, {1,1,1,1,5,1,2,5}, {1,1,1,2,1,3,4,4}}, + {{1,1,1,2,2,3,2,5}, {2,1,1,1,5,1,3,3}, {2,1,1,2,1,3,5,2}}, + {{2,1,1,2,2,3,3,3}, {3,1,1,1,5,1,4,1}, {1,1,1,2,1,4,4,3}}, + {{3,1,1,2,2,3,4,1}, {1,1,1,1,5,2,2,4}, {2,1,1,2,1,4,5,1}}, + {{1,1,1,2,2,4,2,4}, {2,1,1,1,5,2,3,2}, {1,1,1,2,1,5,4,2}}, + {{2,1,1,2,2,4,3,2}, {1,1,1,1,5,3,2,3}, {6,1,1,2,2,1,1,3}}, + {{1,1,1,2,3,1,3,5}, {2,1,1,1,5,3,3,1}, {1,1,1,2,2,1,5,4}}, + {{2,1,1,2,3,1,4,3}, {1,1,1,1,5,4,2,2}, {2,1,1,2,2,1,6,2}}, + {{3,1,1,2,3,1,5,1}, {1,1,1,1,6,1,3,3}, {6,1,1,2,2,2,1,2}}, + {{1,1,1,2,3,2,3,4}, {2,1,1,1,6,1,4,1}, {1,1,1,2,2,2,5,3}}, + {{2,1,1,2,3,2,4,2}, {1,1,1,1,6,2,3,2}, {2,1,1,2,2,2,6,1}}, + {{1,1,1,2,3,3,3,3}, {1,1,1,1,6,3,3,1}, {6,1,1,2,2,3,1,1}}, + {{2,1,1,2,3,3,4,1}, {4,1,1,2,1,1,1,6}, {1,1,1,2,2,3,5,2}}, + {{1,1,1,2,4,1,4,3}, {5,1,1,2,1,1,2,4}, {1,1,1,2,2,4,5,1}}, + {{2,1,1,2,4,1,5,1}, {6,1,1,2,1,1,3,2}, {5,1,1,2,3,1,1,3}}, + {{1,1,1,2,4,2,4,2}, {4,1,1,2,1,2,1,5}, {6,1,1,2,3,1,2,1}}, + {{1,1,1,2,4,3,4,1}, {5,1,1,2,1,2,2,3}, {1,1,1,2,3,1,6,2}}, + {{2,1,1,3,1,1,2,6}, {6,1,1,2,1,2,3,1}, {5,1,1,2,3,2,1,2}}, + {{3,1,1,3,1,1,3,4}, {4,1,1,2,1,3,1,4}, {1,1,1,2,3,2,6,1}}, + {{4,1,1,3,1,1,4,2}, {5,1,1,2,1,3,2,2}, {5,1,1,2,3,3,1,1}}, + {{2,1,1,3,1,2,2,5}, {4,1,1,2,1,4,1,3}, {4,1,1,2,4,1,1,3}}, + {{3,1,1,3,1,2,3,3}, {5,1,1,2,1,4,2,1}, {5,1,1,2,4,1,2,1}}, + {{4,1,1,3,1,2,4,1}, {4,1,1,2,1,5,1,2}, {4,1,1,2,4,2,1,2}}, + {{1,1,1,3,1,3,1,6}, {4,1,1,2,1,6,1,1}, {4,1,1,2,4,3,1,1}}, + {{2,1,1,3,1,3,2,4}, {3,1,1,2,2,1,1,6}, {3,1,1,2,5,1,1,3}}, + {{3,1,1,3,1,3,3,2}, {4,1,1,2,2,1,2,4}, {4,1,1,2,5,1,2,1}}, + {{1,1,1,3,1,4,1,5}, {5,1,1,2,2,1,3,2}, {3,1,1,2,5,2,1,2}}, + {{2,1,1,3,1,4,2,3}, {3,1,1,2,2,2,1,5}, {3,1,1,2,5,3,1,1}}, + {{1,1,1,3,1,5,1,4}, {4,1,1,2,2,2,2,3}, {2,1,1,2,6,1,1,3}}, + {{1,1,1,3,1,6,1,3}, {5,1,1,2,2,2,3,1}, {3,1,1,2,6,1,2,1}}, + {{1,1,1,3,2,1,2,6}, {3,1,1,2,2,3,1,4}, {2,1,1,2,6,2,1,2}}, + {{2,1,1,3,2,1,3,4}, {4,1,1,2,2,3,2,2}, {2,1,1,2,6,3,1,1}}, + {{3,1,1,3,2,1,4,2}, {3,1,1,2,2,4,1,3}, {1,1,1,3,1,1,4,5}}, + {{1,1,1,3,2,2,2,5}, {4,1,1,2,2,4,2,1}, {2,1,1,3,1,1,5,3}}, + {{2,1,1,3,2,2,3,3}, {3,1,1,2,2,5,1,2}, {3,1,1,3,1,1,6,1}}, + {{3,1,1,3,2,2,4,1}, {3,1,1,2,2,6,1,1}, {1,1,1,3,1,2,4,4}}, + {{1,1,1,3,2,3,2,4}, {2,1,1,2,3,1,1,6}, {2,1,1,3,1,2,5,2}}, + {{2,1,1,3,2,3,3,2}, {3,1,1,2,3,1,2,4}, {1,1,1,3,1,3,4,3}}, + {{1,1,1,3,2,4,2,3}, {4,1,1,2,3,1,3,2}, {2,1,1,3,1,3,5,1}}, + {{1,1,1,3,2,5,2,2}, {2,1,1,2,3,2,1,5}, {1,1,1,3,1,4,4,2}}, + {{1,1,1,3,3,1,3,4}, {3,1,1,2,3,2,2,3}, {1,1,1,3,1,5,4,1}}, + {{2,1,1,3,3,1,4,2}, {4,1,1,2,3,2,3,1}, {6,1,1,3,2,1,1,2}}, + {{1,1,1,3,3,2,3,3}, {2,1,1,2,3,3,1,4}, {1,1,1,3,2,1,5,3}}, + {{2,1,1,3,3,2,4,1}, {3,1,1,2,3,3,2,2}, {2,1,1,3,2,1,6,1}}, + {{1,1,1,3,3,3,3,2}, {2,1,1,2,3,4,1,3}, {6,1,1,3,2,2,1,1}}, + {{1,1,1,3,4,1,4,2}, {3,1,1,2,3,4,2,1}, {1,1,1,3,2,2,5,2}}, + {{2,1,1,4,1,1,2,5}, {2,1,1,2,3,5,1,2}, {1,1,1,3,2,3,5,1}}, + {{3,1,1,4,1,1,3,3}, {2,1,1,2,3,6,1,1}, {5,1,1,3,3,1,1,2}}, + {{4,1,1,4,1,1,4,1}, {1,1,1,2,4,1,1,6}, {1,1,1,3,3,1,6,1}}, + {{1,1,1,4,1,2,1,6}, {2,1,1,2,4,1,2,4}, {5,1,1,3,3,2,1,1}}, + {{2,1,1,4,1,2,2,4}, {3,1,1,2,4,1,3,2}, {4,1,1,3,4,1,1,2}}, + {{3,1,1,4,1,2,3,2}, {1,1,1,2,4,2,1,5}, {4,1,1,3,4,2,1,1}}, + {{1,1,1,4,1,3,1,5}, {2,1,1,2,4,2,2,3}, {3,1,1,3,5,1,1,2}}, + {{2,1,1,4,1,3,2,3}, {3,1,1,2,4,2,3,1}, {3,1,1,3,5,2,1,1}}, + {{3,1,1,4,1,3,3,1}, {1,1,1,2,4,3,1,4}, {2,1,1,3,6,1,1,2}}, + {{1,1,1,4,1,4,1,4}, {2,1,1,2,4,3,2,2}, {2,1,1,3,6,2,1,1}}, + {{2,1,1,4,1,4,2,2}, {1,1,1,2,4,4,1,3}, {1,1,1,4,1,1,4,4}}, + {{1,1,1,4,1,5,1,3}, {2,1,1,2,4,4,2,1}, {2,1,1,4,1,1,5,2}}, + {{2,1,1,4,1,5,2,1}, {1,1,1,2,4,5,1,2}, {1,1,1,4,1,2,4,3}}, + {{1,1,1,4,2,1,2,5}, {1,1,1,2,5,1,2,4}, {2,1,1,4,1,2,5,1}}, + {{2,1,1,4,2,1,3,3}, {2,1,1,2,5,1,3,2}, {1,1,1,4,1,3,4,2}}, + {{3,1,1,4,2,1,4,1}, {1,1,1,2,5,2,2,3}, {1,1,1,4,1,4,4,1}}, + {{1,1,1,4,2,2,2,4}, {2,1,1,2,5,2,3,1}, {6,1,1,4,2,1,1,1}}, + {{2,1,1,4,2,2,3,2}, {1,1,1,2,5,3,2,2}, {1,1,1,4,2,1,5,2}}, + {{1,1,1,4,2,3,2,3}, {1,1,1,2,5,4,2,1}, {1,1,1,4,2,2,5,1}}, + {{2,1,1,4,2,3,3,1}, {1,1,1,2,6,1,3,2}, {5,1,1,4,3,1,1,1}}, + {{1,1,1,4,2,4,2,2}, {1,1,1,2,6,2,3,1}, {4,1,1,4,4,1,1,1}}, + {{1,1,1,4,2,5,2,1}, {4,1,1,3,1,1,1,5}, {3,1,1,4,5,1,1,1}}, + {{2,1,1,4,3,1,4,1}, {5,1,1,3,1,1,2,3}, {1,1,1,5,1,1,4,3}}, + {{1,1,1,4,3,3,3,1}, {6,1,1,3,1,1,3,1}, {2,1,1,5,1,1,5,1}}, + {{1,1,1,5,1,1,1,6}, {4,1,1,3,1,2,1,4}, {1,1,1,5,1,2,4,2}}, + {{2,1,1,5,1,1,2,4}, {5,1,1,3,1,2,2,2}, {1,1,1,5,1,3,4,1}}, + {{3,1,1,5,1,1,3,2}, {4,1,1,3,1,3,1,3}, {1,1,1,5,2,1,5,1}}, + {{1,1,1,5,1,2,1,5}, {5,1,1,3,1,3,2,1}, {1,1,1,6,1,1,4,2}}, + {{2,1,1,5,1,2,2,3}, {4,1,1,3,1,4,1,2}, {1,1,1,6,1,2,4,1}}, + {{3,1,1,5,1,2,3,1}, {4,1,1,3,1,5,1,1}, {1,2,1,1,1,1,4,6}}, + {{1,1,1,5,1,3,1,4}, {3,1,1,3,2,1,1,5}, {2,2,1,1,1,1,5,4}}, + {{2,1,1,5,1,3,2,2}, {4,1,1,3,2,1,2,3}, {3,2,1,1,1,1,6,2}}, + {{1,1,1,5,1,4,1,3}, {5,1,1,3,2,1,3,1}, {1,2,1,1,1,2,4,5}}, + {{2,1,1,5,1,4,2,1}, {3,1,1,3,2,2,1,4}, {2,2,1,1,1,2,5,3}}, + {{1,1,1,5,1,5,1,2}, {4,1,1,3,2,2,2,2}, {3,2,1,1,1,2,6,1}}, + {{1,1,1,5,2,1,2,4}, {3,1,1,3,2,3,1,3}, {1,2,1,1,1,3,4,4}}, + {{1,1,1,5,2,2,2,3}, {4,1,1,3,2,3,2,1}, {2,2,1,1,1,3,5,2}}, + {{1,1,1,5,2,3,2,2}, {3,1,1,3,2,4,1,2}, {1,2,1,1,1,4,4,3}}, + {{1,1,1,6,1,1,1,5}, {3,1,1,3,2,5,1,1}, {2,2,1,1,1,4,5,1}}, + {{3,1,1,6,1,1,3,1}, {2,1,1,3,3,1,1,5}, {1,2,1,1,1,5,4,2}}, + {{2,1,1,6,1,2,2,2}, {3,1,1,3,3,1,2,3}, {6,2,1,1,2,1,1,3}}, + {{2,1,1,6,1,3,2,1}, {4,1,1,3,3,1,3,1}, {1,2,1,1,2,1,5,4}}, + {{1,1,1,6,1,5,1,1}, {2,1,1,3,3,2,1,4}, {2,2,1,1,2,1,6,2}}, + {{3,2,1,1,1,1,3,5}, {3,1,1,3,3,2,2,2}, {6,2,1,1,2,2,1,2}}, + {{4,2,1,1,1,1,4,3}, {2,1,1,3,3,3,1,3}, {1,2,1,1,2,2,5,3}}, + {{5,2,1,1,1,1,5,1}, {3,1,1,3,3,3,2,1}, {2,2,1,1,2,2,6,1}}, + {{2,2,1,1,1,2,2,6}, {2,1,1,3,3,4,1,2}, {6,2,1,1,2,3,1,1}}, + {{3,2,1,1,1,2,3,4}, {2,1,1,3,3,5,1,1}, {1,2,1,1,2,3,5,2}}, + {{4,2,1,1,1,2,4,2}, {1,1,1,3,4,1,1,5}, {1,2,1,1,2,4,5,1}}, + {{2,2,1,1,1,3,2,5}, {2,1,1,3,4,1,2,3}, {5,2,1,1,3,1,1,3}}, + {{3,2,1,1,1,3,3,3}, {3,1,1,3,4,1,3,1}, {6,2,1,1,3,1,2,1}}, + {{4,2,1,1,1,3,4,1}, {1,1,1,3,4,2,1,4}, {1,2,1,1,3,1,6,2}}, + {{1,2,1,1,1,4,1,6}, {2,1,1,3,4,2,2,2}, {5,2,1,1,3,2,1,2}}, + {{2,2,1,1,1,4,2,4}, {1,1,1,3,4,3,1,3}, {1,2,1,1,3,2,6,1}}, + {{1,2,1,1,1,5,1,5}, {2,1,1,3,4,3,2,1}, {5,2,1,1,3,3,1,1}}, + {{2,2,1,1,2,1,3,5}, {1,1,1,3,4,4,1,2}, {4,2,1,1,4,1,1,3}}, + {{3,2,1,1,2,1,4,3}, {1,1,1,3,4,5,1,1}, {5,2,1,1,4,1,2,1}}, + {{4,2,1,1,2,1,5,1}, {1,1,1,3,5,1,2,3}, {4,2,1,1,4,2,1,2}}, + {{1,2,1,1,2,2,2,6}, {2,1,1,3,5,1,3,1}, {4,2,1,1,4,3,1,1}}, + {{2,2,1,1,2,2,3,4}, {1,1,1,3,5,2,2,2}, {3,2,1,1,5,1,1,3}}, + {{3,2,1,1,2,2,4,2}, {1,1,1,3,5,3,2,1}, {4,2,1,1,5,1,2,1}}, + {{1,2,1,1,2,3,2,5}, {1,1,1,3,6,1,3,1}, {3,2,1,1,5,2,1,2}}, + {{2,2,1,1,2,3,3,3}, {4,1,1,4,1,1,1,4}, {3,2,1,1,5,3,1,1}}, + {{1,2,1,1,2,4,2,4}, {5,1,1,4,1,1,2,2}, {2,2,1,1,6,1,1,3}}, + {{1,2,1,1,2,5,2,3}, {4,1,1,4,1,2,1,3}, {3,2,1,1,6,1,2,1}}, + {{1,2,1,1,3,1,3,5}, {5,1,1,4,1,2,2,1}, {2,2,1,1,6,2,1,2}}, + {{2,2,1,1,3,1,4,3}, {4,1,1,4,1,3,1,2}, {2,2,1,1,6,3,1,1}}, + {{3,2,1,1,3,1,5,1}, {4,1,1,4,1,4,1,1}, {2,1,2,1,1,1,4,5}}, + {{1,2,1,1,3,2,3,4}, {3,1,1,4,2,1,1,4}, {3,1,2,1,1,1,5,3}}, + {{2,2,1,1,3,2,4,2}, {4,1,1,4,2,1,2,2}, {4,1,2,1,1,1,6,1}}, + {{1,2,1,1,3,3,3,3}, {3,1,1,4,2,2,1,3}, {1,1,2,1,1,2,3,6}}, + {{1,2,1,1,3,4,3,2}, {4,1,1,4,2,2,2,1}, {2,1,2,1,1,2,4,4}}, + {{1,2,1,1,4,1,4,3}, {3,1,1,4,2,3,1,2}, {3,1,2,1,1,2,5,2}}, + {{2,2,1,1,4,1,5,1}, {3,1,1,4,2,4,1,1}, {1,1,2,1,1,3,3,5}}, + {{1,2,1,1,4,2,4,2}, {2,1,1,4,3,1,1,4}, {2,1,2,1,1,3,4,3}}, + {{1,2,1,1,5,1,5,1}, {3,1,1,4,3,1,2,2}, {3,1,2,1,1,3,5,1}}, + {{3,1,2,1,1,1,2,6}, {2,1,1,4,3,2,1,3}, {1,1,2,1,1,4,3,4}}, + {{4,1,2,1,1,1,3,4}, {3,1,1,4,3,2,2,1}, {2,1,2,1,1,4,4,2}}, + {{5,1,2,1,1,1,4,2}, {2,1,1,4,3,3,1,2}, {1,1,2,1,1,5,3,3}}, + {{3,1,2,1,1,2,2,5}, {2,1,1,4,3,4,1,1}, {2,1,2,1,1,5,4,1}}, + {{4,1,2,1,1,2,3,3}, {1,1,1,4,4,1,1,4}, {1,1,2,1,1,6,3,2}}, + {{5,1,2,1,1,2,4,1}, {2,1,1,4,4,1,2,2}, {1,2,1,2,1,1,4,5}}, + {{2,1,2,1,1,3,1,6}, {1,1,1,4,4,2,1,3}, {2,2,1,2,1,1,5,3}}, + {{3,1,2,1,1,3,2,4}, {2,1,1,4,4,2,2,1}, {3,2,1,2,1,1,6,1}}, + {{4,1,2,1,1,3,3,2}, {1,1,1,4,4,3,1,2}, {1,1,2,1,2,1,4,5}}, + {{2,1,2,1,1,4,1,5}, {1,1,1,4,4,4,1,1}, {1,2,1,2,1,2,4,4}}, + {{3,1,2,1,1,4,2,3}, {1,1,1,4,5,1,2,2}, {2,2,1,2,1,2,5,2}}, + {{4,1,2,1,1,4,3,1}, {1,1,1,4,5,2,2,1}, {1,1,2,1,2,2,4,4}}, + {{2,1,2,1,1,5,1,4}, {4,1,1,5,1,1,1,3}, {2,1,2,1,2,2,5,2}}, + {{3,1,2,1,1,5,2,2}, {5,1,1,5,1,1,2,1}, {2,2,1,2,1,3,5,1}}, + {{2,2,1,2,1,1,2,6}, {4,1,1,5,1,2,1,2}, {1,1,2,1,2,3,4,3}}, + {{3,2,1,2,1,1,3,4}, {4,1,1,5,1,3,1,1}, {1,2,1,2,1,4,4,2}}, + {{4,2,1,2,1,1,4,2}, {3,1,1,5,2,1,1,3}, {1,1,2,1,2,4,4,2}}, + {{2,1,2,1,2,1,2,6}, {4,1,1,5,2,1,2,1}, {1,2,1,2,1,5,4,1}}, + {{2,2,1,2,1,2,2,5}, {3,1,1,5,2,2,1,2}, {1,1,2,1,2,5,4,1}}, + {{3,2,1,2,1,2,3,3}, {3,1,1,5,2,3,1,1}, {6,2,1,2,2,1,1,2}}, + {{4,2,1,2,1,2,4,1}, {2,1,1,5,3,1,1,3}, {1,2,1,2,2,1,5,3}}, + {{2,1,2,1,2,2,2,5}, {3,1,1,5,3,1,2,1}, {2,2,1,2,2,1,6,1}}, + {{3,1,2,1,2,2,3,3}, {2,1,1,5,3,2,1,2}, {6,1,2,1,3,1,1,2}}, + {{4,1,2,1,2,2,4,1}, {2,1,1,5,3,3,1,1}, {6,2,1,2,2,2,1,1}}, + {{1,1,2,1,2,3,1,6}, {1,1,1,5,4,1,1,3}, {1,1,2,1,3,1,5,3}}, + {{1,2,1,2,1,4,1,5}, {2,1,1,5,4,1,2,1}, {1,2,1,2,2,2,5,2}}, + {{2,2,1,2,1,4,2,3}, {1,1,1,5,4,2,1,2}, {6,1,2,1,3,2,1,1}}, + {{3,2,1,2,1,4,3,1}, {1,1,1,5,4,3,1,1}, {1,1,2,1,3,2,5,2}}, + {{1,1,2,1,2,4,1,5}, {4,1,1,6,1,1,1,2}, {1,2,1,2,2,3,5,1}}, + {{2,1,2,1,2,4,2,3}, {4,1,1,6,1,2,1,1}, {1,1,2,1,3,3,5,1}}, + {{1,1,2,1,2,5,1,4}, {3,1,1,6,2,1,1,2}, {5,2,1,2,3,1,1,2}}, + {{1,2,1,2,2,1,2,6}, {3,1,1,6,2,2,1,1}, {1,2,1,2,3,1,6,1}}, + {{2,2,1,2,2,1,3,4}, {2,1,1,6,3,1,1,2}, {5,1,2,1,4,1,1,2}}, + {{3,2,1,2,2,1,4,2}, {2,1,1,6,3,2,1,1}, {5,2,1,2,3,2,1,1}}, + {{1,1,2,1,3,1,2,6}, {4,2,1,1,1,1,1,6}, {1,1,2,1,4,1,6,1}}, + {{1,2,1,2,2,2,2,5}, {5,2,1,1,1,1,2,4}, {5,1,2,1,4,2,1,1}}, + {{2,2,1,2,2,2,3,3}, {6,2,1,1,1,1,3,2}, {4,2,1,2,4,1,1,2}}, + {{3,2,1,2,2,2,4,1}, {4,2,1,1,1,2,1,5}, {4,1,2,1,5,1,1,2}}, + {{1,1,2,1,3,2,2,5}, {5,2,1,1,1,2,2,3}, {4,2,1,2,4,2,1,1}}, + {{2,1,2,1,3,2,3,3}, {6,2,1,1,1,2,3,1}, {4,1,2,1,5,2,1,1}}, + {{3,1,2,1,3,2,4,1}, {4,2,1,1,1,3,1,4}, {3,2,1,2,5,1,1,2}}, + {{1,1,2,1,3,3,2,4}, {5,2,1,1,1,3,2,2}, {3,1,2,1,6,1,1,2}}, + {{1,2,1,2,2,4,2,3}, {4,2,1,1,1,4,1,3}, {3,2,1,2,5,2,1,1}}, + {{1,1,2,1,3,4,2,3}, {5,2,1,1,1,4,2,1}, {3,1,2,1,6,2,1,1}}, + {{1,2,1,2,3,1,3,4}, {4,2,1,1,1,5,1,2}, {2,2,1,2,6,1,1,2}}, + {{2,2,1,2,3,1,4,2}, {4,2,1,1,1,6,1,1}, {2,2,1,2,6,2,1,1}}, + {{1,1,2,1,4,1,3,4}, {3,2,1,1,2,1,1,6}, {1,1,2,2,1,1,3,6}}, + {{1,2,1,2,3,2,3,3}, {4,2,1,1,2,1,2,4}, {2,1,2,2,1,1,4,4}}, + {{2,2,1,2,3,2,4,1}, {5,2,1,1,2,1,3,2}, {3,1,2,2,1,1,5,2}}, + {{1,1,2,1,4,2,3,3}, {3,2,1,1,2,2,1,5}, {1,1,2,2,1,2,3,5}}, + {{2,1,2,1,4,2,4,1}, {4,2,1,1,2,2,2,3}, {2,1,2,2,1,2,4,3}}, + {{1,1,2,1,4,3,3,2}, {5,2,1,1,2,2,3,1}, {3,1,2,2,1,2,5,1}}, + {{1,2,1,2,4,1,4,2}, {3,2,1,1,2,3,1,4}, {1,1,2,2,1,3,3,4}}, + {{1,1,2,1,5,1,4,2}, {4,2,1,1,2,3,2,2}, {2,1,2,2,1,3,4,2}}, + {{1,2,1,2,4,2,4,1}, {3,2,1,1,2,4,1,3}, {1,1,2,2,1,4,3,3}}, + {{1,1,2,1,5,2,4,1}, {4,2,1,1,2,4,2,1}, {2,1,2,2,1,4,4,1}}, + {{3,1,2,2,1,1,2,5}, {3,2,1,1,2,5,1,2}, {1,1,2,2,1,5,3,2}}, + {{4,1,2,2,1,1,3,3}, {3,2,1,1,2,6,1,1}, {1,1,2,2,1,6,3,1}}, + {{5,1,2,2,1,1,4,1}, {2,2,1,1,3,1,1,6}, {1,2,1,3,1,1,4,4}}, + {{2,1,2,2,1,2,1,6}, {3,2,1,1,3,1,2,4}, {2,2,1,3,1,1,5,2}}, + {{3,1,2,2,1,2,2,4}, {4,2,1,1,3,1,3,2}, {1,1,2,2,2,1,4,4}}, + {{4,1,2,2,1,2,3,2}, {2,2,1,1,3,2,1,5}, {1,2,1,3,1,2,4,3}}, + {{2,1,2,2,1,3,1,5}, {3,2,1,1,3,2,2,3}, {2,2,1,3,1,2,5,1}}, + {{3,1,2,2,1,3,2,3}, {4,2,1,1,3,2,3,1}, {1,1,2,2,2,2,4,3}}, + {{4,1,2,2,1,3,3,1}, {2,2,1,1,3,3,1,4}, {2,1,2,2,2,2,5,1}}, + {{2,1,2,2,1,4,1,4}, {3,2,1,1,3,3,2,2}, {1,1,2,2,2,3,4,2}}, + {{3,1,2,2,1,4,2,2}, {2,2,1,1,3,4,1,3}, {1,2,1,3,1,4,4,1}}, + {{2,1,2,2,1,5,1,3}, {3,2,1,1,3,4,2,1}, {1,1,2,2,2,4,4,1}}, + {{2,1,2,2,1,6,1,2}, {2,2,1,1,3,5,1,2}, {6,2,1,3,2,1,1,1}}, + {{2,2,1,3,1,1,2,5}, {2,2,1,1,3,6,1,1}, {1,2,1,3,2,1,5,2}}, + {{3,2,1,3,1,1,3,3}, {1,2,1,1,4,1,1,6}, {6,1,2,2,3,1,1,1}}, + {{4,2,1,3,1,1,4,1}, {2,2,1,1,4,1,2,4}, {1,1,2,2,3,1,5,2}}, + {{2,1,2,2,2,1,2,5}, {3,2,1,1,4,1,3,2}, {1,2,1,3,2,2,5,1}}, + {{2,2,1,3,1,2,2,4}, {1,2,1,1,4,2,1,5}, {1,1,2,2,3,2,5,1}}, + {{3,2,1,3,1,2,3,2}, {2,2,1,1,4,2,2,3}, {5,2,1,3,3,1,1,1}}, + {{1,1,2,2,2,2,1,6}, {3,2,1,1,4,2,3,1}, {5,1,2,2,4,1,1,1}}, + {{1,2,1,3,1,3,1,5}, {1,2,1,1,4,3,1,4}, {4,2,1,3,4,1,1,1}}, + {{3,1,2,2,2,2,3,2}, {2,2,1,1,4,3,2,2}, {4,1,2,2,5,1,1,1}}, + {{3,2,1,3,1,3,3,1}, {1,2,1,1,4,4,1,3}, {3,2,1,3,5,1,1,1}}, + {{1,1,2,2,2,3,1,5}, {2,2,1,1,4,4,2,1}, {3,1,2,2,6,1,1,1}}, + {{1,2,1,3,1,4,1,4}, {1,2,1,1,4,5,1,2}, {2,2,1,3,6,1,1,1}}, + {{2,2,1,3,1,4,2,2}, {1,2,1,1,5,1,2,4}, {1,1,2,3,1,1,3,5}}, + {{1,1,2,2,2,4,1,4}, {2,2,1,1,5,1,3,2}, {2,1,2,3,1,1,4,3}}, + {{2,1,2,2,2,4,2,2}, {1,2,1,1,5,2,2,3}, {3,1,2,3,1,1,5,1}}, + {{2,2,1,3,1,5,2,1}, {2,2,1,1,5,2,3,1}, {1,1,2,3,1,2,3,4}}, + {{1,2,1,3,1,6,1,2}, {1,2,1,1,5,3,2,2}, {2,1,2,3,1,2,4,2}}, + {{1,2,1,3,2,1,2,5}, {1,2,1,1,5,4,2,1}, {1,1,2,3,1,3,3,3}}, + {{2,2,1,3,2,1,3,3}, {1,2,1,1,6,1,3,2}, {2,1,2,3,1,3,4,1}}, + {{3,2,1,3,2,1,4,1}, {1,2,1,1,6,2,3,1}, {1,1,2,3,1,4,3,2}}, + {{1,1,2,2,3,1,2,5}, {5,1,2,1,1,1,1,5}, {1,1,2,3,1,5,3,1}}, + {{1,2,1,3,2,2,2,4}, {6,1,2,1,1,1,2,3}, {1,2,1,4,1,1,4,3}}, + {{2,2,1,3,2,2,3,2}, {1,1,2,1,1,1,6,4}, {2,2,1,4,1,1,5,1}}, + {{1,1,2,2,3,2,2,4}, {5,1,2,1,1,2,1,4}, {1,1,2,3,2,1,4,3}}, + {{2,1,2,2,3,2,3,2}, {6,1,2,1,1,2,2,2}, {1,2,1,4,1,2,4,2}}, + {{2,2,1,3,2,3,3,1}, {1,1,2,1,1,2,6,3}, {1,1,2,3,2,2,4,2}}, + {{1,1,2,2,3,3,2,3}, {5,1,2,1,1,3,1,3}, {1,2,1,4,1,3,4,1}}, + {{1,2,1,3,2,4,2,2}, {6,1,2,1,1,3,2,1}, {1,1,2,3,2,3,4,1}}, + {{1,2,1,3,2,5,2,1}, {1,1,2,1,1,3,6,2}, {1,2,1,4,2,1,5,1}}, + {{1,2,1,3,3,1,3,3}, {5,1,2,1,1,4,1,2}, {1,1,2,3,3,1,5,1}}, + {{2,2,1,3,3,1,4,1}, {5,1,2,1,1,5,1,1}, {1,1,2,4,1,1,3,4}}, + {{1,1,2,2,4,1,3,3}, {4,2,1,2,1,1,1,5}, {2,1,2,4,1,1,4,2}}, + {{1,2,1,3,3,2,3,2}, {5,2,1,2,1,1,2,3}, {1,1,2,4,1,2,3,3}}, + {{1,1,2,2,4,2,3,2}, {6,2,1,2,1,1,3,1}, {2,1,2,4,1,2,4,1}}, + {{1,2,1,3,3,3,3,1}, {4,1,2,1,2,1,1,5}, {1,1,2,4,1,3,3,2}}, + {{1,1,2,2,4,3,3,1}, {4,2,1,2,1,2,1,4}, {1,1,2,4,1,4,3,1}}, + {{1,1,2,2,5,1,4,1}, {6,1,2,1,2,1,3,1}, {1,2,1,5,1,1,4,2}}, + {{2,1,2,3,1,1,1,6}, {4,1,2,1,2,2,1,4}, {1,1,2,4,2,1,4,2}}, + {{3,1,2,3,1,1,2,4}, {5,1,2,1,2,2,2,2}, {1,2,1,5,1,2,4,1}}, + {{4,1,2,3,1,1,3,2}, {5,2,1,2,1,3,2,1}, {1,1,2,4,2,2,4,1}}, + {{2,1,2,3,1,2,1,5}, {4,1,2,1,2,3,1,3}, {1,1,2,5,1,1,3,3}}, + {{3,1,2,3,1,2,2,3}, {4,2,1,2,1,4,1,2}, {2,1,2,5,1,1,4,1}}, + {{4,1,2,3,1,2,3,1}, {4,1,2,1,2,4,1,2}, {1,1,2,5,1,2,3,2}}, + {{2,1,2,3,1,3,1,4}, {4,2,1,2,1,5,1,1}, {1,1,2,5,1,3,3,1}}, + {{3,1,2,3,1,3,2,2}, {4,1,2,1,2,5,1,1}, {1,2,1,6,1,1,4,1}}, + {{2,1,2,3,1,4,1,3}, {3,2,1,2,2,1,1,5}, {1,1,2,5,2,1,4,1}}, + {{3,1,2,3,1,4,2,1}, {4,2,1,2,2,1,2,3}, {1,1,2,6,1,1,3,2}}, + {{2,1,2,3,1,5,1,2}, {5,2,1,2,2,1,3,1}, {1,1,2,6,1,2,3,1}}, + {{2,1,2,3,1,6,1,1}, {3,1,2,1,3,1,1,5}, {1,3,1,1,1,1,4,5}}, + {{1,2,1,4,1,1,1,6}, {3,2,1,2,2,2,1,4}, {2,3,1,1,1,1,5,3}}, + {{2,2,1,4,1,1,2,4}, {4,2,1,2,2,2,2,2}, {3,3,1,1,1,1,6,1}}, + {{3,2,1,4,1,1,3,2}, {3,1,2,1,3,2,1,4}, {1,3,1,1,1,2,4,4}}, + {{1,1,2,3,2,1,1,6}, {4,1,2,1,3,2,2,2}, {2,3,1,1,1,2,5,2}}, + {{1,2,1,4,1,2,1,5}, {4,2,1,2,2,3,2,1}, {1,3,1,1,1,3,4,3}}, + {{2,2,1,4,1,2,2,3}, {3,1,2,1,3,3,1,3}, {2,3,1,1,1,3,5,1}}, + {{3,2,1,4,1,2,3,1}, {3,2,1,2,2,4,1,2}, {1,3,1,1,1,4,4,2}}, + {{1,1,2,3,2,2,1,5}, {3,1,2,1,3,4,1,2}, {1,3,1,1,1,5,4,1}}, + {{2,1,2,3,2,2,2,3}, {3,2,1,2,2,5,1,1}, {6,3,1,1,2,1,1,2}}, + {{3,1,2,3,2,2,3,1}, {3,1,2,1,3,5,1,1}, {1,3,1,1,2,1,5,3}}, + {{1,1,2,3,2,3,1,4}, {2,2,1,2,3,1,1,5}, {2,3,1,1,2,1,6,1}}, + {{1,2,1,4,1,4,1,3}, {3,2,1,2,3,1,2,3}, {6,3,1,1,2,2,1,1}}, + {{2,2,1,4,1,4,2,1}, {4,2,1,2,3,1,3,1}, {1,3,1,1,2,2,5,2}}, + {{1,1,2,3,2,4,1,3}, {2,1,2,1,4,1,1,5}, {1,3,1,1,2,3,5,1}}, + {{2,1,2,3,2,4,2,1}, {2,2,1,2,3,2,1,4}, {5,3,1,1,3,1,1,2}}, + {{1,1,2,3,2,5,1,2}, {3,2,1,2,3,2,2,2}, {1,3,1,1,3,1,6,1}}, + {{1,2,1,4,2,1,2,4}, {2,1,2,1,4,2,1,4}, {5,3,1,1,3,2,1,1}}, + {{2,2,1,4,2,1,3,2}, {3,1,2,1,4,2,2,2}, {4,3,1,1,4,1,1,2}}, + {{1,1,2,3,3,1,2,4}, {3,2,1,2,3,3,2,1}, {4,3,1,1,4,2,1,1}}, + {{1,2,1,4,2,2,2,3}, {2,1,2,1,4,3,1,3}, {3,3,1,1,5,1,1,2}}, + {{2,2,1,4,2,2,3,1}, {2,2,1,2,3,4,1,2}, {3,3,1,1,5,2,1,1}}, + {{1,1,2,3,3,2,2,3}, {2,1,2,1,4,4,1,2}, {2,3,1,1,6,1,1,2}}, + {{2,1,2,3,3,2,3,1}, {2,2,1,2,3,5,1,1}, {2,3,1,1,6,2,1,1}}, + {{1,1,2,3,3,3,2,2}, {2,1,2,1,4,5,1,1}, {1,2,2,1,1,1,3,6}}, + {{1,2,1,4,2,4,2,1}, {1,2,1,2,4,1,1,5}, {2,2,2,1,1,1,4,4}}, + {{1,1,2,3,3,4,2,1}, {2,2,1,2,4,1,2,3}, {3,2,2,1,1,1,5,2}}, + {{1,1,2,3,4,1,3,2}, {3,2,1,2,4,1,3,1}, {1,2,2,1,1,2,3,5}}, + {{1,1,2,3,4,2,3,1}, {1,1,2,1,5,1,1,5}, {2,2,2,1,1,2,4,3}}, + {{2,1,2,4,1,1,1,5}, {1,2,1,2,4,2,1,4}, {3,2,2,1,1,2,5,1}}, + {{3,1,2,4,1,1,2,3}, {2,2,1,2,4,2,2,2}, {1,2,2,1,1,3,3,4}}, + {{4,1,2,4,1,1,3,1}, {1,1,2,1,5,2,1,4}, {2,2,2,1,1,3,4,2}}, + {{2,1,2,4,1,2,1,4}, {2,1,2,1,5,2,2,2}, {1,2,2,1,1,4,3,3}}, + {{3,1,2,4,1,2,2,2}, {2,2,1,2,4,3,2,1}, {2,2,2,1,1,4,4,1}}, + {{2,1,2,4,1,3,1,3}, {1,1,2,1,5,3,1,3}, {1,2,2,1,1,5,3,2}}, + {{3,1,2,4,1,3,2,1}, {1,2,1,2,4,4,1,2}, {1,2,2,1,1,6,3,1}}, + {{2,1,2,4,1,4,1,2}, {1,1,2,1,5,4,1,2}, {1,3,1,2,1,1,4,4}}, + {{2,1,2,4,1,5,1,1}, {1,2,1,2,4,5,1,1}, {2,3,1,2,1,1,5,2}}, + {{1,2,1,5,1,1,1,5}, {1,2,1,2,5,1,2,3}, {1,2,2,1,2,1,4,4}}, + {{2,2,1,5,1,1,2,3}, {2,2,1,2,5,1,3,1}, {1,3,1,2,1,2,4,3}}, + {{3,2,1,5,1,1,3,1}, {1,1,2,1,6,1,2,3}, {2,3,1,2,1,2,5,1}}, + {{1,1,2,4,2,1,1,5}, {1,2,1,2,5,2,2,2}, {1,2,2,1,2,2,4,3}}, + {{1,2,1,5,1,2,1,4}, {1,1,2,1,6,2,2,2}, {2,2,2,1,2,2,5,1}}, + {{2,2,1,5,1,2,2,2}, {1,2,1,2,5,3,2,1}, {1,2,2,1,2,3,4,2}}, + {{1,1,2,4,2,2,1,4}, {1,1,2,1,6,3,2,1}, {1,3,1,2,1,4,4,1}}, + {{2,1,2,4,2,2,2,2}, {1,2,1,2,6,1,3,1}, {1,2,2,1,2,4,4,1}}, + {{2,2,1,5,1,3,2,1}, {5,1,2,2,1,1,1,4}, {6,3,1,2,2,1,1,1}}, + {{1,1,2,4,2,3,1,3}, {6,1,2,2,1,1,2,2}, {1,3,1,2,2,1,5,2}}, + {{1,2,1,5,1,4,1,2}, {1,1,2,2,1,1,6,3}, {6,2,2,1,3,1,1,1}}, + {{1,1,2,4,2,4,1,2}, {5,1,2,2,1,2,1,3}, {1,2,2,1,3,1,5,2}}, + {{1,2,1,5,1,5,1,1}, {6,1,2,2,1,2,2,1}, {1,3,1,2,2,2,5,1}}, + {{1,2,1,5,2,1,2,3}, {1,1,2,2,1,2,6,2}, {1,2,2,1,3,2,5,1}}, + {{1,1,2,4,3,1,2,3}, {5,1,2,2,1,3,1,2}, {5,3,1,2,3,1,1,1}}, + {{1,1,2,4,3,2,2,2}, {1,1,2,2,1,3,6,1}, {5,2,2,1,4,1,1,1}}, + {{1,1,2,4,3,3,2,1}, {5,1,2,2,1,4,1,1}, {4,3,1,2,4,1,1,1}}, + {{3,1,2,5,1,1,2,2}, {4,2,1,3,1,1,1,4}, {4,2,2,1,5,1,1,1}}, + {{3,1,2,5,1,2,2,1}, {5,2,1,3,1,1,2,2}, {3,3,1,2,5,1,1,1}}, + {{2,1,2,5,1,4,1,1}, {4,1,2,2,2,1,1,4}, {3,2,2,1,6,1,1,1}}, + {{2,2,1,6,1,1,2,2}, {4,2,1,3,1,2,1,3}, {2,3,1,2,6,1,1,1}}, + {{1,2,1,6,1,2,1,3}, {5,2,1,3,1,2,2,1}, {2,1,3,1,1,1,3,5}}, + {{1,1,2,5,2,2,1,3}, {4,1,2,2,2,2,1,3}, {3,1,3,1,1,1,4,3}}, + {{1,1,2,5,2,3,1,2}, {5,1,2,2,2,2,2,1}, {4,1,3,1,1,1,5,1}}, + {{1,1,2,5,2,4,1,1}, {4,1,2,2,2,3,1,2}, {1,1,3,1,1,2,2,6}}, + {{2,3,1,1,1,1,2,6}, {4,2,1,3,1,4,1,1}, {2,1,3,1,1,2,3,4}}, + {{3,3,1,1,1,1,3,4}, {4,1,2,2,2,4,1,1}, {3,1,3,1,1,2,4,2}}, + {{4,3,1,1,1,1,4,2}, {3,2,1,3,2,1,1,4}, {1,1,3,1,1,3,2,5}}, + {{2,3,1,1,1,2,2,5}, {4,2,1,3,2,1,2,2}, {2,1,3,1,1,3,3,3}}, + {{3,3,1,1,1,2,3,3}, {3,1,2,2,3,1,1,4}, {3,1,3,1,1,3,4,1}}, + {{1,3,1,1,1,3,1,6}, {3,2,1,3,2,2,1,3}, {1,1,3,1,1,4,2,4}}, + {{2,3,1,1,1,3,2,4}, {4,2,1,3,2,2,2,1}, {2,1,3,1,1,4,3,2}}, + {{3,3,1,1,1,3,3,2}, {3,1,2,2,3,2,1,3}, {1,1,3,1,1,5,2,3}}, + {{1,3,1,1,1,4,1,5}, {4,1,2,2,3,2,2,1}, {2,1,3,1,1,5,3,1}}, + {{2,3,1,1,1,4,2,3}, {3,1,2,2,3,3,1,2}, {1,1,3,1,1,6,2,2}}, + {{1,3,1,1,1,5,1,4}, {3,2,1,3,2,4,1,1}, {1,2,2,2,1,1,3,5}}, + {{1,3,1,1,1,6,1,3}, {3,1,2,2,3,4,1,1}, {2,2,2,2,1,1,4,3}}, + {{1,3,1,1,2,1,2,6}, {2,2,1,3,3,1,1,4}, {3,2,2,2,1,1,5,1}}, + {{2,3,1,1,2,1,3,4}, {3,2,1,3,3,1,2,2}, {1,1,3,1,2,1,3,5}}, + {{3,3,1,1,2,1,4,2}, {2,1,2,2,4,1,1,4}, {1,2,2,2,1,2,3,4}}, + {{1,3,1,1,2,2,2,5}, {2,2,1,3,3,2,1,3}, {2,2,2,2,1,2,4,2}}, + {{2,3,1,1,2,2,3,3}, {3,2,1,3,3,2,2,1}, {1,1,3,1,2,2,3,4}}, + {{3,3,1,1,2,2,4,1}, {2,1,2,2,4,2,1,3}, {2,1,3,1,2,2,4,2}}, + {{1,3,1,1,2,3,2,4}, {3,1,2,2,4,2,2,1}, {2,2,2,2,1,3,4,1}}, + {{2,3,1,1,2,3,3,2}, {2,1,2,2,4,3,1,2}, {1,1,3,1,2,3,3,3}}, + {{1,3,1,1,2,4,2,3}, {2,2,1,3,3,4,1,1}, {1,2,2,2,1,4,3,2}}, + {{1,3,1,1,2,5,2,2}, {2,1,2,2,4,4,1,1}, {1,1,3,1,2,4,3,2}}, + {{1,3,1,1,3,1,3,4}, {1,2,1,3,4,1,1,4}, {1,2,2,2,1,5,3,1}}, + {{2,3,1,1,3,1,4,2}, {2,2,1,3,4,1,2,2}, {1,1,3,1,2,5,3,1}}, + {{1,3,1,1,3,2,3,3}, {1,1,2,2,5,1,1,4}, {1,3,1,3,1,1,4,3}}, + {{2,3,1,1,3,2,4,1}, {1,2,1,3,4,2,1,3}, {2,3,1,3,1,1,5,1}}, + {{1,3,1,1,3,3,3,2}, {2,2,1,3,4,2,2,1}, {1,2,2,2,2,1,4,3}}, + {{1,3,1,1,4,1,4,2}, {1,1,2,2,5,2,1,3}, {1,3,1,3,1,2,4,2}}, + {{1,3,1,1,4,2,4,1}, {2,1,2,2,5,2,2,1}, {1,1,3,1,3,1,4,3}}, + {{3,2,2,1,1,1,2,5}, {1,1,2,2,5,3,1,2}, {1,2,2,2,2,2,4,2}}, + {{4,2,2,1,1,1,3,3}, {1,2,1,3,4,4,1,1}, {1,3,1,3,1,3,4,1}}, + {{5,2,2,1,1,1,4,1}, {1,1,2,2,5,4,1,1}, {1,1,3,1,3,2,4,2}}, + {{2,2,2,1,1,2,1,6}, {1,2,1,3,5,1,2,2}, {1,2,2,2,2,3,4,1}}, + {{3,2,2,1,1,2,2,4}, {1,1,2,2,6,1,2,2}, {1,1,3,1,3,3,4,1}}, + {{4,2,2,1,1,2,3,2}, {1,2,1,3,5,2,2,1}, {1,3,1,3,2,1,5,1}}, + {{2,2,2,1,1,3,1,5}, {1,1,2,2,6,2,2,1}, {1,2,2,2,3,1,5,1}}, + {{3,2,2,1,1,3,2,3}, {5,1,2,3,1,1,1,3}, {1,1,3,1,4,1,5,1}}, + {{4,2,2,1,1,3,3,1}, {6,1,2,3,1,1,2,1}, {1,1,3,2,1,1,2,6}}, + {{2,2,2,1,1,4,1,4}, {1,1,2,3,1,1,6,2}, {2,1,3,2,1,1,3,4}}, + {{3,2,2,1,1,4,2,2}, {5,1,2,3,1,2,1,2}, {3,1,3,2,1,1,4,2}}, + {{2,2,2,1,1,5,1,3}, {1,1,2,3,1,2,6,1}, {1,1,3,2,1,2,2,5}}, + {{3,2,2,1,1,5,2,1}, {5,1,2,3,1,3,1,1}, {2,1,3,2,1,2,3,3}}, + {{2,3,1,2,1,1,2,5}, {4,2,1,4,1,1,1,3}, {3,1,3,2,1,2,4,1}}, + {{3,3,1,2,1,1,3,3}, {5,2,1,4,1,1,2,1}, {1,1,3,2,1,3,2,4}}, + {{4,3,1,2,1,1,4,1}, {4,1,2,3,2,1,1,3}, {2,1,3,2,1,3,3,2}}, + {{2,2,2,1,2,1,2,5}, {5,1,2,3,2,1,2,1}, {1,1,3,2,1,4,2,3}}, + {{2,3,1,2,1,2,2,4}, {4,1,2,3,2,2,1,2}, {2,1,3,2,1,4,3,1}}, + {{3,3,1,2,1,2,3,2}, {4,2,1,4,1,3,1,1}, {1,1,3,2,1,5,2,2}}, + {{1,2,2,1,2,2,1,6}, {4,1,2,3,2,3,1,1}, {1,1,3,2,1,6,2,1}}, + {{1,3,1,2,1,3,1,5}, {3,2,1,4,2,1,1,3}, {1,2,2,3,1,1,3,4}}, + {{3,2,2,1,2,2,3,2}, {4,2,1,4,2,1,2,1}, {2,2,2,3,1,1,4,2}}, + {{3,3,1,2,1,3,3,1}, {3,1,2,3,3,1,1,3}, {1,1,3,2,2,1,3,4}}, + {{1,2,2,1,2,3,1,5}, {3,2,1,4,2,2,1,2}, {1,2,2,3,1,2,3,3}}, + {{2,2,2,1,2,3,2,3}, {3,1,2,3,3,2,1,2}, {2,2,2,3,1,2,4,1}}, + {{2,3,1,2,1,4,2,2}, {3,2,1,4,2,3,1,1}, {1,1,3,2,2,2,3,3}}, + {{1,2,2,1,2,4,1,4}, {3,1,2,3,3,3,1,1}, {2,1,3,2,2,2,4,1}}, + {{1,3,1,2,1,5,1,3}, {2,2,1,4,3,1,1,3}, {1,1,3,2,2,3,3,2}}, + {{1,2,2,1,2,5,1,3}, {3,2,1,4,3,1,2,1}, {1,2,2,3,1,4,3,1}}, + {{1,3,1,2,2,1,2,5}, {2,1,2,3,4,1,1,3}, {1,1,3,2,2,4,3,1}}, + {{2,3,1,2,2,1,3,3}, {3,1,2,3,4,1,2,1}, {1,3,1,4,1,1,4,2}}, + {{3,3,1,2,2,1,4,1}, {2,1,2,3,4,2,1,2}, {1,2,2,3,2,1,4,2}}, + {{1,2,2,1,3,1,2,5}, {2,2,1,4,3,3,1,1}, {1,3,1,4,1,2,4,1}}, + {{1,3,1,2,2,2,2,4}, {2,1,2,3,4,3,1,1}, {1,1,3,2,3,1,4,2}}, + {{3,2,2,1,3,1,4,1}, {1,2,1,4,4,1,1,3}, {1,2,2,3,2,2,4,1}}, + {{1,2,2,1,3,2,2,4}, {2,2,1,4,4,1,2,1}, {1,1,3,2,3,2,4,1}}, + {{2,2,2,1,3,2,3,2}, {1,1,2,3,5,1,1,3}, {1,1,3,3,1,1,2,5}}, + {{2,3,1,2,2,3,3,1}, {1,2,1,4,4,2,1,2}, {2,1,3,3,1,1,3,3}}, + {{1,2,2,1,3,3,2,3}, {1,1,2,3,5,2,1,2}, {3,1,3,3,1,1,4,1}}, + {{1,3,1,2,2,4,2,2}, {1,2,1,4,4,3,1,1}, {1,1,3,3,1,2,2,4}}, + {{1,2,2,1,3,4,2,2}, {1,1,2,3,5,3,1,1}, {2,1,3,3,1,2,3,2}}, + {{1,3,1,2,3,1,3,3}, {1,2,1,4,5,1,2,1}, {1,1,3,3,1,3,2,3}}, + {{2,3,1,2,3,1,4,1}, {1,1,2,3,6,1,2,1}, {2,1,3,3,1,3,3,1}}, + {{1,2,2,1,4,1,3,3}, {5,1,2,4,1,1,1,2}, {1,1,3,3,1,4,2,2}}, + {{1,3,1,2,3,2,3,2}, {1,1,2,4,1,1,6,1}, {1,1,3,3,1,5,2,1}}, + {{1,2,2,1,4,2,3,2}, {5,1,2,4,1,2,1,1}, {1,2,2,4,1,1,3,3}}, + {{1,3,1,2,3,3,3,1}, {4,2,1,5,1,1,1,2}, {2,2,2,4,1,1,4,1}}, + {{1,3,1,2,4,1,4,1}, {4,1,2,4,2,1,1,2}, {1,1,3,3,2,1,3,3}}, + {{1,2,2,1,5,1,4,1}, {4,2,1,5,1,2,1,1}, {1,2,2,4,1,2,3,2}}, + {{3,1,3,1,1,1,1,6}, {4,1,2,4,2,2,1,1}, {1,1,3,3,2,2,3,2}}, + {{4,1,3,1,1,1,2,4}, {3,2,1,5,2,1,1,2}, {1,2,2,4,1,3,3,1}}, + {{5,1,3,1,1,1,3,2}, {3,1,2,4,3,1,1,2}, {1,1,3,3,2,3,3,1}}, + {{3,1,3,1,1,2,1,5}, {3,2,1,5,2,2,1,1}, {1,3,1,5,1,1,4,1}}, + {{4,1,3,1,1,2,2,3}, {3,1,2,4,3,2,1,1}, {1,2,2,4,2,1,4,1}}, + {{5,1,3,1,1,2,3,1}, {2,2,1,5,3,1,1,2}, {1,1,3,3,3,1,4,1}}, + {{3,1,3,1,1,3,1,4}, {2,1,2,4,4,1,1,2}, {1,1,3,4,1,1,2,4}}, + {{4,1,3,1,1,3,2,2}, {2,2,1,5,3,2,1,1}, {2,1,3,4,1,1,3,2}}, + {{3,1,3,1,1,4,1,3}, {2,1,2,4,4,2,1,1}, {1,1,3,4,1,2,2,3}}, + {{4,1,3,1,1,4,2,1}, {1,2,1,5,4,1,1,2}, {2,1,3,4,1,2,3,1}}, + {{3,1,3,1,1,5,1,2}, {1,1,2,4,5,1,1,2}, {1,1,3,4,1,3,2,2}}, + {{2,2,2,2,1,1,1,6}, {1,2,1,5,4,2,1,1}, {1,1,3,4,1,4,2,1}}, + {{3,2,2,2,1,1,2,4}, {1,1,2,4,5,2,1,1}, {1,2,2,5,1,1,3,2}}, + {{4,2,2,2,1,1,3,2}, {5,1,2,5,1,1,1,1}, {1,1,3,4,2,1,3,2}}, + {{2,1,3,1,2,1,1,6}, {4,2,1,6,1,1,1,1}, {1,2,2,5,1,2,3,1}}, + {{2,2,2,2,1,2,1,5}, {4,1,2,5,2,1,1,1}, {1,1,3,4,2,2,3,1}}, + {{4,1,3,1,2,1,3,2}, {3,2,1,6,2,1,1,1}, {1,1,3,5,1,1,2,3}}, + {{4,2,2,2,1,2,3,1}, {3,1,2,5,3,1,1,1}, {2,1,3,5,1,1,3,1}}, + {{2,1,3,1,2,2,1,5}, {2,2,1,6,3,1,1,1}, {1,1,3,5,1,2,2,2}}, + {{3,1,3,1,2,2,2,3}, {2,1,2,5,4,1,1,1}, {1,1,3,5,1,3,2,1}}, + {{4,1,3,1,2,2,3,1}, {4,3,1,1,1,1,1,5}, {1,2,2,6,1,1,3,1}}, + {{2,1,3,1,2,3,1,4}, {5,3,1,1,1,1,2,3}, {1,1,3,5,2,1,3,1}}, + {{2,2,2,2,1,4,1,3}, {6,3,1,1,1,1,3,1}, {1,1,3,6,1,1,2,2}}, + {{3,2,2,2,1,4,2,1}, {4,3,1,1,1,2,1,4}, {1,1,3,6,1,2,2,1}}, + {{2,1,3,1,2,4,1,3}, {5,3,1,1,1,2,2,2}, {1,4,1,1,1,1,4,4}}, + {{3,1,3,1,2,4,2,1}, {4,3,1,1,1,3,1,3}, {2,4,1,1,1,1,5,2}}, + {{2,2,2,2,1,6,1,1}, {5,3,1,1,1,3,2,1}, {1,4,1,1,1,2,4,3}}, + {{1,3,1,3,1,1,1,6}, {4,3,1,1,1,4,1,2}, {2,4,1,1,1,2,5,1}}, + {{2,3,1,3,1,1,2,4}, {4,3,1,1,1,5,1,1}, {1,4,1,1,1,3,4,2}}, + {{3,3,1,3,1,1,3,2}, {3,3,1,1,2,1,1,5}, {1,4,1,1,1,4,4,1}}, + {{1,2,2,2,2,1,1,6}, {4,3,1,1,2,1,2,3}, {1,4,1,1,2,1,5,2}}, + {{1,3,1,3,1,2,1,5}, {5,3,1,1,2,1,3,1}, {1,4,1,1,2,2,5,1}}, + {{2,3,1,3,1,2,2,3}, {3,3,1,1,2,2,1,4}, {5,4,1,1,3,1,1,1}}, + {{3,3,1,3,1,2,3,1}, {4,3,1,1,2,2,2,2}, {4,4,1,1,4,1,1,1}}, + {{1,1,3,1,3,1,1,6}, {3,3,1,1,2,3,1,3}, {3,4,1,1,5,1,1,1}}, + {{1,2,2,2,2,2,1,5}, {4,3,1,1,2,3,2,1}, {2,4,1,1,6,1,1,1}}, + {{2,2,2,2,2,2,2,3}, {3,3,1,1,2,4,1,2}, {1,3,2,1,1,1,3,5}}, + {{3,2,2,2,2,2,3,1}, {3,3,1,1,2,5,1,1}, {2,3,2,1,1,1,4,3}}, + {{1,1,3,1,3,2,1,5}, {2,3,1,1,3,1,1,5}, {3,3,2,1,1,1,5,1}}, + {{2,1,3,1,3,2,2,3}, {3,3,1,1,3,1,2,3}, {1,3,2,1,1,2,3,4}}, + {{3,1,3,1,3,2,3,1}, {4,3,1,1,3,1,3,1}, {2,3,2,1,1,2,4,2}}, + {{2,3,1,3,1,4,2,1}, {2,3,1,1,3,2,1,4}, {1,3,2,1,1,3,3,3}}, + {{1,1,3,1,3,3,1,4}, {3,3,1,1,3,2,2,2}, {2,3,2,1,1,3,4,1}}, + {{1,2,2,2,2,4,1,3}, {2,3,1,1,3,3,1,3}, {1,3,2,1,1,4,3,2}}, + {{2,2,2,2,2,4,2,1}, {3,3,1,1,3,3,2,1}, {1,3,2,1,1,5,3,1}}, + {{1,1,3,1,3,4,1,3}, {2,3,1,1,3,4,1,2}, {1,4,1,2,1,1,4,3}}, + {{1,3,1,3,1,6,1,1}, {2,3,1,1,3,5,1,1}, {2,4,1,2,1,1,5,1}}, + {{1,3,1,3,2,1,2,4}, {1,3,1,1,4,1,1,5}, {1,3,2,1,2,1,4,3}}, + {{2,3,1,3,2,1,3,2}, {2,3,1,1,4,1,2,3}, {1,4,1,2,1,2,4,2}}, + {{1,2,2,2,3,1,2,4}, {3,3,1,1,4,1,3,1}, {1,3,2,1,2,2,4,2}}, + {{1,3,1,3,2,2,2,3}, {1,3,1,1,4,2,1,4}, {1,4,1,2,1,3,4,1}}, + {{2,3,1,3,2,2,3,1}, {2,3,1,1,4,2,2,2}, {1,3,2,1,2,3,4,1}}, + {{1,1,3,1,4,1,2,4}, {1,3,1,1,4,3,1,3}, {1,4,1,2,2,1,5,1}}, + {{1,2,2,2,3,2,2,3}, {2,3,1,1,4,3,2,1}, {1,3,2,1,3,1,5,1}}, + {{2,2,2,2,3,2,3,1}, {1,3,1,1,4,4,1,2}, {1,2,3,1,1,1,2,6}}, + {{1,1,3,1,4,2,2,3}, {1,3,1,1,4,5,1,1}, {2,2,3,1,1,1,3,4}}, + {{2,1,3,1,4,2,3,1}, {1,3,1,1,5,1,2,3}, {3,2,3,1,1,1,4,2}}, + {{1,3,1,3,2,4,2,1}, {2,3,1,1,5,1,3,1}, {1,2,3,1,1,2,2,5}}, + {{1,2,2,2,3,4,2,1}, {1,3,1,1,5,2,2,2}, {2,2,3,1,1,2,3,3}}, + {{1,3,1,3,3,1,3,2}, {1,3,1,1,5,3,2,1}, {3,2,3,1,1,2,4,1}}, + {{1,2,2,2,4,1,3,2}, {1,3,1,1,6,1,3,1}, {1,2,3,1,1,3,2,4}}, + {{1,3,1,3,3,2,3,1}, {5,2,2,1,1,1,1,4}, {2,2,3,1,1,3,3,2}}, + {{1,1,3,1,5,1,3,2}, {6,2,2,1,1,1,2,2}, {1,2,3,1,1,4,2,3}}, + {{1,2,2,2,4,2,3,1}, {1,2,2,1,1,1,6,3}, {2,2,3,1,1,4,3,1}}, + {{3,1,3,2,1,1,1,5}, {5,2,2,1,1,2,1,3}, {1,2,3,1,1,5,2,2}}, + {{4,1,3,2,1,1,2,3}, {6,2,2,1,1,2,2,1}, {1,2,3,1,1,6,2,1}}, + {{5,1,3,2,1,1,3,1}, {1,2,2,1,1,2,6,2}, {1,3,2,2,1,1,3,4}}, + {{3,1,3,2,1,2,1,4}, {5,2,2,1,1,3,1,2}, {2,3,2,2,1,1,4,2}}, + {{4,1,3,2,1,2,2,2}, {1,2,2,1,1,3,6,1}, {1,2,3,1,2,1,3,4}}, + {{3,1,3,2,1,3,1,3}, {5,2,2,1,1,4,1,1}, {1,3,2,2,1,2,3,3}}, + {{4,1,3,2,1,3,2,1}, {4,3,1,2,1,1,1,4}, {2,3,2,2,1,2,4,1}}, + {{3,1,3,2,1,4,1,2}, {5,3,1,2,1,1,2,2}, {1,2,3,1,2,2,3,3}}, + {{3,1,3,2,1,5,1,1}, {4,2,2,1,2,1,1,4}, {1,3,2,2,1,3,3,2}}, + {{2,2,2,3,1,1,1,5}, {4,3,1,2,1,2,1,3}, {1,2,3,1,2,3,3,2}}, + {{3,2,2,3,1,1,2,3}, {5,3,1,2,1,2,2,1}, {1,3,2,2,1,4,3,1}}, + {{4,2,2,3,1,1,3,1}, {4,2,2,1,2,2,1,3}, {1,2,3,1,2,4,3,1}}, + {{2,1,3,2,2,1,1,5}, {5,2,2,1,2,2,2,1}, {1,4,1,3,1,1,4,2}}, + {{2,2,2,3,1,2,1,4}, {4,2,2,1,2,3,1,2}, {1,3,2,2,2,1,4,2}}, + {{4,1,3,2,2,1,3,1}, {4,3,1,2,1,4,1,1}, {1,4,1,3,1,2,4,1}}, + {{2,1,3,2,2,2,1,4}, {4,2,2,1,2,4,1,1}, {1,2,3,1,3,1,4,2}}, + {{3,1,3,2,2,2,2,2}, {3,3,1,2,2,1,1,4}, {1,3,2,2,2,2,4,1}}, + {{3,2,2,3,1,3,2,1}, {4,3,1,2,2,1,2,2}, {1,2,3,1,3,2,4,1}}, + {{2,1,3,2,2,3,1,3}, {3,2,2,1,3,1,1,4}, {2,1,4,1,1,1,2,5}}, + {{2,2,2,3,1,4,1,2}, {3,3,1,2,2,2,1,3}, {3,1,4,1,1,1,3,3}}, + {{2,1,3,2,2,4,1,2}, {4,3,1,2,2,2,2,1}, {4,1,4,1,1,1,4,1}}, + {{2,2,2,3,1,5,1,1}, {3,2,2,1,3,2,1,3}, {1,1,4,1,1,2,1,6}}, + {{2,1,3,2,2,5,1,1}, {4,2,2,1,3,2,2,1}, {2,1,4,1,1,2,2,4}}, + {{1,3,1,4,1,1,1,5}, {3,2,2,1,3,3,1,2}, {3,1,4,1,1,2,3,2}}, + {{2,3,1,4,1,1,2,3}, {3,3,1,2,2,4,1,1}, {1,1,4,1,1,3,1,5}}, + {{3,3,1,4,1,1,3,1}, {3,2,2,1,3,4,1,1}, {2,1,4,1,1,3,2,3}}, + {{1,2,2,3,2,1,1,5}, {2,3,1,2,3,1,1,4}, {3,1,4,1,1,3,3,1}}, + {{1,3,1,4,1,2,1,4}, {3,3,1,2,3,1,2,2}, {1,1,4,1,1,4,1,4}}, + {{2,3,1,4,1,2,2,2}, {2,2,2,1,4,1,1,4}, {2,1,4,1,1,4,2,2}}, + {{1,1,3,2,3,1,1,5}, {2,3,1,2,3,2,1,3}, {1,1,4,1,1,5,1,3}}, + {{1,2,2,3,2,2,1,4}, {3,3,1,2,3,2,2,1}, {2,1,4,1,1,5,2,1}}, + {{2,2,2,3,2,2,2,2}, {2,2,2,1,4,2,1,3}, {1,1,4,1,1,6,1,2}}, + {{2,3,1,4,1,3,2,1}, {3,2,2,1,4,2,2,1}, {1,2,3,2,1,1,2,5}}, + {{1,1,3,2,3,2,1,4}, {2,2,2,1,4,3,1,2}, {2,2,3,2,1,1,3,3}}, + {{2,1,3,2,3,2,2,2}, {2,3,1,2,3,4,1,1}, {3,2,3,2,1,1,4,1}}, + {{1,3,1,4,1,4,1,2}, {2,2,2,1,4,4,1,1}, {1,1,4,1,2,1,2,5}}, + {{1,1,3,2,3,3,1,3}, {1,3,1,2,4,1,1,4}, {1,2,3,2,1,2,2,4}}, + {{1,2,2,3,2,4,1,2}, {2,3,1,2,4,1,2,2}, {2,2,3,2,1,2,3,2}}, + {{1,3,1,4,1,5,1,1}, {1,2,2,1,5,1,1,4}, {1,1,4,1,2,2,2,4}}, + {{1,2,2,3,2,5,1,1}, {1,3,1,2,4,2,1,3}, {2,1,4,1,2,2,3,2}}, + {{1,3,1,4,2,1,2,3}, {2,3,1,2,4,2,2,1}, {2,2,3,2,1,3,3,1}}, + {{2,3,1,4,2,1,3,1}, {1,2,2,1,5,2,1,3}, {1,1,4,1,2,3,2,3}}, + {{1,2,2,3,3,1,2,3}, {2,2,2,1,5,2,2,1}, {1,2,3,2,1,4,2,2}}, + {{1,3,1,4,2,2,2,2}, {1,2,2,1,5,3,1,2}, {1,1,4,1,2,4,2,2}}, + {{1,1,3,2,4,1,2,3}, {1,3,1,2,4,4,1,1}, {1,2,3,2,1,5,2,1}}, + {{1,2,2,3,3,2,2,2}, {1,2,2,1,5,4,1,1}, {1,1,4,1,2,5,2,1}}, + {{1,3,1,4,2,3,2,1}, {1,3,1,2,5,1,2,2}, {1,3,2,3,1,1,3,3}}, + {{1,1,3,2,4,2,2,2}, {1,2,2,1,6,1,2,2}, {2,3,2,3,1,1,4,1}}, + {{1,2,2,3,3,3,2,1}, {1,3,1,2,5,2,2,1}, {1,2,3,2,2,1,3,3}}, + {{1,3,1,4,3,1,3,1}, {1,2,2,1,6,2,2,1}, {1,3,2,3,1,2,3,2}}, + {{1,1,3,2,5,1,3,1}, {6,1,3,1,1,1,1,3}, {1,1,4,1,3,1,3,3}}, + {{3,1,3,3,1,1,1,4}, {1,1,3,1,1,1,5,4}, {1,2,3,2,2,2,3,2}}, + {{4,1,3,3,1,1,2,2}, {2,1,3,1,1,1,6,2}, {1,3,2,3,1,3,3,1}}, + {{3,1,3,3,1,2,1,3}, {6,1,3,1,1,2,1,2}, {1,1,4,1,3,2,3,2}}, + {{4,1,3,3,1,2,2,1}, {1,1,3,1,1,2,5,3}, {1,2,3,2,2,3,3,1}}, + {{3,1,3,3,1,3,1,2}, {2,1,3,1,1,2,6,1}, {1,1,4,1,3,3,3,1}}, + {{3,1,3,3,1,4,1,1}, {6,1,3,1,1,3,1,1}, {1,4,1,4,1,1,4,1}}, + {{2,2,2,4,1,1,1,4}, {1,1,3,1,1,3,5,2}, {1,3,2,3,2,1,4,1}}, + {{3,2,2,4,1,1,2,2}, {1,1,3,1,1,4,5,1}, {1,2,3,2,3,1,4,1}}, + {{2,1,3,3,2,1,1,4}, {5,2,2,2,1,1,1,3}, {1,1,4,1,4,1,4,1}}, + {{2,2,2,4,1,2,1,3}, {6,2,2,2,1,1,2,1}, {1,1,4,2,1,1,1,6}}, + {{3,2,2,4,1,2,2,1}, {1,2,2,2,1,1,6,2}, {2,1,4,2,1,1,2,4}}, + {{2,1,3,3,2,2,1,3}, {5,1,3,1,2,1,1,3}, {3,1,4,2,1,1,3,2}}, + {{3,1,3,3,2,2,2,1}, {6,1,3,1,2,1,2,1}, {1,1,4,2,1,2,1,5}}, + {{2,1,3,3,2,3,1,2}, {1,1,3,1,2,1,6,2}, {2,1,4,2,1,2,2,3}}, + {{2,2,2,4,1,4,1,1}, {1,2,2,2,1,2,6,1}, {3,1,4,2,1,2,3,1}}, + {{2,1,3,3,2,4,1,1}, {5,1,3,1,2,2,1,2}, {1,1,4,2,1,3,1,4}}, + {{1,3,1,5,1,1,1,4}, {5,2,2,2,1,3,1,1}, {2,1,4,2,1,3,2,2}}, + {{2,3,1,5,1,1,2,2}, {1,1,3,1,2,2,6,1}, {1,1,4,2,1,4,1,3}}, + {{1,2,2,4,2,1,1,4}, {5,1,3,1,2,3,1,1}, {2,1,4,2,1,4,2,1}}, + {{1,3,1,5,1,2,1,3}, {4,3,1,3,1,1,1,3}, {1,1,4,2,1,5,1,2}}, + {{2,3,1,5,1,2,2,1}, {5,3,1,3,1,1,2,1}, {1,1,4,2,1,6,1,1}}, + {{1,1,3,3,3,1,1,4}, {4,2,2,2,2,1,1,3}, {1,2,3,3,1,1,2,4}}, + {{1,2,2,4,2,2,1,3}, {4,3,1,3,1,2,1,2}, {2,2,3,3,1,1,3,2}}, + {{2,2,2,4,2,2,2,1}, {4,1,3,1,3,1,1,3}, {1,1,4,2,2,1,2,4}}, + {{1,1,3,3,3,2,1,3}, {5,1,3,1,3,1,2,1}, {1,2,3,3,1,2,2,3}}, + {{2,1,3,3,3,2,2,1}, {4,3,1,3,1,3,1,1}, {2,2,3,3,1,2,3,1}}, + {{1,3,1,5,1,4,1,1}, {4,1,3,1,3,2,1,2}, {1,1,4,2,2,2,2,3}}, + {{1,1,3,3,3,3,1,2}, {4,2,2,2,2,3,1,1}, {2,1,4,2,2,2,3,1}}, + {{1,2,2,4,2,4,1,1}, {4,1,3,1,3,3,1,1}, {1,1,4,2,2,3,2,2}}, + {{1,1,3,3,3,4,1,1}, {3,3,1,3,2,1,1,3}, {1,2,3,3,1,4,2,1}}, + {{1,2,2,4,3,1,2,2}, {4,3,1,3,2,1,2,1}, {1,1,4,2,2,4,2,1}}, + {{1,1,3,3,4,1,2,2}, {3,2,2,2,3,1,1,3}, {1,3,2,4,1,1,3,2}}, + {{1,1,3,3,4,2,2,1}, {3,3,1,3,2,2,1,2}, {1,2,3,3,2,1,3,2}}, + {{4,1,3,4,1,1,2,1}, {3,1,3,1,4,1,1,3}, {1,3,2,4,1,2,3,1}}, + {{3,1,3,4,1,3,1,1}, {3,2,2,2,3,2,1,2}, {1,1,4,2,3,1,3,2}}, + {{3,2,2,5,1,1,2,1}, {3,3,1,3,2,3,1,1}, {1,2,3,3,2,2,3,1}}, + {{2,2,2,5,1,2,1,2}, {3,1,3,1,4,2,1,2}, {1,1,4,2,3,2,3,1}}, + {{2,2,2,5,1,3,1,1}, {3,2,2,2,3,3,1,1}, {1,1,4,3,1,1,1,5}}, + {{1,3,1,6,1,1,1,3}, {3,1,3,1,4,3,1,1}, {2,1,4,3,1,1,2,3}}, + {{1,2,2,5,2,1,1,3}, {2,3,1,3,3,1,1,3}, {3,1,4,3,1,1,3,1}}, + {{1,1,3,4,3,1,1,3}, {3,3,1,3,3,1,2,1}, {1,1,4,3,1,2,1,4}}, + {{1,3,1,6,1,3,1,1}, {2,2,2,2,4,1,1,3}, {2,1,4,3,1,2,2,2}}, + {{1,2,2,5,2,3,1,1}, {2,3,1,3,3,2,1,2}, {1,1,4,3,1,3,1,3}}, + {{2,4,1,1,1,1,2,5}, {2,1,3,1,5,1,1,3}, {2,1,4,3,1,3,2,1}}, + {{1,4,1,1,1,2,1,6}, {2,2,2,2,4,2,1,2}, {1,1,4,3,1,4,1,2}}, + {{2,4,1,1,1,2,2,4}, {2,3,1,3,3,3,1,1}, {1,1,4,3,1,5,1,1}}, + {{1,4,1,1,1,3,1,5}, {2,1,3,1,5,2,1,2}, {1,2,3,4,1,1,2,3}}, + {{2,4,1,1,1,3,2,3}, {2,2,2,2,4,3,1,1}, {2,2,3,4,1,1,3,1}}, + {{3,4,1,1,1,3,3,1}, {2,1,3,1,5,3,1,1}, {1,1,4,3,2,1,2,3}}, + {{1,4,1,1,1,4,1,4}, {1,3,1,3,4,1,1,3}, {1,2,3,4,1,2,2,2}}, + {{2,4,1,1,1,4,2,2}, {2,3,1,3,4,1,2,1}, {1,1,4,3,2,2,2,2}}, + {{1,4,1,1,1,5,1,3}, {1,2,2,2,5,1,1,3}, {1,2,3,4,1,3,2,1}}, + {{2,4,1,1,1,5,2,1}, {1,3,1,3,4,2,1,2}, {1,1,4,3,2,3,2,1}}, + {{1,4,1,1,2,1,2,5}, {1,1,3,1,6,1,1,3}, {1,3,2,5,1,1,3,1}}, + {{2,4,1,1,2,1,3,3}, {1,2,2,2,5,2,1,2}, {1,2,3,4,2,1,3,1}}, + {{3,4,1,1,2,1,4,1}, {1,3,1,3,4,3,1,1}, {1,1,4,3,3,1,3,1}}, + {{1,4,1,1,2,2,2,4}, {1,1,3,1,6,2,1,2}, {1,1,4,4,1,1,1,4}}, + {{2,4,1,1,2,2,3,2}, {1,2,2,2,5,3,1,1}, {2,1,4,4,1,1,2,2}}, + {{1,4,1,1,2,3,2,3}, {1,1,3,1,6,3,1,1}, {1,1,4,4,1,2,1,3}}, + {{2,4,1,1,2,3,3,1}, {1,3,1,3,5,1,2,1}, {2,1,4,4,1,2,2,1}}, + {{1,4,1,1,2,4,2,2}, {1,2,2,2,6,1,2,1}, {1,1,4,4,1,3,1,2}}, + {{1,4,1,1,2,5,2,1}, {6,1,3,2,1,1,1,2}, {1,1,4,4,1,4,1,1}}, + {{1,4,1,1,3,1,3,3}, {1,1,3,2,1,1,5,3}, {1,2,3,5,1,1,2,2}}, + {{2,4,1,1,3,1,4,1}, {2,1,3,2,1,1,6,1}, {1,1,4,4,2,1,2,2}}, + {{1,4,1,1,3,2,3,2}, {6,1,3,2,1,2,1,1}, {1,2,3,5,1,2,2,1}}, + {{1,4,1,1,3,3,3,1}, {1,1,3,2,1,2,5,2}, {1,1,4,4,2,2,2,1}}, + {{1,4,1,1,4,1,4,1}, {1,1,3,2,1,3,5,1}, {1,1,4,5,1,1,1,3}}, + {{2,3,2,1,1,1,1,6}, {5,2,2,3,1,1,1,2}, {2,1,4,5,1,1,2,1}}, + {{3,3,2,1,1,1,2,4}, {1,2,2,3,1,1,6,1}, {1,1,4,5,1,2,1,2}}, + {{4,3,2,1,1,1,3,2}, {5,1,3,2,2,1,1,2}, {1,1,4,5,1,3,1,1}}, + {{2,3,2,1,1,2,1,5}, {5,2,2,3,1,2,1,1}, {1,2,3,6,1,1,2,1}}, + {{3,3,2,1,1,2,2,3}, {1,1,3,2,2,1,6,1}, {1,1,4,5,2,1,2,1}}, + {{2,3,2,1,1,3,1,4}, {5,1,3,2,2,2,1,1}, {1,5,1,1,1,1,4,3}}, + {{3,3,2,1,1,3,2,2}, {4,3,1,4,1,1,1,2}, {2,5,1,1,1,1,5,1}}, + {{2,3,2,1,1,4,1,3}, {4,2,2,3,2,1,1,2}, {1,5,1,1,1,2,4,2}}, + {{3,3,2,1,1,4,2,1}, {4,3,1,4,1,2,1,1}, {1,5,1,1,1,3,4,1}}, + {{2,3,2,1,1,5,1,2}, {4,1,3,2,3,1,1,2}, {1,5,1,1,2,1,5,1}}, + {{1,4,1,2,1,1,1,6}, {4,2,2,3,2,2,1,1}, {1,4,2,1,1,1,3,4}}, + {{2,4,1,2,1,1,2,4}, {4,1,3,2,3,2,1,1}, {2,4,2,1,1,1,4,2}}, + {{3,4,1,2,1,1,3,2}, {3,3,1,4,2,1,1,2}, {1,4,2,1,1,2,3,3}}, + {{1,3,2,1,2,1,1,6}, {3,2,2,3,3,1,1,2}, {2,4,2,1,1,2,4,1}}, + {{1,4,1,2,1,2,1,5}, {3,3,1,4,2,2,1,1}, {1,4,2,1,1,3,3,2}}, + {{3,3,2,1,2,1,3,2}, {3,1,3,2,4,1,1,2}, {1,4,2,1,1,4,3,1}}, + {{3,4,1,2,1,2,3,1}, {3,2,2,3,3,2,1,1}, {1,5,1,2,1,1,4,2}}, + {{1,3,2,1,2,2,1,5}, {3,1,3,2,4,2,1,1}, {1,4,2,1,2,1,4,2}}, + {{2,3,2,1,2,2,2,3}, {2,3,1,4,3,1,1,2}, {1,5,1,2,1,2,4,1}}, + {{3,3,2,1,2,2,3,1}, {2,2,2,3,4,1,1,2}, {1,4,2,1,2,2,4,1}}, + {{1,3,2,1,2,3,1,4}, {2,3,1,4,3,2,1,1}, {1,3,3,1,1,1,2,5}}, + {{1,4,1,2,1,4,1,3}, {2,1,3,2,5,1,1,2}, {2,3,3,1,1,1,3,3}}, + {{2,4,1,2,1,4,2,1}, {2,2,2,3,4,2,1,1}, {3,3,3,1,1,1,4,1}}, + {{1,3,2,1,2,4,1,3}, {2,1,3,2,5,2,1,1}, {1,3,3,1,1,2,2,4}}, + {{2,3,2,1,2,4,2,1}, {1,3,1,4,4,1,1,2}, {2,3,3,1,1,2,3,2}}, + {{1,4,1,2,1,6,1,1}, {1,2,2,3,5,1,1,2}, {1,3,3,1,1,3,2,3}}, + {{1,4,1,2,2,1,2,4}, {1,3,1,4,4,2,1,1}, {2,3,3,1,1,3,3,1}}, + {{2,4,1,2,2,1,3,2}, {1,1,3,2,6,1,1,2}, {1,3,3,1,1,4,2,2}}, + {{1,3,2,1,3,1,2,4}, {1,2,2,3,5,2,1,1}, {1,3,3,1,1,5,2,1}}, + {{1,4,1,2,2,2,2,3}, {1,1,3,2,6,2,1,1}, {1,4,2,2,1,1,3,3}}, + {{2,4,1,2,2,2,3,1}, {6,1,3,3,1,1,1,1}, {2,4,2,2,1,1,4,1}}, + {{1,3,2,1,3,2,2,3}, {1,1,3,3,1,1,5,2}, {1,3,3,1,2,1,3,3}}, + {{2,3,2,1,3,2,3,1}, {1,1,3,3,1,2,5,1}, {1,4,2,2,1,2,3,2}}, + {{1,3,2,1,3,3,2,2}, {5,2,2,4,1,1,1,1}, {1,3,3,1,2,2,3,2}}, + {{1,4,1,2,2,4,2,1}, {5,1,3,3,2,1,1,1}, {1,4,2,2,1,3,3,1}}, + {{1,4,1,2,3,1,3,2}, {4,3,1,5,1,1,1,1}, {1,3,3,1,2,3,3,1}}, + {{1,3,2,1,4,1,3,2}, {4,2,2,4,2,1,1,1}, {1,5,1,3,1,1,4,1}}, + {{1,4,1,2,3,2,3,1}, {4,1,3,3,3,1,1,1}, {1,4,2,2,2,1,4,1}}, + {{1,3,2,1,4,2,3,1}, {3,3,1,5,2,1,1,1}, {1,3,3,1,3,1,4,1}}, + {{3,2,3,1,1,1,1,5}, {3,2,2,4,3,1,1,1}, {1,2,4,1,1,1,1,6}}, + {{4,2,3,1,1,1,2,3}, {3,1,3,3,4,1,1,1}, {2,2,4,1,1,1,2,4}}, + {{5,2,3,1,1,1,3,1}, {2,3,1,5,3,1,1,1}, {3,2,4,1,1,1,3,2}}, + {{3,2,3,1,1,2,1,4}, {2,2,2,4,4,1,1,1}, {1,2,4,1,1,2,1,5}}, + {{4,2,3,1,1,2,2,2}, {2,1,3,3,5,1,1,1}, {2,2,4,1,1,2,2,3}}, + {{3,2,3,1,1,3,1,3}, {1,3,1,5,4,1,1,1}, {3,2,4,1,1,2,3,1}}, + {{4,2,3,1,1,3,2,1}, {1,2,2,4,5,1,1,1}, {1,2,4,1,1,3,1,4}}, + {{3,2,3,1,1,4,1,2}, {1,1,3,3,6,1,1,1}, {2,2,4,1,1,3,2,2}}, + {{3,2,3,1,1,5,1,1}, {1,1,3,4,1,1,5,1}, {1,2,4,1,1,4,1,3}}, + {{2,3,2,2,1,1,1,5}, {4,4,1,1,1,1,1,4}, {2,2,4,1,1,4,2,1}}, + {{3,3,2,2,1,1,2,3}, {5,4,1,1,1,1,2,2}, {1,2,4,1,1,5,1,2}}, + {{2,2,3,1,2,1,1,5}, {4,4,1,1,1,2,1,3}, {1,2,4,1,1,6,1,1}}, + {{2,3,2,2,1,2,1,4}, {5,4,1,1,1,2,2,1}, {1,3,3,2,1,1,2,4}}, + {{3,3,2,2,1,2,2,2}, {4,4,1,1,1,3,1,2}, {2,3,3,2,1,1,3,2}}, + {{2,2,3,1,2,2,1,4}, {4,4,1,1,1,4,1,1}, {1,2,4,1,2,1,2,4}}, + {{3,2,3,1,2,2,2,2}, {3,4,1,1,2,1,1,4}, {1,3,3,2,1,2,2,3}}, + {{3,3,2,2,1,3,2,1}, {4,4,1,1,2,1,2,2}, {2,3,3,2,1,2,3,1}}, + {{2,2,3,1,2,3,1,3}, {3,4,1,1,2,2,1,3}, {1,2,4,1,2,2,2,3}}, + {{2,3,2,2,1,4,1,2}, {4,4,1,1,2,2,2,1}, {2,2,4,1,2,2,3,1}}, + {{2,2,3,1,2,4,1,2}, {3,4,1,1,2,3,1,2}, {1,2,4,1,2,3,2,2}}, + {{2,3,2,2,1,5,1,1}, {3,4,1,1,2,4,1,1}, {1,3,3,2,1,4,2,1}}, + {{2,2,3,1,2,5,1,1}, {2,4,1,1,3,1,1,4}, {1,2,4,1,2,4,2,1}}, + {{1,4,1,3,1,1,1,5}, {3,4,1,1,3,1,2,2}, {1,4,2,3,1,1,3,2}}, + {{2,4,1,3,1,1,2,3}, {2,4,1,1,3,2,1,3}, {1,3,3,2,2,1,3,2}}, + {{1,3,2,2,2,1,1,5}, {3,4,1,1,3,2,2,1}, {1,4,2,3,1,2,3,1}}, + {{1,4,1,3,1,2,1,4}, {2,4,1,1,3,3,1,2}, {1,2,4,1,3,1,3,2}}, + {{3,3,2,2,2,1,3,1}, {2,4,1,1,3,4,1,1}, {1,3,3,2,2,2,3,1}}, + {{1,2,3,1,3,1,1,5}, {1,4,1,1,4,1,1,4}, {1,2,4,1,3,2,3,1}}, + {{1,3,2,2,2,2,1,4}, {2,4,1,1,4,1,2,2}, {2,1,5,1,1,1,1,5}}, + {{2,3,2,2,2,2,2,2}, {1,4,1,1,4,2,1,3}, {3,1,5,1,1,1,2,3}}, + {{2,4,1,3,1,3,2,1}, {2,4,1,1,4,2,2,1}, {4,1,5,1,1,1,3,1}}, + {{1,2,3,1,3,2,1,4}, {1,4,1,1,4,3,1,2}, {2,1,5,1,1,2,1,4}}, + {{2,2,3,1,3,2,2,2}, {1,4,1,1,4,4,1,1}, {3,1,5,1,1,2,2,2}}, + {{1,4,1,3,1,4,1,2}, {1,4,1,1,5,1,2,2}, {2,1,5,1,1,3,1,3}}, + {{1,2,3,1,3,3,1,3}, {1,4,1,1,5,2,2,1}, {3,1,5,1,1,3,2,1}}, + {{1,3,2,2,2,4,1,2}, {5,3,2,1,1,1,1,3}, {2,1,5,1,1,4,1,2}}, + {{1,4,1,3,1,5,1,1}, {6,3,2,1,1,1,2,1}, {2,1,5,1,1,5,1,1}}, + {{1,3,2,2,2,5,1,1}, {1,3,2,1,1,1,6,2}, {1,2,4,2,1,1,1,5}}, + {{1,4,1,3,2,1,2,3}, {5,3,2,1,1,2,1,2}, {2,2,4,2,1,1,2,3}}, + {{2,4,1,3,2,1,3,1}, {1,3,2,1,1,2,6,1}, {3,2,4,2,1,1,3,1}}, + {{1,3,2,2,3,1,2,3}, {5,3,2,1,1,3,1,1}, {1,1,5,1,2,1,1,5}}, + {{1,4,1,3,2,2,2,2}, {4,4,1,2,1,1,1,3}, {1,2,4,2,1,2,1,4}}, + {{1,2,3,1,4,1,2,3}, {5,4,1,2,1,1,2,1}, {2,2,4,2,1,2,2,2}}, + {{1,3,2,2,3,2,2,2}, {4,3,2,1,2,1,1,3}, {1,1,5,1,2,2,1,4}}, + {{1,4,1,3,2,3,2,1}, {4,4,1,2,1,2,1,2}, {2,1,5,1,2,2,2,2}}, + {{1,2,3,1,4,2,2,2}, {4,3,2,1,2,2,1,2}, {2,2,4,2,1,3,2,1}}, + {{1,3,2,2,3,3,2,1}, {4,4,1,2,1,3,1,1}, {1,1,5,1,2,3,1,3}}, + {{1,4,1,3,3,1,3,1}, {4,3,2,1,2,3,1,1}, {1,2,4,2,1,4,1,2}}, + {{1,3,2,2,4,1,3,1}, {3,4,1,2,2,1,1,3}, {1,1,5,1,2,4,1,2}}, + {{1,2,3,1,5,1,3,1}, {4,4,1,2,2,1,2,1}, {1,2,4,2,1,5,1,1}}, + {{4,1,4,1,1,1,1,4}, {3,3,2,1,3,1,1,3}, {1,1,5,1,2,5,1,1}}, + {{5,1,4,1,1,1,2,2}, {3,4,1,2,2,2,1,2}, {1,3,3,3,1,1,2,3}}, + {{4,1,4,1,1,2,1,3}, {3,3,2,1,3,2,1,2}, {2,3,3,3,1,1,3,1}}, + {{5,1,4,1,1,2,2,1}, {3,4,1,2,2,3,1,1}, {1,2,4,2,2,1,2,3}}, + {{4,1,4,1,1,3,1,2}, {3,3,2,1,3,3,1,1}, {1,3,3,3,1,2,2,2}}, + {{4,1,4,1,1,4,1,1}, {2,4,1,2,3,1,1,3}, {1,1,5,1,3,1,2,3}}, + {{3,2,3,2,1,1,1,4}, {3,4,1,2,3,1,2,1}, {1,2,4,2,2,2,2,2}}, + {{4,2,3,2,1,1,2,2}, {2,3,2,1,4,1,1,3}, {1,3,3,3,1,3,2,1}}, + {{3,1,4,1,2,1,1,4}, {2,4,1,2,3,2,1,2}, {1,1,5,1,3,2,2,2}}, + {{4,1,4,1,2,1,2,2}, {2,3,2,1,4,2,1,2}, {1,2,4,2,2,3,2,1}}, + {{4,2,3,2,1,2,2,1}, {2,4,1,2,3,3,1,1}, {1,1,5,1,3,3,2,1}}, + {{3,1,4,1,2,2,1,3}, {2,3,2,1,4,3,1,1}, {1,4,2,4,1,1,3,1}}, + {{4,1,4,1,2,2,2,1}, {1,4,1,2,4,1,1,3}, {1,3,3,3,2,1,3,1}}, + {{3,1,4,1,2,3,1,2}, {2,4,1,2,4,1,2,1}, {1,2,4,2,3,1,3,1}}, + {{3,2,3,2,1,4,1,1}, {1,3,2,1,5,1,1,3}, {1,1,5,1,4,1,3,1}}, + {{3,1,4,1,2,4,1,1}, {1,4,1,2,4,2,1,2}, {2,1,5,2,1,1,1,4}}, + {{2,3,2,3,1,1,1,4}, {1,3,2,1,5,2,1,2}, {3,1,5,2,1,1,2,2}}, + {{3,3,2,3,1,1,2,2}, {1,4,1,2,4,3,1,1}, {2,1,5,2,1,2,1,3}}, + {{2,2,3,2,2,1,1,4}, {1,3,2,1,5,3,1,1}, {3,1,5,2,1,2,2,1}}, + {{2,3,2,3,1,2,1,3}, {1,4,1,2,5,1,2,1}, {2,1,5,2,1,3,1,2}}, + {{3,3,2,3,1,2,2,1}, {1,3,2,1,6,1,2,1}, {2,1,5,2,1,4,1,1}}, + {{2,1,4,1,3,1,1,4}, {6,2,3,1,1,1,1,2}, {1,2,4,3,1,1,1,4}}, + {{2,2,3,2,2,2,1,3}, {1,2,3,1,1,1,5,3}, {2,2,4,3,1,1,2,2}}, + {{3,2,3,2,2,2,2,1}, {2,2,3,1,1,1,6,1}, {1,1,5,2,2,1,1,4}}, + {{2,1,4,1,3,2,1,3}, {6,2,3,1,1,2,1,1}, {1,2,4,3,1,2,1,3}}, + {{3,1,4,1,3,2,2,1}, {1,2,3,1,1,2,5,2}, {2,2,4,3,1,2,2,1}}, + {{2,3,2,3,1,4,1,1}, {1,2,3,1,1,3,5,1}, {1,1,5,2,2,2,1,3}}, + {{2,1,4,1,3,3,1,2}, {5,3,2,2,1,1,1,2}, {2,1,5,2,2,2,2,1}}, + {{2,2,3,2,2,4,1,1}, {1,3,2,2,1,1,6,1}, {1,1,5,2,2,3,1,2}}, + {{2,1,4,1,3,4,1,1}, {5,2,3,1,2,1,1,2}, {1,2,4,3,1,4,1,1}}, + {{1,4,1,4,1,1,1,4}, {5,3,2,2,1,2,1,1}, {1,1,5,2,2,4,1,1}}, + {{2,4,1,4,1,1,2,2}, {1,2,3,1,2,1,6,1}, {1,3,3,4,1,1,2,2}}, + {{1,3,2,3,2,1,1,4}, {5,2,3,1,2,2,1,1}, {1,2,4,3,2,1,2,2}}, + {{1,4,1,4,1,2,1,3}, {4,4,1,3,1,1,1,2}, {1,3,3,4,1,2,2,1}}, + {{2,4,1,4,1,2,2,1}, {4,3,2,2,2,1,1,2}, {1,1,5,2,3,1,2,2}}, + {{1,2,3,2,3,1,1,4}, {4,4,1,3,1,2,1,1}, {1,2,4,3,2,2,2,1}}, + {{1,3,2,3,2,2,1,3}, {4,2,3,1,3,1,1,2}, {1,1,5,2,3,2,2,1}}, + {{2,3,2,3,2,2,2,1}, {4,3,2,2,2,2,1,1}, {2,1,5,3,1,1,1,3}}, + {{1,1,4,1,4,1,1,4}, {4,2,3,1,3,2,1,1}, {3,1,5,3,1,1,2,1}}, + {{1,2,3,2,3,2,1,3}, {3,4,1,3,2,1,1,2}, {2,1,5,3,1,2,1,2}}, + {{2,2,3,2,3,2,2,1}, {3,3,2,2,3,1,1,2}, {2,1,5,3,1,3,1,1}}, + {{1,4,1,4,1,4,1,1}, {3,4,1,3,2,2,1,1}, {1,2,4,4,1,1,1,3}}, + {{1,1,4,1,4,2,1,3}, {3,2,3,1,4,1,1,2}, {2,2,4,4,1,1,2,1}}, + {{2,1,4,1,4,2,2,1}, {3,3,2,2,3,2,1,1}, {1,1,5,3,2,1,1,3}}, + {{1,3,2,3,2,4,1,1}, {3,2,3,1,4,2,1,1}, {1,2,4,4,1,2,1,2}}, + {{1,1,4,1,4,3,1,2}, {2,4,1,3,3,1,1,2}, {1,1,5,3,2,2,1,2}}, + {{1,4,1,4,2,1,2,2}, {2,3,2,2,4,1,1,2}, {1,2,4,4,1,3,1,1}}, + {{1,3,2,3,3,1,2,2}, {2,4,1,3,3,2,1,1}, {1,1,5,3,2,3,1,1}}, + {{1,4,1,4,2,2,2,1}, {2,2,3,1,5,1,1,2}, {1,3,3,5,1,1,2,1}}, + {{1,2,3,2,4,1,2,2}, {2,3,2,2,4,2,1,1}, {1,2,4,4,2,1,2,1}}, + {{1,3,2,3,3,2,2,1}, {2,2,3,1,5,2,1,1}, {1,1,5,3,3,1,2,1}}, + {{1,1,4,1,5,1,2,2}, {1,4,1,3,4,1,1,2}, {2,1,5,4,1,1,1,2}}, + {{1,2,3,2,4,2,2,1}, {1,3,2,2,5,1,1,2}, {2,1,5,4,1,2,1,1}}, + {{1,1,4,1,5,2,2,1}, {1,4,1,3,4,2,1,1}, {1,2,4,5,1,1,1,2}}, + {{4,1,4,2,1,1,1,3}, {1,2,3,1,6,1,1,2}, {1,1,5,4,2,1,1,2}}, + {{5,1,4,2,1,1,2,1}, {1,3,2,2,5,2,1,1}, {1,2,4,5,1,2,1,1}}, + {{4,1,4,2,1,2,1,2}, {1,2,3,1,6,2,1,1}, {1,1,5,4,2,2,1,1}}, + {{4,1,4,2,1,3,1,1}, {1,1,4,1,1,1,4,4}, {1,6,1,1,1,1,4,2}}, + {{3,2,3,3,1,1,1,3}, {2,1,4,1,1,1,5,2}, {1,6,1,1,1,2,4,1}}, + {{4,2,3,3,1,1,2,1}, {1,1,4,1,1,2,4,3}, {1,5,2,1,1,1,3,3}}, + {{3,1,4,2,2,1,1,3}, {2,1,4,1,1,2,5,1}, {2,5,2,1,1,1,4,1}}, + {{4,1,4,2,2,1,2,1}, {1,1,4,1,1,3,4,2}, {1,5,2,1,1,2,3,2}}, + {{3,1,4,2,2,2,1,2}, {1,1,4,1,1,4,4,1}, {1,5,2,1,1,3,3,1}}, + {{3,2,3,3,1,3,1,1}, {6,2,3,2,1,1,1,1}, {1,6,1,2,1,1,4,1}}, + {{3,1,4,2,2,3,1,1}, {1,2,3,2,1,1,5,2}, {1,5,2,1,2,1,4,1}}, + {{2,3,2,4,1,1,1,3}, {6,1,4,1,2,1,1,1}, {1,4,3,1,1,1,2,4}}, + {{3,3,2,4,1,1,2,1}, {1,1,4,1,2,1,5,2}, {2,4,3,1,1,1,3,2}}, + {{2,2,3,3,2,1,1,3}, {1,2,3,2,1,2,5,1}, {1,4,3,1,1,2,2,3}}, + {{2,3,2,4,1,2,1,2}, {1,1,4,1,2,2,5,1}, {2,4,3,1,1,2,3,1}}, + {{2,1,4,2,3,1,1,3}, {5,3,2,3,1,1,1,1}, {1,4,3,1,1,3,2,2}}, + {{2,2,3,3,2,2,1,2}, {5,2,3,2,2,1,1,1}, {1,4,3,1,1,4,2,1}}, + {{2,3,2,4,1,3,1,1}, {5,1,4,1,3,1,1,1}, {1,5,2,2,1,1,3,2}}, + {{2,1,4,2,3,2,1,2}, {4,4,1,4,1,1,1,1}, {1,4,3,1,2,1,3,2}}, + {{2,2,3,3,2,3,1,1}, {4,3,2,3,2,1,1,1}, {1,5,2,2,1,2,3,1}}, + {{2,1,4,2,3,3,1,1}, {4,2,3,2,3,1,1,1}, {1,4,3,1,2,2,3,1}}, + {{1,4,1,5,1,1,1,3}, {4,1,4,1,4,1,1,1}, {1,3,4,1,1,1,1,5}}, + {{2,4,1,5,1,1,2,1}, {3,4,1,4,2,1,1,1}, {2,3,4,1,1,1,2,3}}, + {{1,3,2,4,2,1,1,3}, {3,3,2,3,3,1,1,1}, {3,3,4,1,1,1,3,1}}, + {{2,3,2,4,2,1,2,1}, {3,2,3,2,4,1,1,1}, {1,3,4,1,1,2,1,4}}, + {{1,2,3,3,3,1,1,3}, {3,1,4,1,5,1,1,1}, {2,3,4,1,1,2,2,2}}, + {{1,3,2,4,2,2,1,2}, {2,4,1,4,3,1,1,1}, {1,3,4,1,1,3,1,3}}, + {{1,4,1,5,1,3,1,1}, {2,3,2,3,4,1,1,1}, {2,3,4,1,1,3,2,1}}, + {{1,1,4,2,4,1,1,3}, {2,2,3,2,5,1,1,1}, {1,3,4,1,1,4,1,2}}, + {{1,2,3,3,3,2,1,2}, {2,1,4,1,6,1,1,1}, {1,3,4,1,1,5,1,1}}, + {{1,3,2,4,2,3,1,1}, {1,4,1,4,4,1,1,1}, {1,4,3,2,1,1,2,3}}, + {{1,1,4,2,4,2,1,2}, {1,3,2,3,5,1,1,1}, {2,4,3,2,1,1,3,1}}, + {{1,2,3,3,3,3,1,1}, {1,2,3,2,6,1,1,1}, {1,3,4,1,2,1,2,3}}, + {{1,1,4,2,4,3,1,1}, {1,1,4,2,1,1,4,3}, {2,3,4,1,2,1,3,1}}, + {{1,3,2,4,3,1,2,1}, {2,1,4,2,1,1,5,1}, {1,3,4,1,2,2,2,2}}, + {{1,1,4,2,5,1,2,1}, {1,1,4,2,1,2,4,2}, {1,4,3,2,1,3,2,1}}, + {{4,1,4,3,1,2,1,1}, {1,1,4,2,1,3,4,1}, {1,3,4,1,2,3,2,1}}, + {{3,1,4,3,2,1,1,2}, {1,2,3,3,1,1,5,1}, {1,5,2,3,1,1,3,1}}, + {{3,1,4,3,2,2,1,1}, {1,1,4,2,2,1,5,1}, {1,4,3,2,2,1,3,1}}, + {{2,2,3,4,2,1,1,2}, {1,1,4,3,1,1,4,2}, {1,3,4,1,3,1,3,1}}, + {{2,1,4,3,3,1,1,2}, {1,1,4,3,1,2,4,1}, {2,2,5,1,1,1,1,4}}, + {{2,1,4,3,3,2,1,1}, {1,1,4,4,1,1,4,1}, {3,2,5,1,1,1,2,2}}, + {{1,3,2,5,2,1,1,2}, {4,5,1,1,1,1,1,3}, {2,2,5,1,1,2,1,3}}, + {{1,2,3,4,3,1,1,2}, {4,5,1,1,1,2,1,2}, {3,2,5,1,1,2,2,1}}, + {{1,1,4,3,4,1,1,2}, {4,5,1,1,1,3,1,1}, {2,2,5,1,1,3,1,2}}, + {{1,1,4,3,4,2,1,1}, {3,5,1,1,2,1,1,3}, {2,2,5,1,1,4,1,1}}, + {{1,5,1,1,1,1,1,6}, {4,5,1,1,2,1,2,1}, {1,3,4,2,1,1,1,4}}, + {{1,5,1,1,1,2,1,5}, {3,5,1,1,2,2,1,2}, {2,3,4,2,1,1,2,2}}, + {{2,5,1,1,1,2,2,3}, {3,5,1,1,2,3,1,1}, {1,2,5,1,2,1,1,4}}, + {{1,5,1,1,1,3,1,4}, {2,5,1,1,3,1,1,3}, {2,2,5,1,2,1,2,2}}, + {{1,5,1,1,1,4,1,3}, {3,5,1,1,3,1,2,1}, {2,3,4,2,1,2,2,1}}, + {{1,5,1,1,1,5,1,2}, {2,5,1,1,3,2,1,2}, {1,2,5,1,2,2,1,3}}, + {{1,5,1,1,2,1,2,4}, {2,5,1,1,3,3,1,1}, {1,3,4,2,1,3,1,2}}, + {{1,5,1,1,2,2,2,3}, {1,5,1,1,4,1,1,3}, {1,2,5,1,2,3,1,2}}, + {{1,5,1,1,2,3,2,2}, {2,5,1,1,4,1,2,1}, {1,3,4,2,1,4,1,1}}, + {{1,5,1,1,2,4,2,1}, {1,5,1,1,4,2,1,2}, {1,2,5,1,2,4,1,1}}, + {{1,5,1,1,3,1,3,2}, {1,5,1,1,4,3,1,1}, {1,4,3,3,1,1,2,2}}, + {{1,5,1,1,3,2,3,1}, {1,5,1,1,5,1,2,1}, {1,3,4,2,2,1,2,2}}, + {{2,4,2,1,1,1,1,5}, {5,4,2,1,1,1,1,2}, {1,4,3,3,1,2,2,1}}, + {{2,4,2,1,1,2,1,4}, {1,4,2,1,1,1,6,1}, {1,2,5,1,3,1,2,2}}, + {{3,4,2,1,1,2,2,2}, {5,4,2,1,1,2,1,1}, {1,3,4,2,2,2,2,1}}, + {{2,4,2,1,1,3,1,3}, {4,5,1,2,1,1,1,2}, {1,2,5,1,3,2,2,1}}, + {{3,4,2,1,1,3,2,1}, {4,4,2,1,2,1,1,2}, {3,1,6,1,1,1,1,3}}, + {{2,4,2,1,1,4,1,2}, {4,5,1,2,1,2,1,1}, {4,1,6,1,1,1,2,1}}, + {{2,4,2,1,1,5,1,1}, {4,4,2,1,2,2,1,1}, {3,1,6,1,1,2,1,2}}, + {{1,5,1,2,1,1,1,5}, {3,5,1,2,2,1,1,2}, {3,1,6,1,1,3,1,1}}, + {{2,5,1,2,1,1,2,3}, {3,4,2,1,3,1,1,2}, {2,2,5,2,1,1,1,3}}, + {{1,4,2,1,2,1,1,5}, {3,5,1,2,2,2,1,1}, {3,2,5,2,1,1,2,1}}, + {{2,4,2,1,2,1,2,3}, {3,4,2,1,3,2,1,1}, {2,1,6,1,2,1,1,3}}, + {{2,5,1,2,1,2,2,2}, {2,5,1,2,3,1,1,2}, {2,2,5,2,1,2,1,2}}, + {{1,4,2,1,2,2,1,4}, {2,4,2,1,4,1,1,2}, {2,1,6,1,2,2,1,2}}, + {{2,4,2,1,2,2,2,2}, {2,5,1,2,3,2,1,1}, {2,2,5,2,1,3,1,1}}, + {{1,4,2,1,2,3,1,3}, {2,4,2,1,4,2,1,1}, {2,1,6,1,2,3,1,1}}, + {{2,4,2,1,2,3,2,1}, {1,5,1,2,4,1,1,2}, {1,3,4,3,1,1,1,3}}, + {{1,4,2,1,2,4,1,2}, {1,4,2,1,5,1,1,2}, {2,3,4,3,1,1,2,1}}, + {{1,5,1,2,1,5,1,1}, {1,5,1,2,4,2,1,1}, {1,2,5,2,2,1,1,3}}, + {{1,4,2,1,2,5,1,1}, {1,4,2,1,5,2,1,1}, {1,3,4,3,1,2,1,2}}, + {{1,5,1,2,2,1,2,3}, {6,3,3,1,1,1,1,1}, {1,1,6,1,3,1,1,3}}, + {{2,5,1,2,2,1,3,1}, {1,3,3,1,1,1,5,2}, {1,2,5,2,2,2,1,2}}, + {{1,4,2,1,3,1,2,3}, {1,3,3,1,1,2,5,1}, {1,3,4,3,1,3,1,1}}, + {{2,4,2,1,3,1,3,1}, {5,4,2,2,1,1,1,1}, {1,1,6,1,3,2,1,2}}, + {{1,4,2,1,3,2,2,2}, {5,3,3,1,2,1,1,1}, {1,2,5,2,2,3,1,1}}, + {{1,5,1,2,2,3,2,1}, {4,5,1,3,1,1,1,1}, {1,1,6,1,3,3,1,1}}, + {{1,4,2,1,3,3,2,1}, {4,4,2,2,2,1,1,1}, {1,4,3,4,1,1,2,1}}, + {{1,5,1,2,3,1,3,1}, {4,3,3,1,3,1,1,1}, {1,3,4,3,2,1,2,1}}, + {{1,4,2,1,4,1,3,1}, {3,5,1,3,2,1,1,1}, {1,2,5,2,3,1,2,1}}, + {{3,3,3,1,1,1,1,4}, {3,4,2,2,3,1,1,1}, {1,1,6,1,4,1,2,1}}, + {{3,3,3,1,1,2,1,3}, {3,3,3,1,4,1,1,1}, {3,1,6,2,1,1,1,2}}, + {{3,3,3,1,1,3,1,2}, {2,5,1,3,3,1,1,1}, {3,1,6,2,1,2,1,1}}, + {{3,3,3,1,1,4,1,1}, {2,4,2,2,4,1,1,1}, {2,2,5,3,1,1,1,2}}, + {{2,4,2,2,1,1,1,4}, {2,3,3,1,5,1,1,1}, {2,1,6,2,2,1,1,2}}, + {{2,3,3,1,2,1,1,4}, {1,5,1,3,4,1,1,1}, {2,2,5,3,1,2,1,1}}, + {{3,3,3,1,2,1,2,2}, {1,4,2,2,5,1,1,1}, {2,1,6,2,2,2,1,1}}, + {{3,4,2,2,1,2,2,1}, {1,3,3,1,6,1,1,1}, {1,3,4,4,1,1,1,2}}, + {{2,3,3,1,2,2,1,3}, {1,2,4,1,1,1,4,3}, {1,2,5,3,2,1,1,2}}, + {{3,3,3,1,2,2,2,1}, {2,2,4,1,1,1,5,1}, {1,3,4,4,1,2,1,1}}, + {{2,3,3,1,2,3,1,2}, {1,2,4,1,1,2,4,2}, {1,1,6,2,3,1,1,2}}, + {{2,4,2,2,1,4,1,1}, {1,2,4,1,1,3,4,1}, {1,2,5,3,2,2,1,1}}, + {{2,3,3,1,2,4,1,1}, {1,3,3,2,1,1,5,1}, {1,1,6,2,3,2,1,1}}, + {{1,5,1,3,1,1,1,4}, {1,2,4,1,2,1,5,1}, {3,1,6,3,1,1,1,1}}, + {{1,4,2,2,2,1,1,4}, {1,1,5,1,1,1,3,4}, {2,2,5,4,1,1,1,1}}, + {{1,5,1,3,1,2,1,3}, {2,1,5,1,1,1,4,2}, {2,1,6,3,2,1,1,1}}, + {{2,5,1,3,1,2,2,1}, {1,1,5,1,1,2,3,3}, {1,3,4,5,1,1,1,1}}, + {{1,3,3,1,3,1,1,4}, {2,1,5,1,1,2,4,1}, {1,2,5,4,2,1,1,1}}, + {{1,4,2,2,2,2,1,3}, {1,1,5,1,1,3,3,2}, {1,1,6,3,3,1,1,1}}, + {{1,5,1,3,1,3,1,2}, {1,1,5,1,1,4,3,1}, {1,6,2,1,1,1,3,2}}, + {{1,3,3,1,3,2,1,3}, {1,2,4,2,1,1,4,2}, {1,6,2,1,1,2,3,1}}, + {{1,4,2,2,2,3,1,2}, {1,1,5,1,2,1,4,2}, {1,5,3,1,1,1,2,3}}, + {{1,5,1,3,1,4,1,1}, {1,2,4,2,1,2,4,1}, {2,5,3,1,1,1,3,1}}, + {{1,3,3,1,3,3,1,2}, {1,1,5,1,2,2,4,1}, {1,5,3,1,1,2,2,2}}, + {{1,4,2,2,2,4,1,1}, {1,1,5,2,1,1,3,3}, {1,5,3,1,1,3,2,1}}, + {{1,5,1,3,2,1,2,2}, {2,1,5,2,1,1,4,1}, {1,6,2,2,1,1,3,1}}, + {{1,4,2,2,3,1,2,2}, {1,1,5,2,1,2,3,2}, {1,5,3,1,2,1,3,1}}, + {{1,5,1,3,2,2,2,1}, {1,1,5,2,1,3,3,1}, {1,4,4,1,1,1,1,4}}, + {{1,3,3,1,4,1,2,2}, {1,2,4,3,1,1,4,1}, {2,4,4,1,1,1,2,2}}, + {{1,4,2,2,3,2,2,1}, {1,1,5,2,2,1,4,1}, {1,4,4,1,1,2,1,3}}, + {{1,3,3,1,4,2,2,1}, {1,1,5,3,1,1,3,2}, {2,4,4,1,1,2,2,1}}, + {{4,2,4,1,1,1,1,3}, {1,1,5,3,1,2,3,1}, {1,4,4,1,1,3,1,2}}, + {{4,2,4,1,1,2,1,2}, {1,1,5,4,1,1,3,1}, {1,4,4,1,1,4,1,1}}, + {{4,2,4,1,1,3,1,1}, {3,6,1,1,2,1,1,2}, {1,5,3,2,1,1,2,2}}, + {{3,3,3,2,1,1,1,3}, {3,6,1,1,2,2,1,1}, {1,4,4,1,2,1,2,2}}, + {{3,2,4,1,2,1,1,3}, {2,6,1,1,3,1,1,2}, {1,5,3,2,1,2,2,1}}, + {{4,2,4,1,2,1,2,1}, {2,6,1,1,3,2,1,1}, {1,4,4,1,2,2,2,1}}, + {{3,2,4,1,2,2,1,2}, {1,6,1,1,4,1,1,2}, {2,3,5,1,1,1,1,3}}, + {{3,3,3,2,1,3,1,1}, {1,6,1,1,4,2,1,1}, {3,3,5,1,1,1,2,1}}, + {{3,2,4,1,2,3,1,1}, {4,5,2,1,2,1,1,1}, {2,3,5,1,1,2,1,2}}, + {{2,4,2,3,1,1,1,3}, {3,6,1,2,2,1,1,1}, {2,3,5,1,1,3,1,1}}, + {{3,4,2,3,1,1,2,1}, {3,5,2,1,3,1,1,1}, {1,4,4,2,1,1,1,3}}, + {{2,3,3,2,2,1,1,3}, {2,6,1,2,3,1,1,1}, {2,4,4,2,1,1,2,1}}, + {{3,3,3,2,2,1,2,1}, {2,5,2,1,4,1,1,1}, {1,3,5,1,2,1,1,3}}, + {{2,2,4,1,3,1,1,3}, {1,6,1,2,4,1,1,1}, {2,3,5,1,2,1,2,1}}, + {{2,3,3,2,2,2,1,2}, {1,5,2,1,5,1,1,1}, {1,3,5,1,2,2,1,2}}, + {{2,4,2,3,1,3,1,1}, {1,4,3,1,1,1,5,1}, {1,4,4,2,1,3,1,1}}, + {{2,2,4,1,3,2,1,2}, {1,3,4,1,1,1,4,2}, {1,3,5,1,2,3,1,1}}, + {{2,3,3,2,2,3,1,1}, {1,3,4,1,1,2,4,1}, {1,5,3,3,1,1,2,1}}, + {{2,2,4,1,3,3,1,1}, {1,2,5,1,1,1,3,3}, {1,4,4,2,2,1,2,1}}, + {{1,5,1,4,1,1,1,3}, {2,2,5,1,1,1,4,1}, {1,3,5,1,3,1,2,1}}, + {{2,5,1,4,1,1,2,1}, {1,2,5,1,1,2,3,2}, {3,2,6,1,1,1,1,2}}, + {{1,4,2,3,2,1,1,3}, {1,2,5,1,1,3,3,1}, {3,2,6,1,1,2,1,1}}, + {{2,4,2,3,2,1,2,1}, {1,3,4,2,1,1,4,1}, {2,3,5,2,1,1,1,2}}, + {{1,3,3,2,3,1,1,3}, {1,2,5,1,2,1,4,1}, {2,2,6,1,2,1,1,2}}, + {{1,4,2,3,2,2,1,2}, {1,1,6,1,1,1,2,4}, {2,3,5,2,1,2,1,1}}, + {{1,5,1,4,1,3,1,1}, {2,1,6,1,1,1,3,2}, {2,2,6,1,2,2,1,1}}, + {{1,2,4,1,4,1,1,3}, {1,1,6,1,1,2,2,3}, {1,4,4,3,1,1,1,2}}, + {{1,3,3,2,3,2,1,2}, {2,1,6,1,1,2,3,1}, {1,3,5,2,2,1,1,2}}, + {{1,4,2,3,2,3,1,1}, {1,1,6,1,1,3,2,2}, {1,4,4,3,1,2,1,1}}, + {{1,2,4,1,4,2,1,2}, {1,1,6,1,1,4,2,1}, {1,2,6,1,3,1,1,2}}, + {{1,3,3,2,3,3,1,1}, {1,2,5,2,1,1,3,2}, {1,3,5,2,2,2,1,1}}, + {{1,5,1,4,2,1,2,1}, {1,1,6,1,2,1,3,2}, {1,2,6,1,3,2,1,1}}, + {{1,4,2,3,3,1,2,1}, {1,2,5,2,1,2,3,1}, {3,2,6,2,1,1,1,1}}, + {{1,3,3,2,4,1,2,1}, {1,1,6,1,2,2,3,1}, {2,3,5,3,1,1,1,1}}, + {{1,2,4,1,5,1,2,1}, {1,1,6,2,1,1,2,3}, {2,2,6,2,2,1,1,1}}, + {{5,1,5,1,1,1,1,2}, {2,1,6,2,1,1,3,1}, {1,4,4,4,1,1,1,1}}, + {{5,1,5,1,1,2,1,1}, {1,1,6,2,1,2,2,2}, {1,3,5,3,2,1,1,1}}, + {{4,2,4,2,1,1,1,2}, {1,1,6,2,1,3,2,1}, {1,2,6,2,3,1,1,1}}, + {{4,1,5,1,2,1,1,2}, {1,2,5,3,1,1,3,1}, {1,6,3,1,1,1,2,2}}, + {{4,2,4,2,1,2,1,1}, {1,1,6,2,2,1,3,1}, {1,6,3,1,1,2,2,1}}, + {{4,1,5,1,2,2,1,1}, {1,1,6,3,1,1,2,2}, {1,5,4,1,1,1,1,3}}, + {{3,3,3,3,1,1,1,2}, {1,1,6,3,1,2,2,1}, {2,5,4,1,1,1,2,1}}, + {{3,2,4,2,2,1,1,2}, {1,4,4,1,1,1,4,1}, {1,5,4,1,1,2,1,2}}, + {{3,3,3,3,1,2,1,1}, {1,3,5,1,1,1,3,2}, {1,5,4,1,1,3,1,1}}, + {{3,1,5,1,3,1,1,2}, {1,3,5,1,1,2,3,1}, {1,6,3,2,1,1,2,1}}, + {{3,2,4,2,2,2,1,1}, {1,2,6,1,1,1,2,3}, {1,5,4,1,2,1,2,1}}, + {{3,1,5,1,3,2,1,1}, {2,2,6,1,1,1,3,1}, {2,4,5,1,1,1,1,2}}, + {{2,4,2,4,1,1,1,2}, {1,2,6,1,1,2,2,2}, {2,4,5,1,1,2,1,1}}, + {{2,3,3,3,2,1,1,2}, {1,2,6,1,1,3,2,1}, {1,5,4,2,1,1,1,2}}, + {{2,4,2,4,1,2,1,1}, {1,3,5,2,1,1,3,1}, {1,4,5,1,2,1,1,2}}, + {{2,2,4,2,3,1,1,2}, {1,2,6,1,2,1,3,1}, {1,5,4,2,1,2,1,1}}, + {{2,3,3,3,2,2,1,1}, {1,2,6,2,1,1,2,2}, {1,4,5,1,2,2,1,1}}, + {{2,1,5,1,4,1,1,2}, {1,2,6,2,1,2,2,1}, {3,3,6,1,1,1,1,1}} +}; + +//------------------------------------------------------------------------ + +static int makeDataCodewords(GString *value, int *codewords); +static int countNumeric(GString *value, int start); +static int countText(GString *value, int start); +static int countBinary(GString *value, int start); +static GBool makeNumericCodewords(GString *value, int start, int n, + int *codewords, int &codewordIdx); +static int divMod900(int *d, int n); +static GBool makeByteCodewords(GString *value, int start, int n, + int *codewords, int &codewordIdx); +static GBool makeTextCodewords(GString *value, int start, int n, + int *codewords, int &codewordIdx); +static GBool appendTextHalfSymbol(int *codewords, int &codewordIdx, + int halfSymbol, int &prevHalfSymbol); +static GBool appendDataCodeword(int *codewords, int &codewordIdx, + int codeword); +static void makeErrorCorrectionCodewords(int errorCorrectionLevel, + int *codewords, int length); +static void drawBarcode(int *codewords, int totalLength, + int nRows, int nCols, + int errorCorrectionLevel, + double moduleWidth, double moduleHeight, + double fieldWidth, double fieldHeight, + GString *appearBuf); +static void drawPattern(int &x, int y, char *pattern, int length, + GString *appearBuf); + +//------------------------------------------------------------------------ + +GBool drawPDF417Barcode(double fieldWidth, double fieldHeight, + double moduleWidth, double moduleHeight, + int errorCorrectionLevel, GString *value, + GString *appearBuf) { + int codewords[maxDataCodewords + maxErrorCorrectionCodewords]; + + if (moduleWidth <= 0 || moduleHeight <= 0) { + error(errSyntaxError, -1, "Invalid module size in PDF417 barcode"); + return gFalse; + } + + // each row contains: + // - left quiet zone (2 modules, minimum) + // - start code (17 modules) + // - left row indicator (17 modules) + // - nCols codewords (17 modules each) + // - right row indicator (17 modules) + // - stop code (18 modules) + // - right quiet zone (2 modules, minimum) + // total = 73 + nCols * 17 + int nCols = (int)floor((fieldWidth / moduleWidth - 73) / 17); + if (nCols < 1) { + error(errSyntaxError, -1, "Invalid field size for PDF417 barcode"); + return gFalse; + } + if (nCols > 30) { + nCols = 30; + } + + int nDataCodewords = makeDataCodewords(value, codewords); + if (nDataCodewords == maxDataCodewords) { + error(errSyntaxError, -1, "Too many codewords in PDF417 barcode"); + return gFalse; + } + + int nErrorCorrectionCodewords = 1 << (errorCorrectionLevel + 1); + + // total codewords = 1 + nDataCodewords + nPadCodewords + // + nErrorCorrectionCodewords + int nRows = (1 + nDataCodewords + nErrorCorrectionCodewords + (nCols - 1)) + / nCols; + if (nRows < 3) { + nRows = 3; + } + if (nRows > 90) { + error(errSyntaxError, -1, "Too many rows in PDF417 barcode"); + return gFalse; + } + int nPadCodewords = nRows * nCols + - (1 + nDataCodewords + nErrorCorrectionCodewords); + int length = 1 + nDataCodewords + nPadCodewords; + if (length > maxDataCodewords) { + error(errSyntaxError, -1, "Too many codewords in PDF417 barcode"); + return gFalse; + } + codewords[0] = length; + for (int i = 1 + nDataCodewords; i < length; ++i) { + codewords[i] = 900; + } + + makeErrorCorrectionCodewords(errorCorrectionLevel, codewords, length); + + // we need at least 3 modules of vertical quiet space above and below + // (the spec says 2, but Adobe seems to use 3) + if (nRows * moduleHeight + 6 * moduleWidth > fieldHeight) { + error(errSyntaxError, -1, "Too many rows in PDF417 barcode"); + return gFalse; + } + + // Adobe adjusts the module height to fill the available space + double moduleHeight2 = (fieldHeight - 6 * moduleWidth) / nRows; + + drawBarcode(codewords, length + nErrorCorrectionCodewords, + nRows, nCols, errorCorrectionLevel, + moduleWidth, moduleHeight2, fieldWidth, fieldHeight, + appearBuf); + + return gTrue; +} + +// Generate up to maxDataCodewords-1 codewords in codewords[1 .. m], +// leaving codewords[0] unused. Returns the number of generated +// codewords (m), or maxDataCodewords if there are too many to fit. +static int makeDataCodewords(GString *value, int *codewords) { + GBool textMode = gTrue; + int codewordIdx = 1; + int valueIdx = 0; + while (valueIdx < value->getLength()) { + + int nNumeric = countNumeric(value, valueIdx); + if (nNumeric >= 13) { + if (!appendDataCodeword(codewords, codewordIdx, numericModeLatch) || + !makeNumericCodewords(value, valueIdx, nNumeric, + codewords, codewordIdx)) { + return maxDataCodewords; + } + valueIdx += nNumeric; + textMode = gFalse; + + } else { + int nText = countText(value, valueIdx); + if (nText >= 5) { + if (!textMode) { + if (!appendDataCodeword(codewords, codewordIdx, textModeLatch)) { + return maxDataCodewords; + } + } + if (!makeTextCodewords(value, valueIdx, nText, + codewords, codewordIdx)) { + return maxDataCodewords; + } + valueIdx += nText; + textMode = gTrue; + + } else { + int nBinary = countBinary(value, valueIdx); + //~ this doesn't currently use byte mode shift when nBinary==1 + //~ because we don't track the text submode (which is needed + //~ because we'll return to that submode after the byte shift) + int code = (nBinary % 6 == 0) ? byteModeLatchMult6 + : byteModeLatchNonMult6; + if (!appendDataCodeword(codewords, codewordIdx, code) || + !makeByteCodewords(value, valueIdx, nBinary, + codewords, codewordIdx)) { + return maxDataCodewords; + } + valueIdx += nBinary; + textMode = gFalse; + } + } + } + + return codewordIdx - 1; +} + +static int countNumeric(GString *value, int start) { + int n = 0; + for (int i = start; i < value->getLength(); ++i) { + char c = value->getChar(i); + if (!(c >= '0' && c <= '9')) { + break; + } + ++n; + } + return n; +} + +static int countText(GString *value, int start) { + int n = 0; + for (int i = start; i < value->getLength(); ++i) { + char c = value->getChar(i); + if ((c & 0x80) || + (textCompaction[(int)c][0] == 30 && + textCompaction[(int)c][1] == 30 && + textCompaction[(int)c][2] == 30 && + textCompaction[(int)c][3] == 30) || + countNumeric(value, i) >= 13) { + break; + } + ++n; + } + return n; +} + +static int countBinary(GString *value, int start) { + int n = 0; + for (int i = start; i < value->getLength(); ++i) { + if (countNumeric(value, i) >= 13 || + countText(value, i) >= 5) { + break; + } + ++n; + } + return n; +} + +static GBool makeNumericCodewords(GString *value, int start, int n, + int *codewords, int &codewordIdx) { + for (int i = 0; i < n; i += 44) { + int nInDigits = n - i; + if (nInDigits > 44) { + nInDigits = 44; + } + int inDigits[45]; + inDigits[0] = 1; + for (int j = 0; j < nInDigits; ++j) { + inDigits[j+1] = value->getChar(start + i + j) - '0'; + } + int nOutDigits = 1 + nInDigits / 3; + int outDigits[15]; + for (int j = 0; j < nOutDigits; ++j) { + outDigits[nOutDigits - 1 - j] = divMod900(inDigits, nInDigits + 1); + } + for (int j = 0; j < nOutDigits; ++j) { + if (!appendDataCodeword(codewords, codewordIdx, outDigits[j])) { + return gFalse; + } + } + } + return gTrue; +} + +// Given x = sum(i = 0..n-1, d[i] * 10^(n-1-i)) +// Compute x' = x / 900 and return x % 900. +static int divMod900(int *d, int n) { + int r = 0; + for (int i = 0; i < n; ++i) { + int dd = r * 10 + d[i]; + d[i] = dd / 900; + r = dd % 900; + } + return r; +} + +static GBool makeByteCodewords(GString *value, int start, int n, + int *codewords, int &codewordIdx) { + int i; + for (i = 0; i <= n - 6; i += 6) { + long long in = 0; + for (int j = 0; j < 6; ++j) { + in = (in << 8) | (value->getChar(start + i + j) & 0xff); + } + int outCodes[5]; + for (int j = 4; j >= 0; --j) { + outCodes[j] = (int)(in % 900); + in /= 900; + } + for (int j = 0; j < 4; ++j) { + if (!appendDataCodeword(codewords, codewordIdx, outCodes[j])) { + return gFalse; + } + } + } + for (; i < n; ++i) { + if (!appendDataCodeword(codewords, codewordIdx, + value->getChar(start + i) & 0xff)) { + return gFalse; + } + } + return gTrue; +} + +static GBool makeTextCodewords(GString *value, int start, int n, + int *codewords, int &codewordIdx) { + int submode = textSubmodeAlpha; + int prevSubmode = textSubmodeAlpha; + int nextSubmode; + int prevHalfSymbol = 30; + int valueIdx = start; + while (valueIdx < start + n) { + int c = value->getChar(valueIdx) & 0x7f; + nextSubmode = submode; + switch (submode) { + case textSubmodeAlpha: + if (textCompaction[c][textSubmodeAlpha] < 30) { + if (!appendTextHalfSymbol(codewords, codewordIdx, + textCompaction[c][textSubmodeAlpha], + prevHalfSymbol)) { + return gFalse; + } + ++valueIdx; + } else if (textCompaction[c][textSubmodeLower] < 30) { + if (!appendTextHalfSymbol(codewords, codewordIdx, + textAlphaLowerLatch, prevHalfSymbol)) { + return gFalse; + } + nextSubmode = textSubmodeLower; + } else if (textCompaction[c][textSubmodeMixed] < 30) { + if (!appendTextHalfSymbol(codewords, codewordIdx, + textAlphaMixedLatch, prevHalfSymbol)) { + return gFalse; + } + nextSubmode = textSubmodeMixed; + } else if (textCompaction[c][textSubmodePunc] < 30) { + if (valueIdx < start + n - 2 && + textCompaction[value->getChar(valueIdx + 1) & 0x7f] + [textSubmodePunc] < 30 && + textCompaction[value->getChar(valueIdx + 2) & 0x7f] + [textSubmodePunc] < 30) { + if (!appendTextHalfSymbol(codewords, codewordIdx, + textAlphaMixedLatch, prevHalfSymbol) || + !appendTextHalfSymbol(codewords, codewordIdx, + textMixedPuncLatch, prevHalfSymbol)) { + return gFalse; + } + nextSubmode = textSubmodePunc; + } else { + if (!appendTextHalfSymbol(codewords, codewordIdx, + textAlphaPuncShift, prevHalfSymbol)) { + return gFalse; + } + nextSubmode = textSubmodePuncShift; + } + } else { + // this shouldn't happen + ++valueIdx; + } + break; + case textSubmodeAlphaShift: + if (textCompaction[c][textSubmodeAlpha] < 30) { + if (!appendTextHalfSymbol(codewords, codewordIdx, + textCompaction[c][textSubmodeAlpha], + prevHalfSymbol)) { + return gFalse; + } + ++valueIdx; + } else { + // this shouldn't happen + if (!appendTextHalfSymbol(codewords, codewordIdx, + 0, prevHalfSymbol)) { + return gFalse; + } + } + nextSubmode = prevSubmode; + break; + case textSubmodeLower: + if (textCompaction[c][textSubmodeAlpha] < 30) { + if (valueIdx < start + n - 2 && + textCompaction[value->getChar(valueIdx + 1) & 0x7f] + [textSubmodeAlpha] < 30 && + textCompaction[value->getChar(valueIdx + 2) & 0x7f] + [textSubmodeAlpha] < 30) { + if (!appendTextHalfSymbol(codewords, codewordIdx, + textLowerMixedLatch, prevHalfSymbol) || + !appendTextHalfSymbol(codewords, codewordIdx, + textMixedAlphaLatch, prevHalfSymbol)) { + return gFalse; + } + nextSubmode = textSubmodeAlpha; + } else { + if (!appendTextHalfSymbol(codewords, codewordIdx, + textLowerAlphaShift, prevHalfSymbol)) { + return gFalse; + } + nextSubmode = textSubmodeAlphaShift; + } + } else if (textCompaction[c][textSubmodeLower] < 30) { + if (!appendTextHalfSymbol(codewords, codewordIdx, + textCompaction[c][textSubmodeLower], + prevHalfSymbol)) { + return gFalse; + } + ++valueIdx; + } else if (textCompaction[c][textSubmodeMixed] < 30) { + if (!appendTextHalfSymbol(codewords, codewordIdx, + textLowerMixedLatch, prevHalfSymbol)) { + return gFalse; + } + nextSubmode = textSubmodeMixed; + } else if (textCompaction[c][textSubmodePunc] < 30) { + if (valueIdx < start + n - 2 && + textCompaction[value->getChar(valueIdx + 1) & 0x7f] + [textSubmodePunc] < 30 && + textCompaction[value->getChar(valueIdx + 2) & 0x7f] + [textSubmodePunc] < 30) { + if (!appendTextHalfSymbol(codewords, codewordIdx, + textLowerMixedLatch, prevHalfSymbol) || + !appendTextHalfSymbol(codewords, codewordIdx, + textMixedPuncLatch, prevHalfSymbol)) { + return gFalse; + } + nextSubmode = textSubmodePunc; + } else { + if (!appendTextHalfSymbol(codewords, codewordIdx, + textLowerPuncShift, prevHalfSymbol)) { + return gFalse; + } + nextSubmode = textSubmodePuncShift; + } + } else { + // this shouldn't happen + ++valueIdx; + } + break; + case textSubmodeMixed: + if (textCompaction[c][textSubmodeAlpha] < 30) { + if (!appendTextHalfSymbol(codewords, codewordIdx, + textMixedAlphaLatch, prevHalfSymbol)) { + return gFalse; + } + nextSubmode = textSubmodeAlpha; + } else if (textCompaction[c][textSubmodeLower] < 30) { + if (!appendTextHalfSymbol(codewords, codewordIdx, + textMixedLowerLatch, prevHalfSymbol)) { + return gFalse; + } + nextSubmode = textSubmodeLower; + } else if (textCompaction[c][textSubmodeMixed] < 30) { + if (!appendTextHalfSymbol(codewords, codewordIdx, + textCompaction[c][textSubmodeMixed], + prevHalfSymbol)) { + return gFalse; + } + ++valueIdx; + } else if (textCompaction[c][textSubmodePunc] < 30) { + if (valueIdx < start + n - 1 && + textCompaction[value->getChar(valueIdx + 1) & 0x7f] + [textSubmodePunc] < 30) { + if (!appendTextHalfSymbol(codewords, codewordIdx, + textMixedPuncLatch, prevHalfSymbol)) { + return gFalse; + } + nextSubmode = textSubmodePunc; + } else { + if (!appendTextHalfSymbol(codewords, codewordIdx, + textMixedPuncShift, prevHalfSymbol)) { + return gFalse; + } + nextSubmode = textSubmodePuncShift; + } + } else { + // this shouldn't happen + ++valueIdx; + } + break; + case textSubmodePunc: + if (textCompaction[c][textSubmodeAlpha] < 30) { + if (!appendTextHalfSymbol(codewords, codewordIdx, + textPuncAlphaLatch, prevHalfSymbol)) { + return gFalse; + } + nextSubmode = textSubmodeAlpha; + } else if (textCompaction[c][textSubmodeLower] < 30) { + if (!appendTextHalfSymbol(codewords, codewordIdx, + textPuncAlphaLatch, prevHalfSymbol) || + !appendTextHalfSymbol(codewords, codewordIdx, + textAlphaLowerLatch, prevHalfSymbol)) { + return gFalse; + } + nextSubmode = textSubmodeLower; + } else if (textCompaction[c][textSubmodeMixed] < 30) { + if (!appendTextHalfSymbol(codewords, codewordIdx, + textPuncAlphaLatch, prevHalfSymbol) || + !appendTextHalfSymbol(codewords, codewordIdx, + textAlphaMixedLatch, prevHalfSymbol)) { + return gFalse; + } + nextSubmode = textSubmodeMixed; + } else if (textCompaction[c][textSubmodePunc] < 30) { + if (!appendTextHalfSymbol(codewords, codewordIdx, + textCompaction[c][textSubmodePunc], + prevHalfSymbol)) { + return gFalse; + } + ++valueIdx; + } else { + // this shouldn't happen + ++valueIdx; + } + break; + case textSubmodePuncShift: + if (textCompaction[c][textSubmodePunc] < 30) { + if (!appendTextHalfSymbol(codewords, codewordIdx, + textCompaction[c][textSubmodePunc], + prevHalfSymbol)) { + return gFalse; + } + ++valueIdx; + } else { + // this shouldn't happen + if (!appendTextHalfSymbol(codewords, codewordIdx, + 0, prevHalfSymbol)) { + return gFalse; + } + } + nextSubmode = prevSubmode; + break; + } + prevSubmode = submode; + submode = nextSubmode; + } + + // padding + if (prevHalfSymbol < 30) { + appendTextHalfSymbol(codewords, codewordIdx, 29, prevHalfSymbol); + } + + return gTrue; +} + +static GBool appendTextHalfSymbol(int *codewords, int &codewordIdx, + int halfSymbol, int &prevHalfSymbol) { + if (prevHalfSymbol == 30) { + prevHalfSymbol = halfSymbol; + } else { + int codeword = prevHalfSymbol * 30 + halfSymbol; + if (!appendDataCodeword(codewords, codewordIdx, codeword)) { + return gFalse; + } + prevHalfSymbol = 30; + } + return gTrue; +} + +static GBool appendDataCodeword(int *codewords, int &codewordIdx, + int codeword) { + if (codewordIdx >= maxDataCodewords) { + return gFalse; + } + codewords[codewordIdx++] = codeword; + return gTrue; +} + +// Compute the error correction codewords and add to codewords[]. +static void makeErrorCorrectionCodewords(int errorCorrectionLevel, + int *codewords, int length) { + int e[1 << (maxErrorCorrectionLevel + 1)]; + int k = 1 << (errorCorrectionLevel + 1); + for (int i = 0; i < k; ++i) { + e[i] = 0; + } + for (int i = 0; i < length; ++i) { + int t1 = (codewords[i] + e[k-1]) % 929; + int t2, t3; + for (int j = k-1; j >= 1; --j) { + t2 = (t1 * errorCorrectionCoeff[errorCorrectionLevel][j]) % 929; + t3 = 929 - t2; + e[j] = (e[j-1] + t3) % 929; + } + t2 = (t1 * errorCorrectionCoeff[errorCorrectionLevel][0]) % 929; + t3 = 929 - t2; + e[0] = t3 % 929; + } + int j = length; + for (int i = k-1; i >= 0; --i) { + int ee = e[i] ? (929 - e[i]) : 0; + codewords[j++] = ee; + } +} + +// Draw the barcode in the rectangle (0, 0, fieldWidth, fieldHeight). +static void drawBarcode(int *codewords, int totalLength, + int nRows, int nCols, + int errorCorrectionLevel, + double moduleWidth, double moduleHeight, + double fieldWidth, double fieldHeight, + GString *appearBuf) { + double w = (73 + nCols * 17) * moduleWidth; + double h = nRows * moduleHeight; + double x0 = 0.5 * (fieldWidth - w); + double y0 = 0.5 * (fieldHeight - h); + + appearBuf->append("0 g q\n"); + appearBuf->appendf("{0:.4f} 0 0 {1:.4f} {2:.4f} {3:.4f} cm\n", + moduleWidth, moduleHeight, x0, y0); + + int i = 0; + for (int row = 0; row < nRows; ++row) { + int cluster = row % 3; + int y = nRows - 1 - row; + int left = 0; + int right = 0; + switch (cluster) { + case 0: + left = 30 * (row / 3) + (nRows - 1) / 3; + right = 30 * (row / 3) + (nCols - 1); + break; + case 1: + left = 30 * (row / 3) + (errorCorrectionLevel * 3) + (nRows - 1) % 3; + right = 30 * (row / 3) + (nRows - 1) / 3; + break; + case 2: + left = 30 * (row / 3) + (nCols - 1); + right = 30 * (row / 3) + (errorCorrectionLevel * 3) + (nRows - 1) % 3; + break; + } + int x = 0; + drawPattern(x, y, startPattern, startPatternLength, appearBuf); + drawPattern(x, y, patterns[left][cluster], patternLength, appearBuf); + for (int col = 0; col < nCols; ++col) { + drawPattern(x, y, patterns[codewords[i]][cluster], patternLength, + appearBuf); + ++i; + } + drawPattern(x, y, patterns[right][cluster], patternLength, appearBuf); + drawPattern(x, y, stopPattern, stopPatternLength, appearBuf); + } + + appearBuf->append("Q\n"); +} + +static void drawPattern(int &x, int y, char *pattern, int length, + GString *appearBuf) { + for (int i = 0; i < length; ++i) { + if (!(i & 1)) { + appearBuf->appendf("{0:d} {1:d} {2:d} 1 re f\n", x, y, pattern[i]); + } + x += pattern[i]; + } +} diff --git a/xpdf/PDF417Barcode.h b/xpdf/PDF417Barcode.h new file mode 100644 index 0000000..8166865 --- /dev/null +++ b/xpdf/PDF417Barcode.h @@ -0,0 +1,32 @@ +//======================================================================== +// +// PDF417Barcode.h +// +// Copyright 2018 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef PDF417BARCODE_H +#define PDF417BARCODE_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +class GString; + +// Draw a PDF417 barcode: +// fieldWidth, fieldHeight = field size (in points) +// moduleWidth, moduleHeight = requested module size (in points) +// errorCorrectionLevel = 0 .. 8 +// value = byte string +// output is appended to appearBuf +// Returns true on success, false on error. +extern GBool drawPDF417Barcode(double fieldWidth, double fieldHeight, + double moduleWidth, double moduleHeight, + int errorCorrectionLevel, GString *value, + GString *appearBuf); + +#endif diff --git a/xpdf/PDFCore.cc b/xpdf/PDFCore.cc new file mode 100644 index 0000000..b833d5d --- /dev/null +++ b/xpdf/PDFCore.cc @@ -0,0 +1,2024 @@ +//======================================================================== +// +// PDFCore.cc +// +// Copyright 2004-2014 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include "gmempp.h" +#include "GString.h" +#include "GList.h" +#include "GlobalParams.h" +#include "Splash.h" +#include "SplashBitmap.h" +#include "SplashPattern.h" +#include "SplashPath.h" +#include "Error.h" +#include "ErrorCodes.h" +#include "PDFDoc.h" +#include "Link.h" +#include "Annot.h" +#include "AcroForm.h" +#include "OptionalContent.h" +#include "TileMap.h" +#include "TileCache.h" +#include "TileCompositor.h" +#include "PDFCore.h" + +//------------------------------------------------------------------------ +// PDFCore +//------------------------------------------------------------------------ + +PDFCore::PDFCore(SplashColorMode colorMode, int bitmapRowPad, + GBool reverseVideo, SplashColorPtr paperColor) { + GString *initialZoom, *initialDisplayMode; + int z, i; + + doc = NULL; + + linksPage = 0; + links = NULL; + + annotsPage = 0; + annots = NULL; + + textPage = 0; + textDPI = 0; + textRotate = 0; + textOutCtrl.mode = textOutPhysLayout; + text = NULL; + + state = new DisplayState(globalParams->getMaxTileWidth(), + globalParams->getMaxTileHeight(), + globalParams->getTileCacheSize(), + globalParams->getWorkerThreads(), + colorMode, bitmapRowPad); + tileMap = new TileMap(state); + tileCache = new TileCache(state); + tileCompositor = new TileCompositor(state, tileMap, tileCache); + bitmapFinished = gTrue; + + state->setReverseVideo(reverseVideo); + state->setPaperColor(paperColor); + initialZoom = globalParams->getInitialZoom(); + if (!initialZoom->cmp("page")) { + state->setZoom(zoomPage); + } else if (!initialZoom->cmp("width")) { + state->setZoom(zoomWidth); + } else { + z = atoi(initialZoom->getCString()); + if (z <= 0) { + z = zoomWidth; + } + state->setZoom(z); + } + delete initialZoom; + initialDisplayMode = globalParams->getInitialDisplayMode(); + if (!initialDisplayMode->cmp("single")) { + state->setDisplayMode(displaySingle); + } else if (!initialDisplayMode->cmp("sideBySideSingle")) { + state->setDisplayMode(displaySideBySideSingle); + } else if (!initialDisplayMode->cmp("sideBySideContinuous")) { + state->setDisplayMode(displaySideBySideContinuous); + } else if (!initialDisplayMode->cmp("horizontalContinuous")) { + state->setDisplayMode(displayHorizontalContinuous); + } else { + state->setDisplayMode(displayContinuous); + } + delete initialDisplayMode; + + selectMode = selectModeBlock; + selectPage = 0; + selectStartX = selectStartY = 0; + + historyCur = pdfHistorySize - 1; + historyBLen = historyFLen = 0; + for (i = 0; i < pdfHistorySize; ++i) { + history[i].fileName = NULL; + history[i].page = 0; + } +} + +PDFCore::~PDFCore() { + int i; + + delete tileCompositor; + delete tileCache; + delete tileMap; + delete state; + clearPage(); + if (doc) { + delete doc; + } + for (i = 0; i < pdfHistorySize; ++i) { + if (history[i].fileName) { +#ifdef _WIN32 + delete[] history[i].fileName; +#else + delete history[i].fileName; +#endif + } + } +} + +int PDFCore::loadFile(GString *fileName, GString *ownerPassword, + GString *userPassword) { + int err; + + setBusyCursor(gTrue); + err = loadFile2(new PDFDoc(fileName->copy(), ownerPassword, userPassword, + this)); + setBusyCursor(gFalse); + return err; +} + +#ifdef _WIN32 +int PDFCore::loadFile(wchar_t *fileName, int fileNameLen, + GString *ownerPassword, GString *userPassword) { + int err; + + setBusyCursor(gTrue); + err = loadFile2(new PDFDoc(fileName, fileNameLen, + ownerPassword, userPassword, this)); + setBusyCursor(gFalse); + return err; +} +#endif + +int PDFCore::loadFile(BaseStream *stream, GString *ownerPassword, + GString *userPassword) { + int err; + + setBusyCursor(gTrue); + err = loadFile2(new PDFDoc(stream, ownerPassword, userPassword, this)); + setBusyCursor(gFalse); + return err; +} + +void PDFCore::loadDoc(PDFDoc *docA) { + setBusyCursor(gTrue); + loadFile2(docA); + setBusyCursor(gFalse); +} + +int PDFCore::reload() { + int err; + + if (!doc->getFileName()) { + return errOpenFile; + } + setBusyCursor(gTrue); + err = loadFile2(new PDFDoc(doc->getFileName()->copy(), NULL, NULL, this)); + setBusyCursor(gFalse); + startUpdate(); + finishUpdate(gTrue, gFalse); + return err; +} + +int PDFCore::loadFile2(PDFDoc *newDoc) { + int err; + + clearSelection(); + + // open the PDF file + if (!newDoc->isOk()) { + err = newDoc->getErrorCode(); + delete newDoc; + return err; + } + + preLoad(); + + // replace old document + // NB: do not delete doc until after DisplayState::setDoc() returns + state->setDoc(newDoc); + if (doc) { + delete doc; + } + doc = newDoc; + clearPage(); + + postLoad(); + + return errNone; +} + +void PDFCore::clear() { + if (!doc) { + return; + } + + // no document + // NB: do not delete doc until after DisplayState::setDoc() returns + state->setDoc(NULL); + delete doc; + doc = NULL; + clearPage(); + + // redraw + state->setScrollPosition(1, 0, 0); + invalidateWholeWindow(); + updateScrollbars(); +} + +PDFDoc *PDFCore::takeDoc(GBool redraw) { + PDFDoc *docA; + + if (!doc) { + return NULL; + } + + // no document + // NB: do not delete doc until after DisplayState::setDoc() returns + state->setDoc(NULL); + docA = doc; + doc = NULL; + clearPage(); + + // redraw + state->setScrollPosition(1, 0, 0); + if (redraw) { + invalidateWholeWindow(); + updateScrollbars(); + } + + return docA; +} + +void PDFCore::displayPage(int page, GBool scrollToTop, + GBool scrollToBottom, GBool addToHist) { + int scrollX, scrollY; + + if (page <= 0 || page > doc->getNumPages()) { + return; + } + if (!scrollToTop && + (state->getDisplayMode() == displayContinuous || + state->getDisplayMode() == displaySideBySideContinuous)) { + scrollY = tileMap->getPageTopY(page) + + (state->getScrollY() + - tileMap->getPageTopY(tileMap->getFirstPage())); + } else if (scrollToTop || + state->getDisplayMode() == displayContinuous || + state->getDisplayMode() == displaySideBySideContinuous) { + scrollY = tileMap->getPageTopY(page); + } else if (scrollToBottom) { + scrollY = tileMap->getPageBottomY(page); + } else { + scrollY = state->getScrollY(); + } + if (state->getDisplayMode() == displayHorizontalContinuous) { + scrollX = tileMap->getPageLeftX(page); + } else { + scrollX = state->getScrollX(); + } + startUpdate(); + state->setScrollPosition(page, scrollX, scrollY); + finishUpdate(addToHist, gTrue); +} + +void PDFCore::displayDest(LinkDest *dest) { + Ref pageRef; + int page; + int dx, dy, scrollX, scrollY; + + if (dest->isPageRef()) { + pageRef = dest->getPageRef(); + page = doc->findPage(pageRef.num, pageRef.gen); + } else { + page = dest->getPageNum(); + } + if (page <= 0 || page > doc->getNumPages()) { + page = 1; + } + + switch (dest->getKind()) { + case destXYZ: + cvtUserToDev(page, dest->getLeft(), dest->getTop(), &dx, &dy); + scrollX = tileMap->getPageLeftX(page); + if (dest->getChangeLeft()) { + scrollX += dx; + } + scrollY = tileMap->getPageTopY(page); + if (dest->getChangeTop()) { + scrollY += dy; + } + startUpdate(); + state->setScrollPosition(page, scrollX, scrollY); + finishUpdate(gTrue, gTrue); + break; + case destFit: + case destFitB: + state->setZoom(zoomPage); + scrollX = tileMap->getPageLeftX(page); + scrollY = tileMap->getPageTopY(page); + startUpdate(); + state->setScrollPosition(page, scrollX, scrollY); + finishUpdate(gTrue, gTrue); + break; + case destFitH: + case destFitBH: + state->setZoom(zoomWidth); + scrollX = tileMap->getPageLeftX(page); + scrollY = tileMap->getPageTopY(page); + if (dest->getChangeTop()) { + cvtUserToDev(page, 0, dest->getTop(), &dx, &dy); + scrollY += dy; + } + startUpdate(); + state->setScrollPosition(page, scrollX, scrollY); + finishUpdate(gTrue, gTrue); + break; + case destFitV: + case destFitBV: + state->setZoom(zoomHeight); + scrollX = tileMap->getPageLeftX(page); + scrollY = tileMap->getPageTopY(page); + if (dest->getChangeTop()) { + cvtUserToDev(page, dest->getLeft(), 0, &dx, &dy); + scrollX += dx; + } + startUpdate(); + state->setScrollPosition(page, scrollX, scrollY); + finishUpdate(gTrue, gTrue); + break; + case destFitR: + zoomToRect(page, dest->getLeft(), dest->getTop(), + dest->getRight(), dest->getBottom()); + break; + } +} + +void PDFCore::startUpdate() { +} + +void PDFCore::finishUpdate(GBool addToHist, GBool checkForChangedFile) { + int scrollPage, scrollX, scrollY, maxScrollX, maxScrollY; + + if (!doc) { + invalidateWholeWindow(); + updateScrollbars(); + return; + } + + // check for changes to the PDF file + if (checkForChangedFile && + doc->getFileName() && + checkForNewFile()) { + loadFile(doc->getFileName()); + } + + // zero-page documents are a special case + // (check for this *after* checking for changes to the file) + if (!doc->getNumPages()) { + invalidateWholeWindow(); + updateScrollbars(); + return; + } + + // check the scroll position + scrollPage = state->getScrollPage(); + if (state->getDisplayMode() == displaySideBySideSingle && + !(scrollPage & 1)) { + --scrollPage; + } + if (state->displayModeIsContinuous()) { + scrollPage = 0; + } else if (scrollPage <= 0 || scrollPage > doc->getNumPages()) { + scrollPage = 1; + } + scrollX = state->getScrollX(); + scrollY = state->getScrollY(); + // we need to set scrollPage before calling getScrollLimits() + state->setScrollPosition(scrollPage, scrollX, scrollY); + tileMap->getScrollLimits(&maxScrollX, &maxScrollY); + maxScrollX -= state->getWinW(); + maxScrollY -= state->getWinH(); + if (scrollX > maxScrollX) { + scrollX = maxScrollX; + } + if (scrollX < 0) { + scrollX = 0; + } + if (scrollY > maxScrollY) { + scrollY = maxScrollY; + } + if (scrollY < 0) { + scrollY = 0; + } + if (scrollPage != state->getScrollPage() || + scrollX != state->getScrollX() || + scrollY != state->getScrollY()) { + state->setScrollPosition(scrollPage, scrollX, scrollY); + } + + // redraw + // - if the bitmap is available (e.g., we just scrolled), we want to + // redraw immediately; if not, postpone the redraw until a + // tileDone or tick (incremental update) to avoid "flashing" the + // screen (drawing a blank background, followed by the actual + // content slightly later) + getWindowBitmap(gTrue); + if (bitmapFinished) { + invalidateWholeWindow(); + } + updateScrollbars(); + + // add to history + if (addToHist) { + addToHistory(); + } +} + +void PDFCore::addToHistory() { + PDFHistory h; + PDFHistory *cur; + + cur = &history[historyCur]; + h.page = tileMap->getMidPage(); + h.fileName = NULL; +#ifdef _WIN32 + if (doc->getFileNameU()) { + wchar_t dummy; + // NB: if the buffer is too small, GetFullPathNameW returns a + // *maximum* required buffer size, which may be larger than the + // size actually used by the second call (it looks like it just + // adds the size of the current directory and the sizef of the + // input path) + DWORD nChars = GetFullPathNameW(doc->getFileNameU(), 1, &dummy, NULL); + if (nChars > 0) { + h.fileName = (wchar_t *)gmallocn(nChars, sizeof(wchar_t)); + if (GetFullPathNameW(doc->getFileNameU(), nChars, + h.fileName, NULL) == 0) { + gfree(h.fileName); + h.fileName = NULL; + } + } + } +#else + if (doc->getFileName()) { + h.fileName = doc->getFileName()->copy(); + } +#endif + if (historyBLen > 0 && h.page == cur->page) { + if (!h.fileName && !cur->fileName) { + return; + } +#ifdef _WIN32 + if (h.fileName && cur->fileName && !wcscmp(h.fileName, cur->fileName)) { + gfree(h.fileName); + return; + } +#else + if (h.fileName && cur->fileName && !h.fileName->cmp(cur->fileName)) { + delete h.fileName; + return; + } +#endif + } + if (++historyCur == pdfHistorySize) { + historyCur = 0; + } + if (history[historyCur].fileName) { +#ifdef _WIN32 + gfree(history[historyCur].fileName); +#else + delete history[historyCur].fileName; +#endif + } + history[historyCur] = h; + if (historyBLen < pdfHistorySize) { + ++historyBLen; + } + historyFLen = 0; +} + +GBool PDFCore::gotoNextPage(int inc, GBool top) { + GBool sideBySide; + int pg; + + if (!doc || !doc->getNumPages()) { + return gFalse; + } + pg = tileMap->getFirstPage(); + sideBySide = state->displayModeIsSideBySide(); + if (pg + (sideBySide ? 2 : 1) > doc->getNumPages()) { + return gFalse; + } + if (sideBySide && inc < 2) { + inc = 2; + } + if ((pg += inc) > doc->getNumPages()) { + pg = doc->getNumPages(); + } + displayPage(pg, top, gFalse); + return gTrue; +} + +GBool PDFCore::gotoPrevPage(int dec, GBool top, GBool bottom) { + int pg; + + if (!doc || !doc->getNumPages()) { + return gFalse; + } + pg = tileMap->getFirstPage(); + if (state->getDisplayMode() == displayContinuous && + state->getScrollY() > tileMap->getPageTopY(pg)) { + ++pg; + } else if (state->getDisplayMode() == displaySideBySideContinuous && + state->getScrollY() > tileMap->getPageTopY(pg)) { + pg += 2; + } else if (state->getDisplayMode() == displayHorizontalContinuous && + state->getScrollX() > tileMap->getPageLeftX(pg)) { + ++pg; + } + if (pg <= 1) { + return gFalse; + } + if (state->displayModeIsSideBySide() && dec < 2) { + dec = 2; + } + if ((pg -= dec) < 1) { + pg = 1; + } + displayPage(pg, top, bottom); + return gTrue; +} + +GBool PDFCore::gotoNamedDestination(GString *dest) { + LinkDest *d; + + if (!doc) { + return gFalse; + } + if (!(d = doc->findDest(dest))) { + return gFalse; + } + displayDest(d); + delete d; + return gTrue; +} + +GBool PDFCore::goForward() { + int pg; + + if (historyFLen == 0) { + return gFalse; + } + if (++historyCur == pdfHistorySize) { + historyCur = 0; + } + --historyFLen; + ++historyBLen; + if (!history[historyCur].fileName) { + return gFalse; + } +#ifdef _WIN32 + if (!doc || + !doc->getFileNameU() || + wcscmp(history[historyCur].fileName, doc->getFileNameU()) != 0) { + if (loadFile(history[historyCur].fileName, + (int)wcslen(history[historyCur].fileName)) != errNone) { + return gFalse; + } + } +#else + if (!doc || + !doc->getFileName() || + history[historyCur].fileName->cmp(doc->getFileName()) != 0) { + if (loadFile(history[historyCur].fileName) != errNone) { + return gFalse; + } + } +#endif + pg = history[historyCur].page; + displayPage(pg, gFalse, gFalse, gFalse); + return gTrue; +} + +GBool PDFCore::goBackward() { + int pg; + + if (historyBLen <= 1) { + return gFalse; + } + if (--historyCur < 0) { + historyCur = pdfHistorySize - 1; + } + --historyBLen; + ++historyFLen; + if (!history[historyCur].fileName) { + return gFalse; + } +#ifdef _WIN32 + if (!doc || + !doc->getFileNameU() || + wcscmp(history[historyCur].fileName, doc->getFileNameU()) != 0) { + if (loadFile(history[historyCur].fileName, + (int)wcslen(history[historyCur].fileName)) != errNone) { + return gFalse; + } + } +#else + if (!doc || + !doc->getFileName() || + history[historyCur].fileName->cmp(doc->getFileName()) != 0) { + if (loadFile(history[historyCur].fileName) != errNone) { + return gFalse; + } + } +#endif + pg = history[historyCur].page; + displayPage(pg, gFalse, gFalse, gFalse); + return gTrue; +} + +void PDFCore::scrollLeft(int nCols) { + scrollTo(state->getScrollX() - nCols, state->getScrollY()); +} + +void PDFCore::scrollRight(int nCols) { + scrollTo(state->getScrollX() + nCols, state->getScrollY()); +} + +void PDFCore::scrollUp(int nLines, GBool snapToPage) { + scrollTo(state->getScrollX(), state->getScrollY() - nLines, snapToPage); +} + +void PDFCore::scrollUpPrevPage(int nLines) { + if (!state->displayModeIsContinuous() && + state->getScrollY() == 0) { + gotoPrevPage(1, gFalse, gTrue); + } else { + scrollUp(nLines, gTrue); + } +} + +void PDFCore::scrollDown(int nLines, GBool snapToPage) { + scrollTo(state->getScrollX(), state->getScrollY() + nLines, snapToPage); +} + +void PDFCore::scrollDownNextPage(int nLines) { + int horizMax, vertMax; + + if (!state->displayModeIsContinuous()) { + tileMap->getScrollLimits(&horizMax, &vertMax); + if (state->getScrollY() >= vertMax - state->getWinH()) { + gotoNextPage(1, gTrue); + } else { + scrollDown(nLines); + } + } else { + scrollDown(nLines, gTrue); + } +} + +void PDFCore::scrollPageUp() { + scrollUpPrevPage(state->getWinH()); +} + +void PDFCore::scrollPageDown() { + scrollDownNextPage(state->getWinH()); +} + +void PDFCore::scrollTo(int x, int y, GBool snapToPage) { + int next, topPage, topPageY, sy, dy; + + startUpdate(); + state->setScrollPosition(state->getScrollPage(), x, y); + + if (snapToPage) { + if (state->getDisplayMode() == displayContinuous || + state->getDisplayMode() == displaySideBySideContinuous) { + next = state->getDisplayMode() == displaySideBySideContinuous ? 2 : 1; + topPage = tileMap->getFirstPage(); + // NB: topPage can be out of bounds here, because the scroll + // position isn't adjusted until finishUpdate is called, below + if (topPage > 0 && topPage <= doc->getNumPages()) { + topPageY = tileMap->getPageTopY(topPage); + sy = state->getScrollY(); + dy = sy - topPageY; + // note: dy can be negative here if the inter-page gap is at the + // top of the window + if (-16 < dy && dy < 16) { + state->setScrollPosition(state->getScrollPage(), x, topPageY); + } else if (topPage + next <= doc->getNumPages()) { + topPage += next; + topPageY = tileMap->getPageTopY(topPage); + dy = sy - topPageY; + if (-16 < dy && dy < 0) { + state->setScrollPosition(state->getScrollPage(), x, topPageY); + } + } + } + } + } + + finishUpdate(gTrue, gTrue); +} + +void PDFCore::scrollToLeftEdge() { + scrollTo(0, state->getScrollY()); +} + +void PDFCore::scrollToRightEdge() { + int horizMax, vertMax; + + tileMap->getScrollLimits(&horizMax, &vertMax); + scrollTo(horizMax - state->getWinW(), state->getScrollY()); +} + +void PDFCore::scrollToTopEdge() { + scrollTo(state->getScrollX(), + tileMap->getPageTopY(tileMap->getFirstPage())); +} + +void PDFCore::scrollToBottomEdge() { + scrollTo(state->getScrollX(), + tileMap->getPageBottomY(tileMap->getLastPage())); +} + +void PDFCore::scrollToTopLeft() { + scrollTo(tileMap->getPageLeftX(tileMap->getFirstPage()), + tileMap->getPageTopY(tileMap->getFirstPage())); +} + +void PDFCore::scrollToBottomRight() { + scrollTo(tileMap->getPageRightX(tileMap->getLastPage()), + tileMap->getPageBottomY(tileMap->getLastPage())); +} + +void PDFCore::scrollToCentered(int page, double x, double y) { + int wx, wy, sx, sy; + + startUpdate(); + + // scroll to the requested page + state->setScrollPosition(page, tileMap->getPageLeftX(page), + tileMap->getPageTopY(page)); + + // scroll the requested point to the center of the window + cvtUserToWindow(page, x, y, &wx, &wy); + sx = state->getScrollX() + wx - state->getWinW() / 2; + sy = state->getScrollY() + wy - state->getWinH() / 2; + state->setScrollPosition(page, sx, sy); + + finishUpdate(gTrue, gFalse); +} + +void PDFCore::setZoom(double zoom) { + int page; + + if (state->getZoom() == zoom) { + return; + } + if (!doc || !doc->getNumPages()) { + state->setZoom(zoom); + return; + } + startUpdate(); + page = tileMap->getFirstPage(); + state->setZoom(zoom); + state->setScrollPosition(page, tileMap->getPageLeftX(page), + tileMap->getPageTopY(page)); + finishUpdate(gTrue, gTrue); +} + +void PDFCore::zoomToRect(int page, double ulx, double uly, + double lrx, double lry) { + int x0, y0, x1, y1, sx, sy, t; + double dpi, rx, ry, zoom; + + startUpdate(); + + // set the new zoom level + cvtUserToDev(page, ulx, uly, &x0, &y0); + cvtUserToDev(page, lrx, lry, &x1, &y1); + if (x0 > x1) { + t = x0; x0 = x1; x1 = t; + } + if (y0 > y1) { + t = y0; y0 = y1; y1 = t; + } + rx = (double)state->getWinW() / (double)(x1 - x0); + ry = (double)state->getWinH() / (double)(y1 - y0); + dpi = tileMap->getDPI(page); + if (rx < ry) { + zoom = rx * (dpi / (0.01 * 72)); + } else { + zoom = ry * (dpi / (0.01 * 72)); + } + state->setZoom(zoom); + + // scroll to the requested page + state->setScrollPosition(page, tileMap->getPageLeftX(page), + tileMap->getPageTopY(page)); + + // scroll the requested rectangle to the center of the window + cvtUserToWindow(page, 0.5 * (ulx + lrx), 0.5 * (uly + lry), &x0, &y0); + sx = state->getScrollX() + x0 - state->getWinW() / 2; + sy = state->getScrollY() + y0 - state->getWinH() / 2; + state->setScrollPosition(page, sx, sy); + + finishUpdate(gTrue, gFalse); +} + +void PDFCore::zoomCentered(double zoom) { + int page, wx, wy, sx, sy; + double cx, cy; + + if (state->getZoom() == zoom) { + return; + } + + startUpdate(); + + // get the center of the window, in user coords + cvtWindowToUser(state->getWinW() / 2, state->getWinH() / 2, + &page, &cx, &cy); + + // set the new zoom level + state->setZoom(zoom); + + // scroll to re-center + cvtUserToWindow(page, cx, cy, &wx, &wy); + sx = state->getScrollX() + wx - state->getWinW() / 2; + sy = state->getScrollY() + wy - state->getWinH() / 2; + state->setScrollPosition(page, sx, sy); + + finishUpdate(gTrue, gFalse); +} + +// Zoom so that the current page(s) fill the window width. Maintain +// the vertical center. +void PDFCore::zoomToCurrentWidth() { + int page0, page1, page, gap; + double w, w1, zoom; + + startUpdate(); + + // get first and last pages + page0 = tileMap->getFirstPage(); + page1 = tileMap->getLastPage(); + + // compute the desired width (in points) + gap = 0; + switch (state->getDisplayMode()) { + case displaySingle: + default: + w = tileMap->getPageBoxWidth(page0); + break; + case displayContinuous: + w = 0; + for (page = page0; page <= page1; ++page) { + w1 = tileMap->getPageBoxWidth(page); + if (w1 > w) { + w = w1; + } + } + break; + case displaySideBySideSingle: + w = tileMap->getPageBoxWidth(page0); + if (page1 != page0) { + w += tileMap->getPageBoxWidth(page1); + gap = tileMap->getSideBySidePageSpacing(); + } + break; + case displaySideBySideContinuous: + w = 0; + for (page = page0; w <= page1; w += 2) { + w1 = tileMap->getPageBoxWidth(page); + if (page + 1 <= doc->getNumPages()) { + w1 += tileMap->getPageBoxWidth(page + 1); + } + if (w1 > w) { + w = w1; + } + } + gap = tileMap->getSideBySidePageSpacing(); + break; + case displayHorizontalContinuous: + w = 0; + gap = 0; + for (page = page0; page <= page1; ++page) { + w += tileMap->getPageBoxWidth(page); + if (page != page0) { + gap += tileMap->getHorizContinuousPageSpacing(); + } + } + break; + } + + // set the new zoom level + zoom = 100.0 * (state->getWinW() - gap) / w; + state->setZoom(zoom); + + // scroll so that the first page is at the left edge of the window + state->setScrollPosition(page0, tileMap->getPageLeftX(page0), + tileMap->getPageTopY(page0)); + + finishUpdate(gTrue, gFalse); +} + +void PDFCore::setRotate(int rotate) { + int page; + + if (state->getRotate() == rotate) { + return; + } + if (!doc || !doc->getNumPages()) { + state->setRotate(rotate); + return; + } + startUpdate(); + page = tileMap->getFirstPage(); + state->setRotate(rotate); + state->setScrollPosition(page, tileMap->getPageLeftX(page), + tileMap->getPageTopY(page)); + finishUpdate(gTrue, gTrue); +} + +void PDFCore::setDisplayMode(DisplayMode mode) { + int page; + + if (state->getDisplayMode() == mode) { + return; + } + if (!doc || !doc->getNumPages()) { + state->setDisplayMode(mode); + return; + } + startUpdate(); + page = tileMap->getFirstPage(); + state->setDisplayMode(mode); + state->setScrollPosition(page, tileMap->getPageLeftX(page), + tileMap->getPageTopY(page)); + finishUpdate(gTrue, gTrue); +} + +void PDFCore::setOCGState(OptionalContentGroup *ocg, GBool ocgState) { + if (ocgState != ocg->getState()) { + ocg->setState(ocgState); + state->optionalContentChanged(); + invalidateWholeWindow(); + } +} + +void PDFCore::setSelectMode(SelectMode mode) { + if (mode != selectMode) { + selectMode = mode; + clearSelection(); + } +} + +SplashColorPtr PDFCore::getSelectionColor() { + return state->getSelectColor(); +} + +void PDFCore::setSelectionColor(SplashColor color) { + int wx0, wy0, wx1, wy1; + + state->setSelectColor(color); + if (state->hasSelection()) { + getSelectionBBox(&wx0, &wy0, &wx1, &wy1); + checkInvalidate(wx0, wy0, wx1 - wx0, wy1 - wy0); + } +} + +void PDFCore::setSelection(int page, int x0, int y0, int x1, int y1) { + SelectRect *rect; + GBool moveLeft, moveTop, moveRight, moveBottom, needScroll; + double selectX0, selectY0, selectX1, selectY1; + int oldWx0, oldWy0, oldWx1, oldWy1, ix0, iy0, ix1, iy1; + int wx0, wy0, wx1, wy1, sx, sy, t; + + + // if selection rectangle is empty, clear the selection + if (x0 == x1 || y0 == y1) { + clearSelection(); + return; + } + + // x0 = left, x1 = right + // y0 = top, y1 = bottom + if (x0 > x1) { + t = x0; x0 = x1; x1 = t; + } + if (y0 > y1) { + t = y0; y0 = y1; y1 = t; + } + + // convert new selection coords to user space and window space + tileMap->cvtDevToUser(page, x0, y0, &selectX0, &selectY0); + tileMap->cvtDevToUser(page, x1, y1, &selectX1, &selectY1); + cvtUserToWindow(page, selectX0, selectY0, &wx0, &wy0); + cvtUserToWindow(page, selectX1, selectY1, &wx1, &wy1); + if (wx0 > wx1) { + t = wx0; wx0 = wx1; wx1 = t; + } + if (wy0 > wy1) { + t = wy0; wy0 = wy1; wy1 = t; + } + + // convert current selection coords to window space; + // check which edges moved + if (state->hasSelection()) { + rect = state->getSelectRect(0); + tileMap->cvtUserToWindow(rect->page, rect->x0, rect->y0, &oldWx0, &oldWy0); + tileMap->cvtUserToWindow(rect->page, rect->x1, rect->y1, &oldWx1, &oldWy1); + if (oldWx0 > oldWx1) { + t = oldWx0; oldWx0 = oldWx1; oldWx1 = t; + } + if (oldWy0 > oldWy1) { + t = oldWy0; oldWy0 = oldWy1; oldWy1 = t; + } + moveLeft = wx0 != oldWx0; + moveTop = wy0 != oldWy0; + moveRight = wx1 != oldWx1; + moveBottom = wy1 != oldWy1; + } else { + oldWx0 = wx0; + oldWy0 = wy0; + oldWx1 = wx1; + oldWy1 = wy1; + moveLeft = moveTop = moveRight = moveBottom = gTrue; + } + + // set the new selection + state->setSelection(page, selectX0, selectY0, selectX1, selectY1); + + // scroll if necessary + needScroll = gFalse; + sx = state->getScrollX(); + sy = state->getScrollY(); + if (moveLeft && wx0 < 0) { + sx += wx0; + needScroll = gTrue; + } else if (moveRight && wx1 >= state->getWinW()) { + sx += wx1 - state->getWinW(); + needScroll = gTrue; + } else if (moveLeft && wx0 >= state->getWinW()) { + sx += wx0 - state->getWinW(); + needScroll = gTrue; + } else if (moveRight && wx1 < 0) { + sx += wx1; + needScroll = gTrue; + } + if (moveTop && wy0 < 0) { + sy += wy0; + needScroll = gTrue; + } else if (moveBottom && wy1 >= state->getWinH()) { + sy += wy1 - state->getWinH(); + needScroll = gTrue; + } else if (moveTop && wy0 >= state->getWinH()) { + sy += wy0 - state->getWinH(); + needScroll = gTrue; + } else if (moveBottom && wy1 < 0) { + sy += wy1; + needScroll = gTrue; + } + if (needScroll) { + scrollTo(sx, sy); + } else { + ix0 = (wx0 < oldWx0) ? wx0 : oldWx0; + iy0 = (wy0 < oldWy0) ? wy0 : oldWy0; + ix1 = (wx1 > oldWx1) ? wx1 : oldWx1; + iy1 = (wy1 > oldWy1) ? wy1 : oldWy1; + checkInvalidate(ix0, iy0, ix1 - ix0, iy1 - iy0); + } +} + +void PDFCore::setLinearSelection(int page, TextPosition *pos0, + TextPosition *pos1) { + TextPosition begin, end; + GList *rects; + GBool moveLeft, moveTop, moveRight, moveBottom, needScroll; + double x0, y0, x1, y1, x2, y2, x3, y3; + double ux0, uy0, ux1, uy1; + int oldWx0, oldWy0, oldWx1, oldWy1, ix0, iy0, ix1, iy1; + int wx0, wy0, wx1, wy1; + int sx, sy, colIdx; + + + // if selection rectangle is empty, clear the selection + if (*pos0 == *pos1) { + clearSelection(); + return; + } + + // swap into correct order + if (*pos0 < *pos1) { + begin = *pos0; + end = *pos1; + } else { + begin = *pos1; + end = *pos0; + } + + // build the list of rectangles + //~ this doesn't handle RtL, vertical, or rotated text + loadText(page); + rects = new GList(); + if (begin.colIdx == end.colIdx && + begin.parIdx == end.parIdx && + begin.lineIdx == end.lineIdx) { + // same line + text->convertPosToPointUpper(&begin, &x0, &y0); + text->convertPosToPointLower(&end, &x1, &y1); + cvtDevToUser(page, (int)(x0 + 0.5), (int)(y0 + 0.5), &ux0, &uy0); + cvtDevToUser(page, (int)(x1 + 0.5), (int)(y1 + 0.5), &ux1, &uy1); + rects->append(new SelectRect(page, ux0, uy0, ux1, uy1)); + } else if (begin.colIdx == end.colIdx) { + // same column + text->convertPosToPointUpper(&begin, &x0, &y0); + text->convertPosToPointRightEdge(&begin, &x1, &y1); + text->convertPosToPointLeftEdge(&end, &x2, &y2); + text->convertPosToPointLower(&end, &x3, &y3); + cvtDevToUser(page, (int)(x0 + 0.5), (int)(y0 + 0.5), &ux0, &uy0); + cvtDevToUser(page, (int)(x1 + 0.5), (int)(y1 + 0.5), &ux1, &uy1); + rects->append(new SelectRect(page, ux0, uy0, ux1, uy1)); + cvtDevToUser(page, (int)(x2 + 0.5), (int)(y1 + 0.5), &ux0, &uy0); + cvtDevToUser(page, (int)(x1 + 0.5), (int)(y2 + 0.5), &ux1, &uy1); + rects->append(new SelectRect(page, ux0, uy0, ux1, uy1)); + cvtDevToUser(page, (int)(x2 + 0.5), (int)(y2 + 0.5), &ux0, &uy0); + cvtDevToUser(page, (int)(x3 + 0.5), (int)(y3 + 0.5), &ux1, &uy1); + rects->append(new SelectRect(page, ux0, uy0, ux1, uy1)); + } else { + // different columns + text->convertPosToPointUpper(&begin, &x0, &y0); + text->convertPosToPointRightEdge(&begin, &x1, &y1); + text->getColumnLowerLeft(begin.colIdx, &x2, &y2); + cvtDevToUser(page, (int)(x0 + 0.5), (int)(y0 + 0.5), &ux0, &uy0); + cvtDevToUser(page, (int)(x1 + 0.5), (int)(y1 + 0.5), &ux1, &uy1); + rects->append(new SelectRect(page, ux0, uy0, ux1, uy1)); + cvtDevToUser(page, (int)(x2 + 0.5), (int)(y1 + 0.5), &ux0, &uy0); + cvtDevToUser(page, (int)(x1 + 0.5), (int)(y2 + 0.5), &ux1, &uy1); + rects->append(new SelectRect(page, ux0, uy0, ux1, uy1)); + for (colIdx = begin.colIdx + 1; colIdx < end.colIdx; ++colIdx) { + text->getColumnLowerLeft(colIdx, &x0, &y0); + text->getColumnUpperRight(colIdx, &x1, &y1); + cvtDevToUser(page, (int)(x0 + 0.5), (int)(y1 + 0.5), &ux0, &uy0); + cvtDevToUser(page, (int)(x1 + 0.5), (int)(y0 + 0.5), &ux1, &uy1); + rects->append(new SelectRect(page, ux0, uy0, ux1, uy1)); + } + text->getColumnUpperRight(end.colIdx, &x0, &y0); + text->convertPosToPointLeftEdge(&end, &x1, &y1); + text->convertPosToPointLower(&end, &x2, &y2); + cvtDevToUser(page, (int)(x1 + 0.5), (int)(y0 + 0.5), &ux0, &uy0); + cvtDevToUser(page, (int)(x0 + 0.5), (int)(y1 + 0.5), &ux1, &uy1); + rects->append(new SelectRect(page, ux0, uy0, ux1, uy1)); + cvtDevToUser(page, (int)(x1 + 0.5), (int)(y1 + 0.5), &ux0, &uy0); + cvtDevToUser(page, (int)(x2 + 0.5), (int)(y2 + 0.5), &ux1, &uy1); + rects->append(new SelectRect(page, ux0, uy0, ux1, uy1)); + } + + // get window coord bboxes for old selection and new selection; + // check which edges moved + if (state->hasSelection()) { + getSelectionBBox(&oldWx0, &oldWy0, &oldWx1, &oldWy1); + getSelectRectListBBox(rects, &wx0, &wy0, &wx1, &wy1); + moveLeft = wx0 != oldWx0; + moveTop = wy0 != oldWy0; + moveRight = wx1 != oldWx1; + moveBottom = wy1 != oldWy1; + } else { + getSelectRectListBBox(rects, &wx0, &wy0, &wx1, &wy1); + oldWx0 = wx0; + oldWy0 = wy0; + oldWx1 = wx1; + oldWy1 = wy1; + moveLeft = moveTop = moveRight = moveBottom = gTrue; + } + + // set the new selection + state->setSelection(rects); + + // scroll if necessary + needScroll = gFalse; + sx = state->getScrollX(); + sy = state->getScrollY(); + if (moveLeft && wx0 < 0) { + sx += wx0; + needScroll = gTrue; + } else if (moveRight && wx1 >= state->getWinW()) { + sx += wx1 - state->getWinW(); + needScroll = gTrue; + } else if (moveLeft && wx0 >= state->getWinW()) { + sx += wx0 - state->getWinW(); + needScroll = gTrue; + } else if (moveRight && wx1 < 0) { + sx += wx1; + needScroll = gTrue; + } + if (moveTop && wy0 < 0) { + sy += wy0; + needScroll = gTrue; + } else if (moveBottom && wy1 >= state->getWinH()) { + sy += wy1 - state->getWinH(); + needScroll = gTrue; + } else if (moveTop && wy0 >= state->getWinH()) { + sy += wy0 - state->getWinH(); + needScroll = gTrue; + } else if (moveBottom && wy1 < 0) { + sy += wy1; + needScroll = gTrue; + } + if (needScroll) { + scrollTo(sx, sy); + } else { + ix0 = (wx0 < oldWx0) ? wx0 : oldWx0; + iy0 = (wy0 < oldWy0) ? wy0 : oldWy0; + ix1 = (wx1 > oldWx1) ? wx1 : oldWx1; + iy1 = (wy1 > oldWy1) ? wy1 : oldWy1; + checkInvalidate(ix0, iy0, ix1 - ix0, iy1 - iy0); + } +} + +void PDFCore::clearSelection() { + int wx0, wy0, wx1, wy1; + + if (state->hasSelection()) { + getSelectionBBox(&wx0, &wy0, &wx1, &wy1); + state->clearSelection(); + checkInvalidate(wx0, wy0, wx1 - wx0, wy1 - wy0); + } +} + +void PDFCore::startSelectionDrag(int pg, int x, int y) { + clearSelection(); + if (selectMode == selectModeBlock) { + selectPage = pg; + selectStartX = x; + selectStartY = y; + } else { // selectModeLinear + loadText(pg); + if (text->findPointInside(x, y, &selectStartPos)) { + selectPage = pg; + } else { + selectPage = 0; + } + } +} + +void PDFCore::moveSelectionDrag(int pg, int x, int y) { + TextPosition pos; + + // don't allow selections to span multiple pages + // -- this also handles the case where a linear selection was started + // outside any text column, in which case selectPage = 0 + if (pg != selectPage) { + return; + } + + if (selectMode == selectModeBlock) { + setSelection(pg, selectStartX, selectStartY, x, y); + } else { // selectModeLinear + loadText(pg); + if (text->findPointNear(x, y, &pos)) { + setLinearSelection(pg, &selectStartPos, &pos); + } + } +} + +void PDFCore::finishSelectionDrag() { + // nothing +} + +void PDFCore::selectWord(int pg, int x, int y) { + TextPosition endPos; + + loadText(pg); + if (text->findWordPoints(x, y, &selectStartPos, &endPos)) { + selectPage = pg; + setLinearSelection(pg, &selectStartPos, &endPos); + } else { + selectPage = 0; + } +} + +void PDFCore::selectLine(int pg, int x, int y) { + TextPosition endPos; + + loadText(pg); + if (text->findLinePoints(x, y, &selectStartPos, &endPos)) { + selectPage = pg; + setLinearSelection(pg, &selectStartPos, &endPos); + } else { + selectPage = 0; + } +} + +GBool PDFCore::getSelection(int *pg, double *ulx, double *uly, + double *lrx, double *lry) { + SelectRect *rect; + double xMin, yMin, xMax, yMax; + int page, i; + + if (!state->hasSelection()) { + return gFalse; + } + page = state->getSelectRect(0)->page; + xMin = yMin = xMax = yMax = 0; + for (i = 0; i < state->getNumSelectRects(); ++i) { + rect = state->getSelectRect(i); + if (rect->page != page) { + continue; + } + if (i == 0) { + xMin = xMax = rect->x0; + yMin = yMax = rect->y0; + } else { + if (rect->x0 < xMin) { + xMin = rect->x0; + } else if (rect->x0 > xMax) { + xMax = rect->x0; + } + if (rect->y0 < yMin) { + yMin = rect->y0; + } else if (rect->y0 > yMax) { + yMax = rect->y0; + } + } + if (rect->x1 < xMin) { + xMin = rect->x1; + } else if (rect->x1 > xMax) { + xMax = rect->x1; + } + if (rect->y1 < yMin) { + yMin = rect->y1; + } else if (rect->y1 > yMax) { + yMax = rect->y1; + } + } + *pg = page; + *ulx = xMin; + *uly = yMax; + *lrx = xMax; + *lry = yMin; + return gTrue; +} + +GBool PDFCore::hasSelection() { + return state->hasSelection(); +} + +void PDFCore::setTextExtractionMode(TextOutputMode mode) { + if (textOutCtrl.mode != mode) { + textOutCtrl.mode = mode; + if (text) { + delete text; + text = NULL; + } + textPage = 0; + textDPI = 0; + textRotate = 0; + } +} + +GBool PDFCore::getDiscardDiagonalText() { + return textOutCtrl.discardDiagonalText; +} + +void PDFCore::setDiscardDiagonalText(GBool discard) { + if (textOutCtrl.discardDiagonalText != discard) { + textOutCtrl.discardDiagonalText = discard; + if (text) { + delete text; + text = NULL; + } + textPage = 0; + textDPI = 0; + textRotate = 0; + } +} + +GString *PDFCore::extractText(int pg, double xMin, double yMin, + double xMax, double yMax) { + int x0, y0, x1, y1, t; + + loadText(pg); + cvtUserToDev(pg, xMin, yMin, &x0, &y0); + cvtUserToDev(pg, xMax, yMax, &x1, &y1); + if (x0 > x1) { + t = x0; x0 = x1; x1 = t; + } + if (y0 > y1) { + t = y0; y0 = y1; y1 = t; + } + return text->getText(x0, y0, x1, y1); +} + +GString *PDFCore::getSelectedText() { + SelectRect *rect; + GString *ret, *s; + int x0, y0, x1, y1, t, i; + + if (!state->hasSelection()) { + return NULL; + } + ret = new GString(); + for (i = 0; i < state->getNumSelectRects(); ++i) { + rect = state->getSelectRect(i); + loadText(rect->page); + cvtUserToDev(rect->page, rect->x0, rect->y0, &x0, &y0); + cvtUserToDev(rect->page, rect->x1, rect->y1, &x1, &y1); + if (x0 > x1) { + t = x0; x0 = x1; x1 = t; + } + if (y0 > y1) { + t = y0; y0 = y1; y1 = t; + } + s = text->getText(x0, y0, x1, y1, state->getNumSelectRects() > 1); + ret->append(s); + delete s; + } + return ret; +} + +GBool PDFCore::find(char *s, GBool caseSensitive, GBool next, GBool backward, + GBool wholeWord, GBool onePageOnly) { + Unicode *u; + int len, i; + GBool ret; + + // convert to Unicode + 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, wholeWord, onePageOnly); + + gfree(u); + return ret; +} + +GBool PDFCore::findU(Unicode *u, int len, GBool caseSensitive, + GBool next, GBool backward, GBool wholeWord, + GBool onePageOnly) { + TextOutputDev *textOut; + SelectRect *rect; + double xMin, yMin, xMax, yMax; + int topPage, pg, x, y, x2, y2; + GBool startAtTop, startAtLast, stopAtLast; + + // check for zero-length string + if (len == 0) { + return gFalse; + } + + setBusyCursor(gTrue); + + // search current page starting at previous result, current + // selection, or top/bottom of page + startAtTop = startAtLast = gFalse; + rect = NULL; + xMin = yMin = xMax = yMax = 0; + topPage = tileMap->getFirstPage(); + pg = topPage; + if (next) { + if (textPage >= 1 && textPage <= doc->getNumPages()) { + startAtLast = gTrue; + pg = textPage; + } + } else if (state->hasSelection()) { + rect = state->getSelectRect(0); + pg = rect->page; + cvtUserToDev(pg, rect->x0, rect->y0, &x, &y); + cvtUserToDev(pg, rect->x1, rect->y1, &x2, &y2); + if (x2 < x) { + x = x2; + } + if (y2 < y) { + y = y2; + } + if (backward) { + xMin = x - 1; + yMin = y - 1; + } else { + xMin = x + 1; + yMin = y + 1; + } + } else { + startAtTop = gTrue; + } + loadText(pg); + if (text->findText(u, len, startAtTop, gTrue, startAtLast, gFalse, + caseSensitive, backward, wholeWord, + &xMin, &yMin, &xMax, &yMax)) { + goto found; + } + + if (!onePageOnly) { + + // search following/previous pages + textOut = new TextOutputDev(NULL, &textOutCtrl, gFalse); + if (!textOut->isOk()) { + delete textOut; + goto notFound; + } + for (pg = backward ? pg - 1 : pg + 1; + backward ? pg >= 1 : pg <= doc->getNumPages(); + 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, wholeWord, + &xMin, &yMin, &xMax, &yMax)) { + delete textOut; + goto foundPage; + } + } + + // search previous/following pages + for (pg = backward ? doc->getNumPages() : 1; + backward ? pg > topPage : pg < topPage; + 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, wholeWord, + &xMin, &yMin, &xMax, &yMax)) { + delete textOut; + goto foundPage; + } + } + delete textOut; + + } + + // search current page ending at previous result, current selection, + // or bottom/top of page + if (!startAtTop) { + xMin = yMin = xMax = yMax = 0; + if (next) { + stopAtLast = gTrue; + } else { + stopAtLast = gFalse; + cvtUserToDev(pg, rect->x1, rect->y1, &x, &y); + xMax = x; + yMax = y; + } + if (text->findText(u, len, gTrue, gFalse, gFalse, stopAtLast, + caseSensitive, backward, wholeWord, + &xMin, &yMin, &xMax, &yMax)) { + goto found; + } + } + + // not found + notFound: + setBusyCursor(gFalse); + return gFalse; + + // found on a different page + foundPage: + displayPage(pg, gTrue, gFalse); + loadText(pg); + if (!text->findText(u, len, gTrue, gTrue, gFalse, gFalse, + caseSensitive, backward, wholeWord, + &xMin, &yMin, &xMax, &yMax)) { + // this can happen if coalescing is bad + goto notFound; + } + + // found: change the selection + found: + setSelection(pg, (int)floor(xMin), (int)floor(yMin), + (int)ceil(xMax), (int)ceil(yMax)); + + setBusyCursor(gFalse); + return gTrue; +} + +GList *PDFCore::findAll(Unicode *u, int len, GBool caseSensitive, + GBool wholeWord, int firstPage, int lastPage) { + GList *results = new GList(); + + TextOutputDev *textOut = new TextOutputDev(NULL, &textOutCtrl, gFalse); + if (!textOut->isOk()) { + delete textOut; + return results; + } + + for (int pg = firstPage; pg <= lastPage; ++pg) { + doc->displayPage(textOut, pg, 72, 72, 0, gFalse, gTrue, gFalse); + GBool first = gTrue; + while (1) { + double xMin, yMin, xMax, yMax; + if (!textOut->findText(u, len, first, gTrue, !first, gFalse, + caseSensitive, gFalse, wholeWord, + &xMin, &yMin, &xMax, &yMax)) { + break; + } + double uxMin, uyMin, uxMax, uyMax, t; + textOut->cvtDevToUser(xMin, yMin, &uxMin, &uyMin); + textOut->cvtDevToUser(xMax, yMax, &uxMax, &uyMax); + if (uxMin > uxMax) { + t = uxMin; uxMin = uxMax; uxMax = t; + } + if (uyMin > uyMax) { + t = uyMin; uyMin = uyMax; uyMax = t; + } + results->append(new FindResult(pg, uxMin, uyMin, uxMax, uyMax)); + first = gFalse; + } + } + + delete textOut; + + return results; +} + + +GBool PDFCore::cvtWindowToUser(int xw, int yw, + int *pg, double *xu, double *yu) { + return tileMap->cvtWindowToUser(xw, yw, pg, xu, yu); +} + +GBool PDFCore::cvtWindowToDev(int xw, int yw, int *pg, int *xd, int *yd) { + return tileMap->cvtWindowToDev(xw, yw, pg, xd, yd); +} + +GBool PDFCore::cvtUserToWindow(int pg, double xu, double yu, int *xw, int *yw) { + return tileMap->cvtUserToWindow(pg, xu, yu, xw, yw); +} + +void PDFCore::cvtUserToDev(int pg, double xu, double yu, int *xd, int *yd) { + tileMap->cvtUserToDev(pg, xu, yu, xd, yd); +} + +GBool PDFCore::cvtDevToWindow(int pg, int xd, int yd, int *xw, int *yw) { + return tileMap->cvtDevToWindow(pg, xd, yd, xw, yw); +} + +void PDFCore::cvtDevToUser(int pg, int xd, int yd, double *xu, double *yu) { + tileMap->cvtDevToUser(pg, xd, yd, xu, yu); +} + +void PDFCore::getWindowPageRange(int x, int y, int w, int h, + int *firstPage, int *lastPage) { + tileMap->getWindowPageRange(x, y, w, h, firstPage, lastPage); +} + +int PDFCore::getPageNum() { + if (!doc || !doc->getNumPages()) { + return 0; + } + return tileMap->getFirstPage(); +} + +int PDFCore::getMidPageNum() { + if (!doc || !doc->getNumPages()) { + return 0; + } + return tileMap->getMidPage(); +} + +double PDFCore::getZoom() { + return state->getZoom(); +} + +double PDFCore::getZoomDPI(int page) { + if (!doc) { + return 0; + } + return tileMap->getDPI(page); +} + +int PDFCore::getRotate() { + return state->getRotate(); +} + +DisplayMode PDFCore::getDisplayMode() { + return state->getDisplayMode(); +} + +int PDFCore::getScrollX() { + return state->getScrollX(); +} + +int PDFCore::getScrollY() { + return state->getScrollY(); +} + +int PDFCore::getWindowWidth() { + return state->getWinW(); +} + +int PDFCore::getWindowHeight() { + return state->getWinH(); +} + +void PDFCore::setPaperColor(SplashColorPtr paperColor) { + state->setPaperColor(paperColor); + invalidateWholeWindow(); +} + +void PDFCore::setMatteColor(SplashColorPtr matteColor) { + state->setMatteColor(matteColor); + invalidateWholeWindow(); +} + +void PDFCore::setReverseVideo(GBool reverseVideo) { + SplashColorPtr oldPaperColor; + SplashColor newPaperColor; + int i; + + if (reverseVideo != state->getReverseVideo()) { + state->setReverseVideo(reverseVideo); + oldPaperColor = state->getPaperColor(); + for (i = 0; i < splashColorModeNComps[state->getColorMode()]; ++i) { + newPaperColor[i] = oldPaperColor[i] ^ 0xff; + } + state->setPaperColor(newPaperColor); + invalidateWholeWindow(); + } +} + + + +LinkAction *PDFCore::findLink(int pg, double x, double y) { + loadLinks(pg); + return links->find(x, y); +} + +Annot *PDFCore::findAnnot(int pg, double x, double y) { + loadAnnots(pg); + return annots->find(x, y); +} + +int PDFCore::findAnnotIdx(int pg, double x, double y) { + loadAnnots(pg); + return annots->findIdx(x, y); +} + +Annot *PDFCore::getAnnot(int idx) { + if (!annots) { + return NULL; + } + if (idx < 0 || idx >= annots->getNumAnnots()) { + return NULL; + } + return annots->getAnnot(idx); +} + +AcroFormField *PDFCore::findFormField(int pg, double x, double y) { + if (!doc->getCatalog()->getForm()) { + return NULL; + } + return doc->getCatalog()->getForm()->findField(pg, x, y); +} + +int PDFCore::findFormFieldIdx(int pg, double x, double y) { + if (!doc->getCatalog()->getForm()) { + return -1; + } + return doc->getCatalog()->getForm()->findFieldIdx(pg, x, y); +} + +AcroFormField *PDFCore::getFormField(int idx) { + if (!doc->getCatalog()->getForm()) { + return NULL; + } + if (idx < 0 || idx >= doc->getCatalog()->getForm()->getNumFields()) { + return NULL; + } + return doc->getCatalog()->getForm()->getField(idx); +} + +GBool PDFCore::overText(int pg, double x, double y) { + loadText(pg); + return text->checkPointInside(x, y); +} + +void PDFCore::forceRedraw() { + startUpdate(); + state->forceRedraw(); + finishUpdate(gFalse, gFalse); +} + +void PDFCore::setTileDoneCbk(void (*cbk)(void *data), void *data) { + tileCache->setTileDoneCbk(cbk, data); +} + +void PDFCore::setWindowSize(int winWidth, int winHeight) { + GBool doScroll; + int page, wx0, wy0, wx, wy, sx, sy; + double ux, uy; + + startUpdate(); + + wx0 = wy0 = 0; // make gcc happy + doScroll = gFalse; + if (state->getZoom() < 0 && state->displayModeIsContinuous()) { + // save the user coordinates of the appropriate edge of the window + if (state->getDisplayMode() == displayHorizontalContinuous) { + wx0 = 0; + wy0 = state->getWinH() / 2; + } else { + wx0 = state->getWinW() / 2; + wy0 = 0; + } + if (!(doScroll = cvtWindowToUser(wx0, wy0, &page, &ux, &uy))) { + // tweak the save position if it happens to fall in a gutter + if (state->getDisplayMode() == displayContinuous) { + wy0 += tileMap->getContinuousPageSpacing(); + } else if (state->getDisplayMode() == displaySideBySideContinuous) { + wx0 += tileMap->getSideBySidePageSpacing(); + wy0 += tileMap->getContinuousPageSpacing(); + } else { // state->getDisplayMode() == displayHorizontalContinuous + wx0 += tileMap->getHorizContinuousPageSpacing(); + } + doScroll = cvtWindowToUser(wx0, wy0, &page, &ux, &uy); + } + } + + state->setWindowSize(winWidth, winHeight); + + if (doScroll) { + // restore the saved scroll position + cvtUserToWindow(page, ux, uy, &wx, &wy); + sx = state->getScrollX(); + sy = state->getScrollY(); + if (state->getDisplayMode() == displayHorizontalContinuous) { + sx += wx - wx0; + } else { + sy += wy - wy0; + } + state->setScrollPosition(page, sx, sy); + } + + finishUpdate(gTrue, gFalse); +} + +SplashBitmap *PDFCore::getWindowBitmap(GBool wholeWindow) { + GBool dummy; + + return tileCompositor->getBitmap(wholeWindow ? &bitmapFinished : &dummy); +} + +void PDFCore::tick() { + if (!bitmapFinished) { + invalidateWholeWindow(); + } +} + +// Clear cached info (links, text) that's tied to a PDFDoc. +void PDFCore::clearPage() { + if (links) { + delete links; + } + links = NULL; + linksPage = 0; + + if (annots) { + delete annots; + } + annots = NULL; + annotsPage = 0; + + if (text) { + delete text; + } + text = NULL; + textPage = 0; + textDPI = 0; + textRotate = 0; +} + +// Load the links for . +void PDFCore::loadLinks(int pg) { + if (links && linksPage == pg) { + return; + } + if (links) { + delete links; + } + links = doc->getLinks(pg); + linksPage = pg; +} + +// Load the annotations for . +void PDFCore::loadAnnots(int pg) { + Object annotsObj; + + if (annots && annotsPage == pg) { + return; + } + if (annots) { + delete annots; + } + doc->getCatalog()->getPage(pg)->getAnnots(&annotsObj); + annots = new Annots(doc, &annotsObj); + annotsObj.free(); + annotsPage = pg; +} + +// Extract text from . +void PDFCore::loadText(int pg) { + TextOutputDev *textOut; + double dpi; + int rotate; + + dpi = tileMap->getDPI(pg); + rotate = state->getRotate(); + if (text && textPage == pg && textDPI == dpi && textRotate == rotate) { + return; + } + if (text) { + delete text; + } + textOut = new TextOutputDev(NULL, &textOutCtrl, gFalse); + if (!textOut->isOk()) { + text = new TextPage(&textOutCtrl); + } else { + doc->displayPage(textOut, pg, dpi, dpi, rotate, gFalse, gTrue, gFalse); + text = textOut->takeText(); + } + delete textOut; + textPage = pg; + textDPI = dpi; + textRotate = rotate; +} + +void PDFCore::getSelectionBBox(int *wxMin, int *wyMin, int *wxMax, int *wyMax) { + *wxMin = *wyMin = *wxMax = *wyMax = 0; + if (!state->hasSelection()) { + return; + } + getSelectRectListBBox(state->getSelectRects(), wxMin, wyMin, wxMax, wyMax); +} + +void PDFCore::getSelectRectListBBox(GList *rects, int *wxMin, int *wyMin, + int *wxMax, int *wyMax) { + SelectRect *rect; + int x, y, i; + + *wxMin = *wyMin = *wxMax = *wyMax = 0; + for (i = 0; i < rects->getLength(); ++i) { + rect = (SelectRect *)rects->get(i); + tileMap->cvtUserToWindow(rect->page, rect->x0, rect->y0, &x, &y); + if (i == 0) { + *wxMin = *wxMax = x; + *wyMin = *wyMax = y; + } else { + if (x < *wxMin) { + *wxMin = x; + } else if (x > *wxMax) { + *wxMax = x; + } + if (y < *wyMin) { + *wyMin = y; + } else if (y > *wyMax) { + *wyMax = y; + } + } + tileMap->cvtUserToWindow(rect->page, rect->x1, rect->y1, &x, &y); + if (x < *wxMin) { + *wxMin = x; + } else if (x > *wxMax) { + *wxMax = x; + } + if (y < *wyMin) { + *wyMin = y; + } else if (y > *wyMax) { + *wyMax = y; + } + } +} + +void PDFCore::checkInvalidate(int x, int y, int w, int h) { + if (x < 0) { + w += x; + x = 0; + } + if (x + w > state->getWinW()) { + w = state->getWinW() - x; + } + if (w <= 0) { + return; + } + if (y < 0) { + h += y; + y = 0; + } + if (y + h > state->getWinH()) { + h = state->getWinH() - y; + } + if (h <= 0) { + return; + } + invalidate(x, y, w, h); +} + +void PDFCore::invalidateWholeWindow() { + invalidate(0, 0, state->getWinW(), state->getWinH()); +} diff --git a/xpdf/PDFCore.h b/xpdf/PDFCore.h new file mode 100644 index 0000000..accf19d --- /dev/null +++ b/xpdf/PDFCore.h @@ -0,0 +1,357 @@ +//======================================================================== +// +// PDFCore.h +// +// Copyright 2004-2014 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef PDFCORE_H +#define PDFCORE_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include +#include "SplashTypes.h" +#include "CharTypes.h" +#include "DisplayState.h" +#include "TextOutputDev.h" + +class GString; +class GList; +class SplashBitmap; +class SplashPattern; +class BaseStream; +class PDFDoc; +class Links; +class LinkDest; +class LinkAction; +class Annot; +class Annots; +class AcroFormField; +class TextPage; +class HighlightFile; +class OptionalContentGroup; +class TileMap; +class TileCache; +class TileCompositor; +class PDFCore; + +//------------------------------------------------------------------------ +// PDFHistory +//------------------------------------------------------------------------ + +struct PDFHistory { +#ifdef _WIN32 + wchar_t *fileName; +#else + GString *fileName; +#endif + int page; +}; + +#define pdfHistorySize 50 + +//------------------------------------------------------------------------ +// SelectMode +//------------------------------------------------------------------------ + +enum SelectMode { + selectModeBlock, + selectModeLinear +}; + +//------------------------------------------------------------------------ +// FindResult +//------------------------------------------------------------------------ + +struct FindResult { + FindResult(int pageA, double xMinA, double yMinA, double xMaxA, double yMaxA) + : page(pageA), xMin(xMinA), yMin(yMinA), xMax(xMaxA), yMax(yMaxA) {} + int page; + double xMin, yMin, xMax, yMax; +}; + +//------------------------------------------------------------------------ +// PDFCore +//------------------------------------------------------------------------ + +class PDFCore { +public: + + PDFCore(SplashColorMode colorMode, int bitmapRowPad, + GBool reverseVideo, SplashColorPtr paperColor); + virtual ~PDFCore(); + + //----- loadFile / displayPage / displayDest + + // Load a new file. Returns pdfOk or error code. + virtual int loadFile(GString *fileName, GString *ownerPassword = NULL, + GString *userPassword = NULL); + +#ifdef _WIN32 + // Load a new file. Returns pdfOk or error code. + virtual int loadFile(wchar_t *fileName, int fileNameLen, + GString *ownerPassword = NULL, + GString *userPassword = NULL); +#endif + + // Load a new file, via a Stream instead of a file name. Returns + // pdfOk or error code. + virtual int loadFile(BaseStream *stream, GString *ownerPassword = NULL, + GString *userPassword = NULL); + + // Load an already-created PDFDoc object. + virtual void loadDoc(PDFDoc *docA); + + // Reload the current file. This only works if the PDF was loaded + // via a file. Returns pdfOk or error code. + virtual int reload(); + + // Clear out the current document, if any. + virtual void clear(); + + // Same as clear(), but returns the PDFDoc object instead of + // deleting it. + virtual PDFDoc *takeDoc(GBool redraw); + + // Display (or redisplay) the specified page. If is + // set, the window is vertically scrolled to the top; if + // is set, the window is vertically scrolled to the + // bottom; otherwise, no scrolling is done. If is set, + // this page change is added to the history list. + virtual void displayPage(int page, GBool scrollToTop, + GBool scrollToBottom, GBool addToHist = gTrue); + + // Display a link destination. + virtual void displayDest(LinkDest *dest); + + // Called before any update is started. + virtual void startUpdate(); + + // Called after any update is complete. Subclasses can check for + // changes in the display parameters here. + virtual void finishUpdate(GBool addToHist, GBool checkForChangedFile); + + //----- page/position changes + + virtual GBool gotoNextPage(int inc, GBool top); + virtual GBool gotoPrevPage(int dec, GBool top, GBool bottom); + virtual GBool gotoNamedDestination(GString *dest); + virtual GBool goForward(); + virtual GBool goBackward(); + virtual void scrollLeft(int nCols = 16); + virtual void scrollRight(int nCols = 16); + virtual void scrollUp(int nLines = 16, GBool snapToPage = gFalse); + virtual void scrollUpPrevPage(int nLines = 16); + virtual void scrollDown(int nLines = 16, GBool snapToPage = gFalse); + virtual void scrollDownNextPage(int nLines = 16); + virtual void scrollPageUp(); + virtual void scrollPageDown(); + virtual void scrollTo(int x, int y, GBool snapToPage = gFalse); + virtual void scrollToLeftEdge(); + virtual void scrollToRightEdge(); + virtual void scrollToTopEdge(); + virtual void scrollToBottomEdge(); + virtual void scrollToTopLeft(); + virtual void scrollToBottomRight(); + // Scroll so that (page, x, y) is centered in the window. + virtual void scrollToCentered(int page, double x, double y); + virtual void setZoom(double zoom); + virtual void zoomToRect(int page, double ulx, double uly, + double lrx, double lry); + virtual void zoomCentered(double zoom); + virtual void zoomToCurrentWidth(); + virtual void setRotate(int rotate); + virtual void setDisplayMode(DisplayMode mode); + virtual void setOCGState(OptionalContentGroup *ocg, GBool ocgState); + + //----- selection + + // Selection mode. + SelectMode getSelectMode() { return selectMode; } + void setSelectMode(SelectMode mode); + + // Selection color. + SplashColorPtr getSelectionColor(); + void setSelectionColor(SplashColor color); + + // Modify the selection. These functions use device coordinates. + void setSelection(int page, int x0, int y0, int x1, int y1); + void setLinearSelection(int page, TextPosition *pos0, TextPosition *pos1); + void clearSelection(); + void startSelectionDrag(int pg, int x, int y); + void moveSelectionDrag(int pg, int x, int y); + void finishSelectionDrag(); + void selectWord(int pg, int x, int y); + void selectLine(int pg, int x, int y); + + // Retrieve the current selection. This function uses user + // coordinates. Returns false if there is no selection. + GBool getSelection(int *pg, double *ulx, double *uly, + double *lrx, double *lry); + GBool hasSelection(); + + // Text extraction. + void setTextExtractionMode(TextOutputMode mode); + GBool getDiscardDiagonalText(); + void setDiscardDiagonalText(GBool discard); + GString *extractText(int pg, double xMin, double yMin, + double xMax, double yMax); + GString *getSelectedText(); + + //----- find + + 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 wholeWord, + GBool onePageOnly); + GList *findAll(Unicode *u, int len, GBool caseSensitive, + GBool wholeWord, int firstPage, int lastPage); + + + //----- coordinate conversion + + // user space: per-page, as defined by PDF file; unit = point + // device space: (0,0) is upper-left corner of a page; unit = pixel + // window space: (0,0) is upper-left corner of drawing area; unit = pixel + + GBool cvtWindowToUser(int xw, int yw, int *pg, double *xu, double *yu); + GBool cvtWindowToDev(int xw, int yw, int *pg, int *xd, int *yd); + GBool cvtUserToWindow(int pg, double xy, double yu, int *xw, int *yw); + void cvtUserToDev(int pg, double xu, double yu, int *xd, int *yd); + GBool cvtDevToWindow(int pg, int xd, int yd, int *xw, int *yw); + void cvtDevToUser(int pg, int xd, int yd, double *xu, double *yu); + void getWindowPageRange(int x, int y, int w, int h, + int *firstPage, int *lastPage); + + //----- password dialog + + virtual GString *getPassword() { return NULL; } + + //----- misc access + + PDFDoc *getDoc() { return doc; } + int getPageNum(); + int getMidPageNum(); + double getZoom(); + double getZoomDPI(int page); + int getRotate(); + DisplayMode getDisplayMode(); + virtual void setPaperColor(SplashColorPtr paperColor); + virtual void setMatteColor(SplashColorPtr matteColor); + virtual void setReverseVideo(GBool reverseVideo); + GBool canGoBack() { return historyBLen > 1; } + GBool canGoForward() { return historyFLen > 0; } + int getScrollX(); + int getScrollY(); + int getWindowWidth(); + int getWindowHeight(); + virtual void setBusyCursor(GBool busy) = 0; + LinkAction *findLink(int pg, double x, double y); + Annot *findAnnot(int pg, double x, double y); + int findAnnotIdx(int pg, double x, double y); + Annot *getAnnot(int idx); + AcroFormField *findFormField(int pg, double x, double y); + int findFormFieldIdx(int pg, double x, double y); + AcroFormField *getFormField(int idx); + GBool overText(int pg, double x, double y); + void forceRedraw(); + void setTileDoneCbk(void (*cbk)(void *data), void *data); + +protected: + + //--- calls from PDFCore subclass + + // Set the window size (when the window is resized). + void setWindowSize(int winWidthA, int winHeightA); + + // Get the current window bitmap. If is true, the + // full window is being redrawn -- this is used to end incremental + // updates when the rasterization is done. + SplashBitmap *getWindowBitmap(GBool wholeWindow); + + // Returns true if the last call to getWindowBitmap() returned a + // finished bitmap; or false if the bitmap was still being + // rasterized. + GBool isBitmapFinished() { return bitmapFinished; } + + // This should be called periodically (typically every ~0.1 seconds) + // to do incremental updates. If an update is required, it will + // trigger a call to invalidate(). + virtual void tick(); + + //--- callbacks to PDFCore subclass + + // Invalidate the specified rectangle (in window coordinates). + virtual void invalidate(int x, int y, int w, int h) = 0; + + // Update the scrollbars. + virtual void updateScrollbars() = 0; + + // This returns true if the PDF file has changed on disk (if it can + // be checked). + virtual GBool checkForNewFile() { return gFalse; } + + // This is called just before a PDF file is loaded. + virtual void preLoad() {} + + // This is called just after a PDF file is loaded. + virtual void postLoad() {} + + //--- internal + + int loadFile2(PDFDoc *newDoc); + void addToHistory(); + void clearPage(); + void loadLinks(int pg); + void loadAnnots(int pg); + void loadText(int pg); + void getSelectionBBox(int *wxMin, int *wyMin, int *wxMax, int *wyMax); + void getSelectRectListBBox(GList *rects, int *wxMin, int *wyMin, + int *wxMax, int *wyMax); + void checkInvalidate(int x, int y, int w, int h); + void invalidateWholeWindow(); + + PDFDoc *doc; + + int linksPage; // cached links for one page + Links *links; + + int annotsPage; // cached annotations for one page + Annots *annots; + + int textPage; // cached extracted text for one page + double textDPI; + int textRotate; + TextOutputControl textOutCtrl; + TextPage *text; + + DisplayState *state; + TileMap *tileMap; + TileCache *tileCache; + TileCompositor *tileCompositor; + GBool bitmapFinished; + + SelectMode selectMode; + int selectPage; // page of current selection + int selectStartX, // for block mode: start point of current + selectStartY; // selection, in device coords + TextPosition selectStartPos; // for linear mode: start position of + // current selection + + PDFHistory // page history queue + history[pdfHistorySize]; + int historyCur; // currently displayed page + int historyBLen; // number of valid entries backward from + // current entry + int historyFLen; // number of valid entries forward from + // current entry +}; + +#endif diff --git a/xpdf/PDFDoc.cc b/xpdf/PDFDoc.cc new file mode 100644 index 0000000..3e9307d --- /dev/null +++ b/xpdf/PDFDoc.cc @@ -0,0 +1,679 @@ +//======================================================================== +// +// PDFDoc.cc +// +// Copyright 1996-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include +#include +#include +#ifdef _WIN32 +# include +#endif +#include "gmempp.h" +#include "GString.h" +#include "gfile.h" +#include "config.h" +#include "GlobalParams.h" +#include "Page.h" +#include "Catalog.h" +#include "Stream.h" +#include "XRef.h" +#include "Link.h" +#include "OutputDev.h" +#include "Error.h" +#include "ErrorCodes.h" +#include "Lexer.h" +#include "Parser.h" +#include "SecurityHandler.h" +#include "UTF8.h" +#ifndef DISABLE_OUTLINE +#include "Outline.h" +#endif +#include "OptionalContent.h" +#include "PDFDoc.h" + +//------------------------------------------------------------------------ + +#define headerSearchSize 1024 // read this many bytes at beginning of + // file to look for '%PDF' + +// Avoid sharing files with child processes on Windows, where sharing +// can cause problems. +#ifdef _WIN32 +# define fopenReadMode "rbN" +# define wfopenReadMode L"rbN" +#else +# define fopenReadMode "rb" +#endif + +//------------------------------------------------------------------------ +// PDFDoc +//------------------------------------------------------------------------ + +PDFDoc::PDFDoc(GString *fileNameA, GString *ownerPassword, + GString *userPassword, PDFCore *coreA) { + Object obj; + GString *fileName1, *fileName2; +#ifdef _WIN32 + int n, i; +#endif + + init(coreA); + + fileName = fileNameA; +#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(), fopenReadMode, "ctx=stm"))) { + error(errIO, -1, "Couldn't open file '{0:t}'", fileName1); + errCode = errOpenFile; + return; + } +#else + if (!(file = fopen(fileName1->getCString(), fopenReadMode))) { + fileName2 = fileName->copy(); + fileName2->lowerCase(); + if (!(file = fopen(fileName2->getCString(), fopenReadMode))) { + fileName2->upperCase(); + if (!(file = fopen(fileName2->getCString(), fopenReadMode))) { + error(errIO, -1, "Couldn't open file '{0:t}'", fileName); + delete fileName2; + errCode = errOpenFile; + return; + } + } + delete fileName2; + } +#endif + + // create stream + obj.initNull(); + str = new FileStream(file, 0, gFalse, 0, &obj); + + ok = setup(ownerPassword, userPassword); +} + +#ifdef _WIN32 +PDFDoc::PDFDoc(wchar_t *fileNameA, int fileNameLen, GString *ownerPassword, + GString *userPassword, PDFCore *coreA) { + OSVERSIONINFO version; + Object obj; + int i; + + init(coreA); + + // handle a Windows shortcut + wchar_t wPath[winMaxLongPath + 1]; + int n = fileNameLen < winMaxLongPath ? fileNameLen : winMaxLongPath; + memcpy(wPath, fileNameA, n * sizeof(wchar_t)); + wPath[n] = L'\0'; + readWindowsShortcut(wPath, winMaxLongPath + 1); + int wPathLen = (int)wcslen(wPath); + + // save both Unicode and 8-bit copies of the file name + fileName = new GString(); + fileNameU = (wchar_t *)gmallocn(wPathLen + 1, sizeof(wchar_t)); + memcpy(fileNameU, wPath, (wPathLen + 1) * sizeof(wchar_t)); + for (i = 0; i < wPathLen; ++i) { + fileName->append((char)fileNameA[i]); + } + + // 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(fileNameU, wfopenReadMode); + } else { + file = fopen(fileName->getCString(), fopenReadMode); + } + if (!file) { + error(errIO, -1, "Couldn't open file '{0:t}'", fileName); + errCode = errOpenFile; + return; + } + + // create stream + obj.initNull(); + str = new FileStream(file, 0, gFalse, 0, &obj); + + ok = setup(ownerPassword, userPassword); +} +#endif + +PDFDoc::PDFDoc(char *fileNameA, GString *ownerPassword, + GString *userPassword, PDFCore *coreA) { +#ifdef _WIN32 + OSVERSIONINFO version; +#endif + Object obj; +#ifdef _WIN32 + Unicode u; + int i, j; +#endif + + init(coreA); + + fileName = new GString(fileNameA); + +#if defined(_WIN32) + wchar_t wPath[winMaxLongPath + 1]; + i = 0; + j = 0; + while (j < winMaxLongPath && getUTF8(fileName, &i, &u)) { + wPath[j++] = (wchar_t)u; + } + wPath[j] = L'\0'; + readWindowsShortcut(wPath, winMaxLongPath + 1); + int wPathLen = (int)wcslen(wPath); + + fileNameU = (wchar_t *)gmallocn(wPathLen + 1, sizeof(wchar_t)); + memcpy(fileNameU, wPath, (wPathLen + 1) * sizeof(wchar_t)); + + // NB: _wfopen is only available in NT + version.dwOSVersionInfoSize = sizeof(version); + GetVersionEx(&version); + if (version.dwPlatformId == VER_PLATFORM_WIN32_NT) { + file = _wfopen(fileNameU, wfopenReadMode); + } else { + file = fopen(fileName->getCString(), fopenReadMode); + } +#elif defined(VMS) + file = fopen(fileName->getCString(), fopenReadMode, "ctx=stm"); +#else + file = fopen(fileName->getCString(), fopenReadMode); +#endif + + if (!file) { + error(errIO, -1, "Couldn't open file '{0:t}'", fileName); + errCode = errOpenFile; + return; + } + + // create stream + obj.initNull(); + str = new FileStream(file, 0, gFalse, 0, &obj); + + ok = setup(ownerPassword, userPassword); +} + +PDFDoc::PDFDoc(BaseStream *strA, GString *ownerPassword, + GString *userPassword, PDFCore *coreA) { +#ifdef _WIN32 + int n, i; +#endif + + init(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 + } + str = strA; + ok = setup(ownerPassword, userPassword); +} + +void PDFDoc::init(PDFCore *coreA) { + ok = gFalse; + errCode = errNone; + core = coreA; + file = NULL; + str = NULL; + xref = NULL; + catalog = NULL; +#ifndef DISABLE_OUTLINE + outline = NULL; +#endif + optContent = NULL; +} + +GBool PDFDoc::setup(GString *ownerPassword, GString *userPassword) { + + str->reset(); + + // 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, repairXRef); + if (!xref->isOk()) { + 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(this); + if (!catalog->isOk()) { + error(errSyntaxError, -1, "Couldn't read page catalog"); + errCode = errBadCatalog; + delete catalog; + catalog = NULL; + delete xref; + xref = NULL; + return gFalse; + } + + return gTrue; +} + +PDFDoc::~PDFDoc() { + if (optContent) { + delete optContent; + } +#ifndef DISABLE_OUTLINE + if (outline) { + delete outline; + } +#endif + if (catalog) { + delete catalog; + } + if (xref) { + delete xref; + } + if (str) { + delete str; + } + if (file) { + fclose(file); + } + if (fileName) { + delete fileName; + } +#ifdef _WIN32 + if (fileNameU) { + gfree(fileNameU); + } +#endif +} + +// Check for a PDF header on this stream. Skip past some garbage +// if necessary. +void PDFDoc::checkHeader() { + char hdrBuf[headerSearchSize+1]; + char *p; + int i; + + pdfVersion = 0; + memset(hdrBuf, 0, headerSearchSize + 1); + str->getBlock(hdrBuf, headerSearchSize); + for (i = 0; i < headerSearchSize - 5; ++i) { + if (!strncmp(&hdrBuf[i], "%PDF-", 5)) { + break; + } + } + if (i >= headerSearchSize - 5) { + 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(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(errSyntaxWarning, -1, + "PDF version {0:s} -- xpdf supports version {1:s} (continuing anyway)", + p, supportedPDFVersionStr); + } +} + +GBool PDFDoc::checkEncryption(GString *ownerPassword, GString *userPassword) { + Object encrypt; + GBool encrypted; + SecurityHandler *secHdlr; + GBool ret; + + xref->getTrailerDict()->dictLookup("Encrypt", &encrypt); + if ((encrypted = encrypt.isDict())) { + if ((secHdlr = SecurityHandler::make(this, &encrypt))) { + if (secHdlr->isUnencrypted()) { + // no encryption + ret = gTrue; + } else if (secHdlr->checkEncryption(ownerPassword, userPassword)) { + // authorization succeeded + xref->setEncryption(secHdlr->getPermissionFlags(), + secHdlr->getOwnerPasswordOk(), + secHdlr->getFileKey(), + secHdlr->getFileKeyLength(), + secHdlr->getEncVersion(), + secHdlr->getEncAlgorithm()); + ret = gTrue; + } else { + // authorization failed + ret = gFalse; + } + delete secHdlr; + } else { + // couldn't find the matching security handler + ret = gFalse; + } + } else { + // document is not encrypted + ret = gTrue; + } + encrypt.free(); + return ret; +} + +void PDFDoc::displayPage(OutputDev *out, int page, + double hDPI, double vDPI, int rotate, + GBool useMediaBox, GBool crop, GBool printing, + GBool (*abortCheckCbk)(void *data), + void *abortCheckCbkData) { + if (globalParams->getPrintCommands()) { + printf("***** page %d *****\n", page); + } + catalog->getPage(page)->display(out, hDPI, vDPI, + rotate, useMediaBox, crop, printing, + abortCheckCbk, abortCheckCbkData); +} + +void PDFDoc::displayPages(OutputDev *out, int firstPage, int lastPage, + double hDPI, double vDPI, int rotate, + GBool useMediaBox, GBool crop, GBool printing, + GBool (*abortCheckCbk)(void *data), + void *abortCheckCbkData) { + int page; + + for (page = firstPage; page <= lastPage; ++page) { + if (globalParams->getPrintStatusInfo()) { + fflush(stderr); + printf("[processing page %d]\n", page); + fflush(stdout); + } + displayPage(out, page, hDPI, vDPI, rotate, useMediaBox, crop, printing, + abortCheckCbk, abortCheckCbkData); + catalog->doneWithPage(page); + } +} + +void PDFDoc::displayPageSlice(OutputDev *out, int page, + double hDPI, double vDPI, int rotate, + GBool useMediaBox, GBool crop, GBool printing, + int sliceX, int sliceY, int sliceW, int sliceH, + GBool (*abortCheckCbk)(void *data), + void *abortCheckCbkData) { + catalog->getPage(page)->displaySlice(out, hDPI, vDPI, + rotate, useMediaBox, crop, + sliceX, sliceY, sliceW, sliceH, + printing, + abortCheckCbk, abortCheckCbkData); +} + +Links *PDFDoc::getLinks(int page) { + return catalog->getPage(page)->getLinks(); +} + +void PDFDoc::processLinks(OutputDev *out, int page) { + catalog->getPage(page)->processLinks(out); +} + +#ifndef DISABLE_OUTLINE +int PDFDoc::getOutlineTargetPage(OutlineItem *outlineItem) { + LinkAction *action; + LinkActionKind kind; + LinkDest *dest; + GString *namedDest; + Ref pageRef; + int pg; + + if (outlineItem->pageNum >= 0) { + return outlineItem->pageNum; + } + if (!(action = outlineItem->getAction())) { + outlineItem->pageNum = 0; + return 0; + } + kind = action->getKind(); + if (kind != actionGoTo) { + outlineItem->pageNum = 0; + return 0; + } + if ((dest = ((LinkGoTo *)action)->getDest())) { + dest = dest->copy(); + } else if ((namedDest = ((LinkGoTo *)action)->getNamedDest())) { + dest = findDest(namedDest); + } + pg = 0; + if (dest) { + if (dest->isPageRef()) { + pageRef = dest->getPageRef(); + pg = findPage(pageRef.num, pageRef.gen); + } else { + pg = dest->getPageNum(); + } + delete dest; + } + outlineItem->pageNum = pg; + return pg; +} +#endif + +GBool PDFDoc::isLinearized() { + Parser *parser; + Object obj1, obj2, obj3, obj4, obj5; + GBool lin; + + lin = gFalse; + obj1.initNull(); + parser = new Parser(xref, + new Lexer(xref, + str->makeSubStream(str->getStart(), gFalse, 0, &obj1)), + gTrue); + parser->getObj(&obj1); + parser->getObj(&obj2); + parser->getObj(&obj3); + parser->getObj(&obj4); + if (obj1.isInt() && obj2.isInt() && obj3.isCmd("obj") && + obj4.isDict()) { + obj4.dictLookup("Linearized", &obj5); + if (obj5.isNum() && obj5.getNum() > 0) { + lin = gTrue; + } + obj5.free(); + } + obj4.free(); + obj3.free(); + obj2.free(); + obj1.free(); + delete parser; + return lin; +} + +GBool PDFDoc::saveAs(GString *name) { + FILE *f; + char buf[4096]; + int n; + + if (!(f = fopen(name->getCString(), "wb"))) { + error(errIO, -1, "Couldn't open file '{0:t}'", name); + return gFalse; + } + str->reset(); + while ((n = str->getBlock(buf, sizeof(buf))) > 0) { + fwrite(buf, 1, n, f); + } + str->close(); + fclose(f); + return gTrue; +} + +GBool PDFDoc::saveEmbeddedFile(int idx, const char *path) { + FILE *f; + GBool ret; + + if (!(f = fopen(path, "wb"))) { + return gFalse; + } + ret = saveEmbeddedFile2(idx, f); + fclose(f); + return ret; +} + +GBool PDFDoc::saveEmbeddedFileU(int idx, const char *path) { + FILE *f; + GBool ret; + + if (!(f = openFile(path, "wb"))) { + return gFalse; + } + ret = saveEmbeddedFile2(idx, f); + fclose(f); + return ret; +} + +#ifdef _WIN32 +GBool PDFDoc::saveEmbeddedFile(int idx, const wchar_t *path, int pathLen) { + FILE *f; + OSVERSIONINFO version; + wchar_t path2w[winMaxLongPath + 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 < winMaxLongPath; ++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; + char buf[4096]; + int n; + + if (!catalog->getEmbeddedFileStreamObj(idx, &strObj)) { + return gFalse; + } + strObj.streamReset(); + while ((n = strObj.streamGetBlock(buf, sizeof(buf))) > 0) { + fwrite(buf, 1, n, f); + } + strObj.streamClose(); + strObj.free(); + return gTrue; +} + +char *PDFDoc::getEmbeddedFileMem(int idx, int *size) { + Object strObj; + char *buf; + int bufSize, sizeInc, n; + + if (!catalog->getEmbeddedFileStreamObj(idx, &strObj)) { + return NULL; + } + strObj.streamReset(); + bufSize = 0; + buf = NULL; + do { + sizeInc = bufSize ? bufSize : 1024; + if (bufSize > INT_MAX - sizeInc) { + error(errIO, -1, "embedded file is too large"); + *size = 0; + return NULL; + } + buf = (char *)grealloc(buf, bufSize + sizeInc); + n = strObj.streamGetBlock(buf + bufSize, sizeInc); + bufSize += n; + } while (n == sizeInc); + strObj.streamClose(); + strObj.free(); + *size = bufSize; + return buf; +} + diff --git a/xpdf/PDFDoc.h b/xpdf/PDFDoc.h new file mode 100644 index 0000000..2b8eba2 --- /dev/null +++ b/xpdf/PDFDoc.h @@ -0,0 +1,228 @@ +//======================================================================== +// +// PDFDoc.h +// +// Copyright 1996-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef PDFDOC_H +#define PDFDOC_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include +#include "XRef.h" +#include "Catalog.h" +#include "Page.h" + +class GString; +class BaseStream; +class OutputDev; +class Links; +class LinkAction; +class LinkDest; +class Outline; +class OutlineItem; +class OptionalContent; +class PDFCore; + +//------------------------------------------------------------------------ +// PDFDoc +//------------------------------------------------------------------------ + +class PDFDoc { +public: + + PDFDoc(GString *fileNameA, GString *ownerPassword = NULL, + GString *userPassword = NULL, PDFCore *coreA = NULL); + +#ifdef _WIN32 + PDFDoc(wchar_t *fileNameA, int fileNameLen, GString *ownerPassword = NULL, + GString *userPassword = NULL, PDFCore *coreA = NULL); +#endif + + // This version takes a UTF-8 file name (which is only relevant on + // Windows). + PDFDoc(char *fileNameA, GString *ownerPassword = NULL, + GString *userPassword = NULL, PDFCore *coreA = NULL); + + PDFDoc(BaseStream *strA, GString *ownerPassword = NULL, + GString *userPassword = NULL, PDFCore *coreA = NULL); + + ~PDFDoc(); + + // Was PDF document successfully opened? + GBool isOk() { return ok; } + + // Get the error code (if isOk() returns false). + int getErrorCode() { return errCode; } + + // Get file name. + GString *getFileName() { return fileName; } +#ifdef _WIN32 + wchar_t *getFileNameU() { return fileNameU; } +#endif + + // Get the xref table. + XRef *getXRef() { return xref; } + + // Get catalog. + Catalog *getCatalog() { return catalog; } + + // Get base stream. + BaseStream *getBaseStream() { return str; } + + // Get page parameters. + double getPageMediaWidth(int page) + { return catalog->getPage(page)->getMediaWidth(); } + double getPageMediaHeight(int page) + { return catalog->getPage(page)->getMediaHeight(); } + double getPageCropWidth(int page) + { return catalog->getPage(page)->getCropWidth(); } + double getPageCropHeight(int page) + { return catalog->getPage(page)->getCropHeight(); } + int getPageRotate(int page) + { return catalog->getPage(page)->getRotate(); } + + // Get number of pages. + int getNumPages() { return catalog->getNumPages(); } + + // Return the contents of the metadata stream, or NULL if there is + // no metadata. + GString *readMetadata() { return catalog->readMetadata(); } + + // Return the structure tree root object. + Object *getStructTreeRoot() { return catalog->getStructTreeRoot(); } + + // Display a page. + void displayPage(OutputDev *out, int page, + double hDPI, double vDPI, int rotate, + GBool useMediaBox, GBool crop, GBool printing, + GBool (*abortCheckCbk)(void *data) = NULL, + void *abortCheckCbkData = NULL); + + // Display a range of pages. + void displayPages(OutputDev *out, int firstPage, int lastPage, + double hDPI, double vDPI, int rotate, + GBool useMediaBox, GBool crop, GBool printing, + GBool (*abortCheckCbk)(void *data) = NULL, + void *abortCheckCbkData = NULL); + + // Display part of a page. + void displayPageSlice(OutputDev *out, int page, + double hDPI, double vDPI, int rotate, + GBool useMediaBox, GBool crop, GBool printing, + int sliceX, int sliceY, int sliceW, int sliceH, + GBool (*abortCheckCbk)(void *data) = NULL, + void *abortCheckCbkData = NULL); + + // Find a page, given its object ID. Returns page number, or 0 if + // not found. + int findPage(int num, int gen) { return catalog->findPage(num, gen); } + + // Returns the links for the current page, transferring ownership to + // the caller. + Links *getLinks(int page); + + // Find a named destination. Returns the link destination, or + // NULL if is not a destination. + LinkDest *findDest(GString *name) + { return catalog->findDest(name); } + + // Process the links for a page. + void processLinks(OutputDev *out, int page); + +#ifndef DISABLE_OUTLINE + // Return the outline object. + Outline *getOutline() { return outline; } + + // Return the target page number for an outline item. Returns 0 if + // the item doesn't target a page in this PDF file. + int getOutlineTargetPage(OutlineItem *outlineItem); +#endif + + // Return the OptionalContent object. + OptionalContent *getOptionalContent() { return optContent; } + + // Is the file encrypted? + GBool isEncrypted() { return xref->isEncrypted(); } + + // Check various permissions. + GBool okToPrint(GBool ignoreOwnerPW = gFalse) + { return xref->okToPrint(ignoreOwnerPW); } + GBool okToChange(GBool ignoreOwnerPW = gFalse) + { return xref->okToChange(ignoreOwnerPW); } + GBool okToCopy(GBool ignoreOwnerPW = gFalse) + { return xref->okToCopy(ignoreOwnerPW); } + GBool okToAddNotes(GBool ignoreOwnerPW = gFalse) + { return xref->okToAddNotes(ignoreOwnerPW); } + + // Is the PDF file damaged? This checks to see if the xref table + // was constructed by the repair code. + GBool isDamaged() { return xref->isRepaired(); } + + // Is this document linearized? + GBool isLinearized(); + + // Return the document's Info dictionary (if any). + Object *getDocInfo(Object *obj) { return xref->getDocInfo(obj); } + Object *getDocInfoNF(Object *obj) { return xref->getDocInfoNF(obj); } + + // Return the PDF version specified by the file. + double getPDFVersion() { return pdfVersion; } + + // Save this file with another name. + GBool saveAs(GString *name); + + // 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, const char *path); + GBool saveEmbeddedFileU(int idx, const char *path); +#ifdef _WIN32 + GBool saveEmbeddedFile(int idx, const wchar_t *path, int pathLen); +#endif + char *getEmbeddedFileMem(int idx, int *size); + + +private: + + void init(PDFCore *coreA); + 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; + PDFCore *core; + double pdfVersion; + XRef *xref; + Catalog *catalog; +#ifndef DISABLE_OUTLINE + Outline *outline; +#endif + OptionalContent *optContent; + + GBool ok; + int errCode; +}; + +#endif diff --git a/xpdf/PDFDocEncoding.cc b/xpdf/PDFDocEncoding.cc new file mode 100644 index 0000000..8258395 --- /dev/null +++ b/xpdf/PDFDocEncoding.cc @@ -0,0 +1,46 @@ +//======================================================================== +// +// PDFDocEncoding.h +// +// Copyright 2002-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include +#include "gmempp.h" +#include "PDFDocEncoding.h" + +Unicode pdfDocEncoding[256] = { + 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, + 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, // 30 + 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, + 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, // 40 + 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, + 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, // 50 + 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, + 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, // 60 + 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f, + 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, // 70 + 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x0000, + 0x2022, 0x2020, 0x2021, 0x2026, 0x2014, 0x2013, 0x0192, 0x2044, // 80 + 0x2039, 0x203a, 0x2212, 0x2030, 0x201e, 0x201c, 0x201d, 0x2018, + 0x2019, 0x201a, 0x2122, 0xfb01, 0xfb02, 0x0141, 0x0152, 0x0160, // 90 + 0x0178, 0x017d, 0x0131, 0x0142, 0x0153, 0x0161, 0x017e, 0x0000, + 0x20ac, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7, // a0 + 0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x0000, 0x00ae, 0x00af, + 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7, // b0 + 0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf, + 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7, // c0 + 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf, + 0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7, // d0 + 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df, + 0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7, // e0 + 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef, + 0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7, // f0 + 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff +}; diff --git a/xpdf/PDFDocEncoding.h b/xpdf/PDFDocEncoding.h new file mode 100644 index 0000000..3259d3e --- /dev/null +++ b/xpdf/PDFDocEncoding.h @@ -0,0 +1,16 @@ +//======================================================================== +// +// PDFDocEncoding.h +// +// Copyright 2002-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef PDFDOCENCODING_H +#define PDFDOCENCODING_H + +#include "CharTypes.h" + +extern Unicode pdfDocEncoding[256]; + +#endif diff --git a/xpdf/PSOutputDev.cc b/xpdf/PSOutputDev.cc new file mode 100644 index 0000000..b9fff4f --- /dev/null +++ b/xpdf/PSOutputDev.cc @@ -0,0 +1,8448 @@ +//======================================================================== +// +// PSOutputDev.cc +// +// Copyright 1996-2013 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include +#include +#include +#include +#include "gmempp.h" +#include "GString.h" +#include "GList.h" +#include "GHash.h" +#include "config.h" +#include "GlobalParams.h" +#include "Object.h" +#include "Error.h" +#include "Function.h" +#include "Gfx.h" +#include "GfxState.h" +#include "GfxFont.h" +#include "UnicodeMap.h" +#include "FoFiType1C.h" +#include "FoFiTrueType.h" +#include "Catalog.h" +#include "Page.h" +#include "Stream.h" +#include "Annot.h" +#include "PDFDoc.h" +#include "XRef.h" +#include "PreScanOutputDev.h" +#include "CharCodeToUnicode.h" +#include "AcroForm.h" +#include "TextString.h" +#if HAVE_SPLASH +# include "Splash.h" +# include "SplashBitmap.h" +# include "SplashOutputDev.h" +#endif +#include "PSOutputDev.h" + +// the MSVC math.h doesn't define this +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +//------------------------------------------------------------------------ +// PostScript prolog and setup +//------------------------------------------------------------------------ + +// The '~' escapes mark prolog code that is emitted only in certain +// levels: +// +// ~[123][ngs] +// ^ ^----- n=psLevel_, g=psLevel_Gray, s=psLevel_Sep +// +----- 1=psLevel1__, 2=psLevel2__, 3=psLevel3__ + +static const char *prolog[] = { + "/xpdf 75 dict def xpdf begin", + "% PDF special state", + "/pdfDictSize 15 def", + "~1ns", + "/pdfStates 64 array def", + " 0 1 63 {", + " pdfStates exch pdfDictSize dict", + " dup /pdfStateIdx 3 index put", + " put", + " } for", + "~123ngs", + "/bdef { bind def } bind def", + "/pdfSetup {", + " /pdfDuplex exch def", + " /setpagedevice where {", + " pop 2 dict begin", + " /Policies 1 dict dup begin /PageSize 6 def end def", + " pdfDuplex { /Duplex true def } if", + " currentdict end setpagedevice", + " } if", + " /pdfPageW 0 def", + " /pdfPageH 0 def", + "} def", + "/pdfSetupPaper {", + " 2 copy pdfPageH ne exch pdfPageW ne or {", + " /pdfPageH exch def", + " /pdfPageW exch def", + " /setpagedevice where {", + " pop 3 dict begin", + " /PageSize [pdfPageW pdfPageH] def", + " pdfDuplex { /Duplex true def } if", + " /ImagingBBox null def", + " currentdict end setpagedevice", + " } if", + " } {", + " pop pop", + " } ifelse", + "} def", + "~1ns", + "/pdfOpNames [", + " /pdfFill /pdfStroke /pdfLastFill /pdfLastStroke", + " /pdfTextMat /pdfFontSize /pdfCharSpacing /pdfTextRender", + " /pdfTextRise /pdfWordSpacing /pdfHorizScaling /pdfTextClipPath", + "] def", + "~123ngs", + "/pdfStartPage {", + "~1ns", + " pdfStates 0 get begin", + "~23ngs", + " pdfDictSize dict begin", + "~23n", + " /pdfFillCS [] def", + " /pdfFillXform {} def", + " /pdfStrokeCS [] def", + " /pdfStrokeXform {} def", + "~1n", + " /pdfFill 0 def", + " /pdfStroke 0 def", + "~1s", + " /pdfFill [0 0 0 1] def", + " /pdfStroke [0 0 0 1] def", + "~23g", + " /pdfFill 0 def", + " /pdfStroke 0 def", + "~23ns", + " /pdfFill [0] def", + " /pdfStroke [0] def", + " /pdfFillOP false def", + " /pdfStrokeOP false def", + "~123ngs", + " /pdfLastFill false def", + " /pdfLastStroke false def", + " /pdfTextMat [1 0 0 1 0 0] def", + " /pdfFontSize 0 def", + " /pdfCharSpacing 0 def", + " /pdfTextRender 0 def", + " /pdfTextRise 0 def", + " /pdfWordSpacing 0 def", + " /pdfHorizScaling 1 def", + " /pdfTextClipPath [] def", + "} def", + "/pdfEndPage { end } def", + "~23s", + "% separation convention operators", + "/findcmykcustomcolor where {", + " pop", + "}{", + " /findcmykcustomcolor { 5 array astore } def", + "} ifelse", + "/setcustomcolor where {", + " pop", + "}{", + " /setcustomcolor {", + " exch", + " [ exch /Separation exch dup 4 get exch /DeviceCMYK exch", + " 0 4 getinterval cvx", + " [ exch /dup load exch { mul exch dup } /forall load", + " /pop load dup ] cvx", + " ] setcolorspace setcolor", + " } def", + "} ifelse", + "/customcolorimage where {", + " pop", + "}{", + " /customcolorimage {", + " gsave", + " [ exch /Separation exch dup 4 get exch /DeviceCMYK exch", + " 0 4 getinterval", + " [ exch /dup load exch { mul exch dup } /forall load", + " /pop load dup ] cvx", + " ] setcolorspace", + " 10 dict begin", + " /ImageType 1 def", + " /DataSource exch def", + " /ImageMatrix exch def", + " /BitsPerComponent exch def", + " /Height exch def", + " /Width exch def", + " /Decode [1 0] def", + " currentdict end", + " image", + " grestore", + " } def", + "} ifelse", + "~123ngs", + "% PDF color state", + "~1n", + "/g { dup /pdfFill exch def setgray", + " /pdfLastFill true def /pdfLastStroke false def } def", + "/G { dup /pdfStroke exch def setgray", + " /pdfLastStroke true def /pdfLastFill false def } def", + "/fCol {", + " pdfLastFill not {", + " pdfFill setgray", + " /pdfLastFill true def /pdfLastStroke false def", + " } if", + "} def", + "/sCol {", + " pdfLastStroke not {", + " pdfStroke setgray", + " /pdfLastStroke true def /pdfLastFill false def", + " } if", + "} def", + "~1s", + "/k { 4 copy 4 array astore /pdfFill exch def setcmykcolor", + " /pdfLastFill true def /pdfLastStroke false def } def", + "/K { 4 copy 4 array astore /pdfStroke exch def setcmykcolor", + " /pdfLastStroke true def /pdfLastFill false def } def", + "/fCol {", + " pdfLastFill not {", + " pdfFill aload pop setcmykcolor", + " /pdfLastFill true def /pdfLastStroke false def", + " } if", + "} def", + "/sCol {", + " pdfLastStroke not {", + " pdfStroke aload pop setcmykcolor", + " /pdfLastStroke true def /pdfLastFill false def", + " } if", + "} def", + "~23n", + "/cs { /pdfFillXform exch def dup /pdfFillCS exch def", + " setcolorspace } def", + "/CS { /pdfStrokeXform exch def dup /pdfStrokeCS exch def", + " setcolorspace } def", + "/sc { pdfLastFill not {", + " pdfFillCS setcolorspace pdfFillOP setoverprint", + " } if", + " dup /pdfFill exch def aload pop pdfFillXform setcolor", + " /pdfLastFill true def /pdfLastStroke false def } def", + "/SC { pdfLastStroke not {", + " pdfStrokeCS setcolorspace pdfStrokeOP setoverprint", + " } if", + " dup /pdfStroke exch def aload pop pdfStrokeXform setcolor", + " /pdfLastStroke true def /pdfLastFill false def } def", + "/op { /pdfFillOP exch def", + " pdfLastFill { pdfFillOP setoverprint } if } def", + "/OP { /pdfStrokeOP exch def", + " pdfLastStroke { pdfStrokeOP setoverprint } if } def", + "/fCol {", + " pdfLastFill not {", + " pdfFillCS setcolorspace", + " pdfFill aload pop pdfFillXform setcolor", + " pdfFillOP setoverprint", + " /pdfLastFill true def /pdfLastStroke false def", + " } if", + "} def", + "/sCol {", + " pdfLastStroke not {", + " pdfStrokeCS setcolorspace", + " pdfStroke aload pop pdfStrokeXform setcolor", + " pdfStrokeOP setoverprint", + " /pdfLastStroke true def /pdfLastFill false def", + " } if", + "} def", + "~23g", + "/g { dup /pdfFill exch def setgray", + " /pdfLastFill true def /pdfLastStroke false def } def", + "/G { dup /pdfStroke exch def setgray", + " /pdfLastStroke true def /pdfLastFill false def } def", + "/fCol {", + " pdfLastFill not {", + " pdfFill setgray", + " /pdfLastFill true def /pdfLastStroke false def", + " } if", + "} def", + "/sCol {", + " pdfLastStroke not {", + " pdfStroke setgray", + " /pdfLastStroke true def /pdfLastFill false def", + " } if", + "} def", + "~23s", + "/k { 4 copy 4 array astore /pdfFill exch def setcmykcolor", + " pdfFillOP setoverprint", + " /pdfLastFill true def /pdfLastStroke false def } def", + "/K { 4 copy 4 array astore /pdfStroke exch def setcmykcolor", + " pdfStrokeOP setoverprint", + " /pdfLastStroke true def /pdfLastFill false def } def", + "/ck { 6 copy 6 array astore /pdfFill exch def", + " findcmykcustomcolor exch setcustomcolor", + " pdfFillOP setoverprint", + " /pdfLastFill true def /pdfLastStroke false def } def", + "/CK { 6 copy 6 array astore /pdfStroke exch def", + " findcmykcustomcolor exch setcustomcolor", + " pdfStrokeOP setoverprint", + " /pdfLastStroke true def /pdfLastFill false def } def", + "/op { /pdfFillOP exch def", + " pdfLastFill { pdfFillOP setoverprint } if } def", + "/OP { /pdfStrokeOP exch def", + " pdfLastStroke { pdfStrokeOP setoverprint } if } def", + "/fCol {", + " pdfLastFill not {", + " pdfFill aload length 4 eq {", + " setcmykcolor", + " }{", + " findcmykcustomcolor exch setcustomcolor", + " } ifelse", + " pdfFillOP setoverprint", + " /pdfLastFill true def /pdfLastStroke false def", + " } if", + "} def", + "/sCol {", + " pdfLastStroke not {", + " pdfStroke aload length 4 eq {", + " setcmykcolor", + " }{", + " findcmykcustomcolor exch setcustomcolor", + " } ifelse", + " pdfStrokeOP setoverprint", + " /pdfLastStroke true def /pdfLastFill false def", + " } if", + "} def", + "~3ns", + "/opm {", + " /setoverprintmode where { pop setoverprintmode } { pop } ifelse", + "} def", + "~123ngs", + "% build a font", + "/pdfMakeFont {", + " 4 3 roll findfont", + " 4 2 roll matrix scale makefont", + " dup length dict begin", + " { 1 index /FID ne { def } { pop pop } ifelse } forall", + " /Encoding exch def", + " currentdict", + " end", + " definefont pop", + "} def", + "/pdfMakeFont16 {", + " exch findfont", + " dup length dict begin", + " { 1 index /FID ne { def } { pop pop } ifelse } forall", + " /WMode exch def", + " currentdict", + " end", + " definefont pop", + "} def", + "~3ngs", + "/pdfMakeFont16L3 {", + " 1 index /CIDFont resourcestatus {", + " pop pop 1 index /CIDFont findresource /CIDFontType known", + " } {", + " false", + " } ifelse", + " {", + " 0 eq { /Identity-H } { /Identity-V } ifelse", + " exch 1 array astore composefont pop", + " } {", + " pdfMakeFont16", + " } ifelse", + "} def", + "~123ngs", + "% graphics state operators", + "~1ns", + "/q {", + " gsave", + " pdfOpNames length 1 sub -1 0 { pdfOpNames exch get load } for", + " pdfStates pdfStateIdx 1 add get begin", + " pdfOpNames { exch def } forall", + "} def", + "/Q { end grestore } def", + "~23ngs", + "/q { gsave pdfDictSize dict begin } def", + "/Q {", + " end grestore", + "} def", + "~123ngs", + "/cm { concat } def", + "/d { setdash } def", + "/i { setflat } def", + "/j { setlinejoin } def", + "/J { setlinecap } def", + "/M { setmiterlimit } def", + "/w { setlinewidth } def", + "% path segment operators", + "/m { moveto } def", + "/l { lineto } def", + "/c { curveto } def", + "/re { 4 2 roll moveto 1 index 0 rlineto 0 exch rlineto", + " neg 0 rlineto closepath } def", + "/h { closepath } def", + "% path painting operators", + "/S { sCol stroke } def", + "/Sf { fCol stroke } def", + "/f { fCol fill } def", + "/f* { fCol eofill } def", + "% clipping operators", + "/W { clip newpath } bdef", + "/W* { eoclip newpath } bdef", + "/Ws { strokepath clip newpath } bdef", + "% text state operators", + "/Tc { /pdfCharSpacing exch def } def", + "/Tf { dup /pdfFontSize exch def", + " dup pdfHorizScaling mul exch matrix scale", + " pdfTextMat matrix concatmatrix dup 4 0 put dup 5 0 put", + " exch findfont exch makefont setfont } def", + "/Tr { /pdfTextRender exch def } def", + "/Ts { /pdfTextRise exch def } def", + "/Tw { /pdfWordSpacing exch def } def", + "/Tz { /pdfHorizScaling exch def } def", + "% text positioning operators", + "/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", + " /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", + "}{", + " /xycp {", // xycharpath + " currentfont /FontType get 0 eq {", + " 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", + " } {", + " 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", + "/Tj {", + " fCol", // because stringwidth has to draw Type 3 chars + " 0 pdfTextRise pdfTextMat dtransform rmoveto", + " currentpoint 4 2 roll", + " pdfTextRender 1 and 0 eq {", + " 2 copy xyshow2", + " } if", + " pdfTextRender 3 and dup 1 eq exch 2 eq or {", + " 3 index 3 index moveto", + " 2 copy", + " currentfont /FontType get 3 eq { fCol } { sCol } ifelse", + " xycp currentpoint stroke moveto", + " } if", + " pdfTextRender 4 and 0 ne {", + " 4 2 roll moveto xycp", + " /pdfTextClipPath [ pdfTextClipPath aload pop", + " {/moveto cvx}", + " {/lineto cvx}", + " {/curveto cvx}", + " {/closepath cvx}", + " pathforall ] def", + " currentpoint newpath moveto", + " } {", + " pop pop pop pop", + " } ifelse", + " 0 pdfTextRise neg pdfTextMat dtransform rmoveto", + "} def", + "/Tj3 {", + " pdfTextRender 3 and 3 ne {" + " fCol", // because stringwidth has to draw Type 3 chars + " 0 pdfTextRise pdfTextMat dtransform rmoveto", + " xyshow2", + " 0 pdfTextRise neg pdfTextMat dtransform rmoveto", + " } {", + " pop pop", + " } ifelse", + "} def", + "/TJm { 0.001 mul pdfFontSize mul pdfHorizScaling mul neg 0", + " pdfTextMat dtransform rmoveto } def", + "/TJmV { 0.001 mul pdfFontSize mul neg 0 exch", + " pdfTextMat dtransform rmoveto } def", + "/Tclip { pdfTextClipPath cvx exec clip newpath", + " /pdfTextClipPath [] def } def", + "~1ns", + "% Level 1 image operators", + "~1n", + "/pdfIm1 {", + " /pdfImBuf1 4 index string def", + " { currentfile pdfImBuf1 readhexstring pop } image", + "} def", + "~1s", + "/pdfIm1Sep {", + " /pdfImBuf1 4 index string def", + " /pdfImBuf2 4 index string def", + " /pdfImBuf3 4 index string def", + " /pdfImBuf4 4 index string def", + " { currentfile pdfImBuf1 readhexstring pop }", + " { currentfile pdfImBuf2 readhexstring pop }", + " { currentfile pdfImBuf3 readhexstring pop }", + " { currentfile pdfImBuf4 readhexstring pop }", + " true 4 colorimage", + "} def", + "~1ns", + "/pdfImM1 {", + " 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 {", + " { pdfImStr } imagemask", + " pop pop", + "} def", + "~23ngs", + "% Level 2/3 image operators", + "/pdfImBuf 100 string def", + "/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", + "~3ngs", + "/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", + " dup /Width get /pdfImBuf1 exch string def", + " dup /Decode get aload pop 1 index sub /pdfImDecodeRange exch def", + " /pdfImDecodeLow exch def", + " begin Width Height BitsPerComponent ImageMatrix DataSource end", + " /pdfImData exch def", + " { pdfImData pdfImBuf1 readstring pop", + " 0 1 2 index length 1 sub {", + " 1 index exch 2 copy get", + " pdfImDecodeRange mul 255 div pdfImDecodeLow add round cvi", + " 255 exch sub put", + " } for }", + " 6 5 roll customcolorimage", + " skipEOD", + "} def", + "~23ngs", + "/pdfImM { fCol imagemask skipEOD } def", + "/pr {", + " 4 2 roll exch 5 index div exch 4 index div moveto", + " exch 3 index div dup 0 rlineto", + " exch 2 index div 0 exch rlineto", + " neg 0 rlineto", + " closepath", + "} def", + "/pdfImClip { gsave clip } def", + "/pdfImClipEnd { grestore } def", + "~23ns", + "% shading operators", + "/colordelta {", + " false 0 1 3 index length 1 sub {", + " dup 4 index exch get 3 index 3 2 roll get sub abs 0.004 gt {", + " pop true", + " } if", + " } for", + " exch pop exch pop", + "} def", + "/funcCol { func n array astore } def", + "/funcSH {", + " dup 0 eq {", + " true", + " } {", + " dup 6 eq {", + " false", + " } {", + " 4 index 4 index funcCol dup", + " 6 index 4 index funcCol dup", + " 3 1 roll colordelta 3 1 roll", + " 5 index 5 index funcCol dup", + " 3 1 roll colordelta 3 1 roll", + " 6 index 8 index funcCol dup", + " 3 1 roll colordelta 3 1 roll", + " colordelta or or or", + " } ifelse", + " } ifelse", + " {", + " 1 add", + " 4 index 3 index add 0.5 mul exch 4 index 3 index add 0.5 mul exch", + " 6 index 6 index 4 index 4 index 4 index funcSH", + " 2 index 6 index 6 index 4 index 4 index funcSH", + " 6 index 2 index 4 index 6 index 4 index funcSH", + " 5 3 roll 3 2 roll funcSH pop pop", + " } {", + " pop 3 index 2 index add 0.5 mul 3 index 2 index add 0.5 mul", + "~23n", + " funcCol sc", + "~23s", + " funcCol aload pop k", + "~23ns", + " dup 4 index exch mat transform m", + " 3 index 3 index mat transform l", + " 1 index 3 index mat transform l", + " mat transform l pop pop h f*", + " } ifelse", + "} def", + "/axialCol {", + " dup 0 lt {", + " pop t0", + " } {", + " dup 1 gt {", + " pop t1", + " } {", + " dt mul t0 add", + " } ifelse", + " } ifelse", + " func n array astore", + "} def", + "/axialSH {", + " dup 2 lt {", + " true", + " } {", + " dup 8 eq {", + " false", + " } {", + " 2 index axialCol 2 index axialCol colordelta", + " } ifelse", + " } ifelse", + " {", + " 1 add 3 1 roll 2 copy add 0.5 mul", + " dup 4 3 roll exch 4 index axialSH", + " exch 3 2 roll axialSH", + " } {", + " pop 2 copy add 0.5 mul", + "~23n", + " axialCol sc", + "~23s", + " axialCol aload pop k", + "~23ns", + " exch dup dx mul x0 add exch dy mul y0 add", + " 3 2 roll dup dx mul x0 add exch dy mul y0 add", + " dx abs dy abs ge {", + " 2 copy yMin sub dy mul dx div add yMin m", + " yMax sub dy mul dx div add yMax l", + " 2 copy yMax sub dy mul dx div add yMax l", + " yMin sub dy mul dx div add yMin l", + " h f*", + " } {", + " exch 2 copy xMin sub dx mul dy div add xMin exch m", + " xMax sub dx mul dy div add xMax exch l", + " exch 2 copy xMax sub dx mul dy div add xMax exch l", + " xMin sub dx mul dy div add xMin exch l", + " h f*", + " } ifelse", + " } ifelse", + "} def", + "/radialCol {", + " dup t0 lt {", + " pop t0", + " } {", + " dup t1 gt {", + " pop t1", + " } if", + " } ifelse", + " func n array astore", + "} def", + "/radialSH {", + " dup 0 eq {", + " true", + " } {", + " dup 8 eq {", + " false", + " } {", + " 2 index dt mul t0 add radialCol", + " 2 index dt mul t0 add radialCol colordelta", + " } ifelse", + " } ifelse", + " {", + " 1 add 3 1 roll 2 copy add 0.5 mul", + " dup 4 3 roll exch 4 index radialSH", + " exch 3 2 roll radialSH", + " } {", + " pop 2 copy add 0.5 mul dt mul t0 add", + "~23n", + " radialCol sc", + "~23s", + " radialCol aload pop k", + "~23ns", + " encl {", + " exch dup dx mul x0 add exch dup dy mul y0 add exch dr mul r0 add", + " 0 360 arc h", + " dup dx mul x0 add exch dup dy mul y0 add exch dr mul r0 add", + " 360 0 arcn h f", + " } {", + " 2 copy", + " dup dx mul x0 add exch dup dy mul y0 add exch dr mul r0 add", + " a1 a2 arcn", + " dup dx mul x0 add exch dup dy mul y0 add exch dr mul r0 add", + " a2 a1 arcn h", + " dup dx mul x0 add exch dup dy mul y0 add exch dr mul r0 add", + " a1 a2 arc", + " dup dx mul x0 add exch dup dy mul y0 add exch dr mul r0 add", + " a2 a1 arc h f", + " } ifelse", + " } ifelse", + "} def", + "~123ngs", + "end", + NULL +}; + +static const char *minLineWidthProlog[] = { + "/pdfDist { dup dtransform dup mul exch dup mul add 0.5 mul sqrt } def", + "/pdfIDist { dup idtransform dup mul exch dup mul add 0.5 mul sqrt } def", + "/pdfMinLineDist pdfMinLineWidth pdfDist def", + "/setlinewidth {", + " dup pdfDist pdfMinLineDist lt {", + " pop pdfMinLineDist pdfIDist", + " } if", + " setlinewidth", + "} bind def", + NULL +}; + +static const char *cmapProlog[] = { + "/CIDInit /ProcSet findresource begin", + "10 dict begin", + " begincmap", + " /CMapType 1 def", + " /CMapName /Identity-H def", + " /CIDSystemInfo 3 dict dup begin", + " /Registry (Adobe) def", + " /Ordering (Identity) def", + " /Supplement 0 def", + " end def", + " 1 begincodespacerange", + " <0000> ", + " endcodespacerange", + " 0 usefont", + " 1 begincidrange", + " <0000> 0", + " endcidrange", + " endcmap", + " currentdict CMapName exch /CMap defineresource pop", + "end", + "10 dict begin", + " begincmap", + " /CMapType 1 def", + " /CMapName /Identity-V def", + " /CIDSystemInfo 3 dict dup begin", + " /Registry (Adobe) def", + " /Ordering (Identity) def", + " /Supplement 0 def", + " end def", + " /WMode 1 def", + " 1 begincodespacerange", + " <0000> ", + " endcodespacerange", + " 0 usefont", + " 1 begincidrange", + " <0000> 0", + " endcidrange", + " endcmap", + " currentdict CMapName exch /CMap defineresource pop", + "end", + "end", + NULL +}; + +//------------------------------------------------------------------------ +// Fonts +//------------------------------------------------------------------------ + +struct PSSubstFont { + const char *psName; // PostScript name + double mWidth; // width of 'm' character +}; + +// 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}, + {"Helvetica-BoldOblique", 0.889}, + {"Times-Roman", 0.788}, + {"Times-Italic", 0.722}, + {"Times-Bold", 0.833}, + {"Times-BoldItalic", 0.778}, + // the last two are never used for substitution + {"Symbol", 0}, + {"ZapfDingbats", 0} +}; + +class PSFontInfo { +public: + + PSFontInfo(Ref fontIDA) + { fontID = fontIDA; ff = NULL; } + + Ref fontID; + PSFontFileInfo *ff; // pointer to font file info; NULL indicates + // font mapping failed +}; + +enum PSFontFileLocation { + psFontFileResident, + psFontFileEmbedded, + psFontFileExternal +}; + +class PSFontFileInfo { +public: + + PSFontFileInfo(GString *psNameA, GfxFontType typeA, + PSFontFileLocation locA); + ~PSFontFileInfo(); + + GString *psName; // name under which font is defined + GfxFontType type; // font type + PSFontFileLocation loc; // font location + Ref embFontID; // object ID for the embedded font file + // (for all embedded fonts) + GString *extFileName; // external font file path + // (for all external fonts) + GString *encoding; // encoding name (for resident CID fonts) + int *codeToGID; // mapping from code/CID to GID + // (for TrueType, OpenType-TrueType, and + // CID OpenType-CFF fonts) + int codeToGIDLen; // length of codeToGID array +}; + +PSFontFileInfo::PSFontFileInfo(GString *psNameA, GfxFontType typeA, + PSFontFileLocation locA) { + psName = psNameA; + type = typeA; + loc = locA; + embFontID.num = embFontID.gen = -1; + extFileName = NULL; + encoding = NULL; + codeToGID = NULL; + codeToGIDLen = 0; +} + +PSFontFileInfo::~PSFontFileInfo() { + delete psName; + if (extFileName) { + delete extFileName; + } + if (encoding) { + delete encoding; + } + if (codeToGID) { + gfree(codeToGID); + } +} + +//------------------------------------------------------------------------ +// process colors +//------------------------------------------------------------------------ + +#define psProcessCyan 1 +#define psProcessMagenta 2 +#define psProcessYellow 4 +#define psProcessBlack 8 +#define psProcessCMYK 15 + +//------------------------------------------------------------------------ +// PSOutCustomColor +//------------------------------------------------------------------------ + +class PSOutCustomColor { +public: + + PSOutCustomColor(double cA, double mA, + double yA, double kA, GString *nameA); + ~PSOutCustomColor(); + + double c, m, y, k; + GString *name; + PSOutCustomColor *next; +}; + +PSOutCustomColor::PSOutCustomColor(double cA, double mA, + double yA, double kA, GString *nameA) { + c = cA; + m = mA; + y = yA; + k = kA; + name = nameA; + next = NULL; +} + +PSOutCustomColor::~PSOutCustomColor() { + delete name; +} + +//------------------------------------------------------------------------ + +struct PSOutImgClipRect { + int x0, x1, y0, y1; +}; + +//------------------------------------------------------------------------ + +struct PSOutPaperSize { + PSOutPaperSize(int wA, int hA) { w = wA; h = hA; } + int w, h; +}; + +//------------------------------------------------------------------------ +// DeviceNRecoder +//------------------------------------------------------------------------ + +class DeviceNRecoder: public FilterStream { +public: + + DeviceNRecoder(Stream *strA, int widthA, int heightA, + GfxImageColorMap *colorMapA); + virtual ~DeviceNRecoder(); + virtual Stream *copy(); + virtual StreamKind getKind() { return strWeird; } + virtual void reset(); + virtual void close(); + virtual int getChar() + { return (bufIdx >= bufSize && !fillBuf()) ? EOF : buf[bufIdx++]; } + virtual int lookChar() + { return (bufIdx >= bufSize && !fillBuf()) ? EOF : buf[bufIdx]; } + virtual GString *getPSFilter(int psLevel, const char *indent, + GBool okToReadStream) + { return NULL; } + virtual GBool isBinary(GBool last = gTrue) { return gTrue; } + virtual GBool isEncoder() { return gTrue; } + +private: + + GBool fillBuf(); + + int width, height; + GfxImageColorMap *colorMap; + Function *func; + ImageStream *imgStr; + int buf[gfxColorMaxComps]; + int pixelIdx; + int bufIdx; + int bufSize; +}; + +DeviceNRecoder::DeviceNRecoder(Stream *strA, int widthA, int heightA, + GfxImageColorMap *colorMapA): + FilterStream(strA) { + width = widthA; + height = heightA; + colorMap = colorMapA; + imgStr = NULL; + pixelIdx = 0; + bufIdx = gfxColorMaxComps; + bufSize = ((GfxDeviceNColorSpace *)colorMap->getColorSpace())-> + getAlt()->getNComps(); + func = ((GfxDeviceNColorSpace *)colorMap->getColorSpace())-> + getTintTransformFunc(); +} + +DeviceNRecoder::~DeviceNRecoder() { + if (str->isEncoder()) { + delete str; + } +} + +Stream *DeviceNRecoder::copy() { + error(errInternal, -1, "Called copy() on DeviceNRecoder"); + return NULL; +} + +void DeviceNRecoder::reset() { + imgStr = new ImageStream(str, width, colorMap->getNumPixelComps(), + colorMap->getBits()); + imgStr->reset(); +} + +void DeviceNRecoder::close() { + delete imgStr; + imgStr = NULL; + str->close(); +} + +GBool DeviceNRecoder::fillBuf() { + Guchar pixBuf[gfxColorMaxComps]; + GfxColor color; + double x[gfxColorMaxComps], y[gfxColorMaxComps]; + int i; + + if (pixelIdx >= width * height) { + return gFalse; + } + imgStr->getPixel(pixBuf); + colorMap->getColor(pixBuf, &color); + for (i = 0; + i < ((GfxDeviceNColorSpace *)colorMap->getColorSpace())->getNComps(); + ++i) { + x[i] = colToDbl(color.c[i]); + } + func->transform(x, y); + for (i = 0; i < bufSize; ++i) { + buf[i] = (int)(y[i] * 255 + 0.5); + } + bufIdx = 0; + ++pixelIdx; + return gTrue; +} + +//------------------------------------------------------------------------ +// GrayRecoder +//------------------------------------------------------------------------ + +class GrayRecoder: public FilterStream { +public: + + GrayRecoder(Stream *strA, int widthA, int heightA, + GfxImageColorMap *colorMapA); + virtual ~GrayRecoder(); + virtual Stream *copy(); + virtual StreamKind getKind() { return strWeird; } + virtual void reset(); + virtual void close(); + virtual int getChar() + { return (bufIdx >= width && !fillBuf()) ? EOF : buf[bufIdx++]; } + virtual int lookChar() + { return (bufIdx >= width && !fillBuf()) ? EOF : buf[bufIdx]; } + virtual GString *getPSFilter(int psLevel, const char *indent, + GBool okToReadStream) + { return NULL; } + virtual GBool isBinary(GBool last = gTrue) { return gTrue; } + virtual GBool isEncoder() { return gTrue; } + +private: + + GBool fillBuf(); + + int width, height; + GfxImageColorMap *colorMap; + ImageStream *imgStr; + Guchar *buf; + int bufIdx; +}; + +GrayRecoder::GrayRecoder(Stream *strA, int widthA, int heightA, + GfxImageColorMap *colorMapA): + FilterStream(strA) { + width = widthA; + height = heightA; + colorMap = colorMapA; + imgStr = NULL; + buf = (Guchar *)gmalloc(width); + bufIdx = width; +} + +GrayRecoder::~GrayRecoder() { + gfree(buf); + if (str->isEncoder()) { + delete str; + } +} + +Stream *GrayRecoder::copy() { + error(errInternal, -1, "Called copy() on GrayRecoder"); + return NULL; +} + +void GrayRecoder::reset() { + imgStr = new ImageStream(str, width, colorMap->getNumPixelComps(), + colorMap->getBits()); + imgStr->reset(); +} + +void GrayRecoder::close() { + delete imgStr; + imgStr = NULL; + str->close(); +} + +GBool GrayRecoder::fillBuf() { + Guchar *line; + + if (!(line = imgStr->getLine())) { + bufIdx = width; + return gFalse; + } + //~ this should probably use the rendering intent from the image + //~ dict, or from the content stream + colorMap->getGrayByteLine(line, buf, width, + gfxRenderingIntentRelativeColorimetric); + bufIdx = 0; + return gTrue; +} + +//------------------------------------------------------------------------ +// ColorKeyToMaskEncoder +//------------------------------------------------------------------------ + +class ColorKeyToMaskEncoder: public FilterStream { +public: + + ColorKeyToMaskEncoder(Stream *strA, int widthA, int heightA, + GfxImageColorMap *colorMapA, int *maskColorsA); + virtual ~ColorKeyToMaskEncoder(); + virtual Stream *copy(); + virtual StreamKind getKind() { return strWeird; } + virtual void reset(); + virtual void close(); + virtual int getChar() + { return (bufIdx >= bufSize && !fillBuf()) ? EOF : buf[bufIdx++]; } + virtual int lookChar() + { return (bufIdx >= bufSize && !fillBuf()) ? EOF : buf[bufIdx]; } + virtual GString *getPSFilter(int psLevel, const char *indent, + GBool okToReadStream) + { return NULL; } + virtual GBool isBinary(GBool last = gTrue) { return gTrue; } + virtual GBool isEncoder() { return gTrue; } + +private: + + GBool fillBuf(); + + int width, height; + GfxImageColorMap *colorMap; + int numComps; + int *maskColors; + ImageStream *imgStr; + Guchar *buf; + int bufIdx; + int bufSize; +}; + +ColorKeyToMaskEncoder::ColorKeyToMaskEncoder(Stream *strA, + int widthA, int heightA, + GfxImageColorMap *colorMapA, + int *maskColorsA): + FilterStream(strA) +{ + width = widthA; + height = heightA; + colorMap = colorMapA; + numComps = colorMap->getNumPixelComps(); + maskColors = maskColorsA; + imgStr = NULL; + bufSize = (width + 7) / 8; + buf = (Guchar *)gmalloc(bufSize); + bufIdx = width; +} + +ColorKeyToMaskEncoder::~ColorKeyToMaskEncoder() { + gfree(buf); + if (str->isEncoder()) { + delete str; + } +} + +Stream *ColorKeyToMaskEncoder::copy() { + error(errInternal, -1, "Called copy() on ColorKeyToMaskEncoder"); + return NULL; +} + +void ColorKeyToMaskEncoder::reset() { + imgStr = new ImageStream(str, width, colorMap->getNumPixelComps(), + colorMap->getBits()); + imgStr->reset(); +} + +void ColorKeyToMaskEncoder::close() { + delete imgStr; + imgStr = NULL; + str->close(); +} + +GBool ColorKeyToMaskEncoder::fillBuf() { + Guchar *line, *linePtr, *bufPtr; + Guchar byte; + int x, xx, i; + + if (!(line = imgStr->getLine())) { + bufIdx = width; + return gFalse; + } + linePtr = line; + bufPtr = buf; + for (x = 0; x < width; x += 8) { + byte = 0; + for (xx = 0; xx < 8; ++xx) { + byte = (Guchar)(byte << 1); + if (x + xx < width) { + for (i = 0; i < numComps; ++i) { + if (linePtr[i] < maskColors[2 * i] || + linePtr[i] > maskColors[2 * i + 1]) { + break; + } + } + if (i >= numComps) { + byte |= 1; + } + linePtr += numComps; + } else { + byte |= 1; + } + } + *bufPtr++ = byte; + } + bufIdx = 0; + return gTrue; +} + +//------------------------------------------------------------------------ +// PSOutputDev +//------------------------------------------------------------------------ + +extern "C" { +typedef void (*SignalFunc)(int); +} + +static void outputToFile(void *stream, const char *data, int len) { + fwrite(data, 1, len, (FILE *)stream); +} + +PSOutputDev::PSOutputDev(char *fileName, PDFDoc *docA, + int firstPageA, int lastPageA, PSOutMode modeA, + int imgLLXA, int imgLLYA, int imgURXA, int imgURYA, + GBool manualCtrlA, + PSOutCustomCodeCbk customCodeCbkA, + void *customCodeCbkDataA, + GBool honorUserUnitA, + GBool fileNameIsUTF8) { + FILE *f; + PSFileType fileTypeA; + + underlayCbk = NULL; + underlayCbkData = NULL; + overlayCbk = NULL; + overlayCbkData = NULL; + customCodeCbk = customCodeCbkA; + customCodeCbkData = customCodeCbkDataA; + + rasterizePage = NULL; + fontInfo = new GList(); + fontFileInfo = new GHash(); + imgIDs = NULL; + formIDs = NULL; + visitedResources = NULL; + saveStack = NULL; + paperSizes = NULL; + embFontList = NULL; + customColors = NULL; + haveTextClip = gFalse; + t3String = NULL; + + // open file or pipe + if (!strcmp(fileName, "-")) { + fileTypeA = psStdout; + f = stdout; + } else if (fileName[0] == '|') { + fileTypeA = psPipe; +#ifdef HAVE_POPEN +#ifndef _WIN32 + signal(SIGPIPE, (SignalFunc)SIG_IGN); +#endif + if (!(f = popen(fileName + 1, "w"))) { + error(errIO, -1, "Couldn't run print command '{0:s}'", fileName); + ok = gFalse; + return; + } +#else + error(errIO, -1, "Print commands are not supported ('{0:s}')", fileName); + ok = gFalse; + return; +#endif + } else { + fileTypeA = psFile; + if (fileNameIsUTF8) { + f = openFile(fileName, "w"); + } else { + f = fopen(fileName, "w"); + } + if (!f) { + error(errIO, -1, "Couldn't open PostScript file '{0:s}'", fileName); + ok = gFalse; + return; + } + } + + init(outputToFile, f, fileTypeA, + docA, firstPageA, lastPageA, modeA, + imgLLXA, imgLLYA, imgURXA, imgURYA, manualCtrlA, honorUserUnitA); +} + +PSOutputDev::PSOutputDev(PSOutputFunc outputFuncA, void *outputStreamA, + PDFDoc *docA, + int firstPageA, int lastPageA, PSOutMode modeA, + int imgLLXA, int imgLLYA, int imgURXA, int imgURYA, + GBool manualCtrlA, + PSOutCustomCodeCbk customCodeCbkA, + void *customCodeCbkDataA, + GBool honorUserUnitA) { + underlayCbk = NULL; + underlayCbkData = NULL; + overlayCbk = NULL; + overlayCbkData = NULL; + customCodeCbk = customCodeCbkA; + customCodeCbkData = customCodeCbkDataA; + + rasterizePage = NULL; + fontInfo = new GList(); + fontFileInfo = new GHash(); + imgIDs = NULL; + formIDs = NULL; + visitedResources = NULL; + saveStack = NULL; + paperSizes = NULL; + embFontList = NULL; + customColors = NULL; + haveTextClip = gFalse; + t3String = NULL; + + init(outputFuncA, outputStreamA, psGeneric, + docA, firstPageA, lastPageA, modeA, + imgLLXA, imgLLYA, imgURXA, imgURYA, manualCtrlA, honorUserUnitA); +} + +void PSOutputDev::init(PSOutputFunc outputFuncA, void *outputStreamA, + PSFileType fileTypeA, PDFDoc *docA, + int firstPageA, int lastPageA, PSOutMode modeA, + int imgLLXA, int imgLLYA, int imgURXA, int imgURYA, + GBool manualCtrlA, GBool honorUserUnitA) { + Catalog *catalog; + Page *page; + PDFRectangle *box; + PSOutPaperSize *size; + PSFontFileInfo *ff; + GList *names; + double userUnit; + int pg, w, h, i; + + // initialize + ok = gTrue; + outputFunc = outputFuncA; + outputStream = outputStreamA; + fileType = fileTypeA; + doc = docA; + xref = doc->getXRef(); + catalog = doc->getCatalog(); + if ((firstPage = firstPageA) < 1) { + firstPage = 1; + } + if ((lastPage = lastPageA) > doc->getNumPages()) { + lastPage = doc->getNumPages(); + } + level = globalParams->getPSLevel(); + mode = modeA; + honorUserUnit = honorUserUnitA; + paperWidth = globalParams->getPSPaperWidth(); + paperHeight = globalParams->getPSPaperHeight(); + imgLLX = imgLLXA; + imgLLY = imgLLYA; + imgURX = imgURXA; + imgURY = imgURYA; + if (imgLLX == 0 && imgURX == 0 && imgLLY == 0 && imgURY == 0) { + globalParams->getPSImageableArea(&imgLLX, &imgLLY, &imgURX, &imgURY); + } + if (paperWidth < 0 || paperHeight < 0) { + paperMatch = gTrue; + paperSizes = new GList(); + paperWidth = paperHeight = 1; // in case the document has zero pages + for (pg = firstPage; pg <= lastPage; ++pg) { + page = catalog->getPage(pg); + if (honorUserUnit) { + userUnit = page->getUserUnit(); + } else { + userUnit = 1; + } + if (globalParams->getPSUseCropBoxAsPage()) { + w = (int)ceil(page->getCropWidth() * userUnit); + h = (int)ceil(page->getCropHeight() * userUnit); + } else { + w = (int)ceil(page->getMediaWidth() * userUnit); + h = (int)ceil(page->getMediaHeight() * userUnit); + } + 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; + } + } + // NB: img{LLX,LLY,URX,URY} will be set by startPage() + } else { + paperMatch = gFalse; + } + preload = globalParams->getPSPreload(); + manualCtrl = manualCtrlA; + if (mode == psModeForm) { + lastPage = firstPage; + } + processColors = 0; + inType3Char = gFalse; + +#if OPI_SUPPORT + // initialize OPI nesting levels + opi13Nest = 0; + opi20Nest = 0; +#endif + + tx0 = ty0 = -1; + xScale0 = yScale0 = 0; + rotate0 = -1; + clipLLX0 = clipLLY0 = 0; + clipURX0 = clipURY0 = -1; + expandSmallPages = globalParams->getPSExpandSmaller(); + + // initialize font lists, etc. + for (i = 0; i < 14; ++i) { + ff = new PSFontFileInfo(new GString(psBase14SubstFonts[i].psName), + fontType1, psFontFileResident); + fontFileInfo->add(ff->psName, ff); + } + names = globalParams->getPSResidentFonts(); + for (i = 0; i < names->getLength(); ++i) { + if (!fontFileInfo->lookup((GString *)names->get(i))) { + ff = new PSFontFileInfo((GString *)names->get(i), fontType1, + psFontFileResident); + fontFileInfo->add(ff->psName, ff); + } + } + delete names; + imgIDLen = 0; + imgIDSize = 0; + formIDLen = 0; + formIDSize = 0; + + noStateChanges = gFalse; + saveStack = new GList(); + numTilingPatterns = 0; + nextFunc = 0; + + // initialize embedded font resource comment list + embFontList = new GString(); + + if (!manualCtrl) { + // this check is needed in case the document has zero pages + if (firstPage <= catalog->getNumPages()) { + writeHeader(catalog->getPage(firstPage)->getMediaBox(), + catalog->getPage(firstPage)->getCropBox(), + catalog->getPage(firstPage)->getRotate()); + } else { + box = new PDFRectangle(0, 0, 1, 1); + writeHeader(box, box, 0); + delete box; + } + if (mode != psModeForm) { + writePS("%%BeginProlog\n"); + } + writeXpdfProcset(); + if (mode != psModeForm) { + writePS("%%EndProlog\n"); + writePS("%%BeginSetup\n"); + } + writeDocSetup(catalog); + if (mode != psModeForm) { + writePS("%%EndSetup\n"); + } + } + + // initialize sequential page number + seqPage = 1; +} + +PSOutputDev::~PSOutputDev() { + PSOutCustomColor *cc; + + if (ok) { + if (!manualCtrl) { + writePS("%%Trailer\n"); + writeTrailer(); + if (mode != psModeForm) { + writePS("%%EOF\n"); + } + } + if (fileType == psFile) { + fclose((FILE *)outputStream); + } +#ifdef HAVE_POPEN + else if (fileType == psPipe) { + pclose((FILE *)outputStream); +#ifndef _WIN32 + signal(SIGPIPE, (SignalFunc)SIG_DFL); +#endif + } +#endif + } + gfree(rasterizePage); + if (paperSizes) { + deleteGList(paperSizes, PSOutPaperSize); + } + if (embFontList) { + delete embFontList; + } + deleteGList(fontInfo, PSFontInfo); + deleteGHash(fontFileInfo, PSFontFileInfo); + gfree(imgIDs); + gfree(formIDs); + if (saveStack) { + delete saveStack; + } + while (customColors) { + cc = customColors; + customColors = cc->next; + delete cc; + } + if (t3String) { + // this will only happen if the 'd1' operator is used outside of a + // Type 3 CharProc + delete t3String; + } +} + +GBool PSOutputDev::checkIO() { + if (fileType == psFile || fileType == psPipe || fileType == psStdout) { + if (ferror((FILE *)outputStream)) { + error(errIO, -1, "Error writing to PostScript file"); + return gFalse; + } + } + return gTrue; +} + +void PSOutputDev::writeHeader(PDFRectangle *mediaBox, PDFRectangle *cropBox, + int pageRotate) { + Object info, obj1; + PSOutPaperSize *size; + double x1, y1, x2, y2; + int i; + + switch (mode) { + case psModePS: + writePS("%!PS-Adobe-3.0\n"); + break; + case psModeEPS: + writePS("%!PS-Adobe-3.0 EPSF-3.0\n"); + break; + case psModeForm: + writePS("%!PS-Adobe-3.0 Resource-Form\n"); + break; + } + + writePSFmt("%XpdfVersion: {0:s}\n", xpdfVersion); + xref->getDocInfo(&info); + if (info.isDict() && info.dictLookup("Creator", &obj1)->isString()) { + writePS("%%Creator: "); + writePSTextLine(obj1.getString()); + } + obj1.free(); + if (info.isDict() && info.dictLookup("Title", &obj1)->isString()) { + writePS("%%Title: "); + writePSTextLine(obj1.getString()); + } + obj1.free(); + info.free(); + writePSFmt("%%LanguageLevel: {0:d}\n", + level >= psLevel3 ? 3 : level >= psLevel2 ? 2 : 1); + if (level == psLevel1Sep || level == psLevel2Sep || level == psLevel3Sep) { + writePS("%%DocumentProcessColors: (atend)\n"); + writePS("%%DocumentCustomColors: (atend)\n"); + } + writePS("%%DocumentSuppliedResources: (atend)\n"); + + switch (mode) { + case psModePS: + 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"); + if (!paperMatch) { + writePS("%%BeginDefaults\n"); + writePS("%%PageMedia: plain\n"); + writePS("%%EndDefaults\n"); + } + break; + case psModeEPS: + epsX1 = cropBox->x1; + epsY1 = cropBox->y1; + epsX2 = cropBox->x2; + epsY2 = cropBox->y2; + if (pageRotate == 0 || pageRotate == 180) { + x1 = epsX1; + y1 = epsY1; + x2 = epsX2; + y2 = epsY2; + } else { // pageRotate == 90 || pageRotate == 270 + x1 = 0; + y1 = 0; + x2 = epsY2 - epsY1; + y2 = epsX2 - epsX1; + } + writePSFmt("%%BoundingBox: {0:d} {1:d} {2:d} {3:d}\n", + (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:.6g} {1:.6g} {2:.6g} {3:.6g}\n", + x1, y1, x2, y2); + } + writePS("%%EndComments\n"); + break; + case psModeForm: + writePS("%%EndComments\n"); + writePS("32 dict dup begin\n"); + writePSFmt("/BBox [{0:d} {1:d} {2:d} {3:d}] def\n", + (int)floor(mediaBox->x1), (int)floor(mediaBox->y1), + (int)ceil(mediaBox->x2), (int)ceil(mediaBox->y2)); + writePS("/FormType 1 def\n"); + writePS("/Matrix [1 0 0 1 0 0] def\n"); + break; + } +} + +void PSOutputDev::writeXpdfProcset() { + GBool lev1, lev2, lev3, nonSep, gray, sep; + const char **p; + const char *q; + double w; + + writePSFmt("%%BeginResource: procset xpdf {0:s} 0\n", xpdfVersion); + writePSFmt("%%Copyright: {0:s}\n", xpdfCopyright); + lev1 = lev2 = lev3 = nonSep = gray = sep = gTrue; + for (p = prolog; *p; ++p) { + if ((*p)[0] == '~') { + lev1 = lev2 = lev3 = nonSep = gray = sep = gFalse; + for (q = *p + 1; *q; ++q) { + switch (*q) { + case '1': lev1 = gTrue; break; + case '2': lev2 = gTrue; break; + case '3': lev3 = gTrue; break; + case 'g': gray = gTrue; break; + case 'n': nonSep = gTrue; break; + case 's': sep = gTrue; break; + } + } + } else if ((level == psLevel1 && lev1 && nonSep) || + (level == psLevel1Sep && lev1 && sep) || + (level == psLevel2 && lev2 && nonSep) || + (level == psLevel2Gray && lev2 && gray) || + (level == psLevel2Sep && lev2 && sep) || + (level == psLevel3 && lev3 && nonSep) || + (level == psLevel3Gray && lev3 && gray) || + (level == psLevel3Sep && lev3 && sep)) { + writePSFmt("{0:s}\n", *p); + } + } + if ((w = globalParams->getPSMinLineWidth()) > 0) { + writePSFmt("/pdfMinLineWidth {0:.4g} def\n", w); + for (p = minLineWidthProlog; *p; ++p) { + writePSFmt("{0:s}\n", *p); + } + } + writePS("%%EndResource\n"); + + if (level >= psLevel3) { + for (p = cmapProlog; *p; ++p) { + writePSFmt("{0:s}\n", *p); + } + } +} + +void PSOutputDev::writeDocSetup(Catalog *catalog) { + Page *page; + Dict *resDict; + Annots *annots; + AcroForm *form; + Object obj1, obj2, obj3; + GString *s; + GBool needDefaultFont; + int pg, i, j; + + // check to see which pages will be rasterized + if (firstPage <= lastPage) { + rasterizePage = (char *)gmalloc(lastPage - firstPage + 1); + for (pg = firstPage; pg <= lastPage; ++pg) { + rasterizePage[pg - firstPage] = (char)checkIfPageNeedsToBeRasterized(pg); + } + } else { + rasterizePage = NULL; + } + + visitedResources = (char *)gmalloc(xref->getNumObjects()); + memset(visitedResources, 0, xref->getNumObjects()); + + if (mode == psModeForm) { + // swap the form and xpdf dicts + writePS("xpdf end begin dup begin\n"); + } else { + writePS("xpdf begin\n"); + } + needDefaultFont = gFalse; + for (pg = firstPage; pg <= lastPage; ++pg) { + if (rasterizePage[pg - firstPage]) { + continue; + } + page = catalog->getPage(pg); + if ((resDict = page->getResourceDict())) { + setupResources(resDict); + } + annots = new Annots(doc, page->getAnnots(&obj1)); + obj1.free(); + if (annots->getNumAnnots()) { + needDefaultFont = gTrue; + } + for (i = 0; i < annots->getNumAnnots(); ++i) { + if (annots->getAnnot(i)->getAppearance(&obj1)->isStream()) { + obj1.streamGetDict()->lookup("Resources", &obj2); + if (obj2.isDict()) { + setupResources(obj2.getDict()); + } + obj2.free(); + } + obj1.free(); + } + delete annots; + } + if ((form = catalog->getForm())) { + if (form->getNumFields() > 0) { + needDefaultFont = gTrue; + } + for (i = 0; i < form->getNumFields(); ++i) { + form->getField(i)->getResources(&obj1); + if (obj1.isArray()) { + for (j = 0; j < obj1.arrayGetLength(); ++j) { + obj1.arrayGet(j, &obj2); + if (obj2.isDict()) { + setupResources(obj2.getDict()); + } + obj2.free(); + } + } else if (obj1.isDict()) { + setupResources(obj1.getDict()); + } + obj1.free(); + } + } + if (needDefaultFont) { + setupDefaultFont(); + } + if (mode != psModeForm) { + if (mode != psModeEPS && !manualCtrl) { + 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()) { + writePS("/opiMatrix matrix currentmatrix def\n"); + } +#endif + } + if (customCodeCbk) { + if ((s = (*customCodeCbk)(this, psOutCustomDocSetup, 0, + customCodeCbkData))) { + writePS(s->getCString()); + delete s; + } + } + if (mode != psModeForm) { + writePS("end\n"); + } + + gfree(visitedResources); + visitedResources = NULL; +} + +void PSOutputDev::writePageTrailer() { + if (mode != psModeForm) { + writePS("pdfEndPage\n"); + } +} + +void PSOutputDev::writeTrailer() { + PSOutCustomColor *cc; + + if (mode == psModeForm) { + writePS("/Foo exch /Form defineresource pop\n"); + } else { + writePS("%%DocumentSuppliedResources:\n"); + writePS(embFontList->getCString()); + if (level == psLevel1Sep || level == psLevel2Sep || + level == psLevel3Sep) { + writePS("%%DocumentProcessColors:"); + if (processColors & psProcessCyan) { + writePS(" Cyan"); + } + if (processColors & psProcessMagenta) { + writePS(" Magenta"); + } + if (processColors & psProcessYellow) { + writePS(" Yellow"); + } + if (processColors & psProcessBlack) { + writePS(" Black"); + } + writePS("\n"); + writePS("%%DocumentCustomColors:"); + for (cc = customColors; cc; cc = cc->next) { + 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} ", + cc->c, cc->m, cc->y, cc->k); + writePSString(cc->name); + writePS("\n"); + } + } + } +} + +GBool PSOutputDev::checkIfPageNeedsToBeRasterized(int pg) { + PreScanOutputDev *scan; + GBool rasterize; + + if (globalParams->getPSAlwaysRasterize()) { + rasterize = gTrue; + } else { + scan = new PreScanOutputDev(); + //~ this could depend on the printing flag, e.g., if an annotation + //~ uses transparency --> need to pass the printing flag into + //~ constructor, init, writeDocSetup + doc->getCatalog()->getPage(pg)->display(scan, 72, 72, 0, + gTrue, gTrue, gTrue); + rasterize = scan->usesTransparency() || scan->usesPatternImageMask(); + delete scan; + if (rasterize && globalParams->getPSNeverRasterize()) { + error(errSyntaxWarning, -1, + "PDF page uses transparency and the psNeverRasterize option is " + "set - output may not be correct"); + rasterize = gFalse; + } + } + return rasterize; +} + +void PSOutputDev::setupResources(Dict *resDict) { + Object xObjDict, xObjRef, xObj, patDict, patRef, pat; + Object gsDict, gsRef, gs, smask, smaskGroup, resObj; + Ref ref0; + GBool skip; + int i; + + setupFonts(resDict); + setupImages(resDict); + + //----- recursively scan XObjects + resDict->lookup("XObject", &xObjDict); + if (xObjDict.isDict()) { + for (i = 0; i < xObjDict.dictGetLength(); ++i) { + + // check for an already-visited XObject + skip = gFalse; + if ((xObjDict.dictGetValNF(i, &xObjRef)->isRef())) { + ref0 = xObjRef.getRef(); + if (ref0.num < 0 || ref0.num >= xref->getNumObjects()) { + skip = gTrue; + } else { + skip = (GBool)visitedResources[ref0.num]; + visitedResources[ref0.num] = 1; + } + } + if (!skip) { + + // process the XObject's resource dictionary + xObjDict.dictGetVal(i, &xObj); + if (xObj.isStream()) { + xObj.streamGetDict()->lookup("Resources", &resObj); + if (resObj.isDict()) { + setupResources(resObj.getDict()); + } + resObj.free(); + } + xObj.free(); + } + + xObjRef.free(); + } + } + xObjDict.free(); + + //----- recursively scan Patterns + resDict->lookup("Pattern", &patDict); + if (patDict.isDict()) { + inType3Char = gTrue; + for (i = 0; i < patDict.dictGetLength(); ++i) { + + // check for an already-visited Pattern + skip = gFalse; + if ((patDict.dictGetValNF(i, &patRef)->isRef())) { + ref0 = patRef.getRef(); + if (ref0.num < 0 || ref0.num >= xref->getNumObjects()) { + skip = gTrue; + } else { + skip = (GBool)visitedResources[ref0.num]; + visitedResources[ref0.num] = 1; + } + } + if (!skip) { + + // process the Pattern's resource dictionary + patDict.dictGetVal(i, &pat); + if (pat.isStream()) { + pat.streamGetDict()->lookup("Resources", &resObj); + if (resObj.isDict()) { + setupResources(resObj.getDict()); + } + resObj.free(); + } + pat.free(); + } + + patRef.free(); + } + inType3Char = gFalse; + } + patDict.free(); + + + //----- recursively scan SMask transparency groups in ExtGState dicts + resDict->lookup("ExtGState", &gsDict); + if (gsDict.isDict()) { + for (i = 0; i < gsDict.dictGetLength(); ++i) { + + // check for an already-visited ExtGState + skip = gFalse; + if ((gsDict.dictGetValNF(i, &gsRef)->isRef())) { + ref0 = gsRef.getRef(); + if (ref0.num < 0 || ref0.num >= xref->getNumObjects()) { + skip = gTrue; + } else { + skip = (GBool)visitedResources[ref0.num]; + visitedResources[ref0.num] = 1; + } + } + if (!skip) { + + // process the ExtGState's SMask's transparency group's resource dict + if (gsDict.dictGetVal(i, &gs)->isDict()) { + if (gs.dictLookup("SMask", &smask)->isDict()) { + if (smask.dictLookup("G", &smaskGroup)->isStream()) { + smaskGroup.streamGetDict()->lookup("Resources", &resObj); + if (resObj.isDict()) { + setupResources(resObj.getDict()); + } + resObj.free(); + } + smaskGroup.free(); + } + smask.free(); + } + gs.free(); + } + + gsRef.free(); + } + } + gsDict.free(); + + setupForms(resDict); +} + +void PSOutputDev::setupFonts(Dict *resDict) { + Object obj1, obj2; + Ref r; + GfxFontDict *gfxFontDict; + GfxFont *font; + int i; + + gfxFontDict = NULL; + resDict->lookupNF("Font", &obj1); + if (obj1.isRef()) { + obj1.fetch(xref, &obj2); + if (obj2.isDict()) { + r = obj1.getRef(); + gfxFontDict = new GfxFontDict(xref, &r, obj2.getDict()); + } + obj2.free(); + } else if (obj1.isDict()) { + gfxFontDict = new GfxFontDict(xref, NULL, obj1.getDict()); + } + if (gfxFontDict) { + for (i = 0; i < gfxFontDict->getNumFonts(); ++i) { + if ((font = gfxFontDict->getFont(i))) { + setupFont(font, resDict); + } + } + delete gfxFontDict; + } + obj1.free(); +} + +void PSOutputDev::setupFont(GfxFont *font, Dict *parentResDict) { + PSFontInfo *fi; + GfxFontLoc *fontLoc; + GBool subst; + char buf[16]; + UnicodeMap *uMap; + char *charName; + double xs, ys; + int code; + double w1, w2; + int i, j; + + // check if font is already set up + for (i = 0; i < fontInfo->getLength(); ++i) { + fi = (PSFontInfo *)fontInfo->get(i); + if (fi->fontID.num == font->getID()->num && + fi->fontID.gen == font->getID()->gen) { + return; + } + } + + // add fontInfo entry + fi = new PSFontInfo(*font->getID()); + fontInfo->append(fi); + + xs = ys = 1; + subst = gFalse; + + if (font->getType() == fontType3) { + fi->ff = setupType3Font(font, parentResDict); + } else { + if ((fontLoc = font->locateFont(xref, gTrue))) { + switch (fontLoc->locType) { + case gfxFontLocEmbedded: + switch (fontLoc->fontType) { + case fontType1: + fi->ff = setupEmbeddedType1Font(font, &fontLoc->embFontID); + break; + case fontType1C: + fi->ff = setupEmbeddedType1CFont(font, &fontLoc->embFontID); + break; + case fontType1COT: + fi->ff = setupEmbeddedOpenTypeT1CFont(font, &fontLoc->embFontID); + break; + case fontTrueType: + case fontTrueTypeOT: + fi->ff = setupEmbeddedTrueTypeFont(font, &fontLoc->embFontID); + break; + case fontCIDType0C: + fi->ff = setupEmbeddedCIDType0Font(font, &fontLoc->embFontID); + break; + case fontCIDType2: + case fontCIDType2OT: + //~ should check to see if font actually uses vertical mode + fi->ff = setupEmbeddedCIDTrueTypeFont(font, &fontLoc->embFontID, + gTrue); + break; + case fontCIDType0COT: + fi->ff = setupEmbeddedOpenTypeCFFFont(font, &fontLoc->embFontID); + break; + default: + break; + } + break; + case gfxFontLocExternal: + //~ add cases for other external 16-bit fonts + switch (fontLoc->fontType) { + case fontType1: + fi->ff = setupExternalType1Font(font, fontLoc->path); + break; + case fontTrueType: + case fontTrueTypeOT: + fi->ff = setupExternalTrueTypeFont(font, fontLoc->path, + fontLoc->fontNum); + break; + case fontCIDType2: + case fontCIDType2OT: + //~ should check to see if font actually uses vertical mode + fi->ff = setupExternalCIDTrueTypeFont(font, fontLoc->path, + fontLoc->fontNum, gTrue); + break; + case fontCIDType0COT: + fi->ff = setupExternalOpenTypeCFFFont(font, fontLoc->path); + break; + default: + break; + } + break; + case gfxFontLocResident: + if (!(fi->ff = (PSFontFileInfo *)fontFileInfo->lookup(fontLoc->path))) { + // handle psFontPassthrough + fi->ff = new PSFontFileInfo(fontLoc->path->copy(), fontLoc->fontType, + psFontFileResident); + fontFileInfo->add(fi->ff->psName, fi->ff); + } + break; + } + } + + if (!fi->ff) { + if (font->isCIDFont()) { + error(errSyntaxError, -1, + "Couldn't find a font for '{0:s}' ('{1:s}' character collection)", + font->getName() ? font->getName()->getCString() + : "(unnamed)", + ((GfxCIDFont *)font)->getCollection() + ? ((GfxCIDFont *)font)->getCollection()->getCString() + : "(unknown)"); + } else { + error(errSyntaxError, -1, + "Couldn't find a font for '{0:s}'", + font->getName() ? font->getName()->getCString() + : "(unnamed)"); + } + 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') { + break; + } + } + if (code < 256) { + w1 = ((Gfx8BitFont *)font)->getWidth((Guchar)code); + } else { + w1 = 0; + } + w2 = psBase14SubstFonts[fontLoc->substIdx].mWidth; + xs = w1 / w2; + if (xs < 0.1) { + xs = 1; + } + } + + // handle encodings for substituted CID fonts + if (fontLoc->locType == gfxFontLocResident && + fontLoc->fontType >= fontCIDType0) { + subst = gTrue; + if (!fi->ff->encoding) { + if ((uMap = globalParams->getUnicodeMap(fontLoc->encoding))) { + fi->ff->encoding = fontLoc->encoding->copy(); + uMap->decRefCnt(); + } else { + error(errSyntaxError, -1, + "Couldn't find Unicode map for 16-bit font encoding '{0:t}'", + fontLoc->encoding); + } + } + } + + delete fontLoc; + } + + // generate PostScript code to set up the font + if (font->isCIDFont()) { + if (level >= psLevel3) { + writePSFmt("/F{0:d}_{1:d} /{2:t} {3:d} pdfMakeFont16L3\n", + font->getID()->num, font->getID()->gen, fi->ff->psName, + font->getWMode()); + } else { + writePSFmt("/F{0:d}_{1:d} /{2:t} {3:d} pdfMakeFont16\n", + font->getID()->num, font->getID()->gen, fi->ff->psName, + font->getWMode()); + } + } else { + writePSFmt("/F{0:d}_{1:d} /{2:t} {3:.6g} {4:.6g}\n", + font->getID()->num, font->getID()->gen, fi->ff->psName, xs, ys); + for (i = 0; i < 256; i += 8) { + writePS((char *)((i == 0) ? "[ " : " ")); + for (j = 0; j < 8; ++j) { + if (font->getType() == fontTrueType && + !subst && + !((Gfx8BitFont *)font)->getHasEncoding()) { + snprintf(buf, sizeof(buf), "c%02x", i+j); + charName = buf; + } else { + charName = ((Gfx8BitFont *)font)->getCharName(i+j); + } + writePS("/"); + writePSName(charName ? charName : (char *)".notdef"); + // the empty name is legal in PDF and PostScript, but PostScript + // uses a double-slash (//...) for "immediately evaluated names", + // so we need to add a space character here + if (charName && !charName[0]) { + writePS(" "); + } + } + writePS((i == 256-8) ? (char *)"]\n" : (char *)"\n"); + } + writePS("pdfMakeFont\n"); + } +} + +PSFontFileInfo *PSOutputDev::setupEmbeddedType1Font(GfxFont *font, Ref *id) { + GString *psName, *origFont, *cleanFont; + PSFontFileInfo *ff; + Object refObj, strObj, obj1, obj2; + Dict *dict; + char buf[4096]; + GBool rename; + int length1, length2, n; + + // check if font is already embedded + if (!font->getEmbeddedFontName()) { + rename = gTrue; + } else if ((ff = (PSFontFileInfo *) + fontFileInfo->lookup(font->getEmbeddedFontName()))) { + if (ff->loc == psFontFileEmbedded && + ff->embFontID.num == id->num && + ff->embFontID.gen == id->gen) { + return ff; + } + rename = gTrue; + } else { + rename = gFalse; + } + + // generate name + // (this assumes that the PS font name matches the PDF font name) + if (rename) { + psName = makePSFontName(font, id); + } else { + psName = font->getEmbeddedFontName()->copy(); + } + + // get the font stream and info + refObj.initRef(id->num, id->gen); + refObj.fetch(xref, &strObj); + refObj.free(); + if (!strObj.isStream()) { + error(errSyntaxError, -1, "Embedded font file object is not a stream"); + goto err1; + } + if (!(dict = strObj.streamGetDict())) { + error(errSyntaxError, -1, + "Embedded font stream is missing its dictionary"); + goto err1; + } + dict->lookup("Length1", &obj1); + dict->lookup("Length2", &obj2); + if (!obj1.isInt() || !obj2.isInt()) { + error(errSyntaxError, -1, + "Missing length fields in embedded font stream dictionary"); + obj1.free(); + obj2.free(); + goto err1; + } + length1 = obj1.getInt(); + length2 = obj2.getInt(); + obj1.free(); + obj2.free(); + + // read the font file + origFont = new GString(); + strObj.streamReset(); + while ((n = strObj.streamGetBlock(buf, sizeof(buf))) > 0) { + origFont->append(buf, n); + } + strObj.streamClose(); + strObj.free(); + + // beginning comment + writePSFmt("%%BeginResource: font {0:t}\n", psName); + embFontList->append("%%+ font "); + embFontList->append(psName->getCString()); + embFontList->append("\n"); + + // clean up the font file + cleanFont = fixType1Font(origFont, length1, length2); + if (rename) { + renameType1Font(cleanFont, psName); + } + writePSBlock(cleanFont->getCString(), cleanFont->getLength()); + delete cleanFont; + delete origFont; + + // ending comment + writePS("%%EndResource\n"); + + ff = new PSFontFileInfo(psName, font->getType(), psFontFileEmbedded); + ff->embFontID = *id; + fontFileInfo->add(ff->psName, ff); + return ff; + + err1: + strObj.free(); + delete psName; + return NULL; +} + +PSFontFileInfo *PSOutputDev::setupExternalType1Font(GfxFont *font, + GString *fileName) { + static char hexChar[17] = "0123456789abcdef"; + GString *psName; + PSFontFileInfo *ff; + FILE *fontFile; + int buf[6]; + int c, n, i; + + if (font->getName()) { + // check if font is already embedded + if ((ff = (PSFontFileInfo *)fontFileInfo->lookup(font->getName()))) { + return ff; + } + // this assumes that the PS font name matches the PDF font name + psName = font->getName()->copy(); + } else { + // generate name + //~ this won't work -- the PS font name won't match + psName = makePSFontName(font, font->getID()); + } + + // beginning comment + writePSFmt("%%BeginResource: font {0:t}\n", psName); + embFontList->append("%%+ font "); + embFontList->append(psName->getCString()); + embFontList->append("\n"); + + // open the font file + if (!(fontFile = fopen(fileName->getCString(), "rb"))) { + error(errIO, -1, "Couldn't open external font file"); + delete psName; + return NULL; + } + + // check for PFB format + buf[0] = fgetc(fontFile); + buf[1] = fgetc(fontFile); + if (buf[0] == 0x80 && buf[1] == 0x01) { + while (1) { + for (i = 2; i < 6; ++i) { + buf[i] = fgetc(fontFile); + } + if (buf[2] == EOF || buf[3] == EOF || buf[4] == EOF || buf[5] == EOF) { + break; + } + n = buf[2] + (buf[3] << 8) + (buf[4] << 16) + (buf[5] << 24); + if (buf[1] == 0x01) { + for (i = 0; i < n; ++i) { + if ((c = fgetc(fontFile)) == EOF) { + break; + } + writePSChar((char)c); + } + } else { + for (i = 0; i < n; ++i) { + if ((c = fgetc(fontFile)) == EOF) { + break; + } + writePSChar(hexChar[(c >> 4) & 0x0f]); + writePSChar(hexChar[c & 0x0f]); + if (i % 32 == 31) { + writePSChar('\n'); + } + } + } + buf[0] = fgetc(fontFile); + buf[1] = fgetc(fontFile); + if (buf[0] == EOF || buf[1] == EOF || + (buf[0] == 0x80 && buf[1] == 0x03)) { + break; + } else if (!(buf[0] == 0x80 && + (buf[1] == 0x01 || buf[1] == 0x02))) { + error(errSyntaxError, -1, + "Invalid PFB header in external font file"); + break; + } + } + writePSChar('\n'); + + // plain text (PFA) format + } else { + writePSChar((char)buf[0]); + writePSChar((char)buf[1]); + while ((c = fgetc(fontFile)) != EOF) { + writePSChar((char)c); + } + } + + fclose(fontFile); + + // ending comment + writePS("%%EndResource\n"); + + ff = new PSFontFileInfo(psName, font->getType(), psFontFileExternal); + ff->extFileName = fileName->copy(); + fontFileInfo->add(ff->psName, ff); + return ff; +} + +PSFontFileInfo *PSOutputDev::setupEmbeddedType1CFont(GfxFont *font, Ref *id) { + GString *psName; + PSFontFileInfo *ff; + char *fontBuf; + int fontLen; + FoFiType1C *ffT1C; + GHashIter *iter; + + // check if font is already embedded + fontFileInfo->startIter(&iter); + while (fontFileInfo->getNext(&iter, &psName, (void **)&ff)) { + if (ff->loc == psFontFileEmbedded && + ff->embFontID.num == id->num && + ff->embFontID.gen == id->gen) { + fontFileInfo->killIter(&iter); + return ff; + } + } + + // generate name + psName = makePSFontName(font, id); + + // beginning comment + writePSFmt("%%BeginResource: font {0:t}\n", psName); + embFontList->append("%%+ font "); + embFontList->append(psName->getCString()); + embFontList->append("\n"); + + // convert it to a Type 1 font + if ((fontBuf = font->readEmbFontFile(xref, &fontLen))) { + if ((ffT1C = FoFiType1C::make(fontBuf, fontLen))) { + ffT1C->convertToType1(psName->getCString(), NULL, gTrue, + outputFunc, outputStream); + delete ffT1C; + } + gfree(fontBuf); + } + + // ending comment + writePS("%%EndResource\n"); + + ff = new PSFontFileInfo(psName, font->getType(), psFontFileEmbedded); + ff->embFontID = *id; + fontFileInfo->add(ff->psName, ff); + return ff; +} + +PSFontFileInfo *PSOutputDev::setupEmbeddedOpenTypeT1CFont(GfxFont *font, + Ref *id) { + GString *psName; + PSFontFileInfo *ff; + char *fontBuf; + int fontLen; + FoFiTrueType *ffTT; + GHashIter *iter; + + // check if font is already embedded + fontFileInfo->startIter(&iter); + while (fontFileInfo->getNext(&iter, &psName, (void **)&ff)) { + if (ff->loc == psFontFileEmbedded && + ff->embFontID.num == id->num && + ff->embFontID.gen == id->gen) { + fontFileInfo->killIter(&iter); + return ff; + } + } + + // generate name + psName = makePSFontName(font, id); + + // beginning comment + writePSFmt("%%BeginResource: font {0:t}\n", psName); + embFontList->append("%%+ font "); + embFontList->append(psName->getCString()); + embFontList->append("\n"); + + // convert it to a Type 1 font + if ((fontBuf = font->readEmbFontFile(xref, &fontLen))) { + if ((ffTT = FoFiTrueType::make(fontBuf, fontLen, 0, gTrue))) { + if (ffTT->isOpenTypeCFF()) { + ffTT->convertToType1(psName->getCString(), NULL, gTrue, + outputFunc, outputStream); + } + delete ffTT; + } + gfree(fontBuf); + } + + // ending comment + writePS("%%EndResource\n"); + + ff = new PSFontFileInfo(psName, font->getType(), psFontFileEmbedded); + ff->embFontID = *id; + fontFileInfo->add(ff->psName, ff); + return ff; +} + +PSFontFileInfo *PSOutputDev::setupEmbeddedTrueTypeFont(GfxFont *font, Ref *id) { + GString *psName; + PSFontFileInfo *ff; + char *fontBuf; + int fontLen; + FoFiTrueType *ffTT; + int *codeToGID; + GHashIter *iter; + + // get the code-to-GID mapping + if (!(fontBuf = font->readEmbFontFile(xref, &fontLen))) { + return NULL; + } + if (!(ffTT = FoFiTrueType::make(fontBuf, fontLen, 0))) { + gfree(fontBuf); + return NULL; + } + codeToGID = ((Gfx8BitFont *)font)->getCodeToGIDMap(ffTT); + + // check if font is already embedded + fontFileInfo->startIter(&iter); + while (fontFileInfo->getNext(&iter, &psName, (void **)&ff)) { + if (ff->loc == psFontFileEmbedded && + ff->type == font->getType() && + ff->embFontID.num == id->num && + ff->embFontID.gen == id->gen && + ff->codeToGIDLen == 256 && + !memcmp(ff->codeToGID, codeToGID, 256 * sizeof(int))) { + fontFileInfo->killIter(&iter); + gfree(codeToGID); + delete ffTT; + gfree(fontBuf); + return ff; + } + } + + // generate name + psName = makePSFontName(font, id); + + // beginning comment + writePSFmt("%%BeginResource: font {0:t}\n", psName); + embFontList->append("%%+ font "); + embFontList->append(psName->getCString()); + embFontList->append("\n"); + + // convert it to a Type 42 font + ffTT->convertToType42(psName->getCString(), + ((Gfx8BitFont *)font)->getHasEncoding() + ? ((Gfx8BitFont *)font)->getEncoding() + : (char **)NULL, + codeToGID, outputFunc, outputStream); + delete ffTT; + gfree(fontBuf); + + // ending comment + writePS("%%EndResource\n"); + + ff = new PSFontFileInfo(psName, font->getType(), psFontFileEmbedded); + ff->embFontID = *id; + ff->codeToGID = codeToGID; + ff->codeToGIDLen = 256; + fontFileInfo->add(ff->psName, ff); + return ff; +} + +PSFontFileInfo *PSOutputDev::setupExternalTrueTypeFont(GfxFont *font, + GString *fileName, + int fontNum) { + GString *psName; + PSFontFileInfo *ff; + FoFiTrueType *ffTT; + int *codeToGID; + GHashIter *iter; + + // get the code-to-GID mapping + if (!(ffTT = FoFiTrueType::load(fileName->getCString(), fontNum))) { + return NULL; + } + codeToGID = ((Gfx8BitFont *)font)->getCodeToGIDMap(ffTT); + + // check if font is already embedded + fontFileInfo->startIter(&iter); + while (fontFileInfo->getNext(&iter, &psName, (void **)&ff)) { + if (ff->loc == psFontFileExternal && + ff->type == font->getType() && + !ff->extFileName->cmp(fileName) && + ff->codeToGIDLen == 256 && + !memcmp(ff->codeToGID, codeToGID, 256 * sizeof(int))) { + fontFileInfo->killIter(&iter); + gfree(codeToGID); + delete ffTT; + return ff; + } + } + + // generate name + psName = makePSFontName(font, font->getID()); + + // beginning comment + writePSFmt("%%BeginResource: font {0:t}\n", psName); + embFontList->append("%%+ font "); + embFontList->append(psName->getCString()); + embFontList->append("\n"); + + // convert it to a Type 42 font + ffTT->convertToType42(psName->getCString(), + ((Gfx8BitFont *)font)->getHasEncoding() + ? ((Gfx8BitFont *)font)->getEncoding() + : (char **)NULL, + codeToGID, outputFunc, outputStream); + delete ffTT; + + // ending comment + writePS("%%EndResource\n"); + + ff = new PSFontFileInfo(psName, font->getType(), psFontFileExternal); + ff->extFileName = fileName->copy(); + ff->codeToGID = codeToGID; + ff->codeToGIDLen = 256; + fontFileInfo->add(ff->psName, ff); + return ff; +} + +PSFontFileInfo *PSOutputDev::setupEmbeddedCIDType0Font(GfxFont *font, Ref *id) { + GString *psName; + PSFontFileInfo *ff; + char *fontBuf; + int fontLen; + FoFiType1C *ffT1C; + GHashIter *iter; + + // check if font is already embedded + fontFileInfo->startIter(&iter); + while (fontFileInfo->getNext(&iter, &psName, (void **)&ff)) { + if (ff->loc == psFontFileEmbedded && + ff->embFontID.num == id->num && + ff->embFontID.gen == id->gen) { + fontFileInfo->killIter(&iter); + return ff; + } + } + + // generate name + psName = makePSFontName(font, id); + + // 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 ((ffT1C = FoFiType1C::make(fontBuf, fontLen))) { + if (globalParams->getPSLevel() >= psLevel3) { + // Level 3: use a CID font + ffT1C->convertToCIDType0(psName->getCString(), + ((GfxCIDFont *)font)->getCIDToGID(), + ((GfxCIDFont *)font)->getCIDToGIDLen(), + outputFunc, outputStream); + } else { + // otherwise: use a non-CID composite font + ffT1C->convertToType0(psName->getCString(), + ((GfxCIDFont *)font)->getCIDToGID(), + ((GfxCIDFont *)font)->getCIDToGIDLen(), + outputFunc, outputStream); + } + delete ffT1C; + } + gfree(fontBuf); + } + + // ending comment + writePS("%%EndResource\n"); + + ff = new PSFontFileInfo(psName, font->getType(), psFontFileEmbedded); + ff->embFontID = *id; + fontFileInfo->add(ff->psName, ff); + return ff; +} + +PSFontFileInfo *PSOutputDev::setupEmbeddedCIDTrueTypeFont( + GfxFont *font, Ref *id, + GBool needVerticalMetrics) { + GString *psName; + PSFontFileInfo *ff; + char *fontBuf; + int fontLen; + FoFiTrueType *ffTT; + int *codeToGID; + int codeToGIDLen; + GHashIter *iter; + + // get the code-to-GID mapping + codeToGID = ((GfxCIDFont *)font)->getCIDToGID(); + codeToGIDLen = ((GfxCIDFont *)font)->getCIDToGIDLen(); + + // check if font is already embedded + fontFileInfo->startIter(&iter); + while (fontFileInfo->getNext(&iter, &psName, (void **)&ff)) { + if (ff->loc == psFontFileEmbedded && + ff->type == font->getType() && + ff->embFontID.num == id->num && + ff->embFontID.gen == id->gen && + ff->codeToGIDLen == codeToGIDLen && + ((!ff->codeToGID && !codeToGID) || + (ff->codeToGID && codeToGID && + !memcmp(ff->codeToGID, codeToGID, codeToGIDLen * sizeof(int))))) { + fontFileInfo->killIter(&iter); + return ff; + } + } + + // generate name + psName = makePSFontName(font, id); + + // beginning comment + writePSFmt("%%BeginResource: font {0:t}\n", psName); + 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, 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); + } + delete ffTT; + } + gfree(fontBuf); + } + + // ending comment + writePS("%%EndResource\n"); + + ff = new PSFontFileInfo(psName, font->getType(), psFontFileEmbedded); + ff->embFontID = *id; + if (codeToGIDLen) { + ff->codeToGID = (int *)gmallocn(codeToGIDLen, sizeof(int)); + memcpy(ff->codeToGID, codeToGID, codeToGIDLen * sizeof(int)); + ff->codeToGIDLen = codeToGIDLen; + } + fontFileInfo->add(ff->psName, ff); + return ff; +} + +PSFontFileInfo *PSOutputDev::setupExternalCIDTrueTypeFont( + GfxFont *font, + GString *fileName, + int fontNum, + GBool needVerticalMetrics) { + GString *psName; + PSFontFileInfo *ff; + FoFiTrueType *ffTT; + int *codeToGID; + int codeToGIDLen; + CharCodeToUnicode *ctu; + Unicode uBuf[8]; + int cmap, cmapPlatform, cmapEncoding, code; + GHashIter *iter; + + // create a code-to-GID mapping, via Unicode + if (!(ffTT = FoFiTrueType::load(fileName->getCString(), fontNum))) { + return NULL; + } + if (!(ctu = ((GfxCIDFont *)font)->getToUnicode())) { + error(errSyntaxError, -1, + "Couldn't find a mapping to Unicode for font '{0:s}'", + font->getName() ? font->getName()->getCString() : "(unnamed)"); + delete ffTT; + return NULL; + } + // look for a Unicode cmap + for (cmap = 0; cmap < ffTT->getNumCmaps(); ++cmap) { + cmapPlatform = ffTT->getCmapPlatform(cmap); + cmapEncoding = ffTT->getCmapEncoding(cmap); + if ((cmapPlatform == 3 && cmapEncoding == 1) || + (cmapPlatform == 0 && cmapEncoding <= 4)) { + break; + } + } + if (cmap >= ffTT->getNumCmaps()) { + error(errSyntaxError, -1, + "Couldn't find a Unicode cmap in font '{0:s}'", + font->getName() ? font->getName()->getCString() : "(unnamed)"); + ctu->decRefCnt(); + delete ffTT; + return NULL; + } + // map CID -> Unicode -> GID + if (ctu->isIdentity()) { + codeToGIDLen = 65536; + } else { + codeToGIDLen = ctu->getLength(); + } + codeToGID = (int *)gmallocn(codeToGIDLen, sizeof(int)); + for (code = 0; code < codeToGIDLen; ++code) { + if (ctu->mapToUnicode(code, uBuf, 8) > 0) { + codeToGID[code] = ffTT->mapCodeToGID(cmap, uBuf[0]); + } else { + codeToGID[code] = 0; + } + } + ctu->decRefCnt(); + + // check if font is already embedded + fontFileInfo->startIter(&iter); + while (fontFileInfo->getNext(&iter, &psName, (void **)&ff)) { + if (ff->loc == psFontFileExternal && + ff->type == font->getType() && + !ff->extFileName->cmp(fileName) && + ff->codeToGIDLen == codeToGIDLen && + ff->codeToGID && + !memcmp(ff->codeToGID, codeToGID, codeToGIDLen * sizeof(int))) { + fontFileInfo->killIter(&iter); + gfree(codeToGID); + delete ffTT; + return ff; + } + } + + // check for embedding permission + if (ffTT->getEmbeddingRights() < 1) { + error(errSyntaxError, -1, + "TrueType font '{0:s}' does not allow embedding", + font->getName() ? font->getName()->getCString() : "(unnamed)"); + gfree(codeToGID); + delete ffTT; + return NULL; + } + + // generate name + psName = makePSFontName(font, font->getID()); + + // beginning comment + writePSFmt("%%BeginResource: font {0:t}\n", psName); + embFontList->append("%%+ font "); + embFontList->append(psName->getCString()); + embFontList->append("\n"); + + // convert it to a Type 0 font + //~ this should use fontNum to load the correct font + if (globalParams->getPSLevel() >= psLevel3) { + // Level 3: use a CID font + ffTT->convertToCIDType2(psName->getCString(), + codeToGID, codeToGIDLen, + needVerticalMetrics, + outputFunc, outputStream); + } else { + // otherwise: use a non-CID composite font + ffTT->convertToType0(psName->getCString(), + codeToGID, codeToGIDLen, + needVerticalMetrics, + outputFunc, outputStream); + } + delete ffTT; + + // ending comment + writePS("%%EndResource\n"); + + ff = new PSFontFileInfo(psName, font->getType(), psFontFileExternal); + ff->extFileName = fileName->copy(); + ff->codeToGID = codeToGID; + ff->codeToGIDLen = codeToGIDLen; + fontFileInfo->add(ff->psName, ff); + return ff; +} + +PSFontFileInfo *PSOutputDev::setupEmbeddedOpenTypeCFFFont(GfxFont *font, + Ref *id) { + GString *psName; + PSFontFileInfo *ff; + char *fontBuf; + int fontLen; + FoFiTrueType *ffTT; + GHashIter *iter; + int n; + + // check if font is already embedded + fontFileInfo->startIter(&iter); + while (fontFileInfo->getNext(&iter, &psName, (void **)&ff)) { + if (ff->loc == psFontFileEmbedded && + ff->embFontID.num == id->num && + ff->embFontID.gen == id->gen) { + fontFileInfo->killIter(&iter); + return ff; + } + } + + // generate name + psName = makePSFontName(font, id); + + // 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, 0, gTrue))) { + 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; + } + gfree(fontBuf); + } + + // ending comment + writePS("%%EndResource\n"); + + ff = new PSFontFileInfo(psName, font->getType(), psFontFileEmbedded); + ff->embFontID = *id; + if ((n = ((GfxCIDFont *)font)->getCIDToGIDLen())) { + ff->codeToGID = (int *)gmallocn(n, sizeof(int)); + memcpy(ff->codeToGID, ((GfxCIDFont *)font)->getCIDToGID(), n * sizeof(int)); + ff->codeToGIDLen = n; + } + fontFileInfo->add(ff->psName, ff); + return ff; +} + +// This assumes an OpenType CFF font that has a Unicode cmap (in the +// OpenType section), and a CFF blob that uses an identity CID-to-GID +// mapping. +PSFontFileInfo *PSOutputDev::setupExternalOpenTypeCFFFont(GfxFont *font, + GString *fileName) { + GString *psName; + PSFontFileInfo *ff; + FoFiTrueType *ffTT; + GHashIter *iter; + CharCodeToUnicode *ctu; + Unicode uBuf[8]; + int *codeToGID; + int codeToGIDLen; + int cmap, cmapPlatform, cmapEncoding, code; + + // create a code-to-GID mapping, via Unicode + if (!(ffTT = FoFiTrueType::load(fileName->getCString(), 0, gTrue))) { + return NULL; + } + if (!ffTT->isOpenTypeCFF()) { + delete ffTT; + return NULL; + } + if (!(ctu = ((GfxCIDFont *)font)->getToUnicode())) { + error(errSyntaxError, -1, + "Couldn't find a mapping to Unicode for font '{0:s}'", + font->getName() ? font->getName()->getCString() : "(unnamed)"); + delete ffTT; + return NULL; + } + // look for a Unicode cmap + for (cmap = 0; cmap < ffTT->getNumCmaps(); ++cmap) { + cmapPlatform = ffTT->getCmapPlatform(cmap); + cmapEncoding = ffTT->getCmapEncoding(cmap); + if ((cmapPlatform == 3 && cmapEncoding == 1) || + (cmapPlatform == 0 && cmapEncoding <= 4)) { + break; + } + } + if (cmap >= ffTT->getNumCmaps()) { + error(errSyntaxError, -1, + "Couldn't find a Unicode cmap in font '{0:s}'", + font->getName() ? font->getName()->getCString() : "(unnamed)"); + ctu->decRefCnt(); + delete ffTT; + return NULL; + } + // map CID -> Unicode -> GID + if (ctu->isIdentity()) { + codeToGIDLen = 65536; + } else { + codeToGIDLen = ctu->getLength(); + } + codeToGID = (int *)gmallocn(codeToGIDLen, sizeof(int)); + for (code = 0; code < codeToGIDLen; ++code) { + if (ctu->mapToUnicode(code, uBuf, 8) > 0) { + codeToGID[code] = ffTT->mapCodeToGID(cmap, uBuf[0]); + } else { + codeToGID[code] = 0; + } + } + ctu->decRefCnt(); + + // check if font is already embedded + fontFileInfo->startIter(&iter); + while (fontFileInfo->getNext(&iter, &psName, (void **)&ff)) { + if (ff->loc == psFontFileExternal && + ff->type == font->getType() && + !ff->extFileName->cmp(fileName) && + ff->codeToGIDLen == codeToGIDLen && + ff->codeToGID && + !memcmp(ff->codeToGID, codeToGID, codeToGIDLen * sizeof(int))) { + fontFileInfo->killIter(&iter); + gfree(codeToGID); + delete ffTT; + return ff; + } + } + + // generate name + psName = makePSFontName(font, font->getID()); + + // 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 (globalParams->getPSLevel() >= psLevel3) { + // Level 3: use a CID font + ffTT->convertToCIDType0(psName->getCString(), + codeToGID, codeToGIDLen, + outputFunc, outputStream); + } else { + // otherwise: use a non-CID composite font + ffTT->convertToType0(psName->getCString(), + codeToGID, codeToGIDLen, + outputFunc, outputStream); + } + delete ffTT; + + // ending comment + writePS("%%EndResource\n"); + + ff = new PSFontFileInfo(psName, font->getType(), psFontFileExternal); + ff->extFileName = fileName->copy(); + ff->codeToGID = codeToGID; + ff->codeToGIDLen = codeToGIDLen; + fontFileInfo->add(ff->psName, ff); + return ff; +} + +PSFontFileInfo *PSOutputDev::setupType3Font(GfxFont *font, + Dict *parentResDict) { + PSFontFileInfo *ff; + GString *psName; + Dict *resDict; + Dict *charProcs; + Object charProc; + Gfx *gfx; + PDFRectangle box; + double *m; + GString *buf; + int i; + + // generate name + psName = GString::format("T3_{0:d}_{1:d}", + font->getID()->num, font->getID()->gen); + + // set up resources used by font + if ((resDict = ((Gfx8BitFont *)font)->getResources())) { + inType3Char = gTrue; + setupResources(resDict); + inType3Char = gFalse; + } else { + resDict = parentResDict; + } + + // beginning comment + writePSFmt("%%BeginResource: font {0:t}\n", psName); + embFontList->append("%%+ font "); + embFontList->append(psName->getCString()); + embFontList->append("\n"); + + // font dictionary + writePS("8 dict begin\n"); + writePS("/FontType 3 def\n"); + m = font->getFontMatrix(); + 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:.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"); + writePS("/BuildGlyph {\n"); + writePS(" exch /CharProcs get exch\n"); + writePS(" 2 copy known not { pop /.notdef } if\n"); + writePS(" get exec\n"); + writePS("} bind def\n"); + writePS("/BuildChar {\n"); + writePS(" 1 index /Encoding get exch get\n"); + writePS(" 1 index /BuildGlyph get exec\n"); + writePS("} bind def\n"); + if ((charProcs = ((Gfx8BitFont *)font)->getCharProcs())) { + writePSFmt("/CharProcs {0:d} dict def\n", charProcs->getLength()); + writePS("CharProcs begin\n"); + box.x1 = m[0]; + box.y1 = m[1]; + box.x2 = m[2]; + box.y2 = m[3]; + gfx = new Gfx(doc, this, resDict, &box, NULL); + inType3Char = gTrue; + for (i = 0; i < charProcs->getLength(); ++i) { + t3FillColorOnly = gFalse; + t3Cacheable = gFalse; + t3NeedsRestore = gFalse; + writePS("/"); + writePSName(charProcs->getKey(i)); + writePS(" {\n"); + gfx->display(charProcs->getValNF(i, &charProc)); + charProc.free(); + if (t3String) { + if (t3Cacheable) { + 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:.6g} {1:.6g} setcharwidth\n", t3WX, t3WY); + } + (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); + delete buf; + (*outputFunc)(outputStream, t3String->getCString(), + t3String->getLength()); + delete t3String; + t3String = NULL; + } + if (t3NeedsRestore) { + (*outputFunc)(outputStream, "Q\n", 2); + } + writePS("} def\n"); + } + inType3Char = gFalse; + delete gfx; + writePS("end\n"); + } + writePS("currentdict end\n"); + writePSFmt("/{0:t} exch definefont pop\n", psName); + + // ending comment + writePS("%%EndResource\n"); + + ff = new PSFontFileInfo(psName, font->getType(), psFontFileEmbedded); + fontFileInfo->add(ff->psName, ff); + return ff; +} + +// Make a unique PS font name, based on the names given in the PDF +// 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 (!fontFileInfo->lookup(psName)) { + return psName; + } + delete psName; + } + if ((s = font->getName())) { + psName = filterPSName(s); + if (!fontFileInfo->lookup(psName)) { + 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; + } + return psName; +} + +GString *PSOutputDev::fixType1Font(GString *font, int length1, int length2) { + Guchar *fontData; + GString *out, *binSection; + GBool pfb; + int fontSize, i; + + fontData = (Guchar *)font->getCString(); + fontSize = font->getLength(); + + // check for PFB + pfb = fontSize >= 6 && fontData[0] == 0x80 && fontData[1] == 0x01; + out = new GString(); + binSection = new GString(); + if (pfb) { + if (!splitType1PFB(fontData, fontSize, out, binSection)) { + delete out; + delete binSection; + return copyType1PFB(fontData, fontSize); + } + } else { + if (!splitType1PFA(fontData, fontSize, length1, length2, + out, binSection)) { + delete out; + delete binSection; + return copyType1PFA(fontData, fontSize); + } + } + + out->append('\n'); + + binSection = asciiHexDecodeType1EexecSection(binSection); + + if (!fixType1EexecSection(binSection, out)) { + delete out; + delete binSection; + return pfb ? copyType1PFB(fontData, fontSize) + : copyType1PFA(fontData, fontSize); + } + delete binSection; + + for (i = 0; i < 8; ++i) { + out->append("0000000000000000000000000000000000000000000000000000000000000000\n"); + } + out->append("cleartomark\n"); + + return out; +} + +// Split a Type 1 font in PFA format into a text section and a binary +// section. +GBool PSOutputDev::splitType1PFA(Guchar *font, int fontSize, + int length1, int length2, + GString *textSection, GString *binSection) { + int textLength, binStart, binLength, lastSpace, i; + + //--- extract the text section + + // Length1 is correct, and the text section ends with whitespace + if (length1 <= fontSize && + length1 >= 18 && + !memcmp(font + length1 - 18, "currentfile eexec", 17)) { + textLength = length1 - 1; + + // Length1 is correct, but the trailing whitespace is missing + } else if (length1 <= fontSize && + length1 >= 17 && + !memcmp(font + length1 - 17, "currentfile eexec", 17)) { + textLength = length1; + + // Length1 is incorrect + } else { + for (textLength = 17; textLength <= fontSize; ++textLength) { + if (!memcmp(font + textLength - 17, "currentfile eexec", 17)) { + break; + } + } + if (textLength > fontSize) { + return gFalse; + } + } + + textSection->append((char *)font, textLength); + + //--- skip whitespace between the text section and the binary section + + for (i = 0, binStart = textLength; + i < 8 && binStart < fontSize; + ++i, ++binStart) { + if (font[binStart] != ' ' && font[binStart] != '\t' && + font[binStart] != '\n' && font[binStart] != '\r') { + break; + } + } + if (i == 8) { + return gFalse; + } + + //--- extract binary section + + // if we see "0000", assume Length2 is correct + // (if Length2 is too long, it will be corrected by fixType1EexecSection) + if (length2 > 0 && length2 < INT_MAX - 4 && + binStart <= fontSize - length2 - 4 && + !memcmp(font + binStart + length2, "0000", 4)) { + binLength = length2; + + } else { + + // look for "0000" near the end of the font (note that there can + // be intervening "\n", "\r\n", etc.), then search backward + if (fontSize - binStart < 512) { + return gFalse; + } + if (!memcmp(font + fontSize - 256, "0000", 4) || + !memcmp(font + fontSize - 255, "0000", 4) || + !memcmp(font + fontSize - 254, "0000", 4) || + !memcmp(font + fontSize - 253, "0000", 4) || + !memcmp(font + fontSize - 252, "0000", 4) || + !memcmp(font + fontSize - 251, "0000", 4)) { + i = fontSize - 252; + lastSpace = -1; + while (i >= binStart) { + if (font[i] == ' ' || font[i] == '\t' || + font[i] == '\n' || font[i] == '\r') { + lastSpace = i; + --i; + } else if (font[i] == '0') { + --i; + } else { + break; + } + } + if (lastSpace < 0) { + return gFalse; + } + // check for the case where the newline/space is missing between + // the binary section and the first set of 64 '0' chars + if (lastSpace - binStart > 64 && + !memcmp(font + lastSpace - 64, + "0000000000000000000000000000000000000000000000000000000000000000", + 64)) { + binLength = lastSpace - 64 - binStart; + } else { + binLength = lastSpace - binStart; + } + + // couldn't find zeros after binary section -- assume they're + // missing and the binary section extends to the end of the file + } else { + binLength = fontSize - binStart; + } + } + + binSection->append((char *)(font + binStart), binLength); + + return gTrue; +} + +// Split a Type 1 font in PFB format into a text section and a binary +// section. +GBool PSOutputDev::splitType1PFB(Guchar *font, int fontSize, + GString *textSection, GString *binSection) { + Guchar *p; + int state, remain, len, n; + + // states: + // 0: text section + // 1: binary section + // 2: trailer section + // 3: eof + + state = 0; + p = font; + remain = fontSize; + while (remain >= 2) { + if (p[0] != 0x80) { + return gFalse; + } + switch (state) { + case 0: + if (p[1] == 0x02) { + state = 1; + } else if (p[1] != 0x01) { + return gFalse; + } + break; + case 1: + if (p[1] == 0x01) { + state = 2; + } else if (p[1] != 0x02) { + return gFalse; + } + break; + case 2: + if (p[1] == 0x03) { + state = 3; + } else if (p[1] != 0x01) { + return gFalse; + } + break; + default: // shouldn't happen + return gFalse; + } + if (state == 3) { + break; + } + + if (remain < 6) { + break; + } + len = p[2] + (p[3] << 8) + (p[4] << 16) + (p[5] << 24); + if (len < 0 || len > remain - 6) { + return gFalse; + } + + switch (state) { + case 0: + textSection->append((char *)(p + 6), len); + break; + case 1: + binSection->append((char *)(p + 6), len); + break; + case 2: + // we don't use the trailer + break; + default: // shouldn't happen + return gFalse; + } + + p += len + 6; + remain -= len + 6; + } + + if (state != 3) { + return gFalse; + } + + n = textSection->getLength(); + if (n >= 18 && !memcmp(textSection->getCString() + n - 18, + "currentfile eexec", 17)) { + // remove the trailing whitespace + textSection->del(n - 1, 1); + } else if (n >= 17 && !memcmp(textSection->getCString() + n - 17, + "currentfile eexec", 17)) { + // missing whitespace at end -- leave as-is + } else { + return gFalse; + } + + return gTrue; +} + +// If is ASCIIHex-encoded, decode it, delete , and return the +// binary version. Else return unchanged. +GString *PSOutputDev::asciiHexDecodeType1EexecSection(GString *in) { + GString *out; + char c; + Guchar byte; + int state, i; + + out = new GString(); + state = 0; + byte = 0; + for (i = 0; i < in->getLength(); ++i) { + c = in->getChar(i); + if (c == ' ' || c == '\t' || c == '\n' || c == '\r') { + continue; + } + if (c >= '0' && c <= '9') { + byte = (Guchar)(byte + (c - '0')); + } else if (c >= 'A' && c <= 'F') { + byte = (Guchar)(byte + (c - 'A' + 10)); + } else if (c >= 'a' && c <= 'f') { + byte = (Guchar)(byte + (c - 'a' + 10)); + } else { + delete out; + return in; + } + if (state == 0) { + byte = (Guchar)(byte << 4); + state = 1; + } else { + out->append((char)byte); + state = 0; + byte = 0; + } + } + delete in; + return out; +} + +GBool PSOutputDev::fixType1EexecSection(GString *binSection, GString *out) { + static char hexChars[17] = "0123456789abcdef"; + Guchar buf[16], buf2[16]; + Guchar byte; + int r, i, j; + + // eexec-decode the binary section, keeping the last 16 bytes + r = 55665; + for (i = 0; i < binSection->getLength(); ++i) { + byte = (Guchar)binSection->getChar(i); + buf[i & 15] = byte ^ (Guchar)(r >> 8); + r = ((r + byte) * 52845 + 22719) & 0xffff; + } + for (j = 0; j < 16; ++j) { + buf2[j] = buf[(i + j) & 15]; + } + + // look for 'closefile' + for (i = 0; i <= 16 - 9; ++i) { + if (!memcmp(buf2 + i, "closefile", 9)) { + break; + } + } + if (i > 16 - 9) { + return gFalse; + } + // three cases: + // - short: missing space after "closefile" (i == 16 - 9) + // - correct: exactly one space after "closefile" (i == 16 - 10) + // - long: extra chars after "closefile" (i < 16 - 10) + if (i == 16 - 9) { + binSection->append((char)((Guchar)'\n' ^ (Guchar)(r >> 8))); + } else if (i < 16 - 10) { + binSection->del(binSection->getLength() - (16 - 10 - i), 16 - 10 - i); + } + + // ASCIIHex encode + for (i = 0; i < binSection->getLength(); i += 32) { + for (j = 0; j < 32 && i+j < binSection->getLength(); ++j) { + byte = (Guchar)binSection->getChar(i+j); + out->append(hexChars[(byte >> 4) & 0x0f]); + out->append(hexChars[byte & 0x0f]); + } + out->append('\n'); + } + + return gTrue; +} + +// The Type 1 cleanup code failed -- assume it's a valid PFA-format +// font and copy it to the output. +GString *PSOutputDev::copyType1PFA(Guchar *font, int fontSize) { + GString *out; + + error(errSyntaxWarning, -1, "Couldn't parse embedded Type 1 font"); + + out = new GString((char *)font, fontSize); + // append a newline to avoid problems where the original font + // doesn't end with one + out->append('\n'); + return out; +} + +// The Type 1 cleanup code failed -- assume it's a valid PFB-format +// font, decode the PFB blocks, and copy them to the output. +GString *PSOutputDev::copyType1PFB(Guchar *font, int fontSize) { + static char hexChars[17] = "0123456789abcdef"; + GString *out; + Guchar *p; + int remain, len, i, j; + + error(errSyntaxWarning, -1, "Couldn't parse embedded Type 1 (PFB) font"); + + out = new GString(); + p = font; + remain = fontSize; + while (remain >= 6 && + p[0] == 0x80 && + (p[1] == 0x01 || p[1] == 0x02)) { + len = p[2] + (p[3] << 8) + (p[4] << 16) + (p[5] << 24); + if (len < 0 || len > remain - 6) { + break; + } + if (p[1] == 0x01) { + out->append((char *)(p + 6), len); + } else { + for (i = 0; i < len; i += 32) { + for (j = 0; j < 32 && i+j < len; ++j) { + out->append(hexChars[(p[6+i+j] >> 4) & 0x0f]); + out->append(hexChars[p[6+i+j] & 0x0f]); + } + out->append('\n'); + } + } + p += len + 6; + remain -= len + 6; + } + // append a newline to avoid problems where the original font + // doesn't end with one + out->append('\n'); + return out; +} + +void PSOutputDev::renameType1Font(GString *font, GString *name) { + char *p1, *p2; + int i; + + if (!(p1 = strstr(font->getCString(), "\n/FontName")) && + !(p1 = strstr(font->getCString(), "\r/FontName"))) { + return; + } + p1 += 10; + while (*p1 == ' ' || *p1 == '\t' || *p1 == '\n' || *p1 == '\r') { + ++p1; + } + if (*p1 != '/') { + return; + } + ++p1; + p2 = p1; + while (*p2 && *p2 != ' ' && *p2 != '\t' && *p2 != '\n' && *p2 != '\r') { + ++p2; + } + if (!*p2) { + return; + } + i = (int)(p1 - font->getCString()); + font->del(i, (int)(p2 - p1)); + font->insert(i, name); +} + +void PSOutputDev::setupDefaultFont() { + writePS("/xpdf_default_font /Helvetica 1 1 ISOLatin1Encoding pdfMakeFont\n"); +} + +void PSOutputDev::setupImages(Dict *resDict) { + Object xObjDict, xObj, xObjRef, subtypeObj, maskObj, maskRef; + Ref imgID; + int i, j; + + if (!(mode == psModeForm || inType3Char || preload)) { + return; + } + + resDict->lookup("XObject", &xObjDict); + if (xObjDict.isDict()) { + for (i = 0; i < xObjDict.dictGetLength(); ++i) { + xObjDict.dictGetValNF(i, &xObjRef); + xObjDict.dictGetVal(i, &xObj); + if (xObj.isStream()) { + xObj.streamGetDict()->lookup("Subtype", &subtypeObj); + if (subtypeObj.isName("Image")) { + if (xObjRef.isRef()) { + 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, NULL); + if (level >= psLevel3) { + xObj.streamGetDict()->lookup("Mask", &maskObj); + if (maskObj.isStream()) { + setupImage(imgID, maskObj.getStream(), gTrue, NULL); + } else if (level == psLevel3Gray && maskObj.isArray()) { + setupImage(imgID, xObj.getStream(), gFalse, + maskObj.getArray()); + } + maskObj.free(); + } + } + } else { + error(errSyntaxError, -1, + "Image in resource dict is not an indirect reference"); + } + } + subtypeObj.free(); + } + xObj.free(); + xObjRef.free(); + } + } + xObjDict.free(); +} + +void PSOutputDev::setupImage(Ref id, Stream *str, GBool mask, + Array *colorKeyMask) { + StreamColorSpaceMode csMode; + GfxColorSpace *colorSpace; + GfxImageColorMap *colorMap; + int maskColors[2*gfxColorMaxComps]; + Object obj1; + GBool imageMask, useLZW, useRLE, useCompressed, useASCIIHex; + GString *s; + int c, width, height, bits, size, line, col, i; + + // check for mask + str->getDict()->lookup("ImageMask", &obj1); + if (obj1.isBool()) { + imageMask = obj1.getBool(); + } else { + imageMask = gFalse; + } + obj1.free(); + + // get image size + str->getDict()->lookup("Width", &obj1); + if (!obj1.isInt() || obj1.getInt() <= 0) { + error(errSyntaxError, -1, "Invalid Width in image"); + obj1.free(); + return; + } + width = obj1.getInt(); + obj1.free(); + str->getDict()->lookup("Height", &obj1); + if (!obj1.isInt() || obj1.getInt() <= 0) { + error(errSyntaxError, -1, "Invalid Height in image"); + obj1.free(); + return; + } + height = obj1.getInt(); + obj1.free(); + + // build the color map + if (mask || imageMask) { + colorMap = NULL; + } else { + bits = 0; + csMode = streamCSNone; + str->getImageParams(&bits, &csMode); + if (bits == 0) { + str->getDict()->lookup("BitsPerComponent", &obj1); + if (!obj1.isInt()) { + error(errSyntaxError, -1, "Invalid BitsPerComponent in image"); + obj1.free(); + return; + } + bits = obj1.getInt(); + obj1.free(); + } + str->getDict()->lookup("ColorSpace", &obj1); + if (!obj1.isNull()) { + colorSpace = GfxColorSpace::parse(&obj1 + ); + } else if (csMode == streamCSDeviceGray) { + colorSpace = GfxColorSpace::create(csDeviceGray); + } else if (csMode == streamCSDeviceRGB) { + colorSpace = GfxColorSpace::create(csDeviceRGB); + } else if (csMode == streamCSDeviceCMYK) { + colorSpace = GfxColorSpace::create(csDeviceCMYK); + } else { + colorSpace = NULL; + } + obj1.free(); + if (!colorSpace) { + error(errSyntaxError, -1, "Invalid ColorSpace in image"); + return; + } + str->getDict()->lookup("Decode", &obj1); + colorMap = new GfxImageColorMap(bits, &obj1, colorSpace); + obj1.free(); + } + + // filters + str->disableDecompressionBombChecking(); + if (level < psLevel2) { + useLZW = useRLE = gFalse; + useCompressed = gFalse; + useASCIIHex = gTrue; + } else { + if (colorKeyMask) { + if (globalParams->getPSUncompressPreloadedImages()) { + useLZW = useRLE = gFalse; + } else if (globalParams->getPSLZW()) { + useLZW = gTrue; + useRLE = gFalse; + } else { + useRLE = gTrue; + useLZW = gFalse; + } + useCompressed = gFalse; + } else if (colorMap && + (colorMap->getColorSpace()->getMode() == csDeviceN || + level == psLevel2Gray || level == psLevel3Gray)) { + if (globalParams->getPSLZW()) { + useLZW = gTrue; + useRLE = gFalse; + } else { + useRLE = gTrue; + useLZW = gFalse; + } + useCompressed = gFalse; + } else if (globalParams->getPSUncompressPreloadedImages()) { + useLZW = useRLE = gFalse; + useCompressed = gFalse; + } else { + s = str->getPSFilter(level < psLevel3 ? 2 : 3, "", gTrue); + if (s) { + useLZW = useRLE = gFalse; + useCompressed = gTrue; + delete s; + } else { + if (globalParams->getPSLZW()) { + useLZW = gTrue; + useRLE = gFalse; + } else { + useRLE = gTrue; + useLZW = gFalse; + } + useCompressed = gFalse; + } + } + useASCIIHex = globalParams->getPSASCIIHex(); + } + if (useCompressed) { + str = str->getUndecodedStream(); + } + if (colorKeyMask) { + memset(maskColors, 0, sizeof(maskColors)); + for (i = 0; i < colorKeyMask->getLength() && i < 2*gfxColorMaxComps; ++i) { + colorKeyMask->get(i, &obj1); + if (obj1.isInt()) { + maskColors[i] = obj1.getInt(); + } + obj1.free(); + } + str = new ColorKeyToMaskEncoder(str, width, height, colorMap, maskColors); + } else if (colorMap && (level == psLevel2Gray || level == psLevel3Gray)) { + str = new GrayRecoder(str, width, height, colorMap); + } else if (colorMap && colorMap->getColorSpace()->getMode() == csDeviceN) { + str = new DeviceNRecoder(str, width, height, colorMap); + } + if (useLZW) { + str = new LZWEncoder(str); + } else if (useRLE) { + str = new RunLengthEncoder(str); + } + if (useASCIIHex) { + str = new ASCIIHexEncoder(str); + } else { + str = new ASCII85Encoder(str); + } + + // compute image data size + str->reset(); + col = size = 0; + do { + do { + c = str->getChar(); + } while (c == '\n' || c == '\r'); + if (c == (useASCIIHex ? '>' : '~') || c == EOF) { + break; + } + if (c == 'z') { + ++col; + } else { + ++col; + for (i = 1; i <= (useASCIIHex ? 1 : 4); ++i) { + do { + c = str->getChar(); + } while (c == '\n' || c == '\r'); + if (c == (useASCIIHex ? '>' : '~') || c == EOF) { + break; + } + ++col; + } + } + if (col > 225) { + ++size; + col = 0; + } + } while (c != (useASCIIHex ? '>' : '~') && c != EOF); + // add one entry for the final line of data; add another entry + // because the LZWDecode/RunLengthDecode filter may read past the end + ++size; + if (useLZW || useRLE) { + ++size; + } + writePSFmt("{0:d} array dup /{1:s}Data_{2:d}_{3:d} exch def\n", + size, (mask || colorKeyMask) ? "Mask" : "Im", id.num, id.gen); + str->close(); + + // write the data into the array + str->reset(); + line = col = 0; + writePS((char *)(useASCIIHex ? "dup 0 <" : "dup 0 <~")); + do { + do { + c = str->getChar(); + } while (c == '\n' || c == '\r'); + if (c == (useASCIIHex ? '>' : '~') || c == EOF) { + break; + } + if (c == 'z') { + writePSChar((char)c); + ++col; + } else { + writePSChar((char)c); + ++col; + for (i = 1; i <= (useASCIIHex ? 1 : 4); ++i) { + do { + c = str->getChar(); + } while (c == '\n' || c == '\r'); + if (c == (useASCIIHex ? '>' : '~') || c == EOF) { + break; + } + writePSChar((char)c); + ++col; + } + } + // each line is: "dup nnnnn <~...data...~> put" + // so max data length = 255 - 20 = 235 + // chunks are 1 or 4 bytes each, so we have to stop at 232 + // but make it 225 just to be safe + if (col > 225) { + writePS((char *)(useASCIIHex ? "> put\n" : "~> put\n")); + ++line; + writePSFmt((char *)(useASCIIHex ? "dup {0:d} <" : "dup {0:d} <~"), line); + col = 0; + } + } while (c != (useASCIIHex ? '>' : '~') && c != EOF); + writePS((char *)(useASCIIHex ? "> put\n" : "~> put\n")); + if (useLZW || useRLE) { + ++line; + writePSFmt("{0:d} <> put\n", line); + } else { + writePS("pop\n"); + } + str->close(); + + delete str; + + if (colorMap) { + delete colorMap; + } +} + +void PSOutputDev::setupForms(Dict *resDict) { + Object xObjDict, xObj, xObjRef, subtypeObj; + int i; + + if (!preload) { + return; + } + + resDict->lookup("XObject", &xObjDict); + if (xObjDict.isDict()) { + for (i = 0; i < xObjDict.dictGetLength(); ++i) { + xObjDict.dictGetValNF(i, &xObjRef); + xObjDict.dictGetVal(i, &xObj); + if (xObj.isStream()) { + xObj.streamGetDict()->lookup("Subtype", &subtypeObj); + if (subtypeObj.isName("Form")) { + if (xObjRef.isRef()) { + setupForm(&xObjRef, &xObj); + } else { + error(errSyntaxError, -1, + "Form in resource dict is not an indirect reference"); + } + } + subtypeObj.free(); + } + xObj.free(); + xObjRef.free(); + } + } + xObjDict.free(); +} + +void PSOutputDev::setupForm(Object *strRef, Object *strObj) { + Dict *dict, *resDict; + Object matrixObj, bboxObj, resObj, obj1; + double m[6], bbox[4]; + PDFRectangle box; + Gfx *gfx; + int i; + + // check if form is already defined + for (i = 0; i < formIDLen; ++i) { + if (formIDs[i].num == strRef->getRefNum() && + formIDs[i].gen == strRef->getRefGen()) { + return; + } + } + + // add entry to formIDs list + if (formIDLen >= formIDSize) { + if (formIDSize == 0) { + formIDSize = 64; + } else { + formIDSize *= 2; + } + formIDs = (Ref *)greallocn(formIDs, formIDSize, sizeof(Ref)); + } + formIDs[formIDLen++] = strRef->getRef(); + + dict = strObj->streamGetDict(); + + // get bounding box + dict->lookup("BBox", &bboxObj); + if (!bboxObj.isArray()) { + bboxObj.free(); + error(errSyntaxError, -1, "Bad form bounding box"); + return; + } + for (i = 0; i < 4; ++i) { + bboxObj.arrayGet(i, &obj1); + bbox[i] = obj1.getNum(); + obj1.free(); + } + bboxObj.free(); + + // get matrix + dict->lookup("Matrix", &matrixObj); + if (matrixObj.isArray()) { + for (i = 0; i < 6; ++i) { + matrixObj.arrayGet(i, &obj1); + m[i] = obj1.getNum(); + obj1.free(); + } + } else { + m[0] = 1; m[1] = 0; + m[2] = 0; m[3] = 1; + m[4] = 0; m[5] = 0; + } + matrixObj.free(); + + // get resources + dict->lookup("Resources", &resObj); + resDict = resObj.isDict() ? resObj.getDict() : (Dict *)NULL; + + writePSFmt("/f_{0:d}_{1:d} {{\n", strRef->getRefNum(), strRef->getRefGen()); + writePS("q\n"); + writePSFmt("[{0:.6g} {1:.6g} {2:.6g} {3:.6g} {4:.6g} {5:.6g}] cm\n", + m[0], m[1], m[2], m[3], m[4], m[5]); + + box.x1 = bbox[0]; + box.y1 = bbox[1]; + box.x2 = bbox[2]; + box.y2 = bbox[3]; + gfx = new Gfx(doc, this, resDict, &box, &box); + gfx->display(strRef); + delete gfx; + + writePS("Q\n"); + writePS("} def\n"); + + resObj.free(); +} + + +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, + GBool (*abortCheckCbk)(void *data), + void *abortCheckCbkData) { + int pg; +#if HAVE_SPLASH + GBool mono; + GBool useLZW; + double dpi; + SplashOutputDev *splashOut; + SplashColor paperColor; + PDFRectangle box; + GfxState *state; + SplashBitmap *bitmap; + Stream *str0, *str; + Object obj; + Guchar *p; + Guchar col[4]; + char buf[4096]; + double userUnit, hDPI2, vDPI2; + double m0, m1, m2, m3, m4, m5; + int nStripes, stripeH, stripeY; + int w, h, x, y, comp, i, n; +#endif + + pg = page->getNum(); + if (!(pg >= firstPage && pg <= lastPage && + rasterizePage[pg - firstPage])) { + return gTrue; + } + +#if HAVE_SPLASH + // get the rasterization parameters + dpi = globalParams->getPSRasterResolution(); + mono = globalParams->getPSRasterMono() || + level == psLevel1 || + level == psLevel2Gray || + level == psLevel3Gray; + useLZW = globalParams->getPSLZW(); + + // get the UserUnit + if (honorUserUnit) { + userUnit = page->getUserUnit(); + } else { + userUnit = 1; + } + + // start the PS page + page->makeBox(userUnit * dpi, userUnit * 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) { + paperColor[0] = 0xff; + splashOut = new SplashOutputDev(splashModeMono8, 1, 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, gFalse, + globalParams->getAntialiasPrinting()); +#endif + } else { + paperColor[0] = paperColor[1] = paperColor[2] = 0xff; + splashOut = new SplashOutputDev(splashModeRGB8, 1, gFalse, + paperColor, gFalse, + globalParams->getAntialiasPrinting()); + } + splashOut->startDoc(xref); + + // break the page into stripes + // NB: startPage() has already multiplied xScale and yScale by UserUnit + 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); + if (sliceW == 0) { + sliceW = 1; + } + sliceH = (int)((box.y2 - box.y1) * vDPI2 / 72.0); + if (sliceH == 0) { + sliceH = 1; + } + } + nStripes = (int)ceil(((double)sliceW * (double)sliceH) / + (double)globalParams->getPSRasterSliceSize()); + 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; + 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++); + if (++i == 32) { + writePSChar('\n'); + i = 0; + } + } + } + if (i != 0) { + writePSChar('\n'); + } + break; + case psLevel1Sep: +#if SPLASH_CMYK + writePSFmt("{0:d} {1:d} 8 [{2:d} 0 0 {3:d} 0 {4:d}] pdfIm1Sep\n", + w, h, w, -h, h); + p = bitmap->getDataPtr() + (h - 1) * bitmap->getRowSize(); + 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; + // if !SPLASH_CMYK: fall through +#endif + case psLevel2: + case psLevel2Gray: + case psLevel2Sep: + case psLevel3: + case psLevel3Gray: + 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"); + } + if (useLZW) { + writePS(" /LZWDecode filter\n"); + } else { + writePS(" /RunLengthDecode filter\n"); + } + writePS(">>\n"); + writePS("image\n"); + obj.initNull(); + p = bitmap->getDataPtr() + (h - 1) * bitmap->getRowSize(); + str0 = new MemStream((char *)p, 0, w * h * (mono ? 1 : 3), &obj); + if (useLZW) { + str = new LZWEncoder(str0); + } else { + str = new RunLengthEncoder(str0); + } + if (globalParams->getPSASCIIHex()) { + str = new ASCIIHexEncoder(str); + } else { + str = new ASCII85Encoder(str); + } + str->reset(); + while ((n = str->getBlock(buf, sizeof(buf))) > 0) { + writePSBlock(buf, n); + } + str->close(); + delete str; + delete str0; + writePSChar('\n'); + processColors |= mono ? psProcessBlack : psProcessCMYK; + break; + } + writePS("grestore\n"); + } + + delete splashOut; + + // finish the PS page + endPage(); + + return gFalse; + +#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 // HAVE_SPLASH +} + +void PSOutputDev::startPage(int pageNum, GfxState *state) { + Page *page; + double userUnit; + int x1, y1, x2, y2, width, height, t; + int imgWidth, imgHeight, imgWidth2, imgHeight2; + GBool landscape; + GString *s; + + page = doc->getCatalog()->getPage(pageNum); + if (honorUserUnit) { + userUnit = page->getUserUnit(); + } else { + userUnit = 1; + } + + if (mode == psModePS) { + writePSFmt("%%Page: {0:d} {1:d}\n", pageNum, seqPage); + if (paperMatch) { + imgLLX = imgLLY = 0; + if (globalParams->getPSUseCropBoxAsPage()) { + imgURX = (int)ceil(page->getCropWidth() * userUnit); + imgURY = (int)ceil(page->getCropHeight() * userUnit); + } else { + imgURX = (int)ceil(page->getMediaWidth() * userUnit); + imgURY = (int)ceil(page->getMediaHeight() * userUnit); + } + 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"); + } + if (mode != psModeForm) { + writePS("xpdf begin\n"); + } + + // set up paper size for paper=match mode + // NB: this must be done *before* the saveState() for overlays. + if (mode == psModePS && paperMatch) { + writePSFmt("{0:d} {1:d} pdfSetupPaper\n", imgURX, imgURY); + } + + // underlays + if (underlayCbk) { + (*underlayCbk)(this, underlayCbkData); + } + if (overlayCbk) { + saveState(NULL); + } + + switch (mode) { + + case psModePS: + // rotate, translate, and scale page + imgWidth = imgURX - imgLLX; + imgHeight = imgURY - imgLLY; + x1 = (int)floor(state->getX1()); + y1 = (int)floor(state->getY1()); + x2 = (int)ceil(state->getX2()); + y2 = (int)ceil(state->getY2()); + width = x2 - x1; + height = y2 - y1; + tx = ty = 0; + // rotation and portrait/landscape mode + 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; + double scaledWidth = width * userUnit; + double scaledHeight = height * userUnit; + if (xScale0 > 0 && yScale0 > 0) { + scaledWidth *= xScale0; + scaledHeight *= yScale0; + } + if (rotate == 0 || rotate == 180) { + if ((scaledWidth < scaledHeight && imgWidth > imgHeight && + scaledHeight > imgHeight) || + (scaledWidth > scaledHeight && imgWidth < imgHeight && + scaledWidth > imgWidth)) { + rotate += 90; + landscape = gTrue; + } else { + landscape = gFalse; + } + } else { // rotate == 90 || rotate == 270 + if ((scaledHeight < scaledWidth && imgWidth > imgHeight && + scaledWidth > imgHeight) || + (scaledHeight > scaledWidth && imgWidth < imgHeight && + scaledHeight > imgWidth)) { + rotate = 270 - rotate; + landscape = gTrue; + } else { + landscape = gFalse; + } + } + } + writePSFmt("%%PageOrientation: {0:s}\n", + landscape ? "Landscape" : "Portrait"); + writePS("pdfStartPage\n"); + if (rotate == 0) { + imgWidth2 = imgWidth; + imgHeight2 = imgHeight; + } else if (rotate == 90) { + writePS("90 rotate\n"); + ty = -imgWidth; + imgWidth2 = imgHeight; + imgHeight2 = imgWidth; + } else if (rotate == 180) { + writePS("180 rotate\n"); + imgWidth2 = imgWidth; + imgHeight2 = imgHeight; + tx = -imgWidth; + ty = -imgHeight; + } else { // rotate == 270 + writePS("270 rotate\n"); + tx = -imgHeight; + imgWidth2 = imgHeight; + imgHeight2 = imgWidth; + } + // shrink or expand + if (xScale0 > 0 && yScale0 > 0) { + xScale = xScale0 * userUnit; + yScale = yScale0 * userUnit; + } else if ((globalParams->getPSShrinkLarger() && + (width * userUnit > imgWidth2 || + height * userUnit > imgHeight2)) || + (expandSmallPages && + (width * userUnit < imgWidth2 && + height * userUnit < imgHeight2))) { + xScale = (double)imgWidth2 / (double)width; + yScale = (double)imgHeight2 / (double)height; + if (yScale < xScale) { + xScale = yScale; + } else { + yScale = xScale; + } + } else { + xScale = yScale = userUnit; + } + // deal with odd bounding boxes or clipping + if (clipLLX0 < clipURX0 && clipLLY0 < clipURY0) { + tx -= xScale * clipLLX0; + ty -= yScale * clipLLY0; + } else { + tx -= xScale * x1; + ty -= yScale * y1; + } + // center + if (tx0 >= 0 && ty0 >= 0) { + 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; + ty += (imgHeight2 - yScale * (clipURY0 - clipLLY0)) / 2; + } else { + tx += (imgWidth2 - xScale * width) / 2; + ty += (imgHeight2 - yScale * height) / 2; + } + } + tx += (rotate == 0 || rotate == 180) ? imgLLX : imgLLY; + ty += (rotate == 0 || rotate == 180) ? imgLLY : -imgLLX; + if (tx != 0 || ty != 0) { + writePSFmt("{0:.6g} {1:.6g} translate\n", tx, ty); + } + if (xScale != 1 || yScale != 1) { + writePSFmt("{0:.4f} {1:.4f} scale\n", xScale, yScale); + } + if (clipLLX0 < clipURX0 && clipLLY0 < clipURY0) { + 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); + } + + ++seqPage; + break; + + case psModeEPS: + writePS("pdfStartPage\n"); + tx = ty = 0; + rotate = (360 - state->getRotate()) % 360; + if (rotate == 0) { + } else if (rotate == 90) { + writePS("90 rotate\n"); + tx = -epsX1; + ty = -epsY2; + } else if (rotate == 180) { + writePS("180 rotate\n"); + tx = -(epsX1 + epsX2); + ty = -(epsY1 + epsY2); + } else { // rotate == 270 + writePS("270 rotate\n"); + tx = -epsX2; + ty = -epsY1; + } + if (tx != 0 || ty != 0) { + writePSFmt("{0:.6g} {1:.6g} translate\n", tx, ty); + } + xScale = yScale = 1; + break; + + case psModeForm: + writePS("/PaintProc {\n"); + writePS("begin xpdf begin\n"); + writePS("pdfStartPage\n"); + tx = ty = 0; + xScale = yScale = 1; + rotate = 0; + break; + } + + if (level == psLevel2Gray || level == psLevel3Gray) { + writePS("/DeviceGray setcolorspace\n"); + } + + if (customCodeCbk) { + if ((s = (*customCodeCbk)(this, psOutCustomPageSetup, pageNum, + customCodeCbkData))) { + writePS(s->getCString()); + delete s; + } + } + + if (mode == psModePS) { + writePS("%%EndPageSetup\n"); + } + + noStateChanges = gFalse; +} + +void PSOutputDev::endPage() { + if (overlayCbk) { + restoreState(NULL); + (*overlayCbk)(this, overlayCbkData); + } + + if (mode == psModeForm) { + writePS("pdfEndPage\n"); + writePS("end end\n"); + writePS("} def\n"); + writePS("end end\n"); + } else { + if (!manualCtrl) { + writePS("showpage\n"); + } + writePS("%%PageTrailer\n"); + writePageTrailer(); + writePS("end\n"); + } +} + +void PSOutputDev::saveState(GfxState *state) { + // The noStateChanges and saveStack fields are used to implement an + // optimization to reduce gsave/grestore nesting. The idea is to + // look for sequences like this: + // q q AAA Q BBB Q (where AAA and BBB are sequences of operations) + // and transform them to: + // q AAA Q q BBB Q + if (noStateChanges) { + // any non-NULL pointer will work here + saveStack->append(this); + } else { + saveStack->append((PSOutputDev *)NULL); + writePS("q\n"); + noStateChanges = gTrue; + } +} + +void PSOutputDev::restoreState(GfxState *state) { + if (saveStack->getLength()) { + writePS("Q\n"); + if (saveStack->del(saveStack->getLength() - 1)) { + writePS("q\n"); + noStateChanges = gTrue; + } else { + noStateChanges = gFalse; + } + } +} + +void PSOutputDev::updateCTM(GfxState *state, double m11, double m12, + double m21, double m22, double m31, double m32) { + if (m11 == 1 && m12 == 0 && m21 == 0 && m22 == 1 && m31 == 0 && m32 == 0) { + return; + } + if (fabs(m11 * m22 - m12 * m21) < 1e-10) { + // avoid a singular (or close-to-singular) matrix + writePSFmt("[0.00001 0 0 0.00001 {0:.6g} {1:.6g}] cm\n", m31, m32); + } else { + writePSFmt("[{0:.6g} {1:.6g} {2:.6g} {3:.6g} {4:.6g} {5:.6g}] cm\n", + m11, m12, m21, m22, m31, m32); + } + noStateChanges = gFalse; +} + +void PSOutputDev::updateLineDash(GfxState *state) { + double *dash; + double start; + int length, i; + + state->getLineDash(&dash, &length, &start); + writePS("["); + for (i = 0; i < length; ++i) { + writePSFmt("{0:.6g}{1:w}", + dash[i] < 0 ? 0 : dash[i], + (i == length-1) ? 0 : 1); + } + writePSFmt("] {0:.6g} d\n", start); + noStateChanges = gFalse; +} + +void PSOutputDev::updateFlatness(GfxState *state) { + writePSFmt("{0:.4g} i\n", state->getFlatness()); + noStateChanges = gFalse; +} + +void PSOutputDev::updateLineJoin(GfxState *state) { + writePSFmt("{0:d} j\n", state->getLineJoin()); + noStateChanges = gFalse; +} + +void PSOutputDev::updateLineCap(GfxState *state) { + writePSFmt("{0:d} J\n", state->getLineCap()); + noStateChanges = gFalse; +} + +void PSOutputDev::updateMiterLimit(GfxState *state) { + writePSFmt("{0:.4g} M\n", state->getMiterLimit()); + noStateChanges = gFalse; +} + +void PSOutputDev::updateLineWidth(GfxState *state) { + writePSFmt("{0:.6g} w\n", state->getLineWidth()); + noStateChanges = gFalse; +} + +void PSOutputDev::updateFillColorSpace(GfxState *state) { + switch (level) { + case psLevel1: + case psLevel1Sep: + break; + case psLevel2: + case psLevel3: + if (state->getFillColorSpace()->getMode() != csPattern) { + dumpColorSpaceL2(state, state->getFillColorSpace(), + gTrue, gFalse, gFalse); + writePS(" cs\n"); + noStateChanges = gFalse; + } + break; + case psLevel2Gray: + case psLevel3Gray: + case psLevel2Sep: + case psLevel3Sep: + break; + } +} + +void PSOutputDev::updateStrokeColorSpace(GfxState *state) { + switch (level) { + case psLevel1: + case psLevel1Sep: + break; + case psLevel2: + case psLevel3: + if (state->getStrokeColorSpace()->getMode() != csPattern) { + dumpColorSpaceL2(state, state->getStrokeColorSpace(), + gTrue, gFalse, gFalse); + writePS(" CS\n"); + noStateChanges = gFalse; + } + break; + case psLevel2Gray: + case psLevel3Gray: + case psLevel2Sep: + case psLevel3Sep: + break; + } +} + +void PSOutputDev::updateFillColor(GfxState *state) { + GfxColor color; + GfxColor *colorPtr; + GfxGray gray; + GfxCMYK cmyk; + GfxSeparationColorSpace *sepCS; + double c, m, y, k; + int i; + + switch (level) { + case psLevel1: + case psLevel2Gray: + case psLevel3Gray: + state->getFillGray(&gray); + writePSFmt("{0:.4g} g\n", colToDbl(gray)); + break; + case psLevel1Sep: + state->getFillCMYK(&cmyk); + c = colToDbl(cmyk.c); + m = colToDbl(cmyk.m); + y = colToDbl(cmyk.y); + k = colToDbl(cmyk.k); + writePSFmt("{0:.4g} {1:.4g} {2:.4g} {3:.4g} k\n", c, m, y, k); + addProcessColor(c, m, y, k); + break; + case psLevel2: + case psLevel3: + if (state->getFillColorSpace()->getMode() != csPattern) { + colorPtr = state->getFillColor(); + writePS("["); + for (i = 0; i < state->getFillColorSpace()->getNComps(); ++i) { + if (i > 0) { + writePS(" "); + } + writePSFmt("{0:.4g}", colToDbl(colorPtr->c[i])); + } + writePS("] sc\n"); + } + break; + case psLevel2Sep: + case psLevel3Sep: + if (state->getFillColorSpace()->getMode() == csSeparation) { + sepCS = (GfxSeparationColorSpace *)state->getFillColorSpace(); + color.c[0] = gfxColorComp1; + sepCS->getCMYK(&color, &cmyk, state->getRenderingIntent()); + writePSFmt("{0:.4g} {1:.4g} {2:.4g} {3:.4g} {4:.4g} ({5:t}) ck\n", + colToDbl(state->getFillColor()->c[0]), + colToDbl(cmyk.c), colToDbl(cmyk.m), + colToDbl(cmyk.y), colToDbl(cmyk.k), + sepCS->getName()); + addCustomColor(state, sepCS); + } else { + state->getFillCMYK(&cmyk); + c = colToDbl(cmyk.c); + m = colToDbl(cmyk.m); + y = colToDbl(cmyk.y); + k = colToDbl(cmyk.k); + writePSFmt("{0:.4g} {1:.4g} {2:.4g} {3:.4g} k\n", c, m, y, k); + addProcessColor(c, m, y, k); + } + break; + } + t3Cacheable = gFalse; + noStateChanges = gFalse; +} + +void PSOutputDev::updateStrokeColor(GfxState *state) { + GfxColor color; + GfxColor *colorPtr; + GfxGray gray; + GfxCMYK cmyk; + GfxSeparationColorSpace *sepCS; + double c, m, y, k; + int i; + + switch (level) { + case psLevel1: + case psLevel2Gray: + case psLevel3Gray: + state->getStrokeGray(&gray); + writePSFmt("{0:.4g} G\n", colToDbl(gray)); + break; + case psLevel1Sep: + state->getStrokeCMYK(&cmyk); + c = colToDbl(cmyk.c); + m = colToDbl(cmyk.m); + y = colToDbl(cmyk.y); + k = colToDbl(cmyk.k); + writePSFmt("{0:.4g} {1:.4g} {2:.4g} {3:.4g} K\n", c, m, y, k); + addProcessColor(c, m, y, k); + break; + case psLevel2: + case psLevel3: + if (state->getStrokeColorSpace()->getMode() != csPattern) { + colorPtr = state->getStrokeColor(); + writePS("["); + for (i = 0; i < state->getStrokeColorSpace()->getNComps(); ++i) { + if (i > 0) { + writePS(" "); + } + writePSFmt("{0:.4g}", colToDbl(colorPtr->c[i])); + } + writePS("] SC\n"); + } + break; + case psLevel2Sep: + case psLevel3Sep: + if (state->getStrokeColorSpace()->getMode() == csSeparation) { + sepCS = (GfxSeparationColorSpace *)state->getStrokeColorSpace(); + color.c[0] = gfxColorComp1; + sepCS->getCMYK(&color, &cmyk, state->getRenderingIntent()); + writePSFmt("{0:.4g} {1:.4g} {2:.4g} {3:.4g} {4:.4g} ({5:t}) CK\n", + colToDbl(state->getStrokeColor()->c[0]), + colToDbl(cmyk.c), colToDbl(cmyk.m), + colToDbl(cmyk.y), colToDbl(cmyk.k), + sepCS->getName()); + addCustomColor(state, sepCS); + } else { + state->getStrokeCMYK(&cmyk); + c = colToDbl(cmyk.c); + m = colToDbl(cmyk.m); + y = colToDbl(cmyk.y); + k = colToDbl(cmyk.k); + writePSFmt("{0:.4g} {1:.4g} {2:.4g} {3:.4g} K\n", c, m, y, k); + addProcessColor(c, m, y, k); + } + break; + } + t3Cacheable = gFalse; + noStateChanges = gFalse; +} + +void PSOutputDev::addProcessColor(double c, double m, double y, double k) { + if (c > 0) { + processColors |= psProcessCyan; + } + if (m > 0) { + processColors |= psProcessMagenta; + } + if (y > 0) { + processColors |= psProcessYellow; + } + if (k > 0) { + processColors |= psProcessBlack; + } +} + +void PSOutputDev::addCustomColor(GfxState *state, + GfxSeparationColorSpace *sepCS) { + PSOutCustomColor *cc; + GfxColor color; + GfxCMYK cmyk; + + for (cc = customColors; cc; cc = cc->next) { + if (!cc->name->cmp(sepCS->getName())) { + return; + } + } + color.c[0] = gfxColorComp1; + sepCS->getCMYK(&color, &cmyk, state->getRenderingIntent()); + cc = new PSOutCustomColor(colToDbl(cmyk.c), colToDbl(cmyk.m), + colToDbl(cmyk.y), colToDbl(cmyk.k), + sepCS->getName()->copy()); + cc->next = customColors; + customColors = cc; +} + +void PSOutputDev::addCustomColors(GfxState *state, + GfxDeviceNColorSpace *devnCS) { + PSOutCustomColor *cc; + GfxColor color; + GfxCMYK cmyk; + int i; + + for (i = 0; i < devnCS->getNComps(); ++i) { + color.c[i] = 0; + } + for (i = 0; i < devnCS->getNComps(); ++i) { + for (cc = customColors; cc; cc = cc->next) { + if (!cc->name->cmp(devnCS->getColorantName(i))) { + break; + } + } + if (cc) { + continue; + } + color.c[i] = gfxColorComp1; + devnCS->getCMYK(&color, &cmyk, state->getRenderingIntent()); + color.c[i] = 0; + cc = new PSOutCustomColor(colToDbl(cmyk.c), colToDbl(cmyk.m), + colToDbl(cmyk.y), colToDbl(cmyk.k), + devnCS->getColorantName(i)->copy()); + cc->next = customColors; + customColors = cc; + } +} + +void PSOutputDev::updateFillOverprint(GfxState *state) { + if (level == psLevel2 || level == psLevel2Sep || + level == psLevel3 || level == psLevel3Sep) { + writePSFmt("{0:s} op\n", state->getFillOverprint() ? "true" : "false"); + noStateChanges = gFalse; + } +} + +void PSOutputDev::updateStrokeOverprint(GfxState *state) { + if (level == psLevel2 || level == psLevel2Sep || + level == psLevel3 || level == psLevel3Sep) { + writePSFmt("{0:s} OP\n", state->getStrokeOverprint() ? "true" : "false"); + noStateChanges = gFalse; + } +} + +void PSOutputDev::updateOverprintMode(GfxState *state) { + if (level == psLevel3 || level == psLevel3Sep) { + writePSFmt("{0:s} opm\n", state->getOverprintMode() ? "true" : "false"); + noStateChanges = gFalse; + } +} + +void PSOutputDev::updateTransfer(GfxState *state) { + Function **funcs; + int i; + + funcs = state->getTransfer(); + if (funcs[0] && funcs[1] && funcs[2] && funcs[3]) { + if (level == psLevel2 || level == psLevel2Sep || + level == psLevel3 || level == psLevel3Sep) { + for (i = 0; i < 4; ++i) { + cvtFunction(funcs[i]); + } + writePS("setcolortransfer\n"); + } else { + cvtFunction(funcs[3]); + writePS("settransfer\n"); + } + } else if (funcs[0]) { + cvtFunction(funcs[0]); + writePS("settransfer\n"); + } else { + writePS("{} settransfer\n"); + } + noStateChanges = gFalse; +} + +void PSOutputDev::updateFont(GfxState *state) { + if (state->getFont()) { + if (state->getFont()->getTag() && + !state->getFont()->getTag()->cmp("xpdf_default_font")) { + writePSFmt("/xpdf_default_font {0:.6g} Tf\n", + fabs(state->getFontSize()) < 0.0001 ? 0.0001 + : state->getFontSize()); + } else { + writePSFmt("/F{0:d}_{1:d} {2:.6g} Tf\n", + state->getFont()->getID()->num, state->getFont()->getID()->gen, + fabs(state->getFontSize()) < 0.0001 ? 0.0001 + : state->getFontSize()); + } + noStateChanges = gFalse; + } +} + +void PSOutputDev::updateTextMat(GfxState *state) { + double *mat; + + mat = state->getTextMat(); + if (fabs(mat[0] * mat[3] - mat[1] * mat[2]) < 1e-10) { + // avoid a singular (or close-to-singular) matrix + writePSFmt("[0.00001 0 0 0.00001 {0:.6g} {1:.6g}] Tm\n", mat[4], mat[5]); + } else { + 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]); + } + noStateChanges = gFalse; +} + +void PSOutputDev::updateCharSpace(GfxState *state) { + writePSFmt("{0:.6g} Tc\n", state->getCharSpace()); + noStateChanges = gFalse; +} + +void PSOutputDev::updateRender(GfxState *state) { + int rm; + + rm = state->getRender(); + writePSFmt("{0:d} Tr\n", rm); + rm &= 3; + if (rm != 0 && rm != 3) { + t3Cacheable = gFalse; + } + noStateChanges = gFalse; +} + +void PSOutputDev::updateRise(GfxState *state) { + writePSFmt("{0:.6g} Ts\n", state->getRise()); + noStateChanges = gFalse; +} + +void PSOutputDev::updateWordSpace(GfxState *state) { + writePSFmt("{0:.6g} Tw\n", state->getWordSpace()); + noStateChanges = gFalse; +} + +void PSOutputDev::updateHorizScaling(GfxState *state) { + double h; + + h = state->getHorizScaling(); + if (fabs(h) < 0.01) { + h = 0.01; + } + writePSFmt("{0:.6g} Tz\n", h); + noStateChanges = gFalse; +} + +void PSOutputDev::updateTextPos(GfxState *state) { + writePSFmt("{0:.6g} {1:.6g} Td\n", state->getLineX(), state->getLineY()); + noStateChanges = gFalse; +} + +void PSOutputDev::updateTextShift(GfxState *state, double shift) { + if (state->getFont()->getWMode()) { + writePSFmt("{0:.6g} TJmV\n", shift); + } else { + writePSFmt("{0:.6g} TJm\n", shift); + } + noStateChanges = gFalse; +} + +void PSOutputDev::saveTextPos(GfxState *state) { + writePS("currentpoint\n"); + noStateChanges = gFalse; +} + +void PSOutputDev::restoreTextPos(GfxState *state) { + writePS("m\n"); + noStateChanges = gFalse; +} + +void PSOutputDev::stroke(GfxState *state) { + doPath(state->getPath()); + 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 { + writePS("S\n"); + } + noStateChanges = gFalse; +} + +void PSOutputDev::fill(GfxState *state) { + doPath(state->getPath()); + writePS("f\n"); + noStateChanges = gFalse; +} + +void PSOutputDev::eoFill(GfxState *state) { + doPath(state->getPath()); + writePS("f*\n"); + noStateChanges = gFalse; +} + +void PSOutputDev::tilingPatternFill(GfxState *state, Gfx *gfx, Object *strRef, + int paintType, int tilingType, + Dict *resDict, + double *mat, double *bbox, + int x0, int y0, int x1, int y1, + double xStep, double yStep) { + if (level <= psLevel1Sep) { + tilingPatternFillL1(state, gfx, strRef, paintType, tilingType, + resDict, mat, bbox, x0, y0, x1, y1, xStep, yStep); + } else { + tilingPatternFillL2(state, gfx, strRef, paintType, tilingType, + resDict, mat, bbox, x0, y0, x1, y1, xStep, yStep); + } +} + +void PSOutputDev::tilingPatternFillL1(GfxState *state, Gfx *gfx, + Object *strRef, + int paintType, int tilingType, + Dict *resDict, + double *mat, double *bbox, + int x0, int y0, int x1, int y1, + double xStep, double yStep) { + PDFRectangle box; + 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:.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"); + writePS(" Encoding 120 /x put\n"); + writePS("/BuildGlyph {\n"); + writePS(" exch /CharProcs get exch\n"); + writePS(" 2 copy known not { pop /.notdef } if\n"); + writePS(" get exec\n"); + writePS("} bind def\n"); + writePS("/BuildChar {\n"); + writePS(" 1 index /Encoding get exch get\n"); + writePS(" 1 index /BuildGlyph get exec\n"); + writePS("} bind def\n"); + writePS("/CharProcs 1 dict def\n"); + writePS("CharProcs begin\n"); + box.x1 = bbox[0]; + box.y1 = bbox[1]; + box.x2 = bbox[2]; + box.y2 = bbox[3]; + gfx2 = new Gfx(doc, this, resDict, &box, NULL); + gfx2->takeContentStreamStack(gfx); + writePS("/x {\n"); + if (paintType == 2) { + writePSFmt("{0:.6g} 0 {1:.6g} {2:.6g} {3:.6g} {4:.6g} setcachedevice\n", + xStep, bbox[0], bbox[1], bbox[2], bbox[3]); + t3FillColorOnly = gTrue; + } else { + if (x1 - 1 <= x0) { + writePS("1 0 setcharwidth\n"); + } else { + writePSFmt("{0:.6g} 0 setcharwidth\n", xStep); + } + t3FillColorOnly = gFalse; + } + inType3Char = gTrue; + ++numTilingPatterns; + gfx2->display(strRef); + --numTilingPatterns; + inType3Char = gFalse; + writePS("} def\n"); + 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); + 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:.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"); + noStateChanges = gFalse; +} + +void PSOutputDev::tilingPatternFillL2(GfxState *state, Gfx *gfx, + Object *strRef, + int paintType, int tilingType, + Dict *resDict, + double *mat, double *bbox, + int x0, int y0, int x1, int y1, + double xStep, double yStep) { + PDFRectangle box; + Gfx *gfx2; + + // switch to pattern space + 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]); + + // define a pattern + writePSFmt("/xpdfTile{0:d}\n", numTilingPatterns); + writePS("<<\n"); + writePS(" /PatternType 1\n"); + writePSFmt(" /PaintType {0:d}\n", paintType); + writePSFmt(" /TilingType {0:d}\n", tilingType); + writePSFmt(" /BBox [{0:.6g} {1:.6g} {2:.6g} {3:.6g}]\n", + bbox[0], bbox[1], bbox[2], bbox[3]); + writePSFmt(" /XStep {0:.6g}\n", xStep); + writePSFmt(" /YStep {0:.6g}\n", yStep); + writePS(" /PaintProc {\n"); + writePS(" pop\n"); + box.x1 = bbox[0]; + box.y1 = bbox[1]; + box.x2 = bbox[2]; + box.y2 = bbox[3]; + gfx2 = new Gfx(doc, this, resDict, &box, NULL); + gfx2->takeContentStreamStack(gfx); + t3FillColorOnly = paintType == 2; + inType3Char = gTrue; + ++numTilingPatterns; + gfx2->display(strRef); + --numTilingPatterns; + inType3Char = gFalse; + delete gfx2; + writePS(" }\n"); + writePS(">> matrix makepattern def\n"); + + // set the pattern + if (paintType == 2) { + writePS("fCol\n"); + writePS("currentcolor "); + } + writePSFmt("xpdfTile{0:d} setpattern\n", numTilingPatterns); + + // fill with the pattern + writePSFmt("{0:.6g} {1:.6g} {2:.6g} {3:.6g} rectfill\n", + x0 * xStep + bbox[0], + y0 * yStep + bbox[1], + (x1 - x0) * xStep + bbox[2], + (y1 - y0) * yStep + bbox[3]); + + writePS("grestore\n"); + noStateChanges = gFalse; +} + +GBool PSOutputDev::shadedFill(GfxState *state, GfxShading *shading) { + if (level != psLevel2 && + level != psLevel2Sep && + level != psLevel3 && + level != psLevel3Sep) { + return gFalse; + } + + switch (shading->getType()) { + case 1: + functionShadedFill(state, (GfxFunctionShading *)shading); + return gTrue; + case 2: + axialShadedFill(state, (GfxAxialShading *)shading); + return gTrue; + case 3: + radialShadedFill(state, (GfxRadialShading *)shading); + return gTrue; + default: + return gFalse; + } +} + +GBool PSOutputDev::functionShadedFill(GfxState *state, + GfxFunctionShading *shading) { + double x0, y0, x1, y1; + double *mat; + int i; + + if (level == psLevel2Sep || level == psLevel3Sep) { + if (shading->getColorSpace()->getMode() != csDeviceCMYK) { + return gFalse; + } + processColors |= psProcessCMYK; + } + + shading->getDomain(&x0, &y0, &x1, &y1); + mat = shading->getMatrix(); + 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) { + writePS("/func "); + cvtFunction(shading->getFunc(0)); + writePS("def\n"); + } else { + writePS("/func {\n"); + for (i = 0; i < shading->getNFuncs(); ++i) { + if (i < shading->getNFuncs() - 1) { + writePS("2 copy\n"); + } + cvtFunction(shading->getFunc(i)); + writePS("exec\n"); + if (i < shading->getNFuncs() - 1) { + writePS("3 1 roll\n"); + } + } + writePS("} def\n"); + } + writePSFmt("{0:.6g} {1:.6g} {2:.6g} {3:.6g} 0 funcSH\n", x0, y0, x1, y1); + + noStateChanges = gFalse; + return gTrue; +} + +GBool PSOutputDev::axialShadedFill(GfxState *state, GfxAxialShading *shading) { + double xMin, yMin, xMax, yMax; + double x0, y0, x1, y1, dx, dy, mul; + double tMin, tMax, t, t0, t1; + int i; + + if (level == psLevel2Sep || level == psLevel3Sep) { + if (shading->getColorSpace()->getMode() != csDeviceCMYK) { + return gFalse; + } + processColors |= psProcessCMYK; + } + + // get the clip region bbox + state->getUserClipBBox(&xMin, &yMin, &xMax, &yMax); + + // compute min and max t values, based on the four corners of the + // clip region bbox + shading->getCoords(&x0, &y0, &x1, &y1); + dx = x1 - x0; + dy = y1 - y0; + if (fabs(dx) < 0.01 && fabs(dy) < 0.01) { + return gTrue; + } else { + mul = 1 / (dx * dx + dy * dy); + tMin = tMax = ((xMin - x0) * dx + (yMin - y0) * dy) * mul; + t = ((xMin - x0) * dx + (yMax - y0) * dy) * mul; + if (t < tMin) { + tMin = t; + } else if (t > tMax) { + tMax = t; + } + t = ((xMax - x0) * dx + (yMin - y0) * dy) * mul; + if (t < tMin) { + tMin = t; + } else if (t > tMax) { + tMax = t; + } + t = ((xMax - x0) * dx + (yMax - y0) * dy) * mul; + if (t < tMin) { + tMin = t; + } else if (t > tMax) { + tMax = t; + } + if (tMin < 0 && !shading->getExtend0()) { + tMin = 0; + } + if (tMax > 1 && !shading->getExtend1()) { + tMax = 1; + } + } + + // get the function domain + t0 = shading->getDomain0(); + t1 = shading->getDomain1(); + + // generate the PS code + 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 "); + cvtFunction(shading->getFunc(0)); + writePS("def\n"); + } else { + writePS("/func {\n"); + for (i = 0; i < shading->getNFuncs(); ++i) { + if (i < shading->getNFuncs() - 1) { + writePS("dup\n"); + } + cvtFunction(shading->getFunc(i)); + writePS("exec\n"); + if (i < shading->getNFuncs() - 1) { + writePS("exch\n"); + } + } + writePS("} def\n"); + } + writePSFmt("{0:.6g} {1:.6g} 0 axialSH\n", tMin, tMax); + + noStateChanges = gFalse; + return gTrue; +} + +GBool PSOutputDev::radialShadedFill(GfxState *state, + GfxRadialShading *shading) { + double xMin, yMin, xMax, yMax; + double x0, y0, r0, x1, y1, r1, t0, t1; + double xa, ya, ra; + double 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; + + if (level == psLevel2Sep || level == psLevel3Sep) { + if (shading->getColorSpace()->getMode() != csDeviceCMYK) { + return gFalse; + } + processColors |= psProcessCMYK; + } + + // get the shading info + shading->getCoords(&x0, &y0, &r0, &x1, &y1, &r1); + t0 = shading->getDomain0(); + t1 = shading->getDomain1(); + + // Compute the point at which r(s) = 0; check for the enclosed + // circles case; and compute the angles for the tangent lines. + h = sqrt((x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0)); + if (h == 0) { + enclosed = gTrue; + theta = 0; // make gcc happy + } else if (r1 - r0 == 0) { + enclosed = gFalse; + theta = 0; + } else if (fabs(r1 - r0) >= h) { + enclosed = gTrue; + theta = 0; // make gcc happy + } else { + enclosed = gFalse; + theta = asin((r1 - r0) / h); + } + if (enclosed) { + a1 = 0; + a2 = 360; + } else { + alpha = atan2(y1 - y0, x1 - x0); + a1 = (180 / M_PI) * (alpha + theta) + 90; + a2 = (180 / M_PI) * (alpha - theta) - 90; + while (a2 < a1) { + a2 += 360; + } + } + + // compute the (possibly extended) s range + state->getUserClipBBox(&xMin, &yMin, &xMax, &yMax); + if (enclosed) { + sMin = 0; + sMax = 1; + } else { + // 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; + } + // 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:.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:.6g} def\n", a1); + writePSFmt("/a2 {0:.6g} def\n", a2); + if (shading->getNFuncs() == 1) { + writePS("/func "); + cvtFunction(shading->getFunc(0)); + writePS("def\n"); + } else { + writePS("/func {\n"); + for (i = 0; i < shading->getNFuncs(); ++i) { + if (i < shading->getNFuncs() - 1) { + writePS("dup\n"); + } + cvtFunction(shading->getFunc(i)); + writePS("exec\n"); + if (i < shading->getNFuncs() - 1) { + writePS("exch\n"); + } + } + writePS("} def\n"); + } + writePSFmt("{0:.6g} {1:.6g} 0 radialSH\n", sMin, sMax); + + // extend the 'enclosed' case + if (enclosed) { + // extend the smaller circle + if ((shading->getExtend0() && r0 <= r1) || + (shading->getExtend1() && r1 < r0)) { + if (r0 <= r1) { + ta = t0; + ra = r0; + xa = x0; + ya = y0; + } else { + ta = t1; + ra = r1; + xa = x1; + ya = y1; + } + if (level == psLevel2Sep || level == psLevel3Sep) { + writePSFmt("{0:.6g} radialCol aload pop k\n", ta); + } else { + writePSFmt("{0:.6g} radialCol sc\n", ta); + } + writePSFmt("{0:.6g} {1:.6g} {2:.6g} 0 360 arc h f*\n", xa, ya, ra); + } + + // extend the larger circle + if ((shading->getExtend0() && r0 > r1) || + (shading->getExtend1() && r1 >= r0)) { + if (r0 > r1) { + ta = t0; + ra = r0; + xa = x0; + ya = y0; + } else { + ta = t1; + ra = r1; + xa = x1; + ya = y1; + } + if (level == psLevel2Sep || level == psLevel3Sep) { + writePSFmt("{0:.6g} radialCol aload pop k\n", ta); + } else { + writePSFmt("{0:.6g} radialCol sc\n", ta); + } + 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); + } + } + + noStateChanges = gFalse; + return gTrue; +} + +void PSOutputDev::clip(GfxState *state) { + doPath(state->getPath()); + writePS("W\n"); + noStateChanges = gFalse; +} + +void PSOutputDev::eoClip(GfxState *state) { + doPath(state->getPath()); + writePS("W*\n"); + noStateChanges = gFalse; +} + +void PSOutputDev::clipToStrokePath(GfxState *state) { + doPath(state->getPath()); + writePS("Ws\n"); + noStateChanges = gFalse; +} + +void PSOutputDev::doPath(GfxPath *path) { + GfxSubpath *subpath; + double x0, y0, x1, y1, x2, y2, x3, y3, x4, y4; + int n, m, i, j; + + n = path->getNumSubpaths(); + + if (n == 1 && path->getSubpath(0)->getNumPoints() == 5) { + subpath = path->getSubpath(0); + x0 = subpath->getX(0); + y0 = subpath->getY(0); + x4 = subpath->getX(4); + y4 = subpath->getY(4); + if (x4 == x0 && y4 == y0) { + x1 = subpath->getX(1); + y1 = subpath->getY(1); + x2 = subpath->getX(2); + y2 = subpath->getY(2); + x3 = subpath->getX(3); + y3 = subpath->getY(3); + if (x0 == x1 && x2 == x3 && y0 == y3 && y1 == y2) { + 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:.6g} {1:.6g} {2:.6g} {3:.6g} re\n", + x0 < x1 ? x0 : x1, y0 < y2 ? y0 : y2, + fabs(x1 - x0), fabs(y2 - y0)); + return; + } + } + } + + for (i = 0; i < n; ++i) { + subpath = path->getSubpath(i); + m = subpath->getNumPoints(); + writePSFmt("{0:.6g} {1:.6g} m\n", subpath->getX(0), subpath->getY(0)); + j = 1; + while (j < m) { + if (subpath->getCurve(j)) { + 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:.6g} {1:.6g} l\n", subpath->getX(j), subpath->getY(j)); + ++j; + } + } + if (subpath->isClosed()) { + writePS("h\n"); + } + } +} + +void PSOutputDev::drawString(GfxState *state, GString *s) { + GfxFont *font; + int wMode; + int *codeToGID; + GString *s2; + double dx, dy, originX, originY, originX0, originY0, tOriginX0, tOriginY0; + char *p; + PSFontInfo *fi; + UnicodeMap *uMap; + CharCode code; + Unicode u[8]; + char buf[8]; + 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) { + return; + } + + // ignore empty strings + if (s->getLength() == 0) { + return; + } + + // get the font + if (!(font = state->getFont())) { + return; + } + wMode = font->getWMode(); + + fi = NULL; + for (i = 0; i < fontInfo->getLength(); ++i) { + fi = (PSFontInfo *)fontInfo->get(i); + if (fi->fontID.num == font->getID()->num && + fi->fontID.gen == font->getID()->gen) { + break; + } + fi = NULL; + } + + // check for a subtitute 16-bit font + uMap = NULL; + codeToGID = NULL; + if (font->isCIDFont()) { + if (!(fi && fi->ff)) { + // font substitution failed, so don't output any text + return; + } + if (fi->ff->encoding) { + uMap = globalParams->getUnicodeMap(fi->ff->encoding); + } + + // check for an 8-bit code-to-GID map + } else { + if (fi && fi->ff) { + codeToGID = fi->ff->codeToGID; + } + } + + // 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)); + originX0 = originY0 = 0; // make gcc happy + while (len > 0) { + n = font->getNextChar(p, len, &code, + u, (int)(sizeof(u) / sizeof(Unicode)), &uLen, + &dx, &dy, &originX, &originY); + //~ this doesn't handle the case where the origin offset changes + //~ within a string of characters -- which could be fixed by + //~ modifying dx,dy as needed for each character + if (p == s->getCString()) { + originX0 = originX; + originY0 = originY; + } + dx *= state->getFontSize(); + dy *= state->getFontSize(); + if (wMode) { + 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; + } + } 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] >= 0) { + s2->append((char)code); + dxdy[2 * nChars] = dx; + dxdy[2 * nChars + 1] = dy; + ++nChars; + } + } + p += n; + len -= n; + } + if (uMap) { + uMap->decRefCnt(); + } + originX0 *= state->getFontSize(); + originY0 *= state->getFontSize(); + state->textTransformDelta(originX0, originY0, &tOriginX0, &tOriginY0); + + if (nChars > 0) { + if (wMode) { + writePSFmt("{0:.6g} {1:.6g} rmoveto\n", -tOriginX0, -tOriginY0); + } + writePSString(s2); + writePS("\n["); + for (i = 0; i < 2 * nChars; ++i) { + if (i > 0) { + writePS("\n"); + } + writePSFmt("{0:.6g}", dxdy[i]); + } + if (font->getType() == fontType3) { + writePS("] Tj3\n"); + } else { + writePS("] Tj\n"); + } + if (wMode) { + writePSFmt("{0:.6g} {1:.6g} rmoveto\n", tOriginX0, tOriginY0); + } + } + gfree(dxdy); + delete s2; + + if ((state->getRender() & 4) && font->getType() != fontType3) { + haveTextClip = gTrue; + } + + noStateChanges = gFalse; +} + +void PSOutputDev::endTextObject(GfxState *state) { + if (haveTextClip) { + writePS("Tclip\n"); + haveTextClip = gFalse; + noStateChanges = gFalse; + } +} + +void PSOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str, + int width, int height, GBool invert, + GBool inlineImg, GBool interpolate) { + int len; + + len = height * ((width + 7) / 8); + switch (level) { + case psLevel1: + case psLevel1Sep: + doImageL1(ref, state, NULL, invert, inlineImg, str, width, height, len); + break; + case psLevel2: + case psLevel2Gray: + case psLevel2Sep: + doImageL2(ref, state, NULL, invert, inlineImg, str, width, height, len, + NULL, NULL, 0, 0, gFalse); + break; + case psLevel3: + case psLevel3Gray: + case psLevel3Sep: + doImageL3(ref, state, NULL, invert, inlineImg, str, width, height, len, + NULL, NULL, 0, 0, gFalse); + break; + } + noStateChanges = gFalse; +} + +void PSOutputDev::drawImage(GfxState *state, Object *ref, Stream *str, + int width, int height, GfxImageColorMap *colorMap, + int *maskColors, GBool inlineImg, + GBool interpolate) { + int len; + + len = height * ((width * colorMap->getNumPixelComps() * + colorMap->getBits() + 7) / 8); + switch (level) { + case psLevel1: + doImageL1(ref, state, colorMap, gFalse, inlineImg, str, + width, height, len); + break; + case psLevel1Sep: + //~ handle indexed, separation, ... color spaces + doImageL1Sep(state, colorMap, gFalse, inlineImg, str, width, height, len); + break; + case psLevel2: + case psLevel2Gray: + case psLevel2Sep: + doImageL2(ref, state, colorMap, gFalse, inlineImg, str, + width, height, len, maskColors, NULL, 0, 0, gFalse); + break; + case psLevel3: + case psLevel3Gray: + case psLevel3Sep: + doImageL3(ref, state, colorMap, gFalse, inlineImg, str, + width, height, len, maskColors, NULL, 0, 0, gFalse); + break; + } + t3Cacheable = gFalse; + noStateChanges = gFalse; +} + +void PSOutputDev::drawMaskedImage(GfxState *state, Object *ref, Stream *str, + int width, int height, + GfxImageColorMap *colorMap, + Object *maskRef, Stream *maskStr, + int maskWidth, int maskHeight, + GBool maskInvert, GBool interpolate) { + int len; + + len = height * ((width * colorMap->getNumPixelComps() * + colorMap->getBits() + 7) / 8); + switch (level) { + case psLevel1: + doImageL1(ref, state, colorMap, gFalse, gFalse, str, width, height, len); + break; + case psLevel1Sep: + //~ handle indexed, separation, ... color spaces + doImageL1Sep(state, colorMap, gFalse, gFalse, str, width, height, len); + break; + case psLevel2: + case psLevel2Gray: + case psLevel2Sep: + doImageL2(ref, state, colorMap, gFalse, gFalse, str, width, height, len, + NULL, maskStr, maskWidth, maskHeight, maskInvert); + break; + case psLevel3: + case psLevel3Gray: + case psLevel3Sep: + doImageL3(ref, state, colorMap, gFalse, gFalse, str, width, height, len, + NULL, maskStr, maskWidth, maskHeight, maskInvert); + break; + } + t3Cacheable = gFalse; + noStateChanges = gFalse; +} + +void PSOutputDev::doImageL1(Object *ref, GfxState *state, + GfxImageColorMap *colorMap, + GBool invert, GBool inlineImg, + Stream *str, int width, int height, int len) { + ImageStream *imgStr; + Guchar pixBuf[gfxColorMaxComps]; + GfxGray gray; + int col, x, y, c, i; + + if ((inType3Char || preload) && !colorMap) { + if (inlineImg) { + // create an array + str = new FixedLengthEncoder(str, len); + str = new ASCIIHexEncoder(str); + str->reset(); + col = 0; + writePS("[<"); + do { + do { + c = str->getChar(); + } while (c == '\n' || c == '\r'); + if (c == '>' || c == EOF) { + break; + } + writePSChar((char)c); + ++col; + // each line is: "<...data...>" + // so max data length = 255 - 4 = 251 + // but make it 240 just to be safe + // chunks are 2 bytes each, so we need to stop on an even col number + if (col == 240) { + writePS(">\n<"); + col = 0; + } + } while (c != '>' && c != EOF); + writePS(">]\n"); + writePS("0\n"); + str->close(); + delete str; + } else { + // set up to use the array already created by setupImages() + writePSFmt("ImData_{0:d}_{1:d} 0\n", ref->getRefNum(), ref->getRefGen()); + } + } + + // image/imagemask command + if ((inType3Char || preload) && !colorMap) { + writePSFmt("{0:d} {1:d} {2:s} [{3:d} 0 0 {4:d} 0 {5:d}] pdfImM1a\n", + width, height, invert ? "true" : "false", + width, -height, height); + } else if (colorMap) { + writePSFmt("{0:d} {1:d} 8 [{2:d} 0 0 {3:d} 0 {4:d}] pdfIm1\n", + width, height, + width, -height, height); + } else { + writePSFmt("{0:d} {1:d} {2:s} [{3:d} 0 0 {4:d} 0 {5:d}] pdfImM1\n", + width, height, invert ? "true" : "false", + width, -height, height); + } + + // image data + if (!((inType3Char || preload) && !colorMap)) { + + if (colorMap) { + + // set up to process the data stream + imgStr = new ImageStream(str, width, colorMap->getNumPixelComps(), + colorMap->getBits()); + imgStr->reset(); + + // process the data stream + i = 0; + for (y = 0; y < height; ++y) { + + // write the line + for (x = 0; x < width; ++x) { + imgStr->getPixel(pixBuf); + colorMap->getGray(pixBuf, &gray, state->getRenderingIntent()); + writePSFmt("{0:02x}", colToByte(gray)); + if (++i == 32) { + writePSChar('\n'); + i = 0; + } + } + } + if (i != 0) { + writePSChar('\n'); + } + str->close(); + delete imgStr; + + // imagemask + } else { + str->reset(); + i = 0; + for (y = 0; y < height; ++y) { + for (x = 0; x < width; x += 8) { + writePSFmt("{0:02x}", str->getChar() & 0xff); + if (++i == 32) { + writePSChar('\n'); + i = 0; + } + } + } + if (i != 0) { + writePSChar('\n'); + } + str->close(); + } + } +} + +void PSOutputDev::doImageL1Sep(GfxState *state, GfxImageColorMap *colorMap, + GBool invert, GBool inlineImg, + Stream *str, int width, int height, int len) { + ImageStream *imgStr; + Guchar *lineBuf; + Guchar pixBuf[gfxColorMaxComps]; + GfxCMYK cmyk; + int x, y, i, comp; + + // width, height, matrix, bits per component + writePSFmt("{0:d} {1:d} 8 [{2:d} 0 0 {3:d} 0 {4:d}] pdfIm1Sep\n", + width, height, + width, -height, height); + + // allocate a line buffer + lineBuf = (Guchar *)gmallocn(width, 4); + + // set up to process the data stream + imgStr = new ImageStream(str, width, colorMap->getNumPixelComps(), + colorMap->getBits()); + imgStr->reset(); + + // process the data stream + i = 0; + for (y = 0; y < height; ++y) { + + // read the line + for (x = 0; x < width; ++x) { + imgStr->getPixel(pixBuf); + colorMap->getCMYK(pixBuf, &cmyk, state->getRenderingIntent()); + lineBuf[4*x+0] = colToByte(cmyk.c); + lineBuf[4*x+1] = colToByte(cmyk.m); + lineBuf[4*x+2] = colToByte(cmyk.y); + lineBuf[4*x+3] = colToByte(cmyk.k); + addProcessColor(colToDbl(cmyk.c), colToDbl(cmyk.m), + colToDbl(cmyk.y), colToDbl(cmyk.k)); + } + + // write one line of each color component + for (comp = 0; comp < 4; ++comp) { + for (x = 0; x < width; ++x) { + writePSFmt("{0:02x}", lineBuf[4*x + comp]); + if (++i == 32) { + writePSChar('\n'); + i = 0; + } + } + } + } + + if (i != 0) { + writePSChar('\n'); + } + + str->close(); + delete imgStr; + gfree(lineBuf); +} + +void PSOutputDev::doImageL2(Object *ref, GfxState *state, + GfxImageColorMap *colorMap, + GBool invert, GBool inlineImg, + Stream *str, int width, int height, int len, + int *maskColors, Stream *maskStr, + int maskWidth, int maskHeight, GBool maskInvert) { + Stream *str2; + GString *s; + int n, numComps; + GBool useLZW, useRLE, useASCII, useASCIIHex, useCompressed; + GfxSeparationColorSpace *sepCS; + GfxColor color; + GfxCMYK cmyk; + char buf[4096]; + int c, col, i; + + // color key masking + if (maskColors && colorMap && !inlineImg) { + // can't read the stream twice for inline images -- but masking + // isn't allowed with inline images anyway + convertColorKeyMaskToClipRects(colorMap, str, width, height, maskColors); + + // explicit masking + } else if (maskStr) { + convertExplicitMaskToClipRects(maskStr, maskWidth, maskHeight, maskInvert); + } + + // color space + if (colorMap && !(level == psLevel2Gray || level == psLevel3Gray)) { + dumpColorSpaceL2(state, colorMap->getColorSpace(), gFalse, gTrue, gFalse); + writePS(" setcolorspace\n"); + } + + useASCIIHex = globalParams->getPSASCIIHex(); + + // set up the image data + if (mode == psModeForm || inType3Char || preload) { + if (inlineImg) { + // create an array + str2 = new FixedLengthEncoder(str, len); + if (colorMap && (level == psLevel2Gray || level == psLevel3Gray)) { + str2 = new GrayRecoder(str2, width, height, colorMap); + } + if (globalParams->getPSLZW()) { + str2 = new LZWEncoder(str2); + } else { + str2 = new RunLengthEncoder(str2); + } + if (useASCIIHex) { + str2 = new ASCIIHexEncoder(str2); + } else { + str2 = new ASCII85Encoder(str2); + } + str2->reset(); + col = 0; + writePS((char *)(useASCIIHex ? "[<" : "[<~")); + do { + do { + c = str2->getChar(); + } while (c == '\n' || c == '\r'); + if (c == (useASCIIHex ? '>' : '~') || c == EOF) { + break; + } + if (c == 'z') { + writePSChar((char)c); + ++col; + } else { + writePSChar((char)c); + ++col; + for (i = 1; i <= (useASCIIHex ? 1 : 4); ++i) { + do { + c = str2->getChar(); + } while (c == '\n' || c == '\r'); + if (c == (useASCIIHex ? '>' : '~') || c == EOF) { + break; + } + writePSChar((char)c); + ++col; + } + } + // each line is: "<~...data...~>" + // so max data length = 255 - 6 = 249 + // chunks are 1 or 5 bytes each, so we have to stop at 245 + // but make it 240 just to be safe + if (col > 240) { + writePS((char *)(useASCIIHex ? ">\n<" : "~>\n<~")); + col = 0; + } + } while (c != (useASCIIHex ? '>' : '~') && c != EOF); + writePS((char *)(useASCIIHex ? ">\n" : "~>\n")); + // add an extra entry because the LZWDecode/RunLengthDecode + // filter may read past the end + writePS("<>]\n"); + writePS("0\n"); + str2->close(); + delete str2; + } else { + // set up to use the array already created by setupImages() + writePSFmt("ImData_{0:d}_{1:d} 0\n", ref->getRefNum(), ref->getRefGen()); + } + } + + // image dictionary + writePS("<<\n /ImageType 1\n"); + + // width, height, matrix, bits per component + writePSFmt(" /Width {0:d}\n", width); + writePSFmt(" /Height {0:d}\n", height); + writePSFmt(" /ImageMatrix [{0:d} 0 0 {1:d} 0 {2:d}]\n", + width, -height, height); + if (colorMap && (colorMap->getColorSpace()->getMode() == csDeviceN || + level == psLevel2Gray || level == psLevel3Gray)) { + writePS(" /BitsPerComponent 8\n"); + } else { + writePSFmt(" /BitsPerComponent {0:d}\n", + colorMap ? colorMap->getBits() : 1); + } + + // decode + if (colorMap) { + writePS(" /Decode ["); + if ((level == psLevel2Sep || level == psLevel3Sep) && + colorMap->getColorSpace()->getMode() == csSeparation) { + // this matches up with the code in the pdfImSep operator + n = (1 << colorMap->getBits()) - 1; + writePSFmt("{0:.4g} {1:.4g}", colorMap->getDecodeLow(0) * n, + colorMap->getDecodeHigh(0) * n); + } else if (level == psLevel2Gray || level == psLevel3Gray) { + writePS("0 1"); + } else if (colorMap->getColorSpace()->getMode() == csDeviceN) { + numComps = ((GfxDeviceNColorSpace *)colorMap->getColorSpace())-> + getAlt()->getNComps(); + for (i = 0; i < numComps; ++i) { + if (i > 0) { + writePS(" "); + } + writePS("0 1"); + } + } else { + numComps = colorMap->getNumPixelComps(); + for (i = 0; i < numComps; ++i) { + if (i > 0) { + writePS(" "); + } + writePSFmt("{0:.4g} {1:.4g}", + colorMap->getDecodeLow(i), colorMap->getDecodeHigh(i)); + } + } + writePS("]\n"); + } else { + writePSFmt(" /Decode [{0:d} {1:d}]\n", invert ? 1 : 0, invert ? 0 : 1); + } + + // data source + if (mode == psModeForm || inType3Char || preload) { + writePS(" /DataSource { pdfImStr }\n"); + } else { + writePS(" /DataSource currentfile\n"); + } + + // filters + if ((mode == psModeForm || inType3Char || preload) && + globalParams->getPSUncompressPreloadedImages()) { + s = NULL; + useLZW = useRLE = gFalse; + useCompressed = gFalse; + useASCII = gFalse; + } else { + s = str->getPSFilter(level < psLevel2 ? 1 : level < psLevel3 ? 2 : 3, + " ", !inlineImg); + if ((colorMap && (colorMap->getColorSpace()->getMode() == csDeviceN || + level == psLevel2Gray || level == psLevel3Gray)) || + inlineImg || !s) { + if (globalParams->getPSLZW()) { + useLZW = gTrue; + useRLE = gFalse; + } else { + useRLE = gTrue; + useLZW = gFalse; + } + useASCII = !(mode == psModeForm || inType3Char || preload); + useCompressed = gFalse; + } else { + useLZW = useRLE = gFalse; + useASCII = str->isBinary() && + !(mode == psModeForm || inType3Char || preload); + useCompressed = gTrue; + } + } + if (useASCII) { + writePSFmt(" /ASCII{0:s}Decode filter\n", + useASCIIHex ? "Hex" : "85"); + } + if (useLZW) { + writePS(" /LZWDecode filter\n"); + } else if (useRLE) { + writePS(" /RunLengthDecode filter\n"); + } + if (useCompressed) { + writePS(s->getCString()); + } + if (s) { + delete s; + } + + if (mode == psModeForm || inType3Char || preload) { + + // end of image dictionary + writePSFmt(">>\n{0:s}\n", colorMap ? "image" : "imagemask"); + + // get rid of the array and index + writePS("pop pop\n"); + + } else { + + // cut off inline image streams at appropriate length + if (inlineImg) { + str = new FixedLengthEncoder(str, len); + } else if (useCompressed) { + str = str->getUndecodedStream(); + } + + // recode to grayscale + if (colorMap && (level == psLevel2Gray || level == psLevel3Gray)) { + str = new GrayRecoder(str, width, height, colorMap); + + // recode DeviceN data + } else if (colorMap && colorMap->getColorSpace()->getMode() == csDeviceN) { + str = new DeviceNRecoder(str, width, height, colorMap); + } + + // add LZWEncode/RunLengthEncode and ASCIIHex/85 encode filters + if (useLZW) { + str = new LZWEncoder(str); + } else if (useRLE) { + str = new RunLengthEncoder(str); + } + if (useASCII) { + if (useASCIIHex) { + str = new ASCIIHexEncoder(str); + } else { + str = new ASCII85Encoder(str); + } + } + + // end of image dictionary + writePS(">>\n"); +#if OPI_SUPPORT + if (opi13Nest) { + if (inlineImg) { + // this can't happen -- OPI dictionaries are in XObjects + error(errSyntaxError, -1, "OPI in inline image"); + n = 0; + } else { + // need to read the stream to count characters -- the length + // is data-dependent (because of ASCII and LZW/RunLength + // filters) + str->reset(); + n = 0; + do { + i = str->discardChars(4096); + n += i; + } while (i == 4096); + str->close(); + } + // +6/7 for "pdfIm\n" / "pdfImM\n" + // +8 for newline + trailer + n += colorMap ? 14 : 15; + writePSFmt("%%BeginData: {0:d} Hex Bytes\n", n); + } +#endif + if ((level == psLevel2Sep || level == psLevel3Sep) && colorMap && + colorMap->getColorSpace()->getMode() == csSeparation) { + color.c[0] = gfxColorComp1; + sepCS = (GfxSeparationColorSpace *)colorMap->getColorSpace(); + sepCS->getCMYK(&color, &cmyk, state->getRenderingIntent()); + writePSFmt("{0:.4g} {1:.4g} {2:.4g} {3:.4g} ({4:t}) pdfImSep\n", + colToDbl(cmyk.c), colToDbl(cmyk.m), + colToDbl(cmyk.y), colToDbl(cmyk.k), + sepCS->getName()); + } else { + writePSFmt("{0:s}\n", colorMap ? "pdfIm" : "pdfImM"); + } + + // copy the stream data + str->reset(); + while ((n = str->getBlock(buf, sizeof(buf))) > 0) { + writePSBlock(buf, n); + } + str->close(); + + // add newline and trailer to the end + writePSChar('\n'); + writePS("%-EOD-\n"); +#if OPI_SUPPORT + if (opi13Nest) { + writePS("%%EndData\n"); + } +#endif + + // delete encoders + if (useLZW || useRLE || useASCII || inlineImg) { + delete str; + } + } + + if ((maskColors && colorMap && !inlineImg) || maskStr) { + writePS("pdfImClipEnd\n"); + } +} + +// Convert color key masking to a clipping region consisting of a +// sequence of clip rectangles. +void PSOutputDev::convertColorKeyMaskToClipRects(GfxImageColorMap *colorMap, + Stream *str, + int width, int height, + int *maskColors) { + ImageStream *imgStr; + Guchar *line; + PSOutImgClipRect *rects0, *rects1, *rectsTmp, *rectsOut; + int rects0Len, rects1Len, rectsSize, rectsOutLen, rectsOutSize; + GBool emitRect, addRect, extendRect; + int numComps, i, j, x0, x1, y; + + numComps = colorMap->getNumPixelComps(); + imgStr = new ImageStream(str, width, numComps, colorMap->getBits()); + imgStr->reset(); + rects0Len = rects1Len = rectsOutLen = 0; + rectsSize = rectsOutSize = 64; + rects0 = (PSOutImgClipRect *)gmallocn(rectsSize, sizeof(PSOutImgClipRect)); + rects1 = (PSOutImgClipRect *)gmallocn(rectsSize, sizeof(PSOutImgClipRect)); + rectsOut = (PSOutImgClipRect *)gmallocn(rectsOutSize, + sizeof(PSOutImgClipRect)); + for (y = 0; y < height; ++y) { + if (!(line = imgStr->getLine())) { + break; + } + i = 0; + rects1Len = 0; + for (x0 = 0; x0 < width; ++x0) { + for (j = 0; j < numComps; ++j) { + if (line[x0*numComps+j] < maskColors[2*j] || + line[x0*numComps+j] > maskColors[2*j+1]) { + break; + } + } + if (j < numComps) { + break; + } + } + for (x1 = x0; x1 < width; ++x1) { + for (j = 0; j < numComps; ++j) { + if (line[x1*numComps+j] < maskColors[2*j] || + line[x1*numComps+j] > maskColors[2*j+1]) { + break; + } + } + if (j == numComps) { + break; + } + } + while (x0 < width || i < rects0Len) { + emitRect = addRect = extendRect = gFalse; + if (x0 >= width) { + emitRect = gTrue; + } else if (i >= rects0Len) { + addRect = gTrue; + } else if (rects0[i].x0 < x0) { + emitRect = gTrue; + } else if (x0 < rects0[i].x0) { + addRect = gTrue; + } else if (rects0[i].x1 == x1) { + extendRect = gTrue; + } else { + emitRect = addRect = gTrue; + } + if (emitRect) { + if (rectsOutLen == rectsOutSize) { + rectsOutSize *= 2; + rectsOut = (PSOutImgClipRect *)greallocn(rectsOut, rectsOutSize, + sizeof(PSOutImgClipRect)); + } + rectsOut[rectsOutLen].x0 = rects0[i].x0; + rectsOut[rectsOutLen].x1 = rects0[i].x1; + rectsOut[rectsOutLen].y0 = height - y - 1; + rectsOut[rectsOutLen].y1 = height - rects0[i].y0 - 1; + ++rectsOutLen; + ++i; + } + if (addRect || extendRect) { + if (rects1Len == rectsSize) { + rectsSize *= 2; + rects0 = (PSOutImgClipRect *)greallocn(rects0, rectsSize, + sizeof(PSOutImgClipRect)); + rects1 = (PSOutImgClipRect *)greallocn(rects1, rectsSize, + sizeof(PSOutImgClipRect)); + } + rects1[rects1Len].x0 = x0; + rects1[rects1Len].x1 = x1; + if (addRect) { + rects1[rects1Len].y0 = y; + } + if (extendRect) { + rects1[rects1Len].y0 = rects0[i].y0; + ++i; + } + ++rects1Len; + for (x0 = x1; x0 < width; ++x0) { + for (j = 0; j < numComps; ++j) { + if (line[x0*numComps+j] < maskColors[2*j] || + line[x0*numComps+j] > maskColors[2*j+1]) { + break; + } + } + if (j < numComps) { + break; + } + } + for (x1 = x0; x1 < width; ++x1) { + for (j = 0; j < numComps; ++j) { + if (line[x1*numComps+j] < maskColors[2*j] || + line[x1*numComps+j] > maskColors[2*j+1]) { + break; + } + } + if (j == numComps) { + break; + } + } + } + } + rectsTmp = rects0; + rects0 = rects1; + rects1 = rectsTmp; + i = rects0Len; + rects0Len = rects1Len; + rects1Len = i; + } + for (i = 0; i < rects0Len; ++i) { + if (rectsOutLen == rectsOutSize) { + rectsOutSize *= 2; + rectsOut = (PSOutImgClipRect *)greallocn(rectsOut, rectsOutSize, + sizeof(PSOutImgClipRect)); + } + rectsOut[rectsOutLen].x0 = rects0[i].x0; + rectsOut[rectsOutLen].x1 = rects0[i].x1; + rectsOut[rectsOutLen].y0 = height - y - 1; + rectsOut[rectsOutLen].y1 = height - rects0[i].y0 - 1; + ++rectsOutLen; + } + writePSFmt("{0:d} {1:d}\n", width, height); + for (i = 0; i < rectsOutLen; ++i) { + writePSFmt("{0:d} {1:d} {2:d} {3:d} pr\n", + rectsOut[i].x0, rectsOut[i].y0, + rectsOut[i].x1 - rectsOut[i].x0, + rectsOut[i].y1 - rectsOut[i].y0); + } + writePS("pop pop pdfImClip\n"); + gfree(rectsOut); + gfree(rects0); + gfree(rects1); + delete imgStr; + str->close(); +} + +// Convert an explicit mask image to a clipping region consisting of a +// sequence of clip rectangles. +void PSOutputDev::convertExplicitMaskToClipRects(Stream *maskStr, + int maskWidth, int maskHeight, + GBool maskInvert) { + ImageStream *imgStr; + Guchar *line; + PSOutImgClipRect *rects0, *rects1, *rectsTmp, *rectsOut; + int rects0Len, rects1Len, rectsSize, rectsOutLen, rectsOutSize; + GBool emitRect, addRect, extendRect; + int i, x0, x1, y, maskXor; + + imgStr = new ImageStream(maskStr, maskWidth, 1, 1); + imgStr->reset(); + rects0Len = rects1Len = rectsOutLen = 0; + rectsSize = rectsOutSize = 64; + rects0 = (PSOutImgClipRect *)gmallocn(rectsSize, sizeof(PSOutImgClipRect)); + rects1 = (PSOutImgClipRect *)gmallocn(rectsSize, sizeof(PSOutImgClipRect)); + rectsOut = (PSOutImgClipRect *)gmallocn(rectsOutSize, + sizeof(PSOutImgClipRect)); + maskXor = maskInvert ? 1 : 0; + for (y = 0; y < maskHeight; ++y) { + if (!(line = imgStr->getLine())) { + break; + } + i = 0; + rects1Len = 0; + for (x0 = 0; x0 < maskWidth && (line[x0] ^ maskXor); ++x0) ; + for (x1 = x0; x1 < maskWidth && !(line[x1] ^ maskXor); ++x1) ; + while (x0 < maskWidth || i < rects0Len) { + emitRect = addRect = extendRect = gFalse; + if (x0 >= maskWidth) { + emitRect = gTrue; + } else if (i >= rects0Len) { + addRect = gTrue; + } else if (rects0[i].x0 < x0) { + emitRect = gTrue; + } else if (x0 < rects0[i].x0) { + addRect = gTrue; + } else if (rects0[i].x1 == x1) { + extendRect = gTrue; + } else { + emitRect = addRect = gTrue; + } + if (emitRect) { + if (rectsOutLen == rectsOutSize) { + rectsOutSize *= 2; + rectsOut = (PSOutImgClipRect *)greallocn(rectsOut, rectsOutSize, + sizeof(PSOutImgClipRect)); + } + rectsOut[rectsOutLen].x0 = rects0[i].x0; + rectsOut[rectsOutLen].x1 = rects0[i].x1; + rectsOut[rectsOutLen].y0 = maskHeight - y - 1; + rectsOut[rectsOutLen].y1 = maskHeight - rects0[i].y0 - 1; + ++rectsOutLen; + ++i; + } + if (addRect || extendRect) { + if (rects1Len == rectsSize) { + rectsSize *= 2; + rects0 = (PSOutImgClipRect *)greallocn(rects0, rectsSize, + sizeof(PSOutImgClipRect)); + rects1 = (PSOutImgClipRect *)greallocn(rects1, rectsSize, + sizeof(PSOutImgClipRect)); + } + rects1[rects1Len].x0 = x0; + rects1[rects1Len].x1 = x1; + if (addRect) { + rects1[rects1Len].y0 = y; + } + if (extendRect) { + rects1[rects1Len].y0 = rects0[i].y0; + ++i; + } + ++rects1Len; + for (x0 = x1; x0 < maskWidth && (line[x0] ^ maskXor); ++x0) ; + for (x1 = x0; x1 < maskWidth && !(line[x1] ^ maskXor); ++x1) ; + } + } + rectsTmp = rects0; + rects0 = rects1; + rects1 = rectsTmp; + i = rects0Len; + rects0Len = rects1Len; + rects1Len = i; + } + for (i = 0; i < rects0Len; ++i) { + if (rectsOutLen == rectsOutSize) { + rectsOutSize *= 2; + rectsOut = (PSOutImgClipRect *)greallocn(rectsOut, rectsOutSize, + sizeof(PSOutImgClipRect)); + } + rectsOut[rectsOutLen].x0 = rects0[i].x0; + rectsOut[rectsOutLen].x1 = rects0[i].x1; + rectsOut[rectsOutLen].y0 = maskHeight - y - 1; + rectsOut[rectsOutLen].y1 = maskHeight - rects0[i].y0 - 1; + ++rectsOutLen; + } + writePSFmt("{0:d} {1:d}\n", maskWidth, maskHeight); + for (i = 0; i < rectsOutLen; ++i) { + writePSFmt("{0:d} {1:d} {2:d} {3:d} pr\n", + rectsOut[i].x0, rectsOut[i].y0, + rectsOut[i].x1 - rectsOut[i].x0, + rectsOut[i].y1 - rectsOut[i].y0); + } + writePS("pop pop pdfImClip\n"); + gfree(rectsOut); + gfree(rects0); + gfree(rects1); + delete imgStr; + maskStr->close(); +} + +//~ this doesn't currently support OPI +void PSOutputDev::doImageL3(Object *ref, GfxState *state, + GfxImageColorMap *colorMap, + GBool invert, GBool inlineImg, + Stream *str, int width, int height, int len, + int *maskColors, Stream *maskStr, + int maskWidth, int maskHeight, GBool maskInvert) { + Stream *str2; + GString *s; + int n, numComps; + GBool useLZW, useRLE, useASCII, useASCIIHex, useCompressed; + GBool maskUseLZW, maskUseRLE, maskUseASCII, maskUseCompressed; + GString *maskFilters; + GfxSeparationColorSpace *sepCS; + GfxColor color; + GfxCMYK cmyk; + char buf[4096]; + int c; + int col, i; + + useASCIIHex = globalParams->getPSASCIIHex(); + useLZW = useRLE = useASCII = useCompressed = gFalse; // make gcc happy + maskUseLZW = maskUseRLE = maskUseASCII = gFalse; // make gcc happy + maskUseCompressed = gFalse; // make gcc happy + maskFilters = NULL; // make gcc happy + + // explicit masking + // -- this also converts color key masking in grayscale mode + if (maskStr || (maskColors && colorMap && level == psLevel3Gray)) { + + // mask data source + if (maskColors && colorMap && level == psLevel3Gray) { + s = NULL; + if (mode == psModeForm || inType3Char || preload) { + if (globalParams->getPSUncompressPreloadedImages()) { + maskUseLZW = maskUseRLE = gFalse; + } else if (globalParams->getPSLZW()) { + maskUseLZW = gTrue; + maskUseRLE = gFalse; + } else { + maskUseRLE = gTrue; + maskUseLZW = gFalse; + } + maskUseASCII = gFalse; + maskUseCompressed = gFalse; + } else { + if (globalParams->getPSLZW()) { + maskUseLZW = gTrue; + maskUseRLE = gFalse; + } else { + maskUseRLE = gTrue; + maskUseLZW = gFalse; + } + maskUseASCII = gTrue; + } + maskUseCompressed = gFalse; + maskWidth = width; + maskHeight = height; + maskInvert = gFalse; + } else if ((mode == psModeForm || inType3Char || preload) && + globalParams->getPSUncompressPreloadedImages()) { + s = NULL; + maskUseLZW = maskUseRLE = gFalse; + maskUseCompressed = gFalse; + maskUseASCII = gFalse; + } else { + s = maskStr->getPSFilter(3, " ", !inlineImg); + if (!s) { + if (globalParams->getPSLZW()) { + maskUseLZW = gTrue; + maskUseRLE = gFalse; + } else { + maskUseRLE = gTrue; + maskUseLZW = gFalse; + } + maskUseASCII = !(mode == psModeForm || inType3Char || preload); + maskUseCompressed = gFalse; + } else { + maskUseLZW = 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 (maskUseLZW) { + maskFilters->append(" /LZWDecode filter\n"); + } else 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 the ColorKeyToMask filter + if (maskColors && colorMap && level == psLevel3Gray) { + maskStr = new ColorKeyToMaskEncoder(str, width, height, colorMap, + maskColors); + } + + // add LZWEncode/RunLengthEncode and ASCIIHex/85 encode filters + if (maskUseCompressed) { + maskStr = maskStr->getUndecodedStream(); + } + if (maskUseLZW) { + maskStr = new LZWEncoder(maskStr); + } else 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 ((n = maskStr->getBlock(buf, sizeof(buf))) > 0) { + writePSBlock(buf, n); + } + maskStr->close(); + writePSChar('\n'); + writePS("%-EOD-\n"); + + // delete encoders + if (maskUseLZW || maskUseRLE || maskUseASCII) { + delete maskStr; + } + } + } + + // color space + if (colorMap && level != psLevel3Gray) { + dumpColorSpaceL2(state, colorMap->getColorSpace(), gFalse, gTrue, gFalse); + writePS(" setcolorspace\n"); + } + + // set up the image data + if (mode == psModeForm || inType3Char || preload) { + if (inlineImg) { + // create an array + str2 = new FixedLengthEncoder(str, len); + if (colorMap && level == psLevel3Gray) { + str2 = new GrayRecoder(str2, width, height, colorMap); + } + if (globalParams->getPSLZW()) { + str2 = new LZWEncoder(str2); + } else { + str2 = new RunLengthEncoder(str2); + } + if (useASCIIHex) { + str2 = new ASCIIHexEncoder(str2); + } else { + str2 = new ASCII85Encoder(str2); + } + str2->reset(); + col = 0; + writePS((char *)(useASCIIHex ? "[<" : "[<~")); + do { + do { + c = str2->getChar(); + } while (c == '\n' || c == '\r'); + if (c == (useASCIIHex ? '>' : '~') || c == EOF) { + break; + } + if (c == 'z') { + writePSChar((char)c); + ++col; + } else { + writePSChar((char)c); + ++col; + for (i = 1; i <= (useASCIIHex ? 1 : 4); ++i) { + do { + c = str2->getChar(); + } while (c == '\n' || c == '\r'); + if (c == (useASCIIHex ? '>' : '~') || c == EOF) { + break; + } + writePSChar((char)c); + ++col; + } + } + // each line is: "<~...data...~>" + // so max data length = 255 - 6 = 249 + // chunks are 1 or 5 bytes each, so we have to stop at 245 + // but make it 240 just to be safe + if (col > 240) { + writePS((char *)(useASCIIHex ? ">\n<" : "~>\n<~")); + col = 0; + } + } while (c != (useASCIIHex ? '>' : '~') && c != EOF); + writePS((char *)(useASCIIHex ? ">\n" : "~>\n")); + // add an extra entry because the LZWDecode/RunLengthDecode + // filter may read past the end + writePS("<>]\n"); + writePS("0\n"); + str2->close(); + delete str2; + } else { + // set up to use the array already created by setupImages() + writePSFmt("ImData_{0:d}_{1:d} 0\n", ref->getRefNum(), ref->getRefGen()); + } + } + + // explicit masking + if (maskStr || (maskColors && colorMap && level == psLevel3Gray)) { + writePS("<<\n /ImageType 3\n"); + writePS(" /InterleaveType 3\n"); + writePS(" /DataDict\n"); + } + + // image (data) dictionary + writePSFmt("<<\n /ImageType {0:d}\n", + (maskColors && colorMap && level != psLevel3Gray) ? 4 : 1); + + // color key masking + if (maskColors && colorMap && level != psLevel3Gray) { + writePS(" /MaskColor [\n"); + numComps = colorMap->getNumPixelComps(); + for (i = 0; i < 2 * numComps; i += 2) { + writePSFmt(" {0:d} {1:d}\n", maskColors[i], maskColors[i+1]); + } + writePS(" ]\n"); + } + + // width, height, matrix, bits per component + writePSFmt(" /Width {0:d}\n", width); + writePSFmt(" /Height {0:d}\n", height); + writePSFmt(" /ImageMatrix [{0:d} 0 0 {1:d} 0 {2:d}]\n", + width, -height, height); + if (colorMap && level == psLevel3Gray) { + writePS(" /BitsPerComponent 8\n"); + } else { + writePSFmt(" /BitsPerComponent {0:d}\n", + colorMap ? colorMap->getBits() : 1); + } + + // decode + if (colorMap) { + writePS(" /Decode ["); + if (level == psLevel3Sep && + colorMap->getColorSpace()->getMode() == csSeparation) { + // this matches up with the code in the pdfImSep operator + n = (1 << colorMap->getBits()) - 1; + writePSFmt("{0:.4g} {1:.4g}", colorMap->getDecodeLow(0) * n, + colorMap->getDecodeHigh(0) * n); + } else if (level == psLevel3Gray) { + writePS("0 1"); + } else { + numComps = colorMap->getNumPixelComps(); + for (i = 0; i < numComps; ++i) { + if (i > 0) { + writePS(" "); + } + writePSFmt("{0:.4g} {1:.4g}", colorMap->getDecodeLow(i), + colorMap->getDecodeHigh(i)); + } + } + writePS("]\n"); + } else { + writePSFmt(" /Decode [{0:d} {1:d}]\n", invert ? 1 : 0, invert ? 0 : 1); + } + + // data source + if (mode == psModeForm || inType3Char || preload) { + writePS(" /DataSource { pdfImStr }\n"); + } else { + writePS(" /DataSource currentfile\n"); + } + + // filters + if ((mode == psModeForm || inType3Char || preload) && + globalParams->getPSUncompressPreloadedImages()) { + s = NULL; + useLZW = useRLE = gFalse; + useCompressed = gFalse; + useASCII = gFalse; + } else { + s = str->getPSFilter(3, " ", !inlineImg); + if ((colorMap && level == psLevel3Gray) || inlineImg || !s) { + if (globalParams->getPSLZW()) { + useLZW = gTrue; + useRLE = gFalse; + } else { + useRLE = gTrue; + useLZW = gFalse; + } + useASCII = !(mode == psModeForm || inType3Char || preload); + useCompressed = gFalse; + } else { + useLZW = useRLE = gFalse; + useASCII = str->isBinary() && + !(mode == psModeForm || inType3Char || preload); + useCompressed = gTrue; + } + } + if (useASCII) { + writePSFmt(" /ASCII{0:s}Decode filter\n", + useASCIIHex ? "Hex" : "85"); + } + if (useLZW) { + writePS(" /LZWDecode filter\n"); + } else if (useRLE) { + writePS(" /RunLengthDecode filter\n"); + } + if (useCompressed) { + writePS(s->getCString()); + } + if (s) { + delete s; + } + + // end of image (data) dictionary + writePS(">>\n"); + + // explicit masking + if (maskStr || (maskColors && colorMap && level == psLevel3Gray)) { + writePS(" /MaskDict\n"); + writePS("<<\n"); + writePS(" /ImageType 1\n"); + writePSFmt(" /Width {0:d}\n", maskWidth); + writePSFmt(" /Height {0:d}\n", maskHeight); + writePSFmt(" /ImageMatrix [{0:d} 0 0 {1:d} 0 {2:d}]\n", + maskWidth, -maskHeight, maskHeight); + writePS(" /BitsPerComponent 1\n"); + writePSFmt(" /Decode [{0:d} {1:d}]\n", + maskInvert ? 1 : 0, maskInvert ? 0 : 1); + + // mask data source + if (mode == psModeForm || inType3Char || preload) { + writePS(" /DataSource {pdfMaskSrc}\n"); + writePS(maskFilters->getCString()); + } else { + writePS(" /DataSource maskStream\n"); + } + delete maskFilters; + + writePS(">>\n"); + writePS(">>\n"); + } + + if (mode == psModeForm || inType3Char || preload) { + + // image command + writePSFmt("{0:s}\n", colorMap ? "image" : "imagemask"); + + } else { + + if (level == psLevel3Sep && colorMap && + colorMap->getColorSpace()->getMode() == csSeparation) { + color.c[0] = gfxColorComp1; + sepCS = (GfxSeparationColorSpace *)colorMap->getColorSpace(); + sepCS->getCMYK(&color, &cmyk, state->getRenderingIntent()); + writePSFmt("{0:.4g} {1:.4g} {2:.4g} {3:.4g} ({4:t}) pdfImSep\n", + colToDbl(cmyk.c), colToDbl(cmyk.m), + colToDbl(cmyk.y), colToDbl(cmyk.k), + sepCS->getName()); + } else { + writePSFmt("{0:s}\n", colorMap ? "pdfIm" : "pdfImM"); + } + + } + + // get rid of the array and index + if (mode == psModeForm || inType3Char || preload) { + writePS("pop pop\n"); + + // image data + } else { + + // cut off inline image streams at appropriate length + if (inlineImg) { + str = new FixedLengthEncoder(str, len); + } else if (useCompressed) { + str = str->getUndecodedStream(); + } + + // recode to grayscale + if (colorMap && level == psLevel3Gray) { + str = new GrayRecoder(str, width, height, colorMap); + } + + // add LZWEncode/RunLengthEncode and ASCIIHex/85 encode filters + if (useLZW) { + str = new LZWEncoder(str); + } else if (useRLE) { + str = new RunLengthEncoder(str); + } + if (useASCII) { + if (useASCIIHex) { + str = new ASCIIHexEncoder(str); + } else { + str = new ASCII85Encoder(str); + } + } + + // copy the stream data + str->reset(); + while ((n = str->getBlock(buf, sizeof(buf))) > 0) { + writePSBlock(buf, n); + } + str->close(); + + // add newline and trailer to the end + writePSChar('\n'); + writePS("%-EOD-\n"); + + // delete encoders + if (useLZW || useRLE || useASCII || inlineImg) { + delete str; + } + } + + // close the mask stream + if (maskStr || (maskColors && colorMap && level == psLevel3Gray)) { + if (!(mode == psModeForm || inType3Char || preload)) { + writePS("pdfMaskEnd\n"); + } + } +} + +void PSOutputDev::dumpColorSpaceL2(GfxState *state, GfxColorSpace *colorSpace, + GBool genXform, GBool updateColors, + GBool map01) { + switch (colorSpace->getMode()) { + case csDeviceGray: + dumpDeviceGrayColorSpace((GfxDeviceGrayColorSpace *)colorSpace, + genXform, updateColors, map01); + break; + case csCalGray: + dumpCalGrayColorSpace((GfxCalGrayColorSpace *)colorSpace, + genXform, updateColors, map01); + break; + case csDeviceRGB: + dumpDeviceRGBColorSpace((GfxDeviceRGBColorSpace *)colorSpace, + genXform, updateColors, map01); + break; + case csCalRGB: + dumpCalRGBColorSpace((GfxCalRGBColorSpace *)colorSpace, + genXform, updateColors, map01); + break; + case csDeviceCMYK: + dumpDeviceCMYKColorSpace((GfxDeviceCMYKColorSpace *)colorSpace, + genXform, updateColors, map01); + break; + case csLab: + dumpLabColorSpace((GfxLabColorSpace *)colorSpace, + genXform, updateColors, map01); + break; + case csICCBased: + dumpICCBasedColorSpace(state, (GfxICCBasedColorSpace *)colorSpace, + genXform, updateColors, map01); + break; + case csIndexed: + dumpIndexedColorSpace(state, (GfxIndexedColorSpace *)colorSpace, + genXform, updateColors, map01); + break; + case csSeparation: + dumpSeparationColorSpace(state, (GfxSeparationColorSpace *)colorSpace, + genXform, updateColors, map01); + break; + case csDeviceN: + if (level >= psLevel3) { + dumpDeviceNColorSpaceL3(state, (GfxDeviceNColorSpace *)colorSpace, + genXform, updateColors, map01); + } else { + dumpDeviceNColorSpaceL2(state, (GfxDeviceNColorSpace *)colorSpace, + genXform, updateColors, map01); + } + break; + case csPattern: + //~ unimplemented + break; + } +} + +void PSOutputDev::dumpDeviceGrayColorSpace(GfxDeviceGrayColorSpace *cs, + GBool genXform, GBool updateColors, + GBool map01) { + writePS("/DeviceGray"); + if (genXform) { + writePS(" {}"); + } + if (updateColors) { + processColors |= psProcessBlack; + } +} + +void PSOutputDev::dumpCalGrayColorSpace(GfxCalGrayColorSpace *cs, + GBool genXform, GBool updateColors, + GBool map01) { + writePS("[/CIEBasedA <<\n"); + writePSFmt(" /DecodeA {{{0:.4g} exp}} bind\n", cs->getGamma()); + writePSFmt(" /MatrixA [{0:.4g} {1:.4g} {2:.4g}]\n", + cs->getWhiteX(), cs->getWhiteY(), cs->getWhiteZ()); + writePSFmt(" /WhitePoint [{0:.4g} {1:.4g} {2:.4g}]\n", + cs->getWhiteX(), cs->getWhiteY(), cs->getWhiteZ()); + writePSFmt(" /BlackPoint [{0:.4g} {1:.4g} {2:.4g}]\n", + cs->getBlackX(), cs->getBlackY(), cs->getBlackZ()); + writePS(">>]"); + if (genXform) { + writePS(" {}"); + } + if (updateColors) { + processColors |= psProcessBlack; + } +} + +void PSOutputDev::dumpDeviceRGBColorSpace(GfxDeviceRGBColorSpace *cs, + GBool genXform, GBool updateColors, + GBool map01) { + writePS("/DeviceRGB"); + if (genXform) { + writePS(" {}"); + } + if (updateColors) { + processColors |= psProcessCMYK; + } +} + +void PSOutputDev::dumpCalRGBColorSpace(GfxCalRGBColorSpace *cs, + GBool genXform, GBool updateColors, + GBool map01) { + writePS("[/CIEBasedABC <<\n"); + writePSFmt(" /DecodeABC [{{{0:.4g} exp}} bind {{{1:.4g} exp}} bind {{{2:.4g} exp}} bind]\n", + cs->getGammaR(), cs->getGammaG(), cs->getGammaB()); + writePSFmt(" /MatrixABC [{0:.4g} {1:.4g} {2:.4g} {3:.4g} {4:.4g} {5:.4g} {6:.4g} {7:.4g} {8:.4g}]\n", + cs->getMatrix()[0], cs->getMatrix()[1], cs->getMatrix()[2], + cs->getMatrix()[3], cs->getMatrix()[4], cs->getMatrix()[5], + cs->getMatrix()[6], cs->getMatrix()[7], cs->getMatrix()[8]); + writePSFmt(" /WhitePoint [{0:.4g} {1:.4g} {2:.4g}]\n", + cs->getWhiteX(), cs->getWhiteY(), cs->getWhiteZ()); + writePSFmt(" /BlackPoint [{0:.4g} {1:.4g} {2:.4g}]\n", + cs->getBlackX(), cs->getBlackY(), cs->getBlackZ()); + writePS(">>]"); + if (genXform) { + writePS(" {}"); + } + if (updateColors) { + processColors |= psProcessCMYK; + } +} + +void PSOutputDev::dumpDeviceCMYKColorSpace(GfxDeviceCMYKColorSpace *cs, + GBool genXform, GBool updateColors, + GBool map01) { + writePS("/DeviceCMYK"); + if (genXform) { + writePS(" {}"); + } + if (updateColors) { + processColors |= psProcessCMYK; + } +} + +void PSOutputDev::dumpLabColorSpace(GfxLabColorSpace *cs, + GBool genXform, GBool updateColors, + GBool map01) { + writePS("[/CIEBasedABC <<\n"); + if (map01) { + writePS(" /RangeABC [0 1 0 1 0 1]\n"); + writePSFmt(" /DecodeABC [{{100 mul 16 add 116 div}} bind {{{0:.4g} mul {1:.4g} add}} bind {{{2:.4g} mul {3:.4g} add}} bind]\n", + (cs->getAMax() - cs->getAMin()) / 500.0, + cs->getAMin() / 500.0, + (cs->getBMax() - cs->getBMin()) / 200.0, + cs->getBMin() / 200.0); + } else { + writePSFmt(" /RangeABC [0 100 {0:.4g} {1:.4g} {2:.4g} {3:.4g}]\n", + cs->getAMin(), cs->getAMax(), + cs->getBMin(), cs->getBMax()); + writePS(" /DecodeABC [{16 add 116 div} bind {500 div} bind {200 div} bind]\n"); + } + writePS(" /MatrixABC [1 1 1 1 0 0 0 0 -1]\n"); + writePS(" /DecodeLMN\n"); + writePS(" [{dup 6 29 div ge {dup dup mul mul}\n"); + writePSFmt(" {{4 29 div sub 108 841 div mul }} ifelse {0:.4g} mul}} bind\n", + cs->getWhiteX()); + writePS(" {dup 6 29 div ge {dup dup mul mul}\n"); + writePSFmt(" {{4 29 div sub 108 841 div mul }} ifelse {0:.4g} mul}} bind\n", + cs->getWhiteY()); + writePS(" {dup 6 29 div ge {dup dup mul mul}\n"); + writePSFmt(" {{4 29 div sub 108 841 div mul }} ifelse {0:.4g} mul}} bind]\n", + cs->getWhiteZ()); + writePSFmt(" /WhitePoint [{0:.4g} {1:.4g} {2:.4g}]\n", + cs->getWhiteX(), cs->getWhiteY(), cs->getWhiteZ()); + writePSFmt(" /BlackPoint [{0:.4g} {1:.4g} {2:.4g}]\n", + cs->getBlackX(), cs->getBlackY(), cs->getBlackZ()); + writePS(">>]"); + if (genXform) { + writePS(" {}"); + } + if (updateColors) { + processColors |= psProcessCMYK; + } +} + +void PSOutputDev::dumpICCBasedColorSpace(GfxState *state, + GfxICCBasedColorSpace *cs, + GBool genXform, GBool updateColors, + GBool map01) { + // there is no transform function to the alternate color space, so + // we can use it directly + dumpColorSpaceL2(state, cs->getAlt(), genXform, updateColors, gFalse); +} + + +void PSOutputDev::dumpIndexedColorSpace(GfxState *state, + GfxIndexedColorSpace *cs, + GBool genXform, GBool updateColors, + GBool map01) { + GfxColorSpace *baseCS; + GfxLabColorSpace *labCS; + Guchar *lookup, *p; + double x[gfxColorMaxComps], y[gfxColorMaxComps]; + double low[gfxColorMaxComps], range[gfxColorMaxComps]; + GfxColor color; + GfxCMYK cmyk; + Function *func; + int n, numComps, numAltComps; + int byte; + int i, j, k; + + baseCS = cs->getBase(); + writePS("[/Indexed "); + dumpColorSpaceL2(state, baseCS, gFalse, updateColors, gTrue); + n = cs->getIndexHigh(); + numComps = baseCS->getNComps(); + lookup = cs->getLookup(); + writePSFmt(" {0:d} <\n", n); + if (baseCS->getMode() == csDeviceN && level < psLevel3) { + func = ((GfxDeviceNColorSpace *)baseCS)->getTintTransformFunc(); + baseCS->getDefaultRanges(low, range, cs->getIndexHigh()); + if (((GfxDeviceNColorSpace *)baseCS)->getAlt()->getMode() == csLab) { + labCS = (GfxLabColorSpace *)((GfxDeviceNColorSpace *)baseCS)->getAlt(); + } else { + labCS = NULL; + } + numAltComps = ((GfxDeviceNColorSpace *)baseCS)->getAlt()->getNComps(); + p = lookup; + for (i = 0; i <= n; i += 8) { + writePS(" "); + for (j = i; j < i+8 && j <= n; ++j) { + for (k = 0; k < numComps; ++k) { + x[k] = low[k] + (*p++ / 255.0) * range[k]; + } + func->transform(x, y); + if (labCS) { + y[0] /= 100.0; + y[1] = (y[1] - labCS->getAMin()) / + (labCS->getAMax() - labCS->getAMin()); + y[2] = (y[2] - labCS->getBMin()) / + (labCS->getBMax() - labCS->getBMin()); + } + for (k = 0; k < numAltComps; ++k) { + byte = (int)(y[k] * 255 + 0.5); + if (byte < 0) { + byte = 0; + } else if (byte > 255) { + byte = 255; + } + writePSFmt("{0:02x}", byte); + } + if (updateColors) { + color.c[0] = dblToCol(j); + cs->getCMYK(&color, &cmyk, state->getRenderingIntent()); + addProcessColor(colToDbl(cmyk.c), colToDbl(cmyk.m), + colToDbl(cmyk.y), colToDbl(cmyk.k)); + } + } + writePS("\n"); + } + } else { + for (i = 0; i <= n; i += 8) { + writePS(" "); + for (j = i; j < i+8 && j <= n; ++j) { + for (k = 0; k < numComps; ++k) { + writePSFmt("{0:02x}", lookup[j * numComps + k]); + } + if (updateColors) { + color.c[0] = dblToCol(j); + cs->getCMYK(&color, &cmyk, state->getRenderingIntent()); + addProcessColor(colToDbl(cmyk.c), colToDbl(cmyk.m), + colToDbl(cmyk.y), colToDbl(cmyk.k)); + } + } + writePS("\n"); + } + } + writePS(">]"); + if (genXform) { + writePS(" {}"); + } +} + +void PSOutputDev::dumpSeparationColorSpace(GfxState *state, + GfxSeparationColorSpace *cs, + GBool genXform, GBool updateColors, + GBool map01) { + writePS("[/Separation "); + writePSString(cs->getName()); + writePS(" "); + dumpColorSpaceL2(state, cs->getAlt(), gFalse, gFalse, gFalse); + writePS("\n"); + cvtFunction(cs->getFunc()); + writePS("]"); + if (genXform) { + writePS(" {}"); + } + if (updateColors) { + addCustomColor(state, cs); + } +} + +void PSOutputDev::dumpDeviceNColorSpaceL2(GfxState *state, + GfxDeviceNColorSpace *cs, + GBool genXform, GBool updateColors, + GBool map01) { + dumpColorSpaceL2(state, cs->getAlt(), gFalse, updateColors, map01); + if (genXform) { + writePS(" "); + cvtFunction(cs->getTintTransformFunc()); + } +} + +void PSOutputDev::dumpDeviceNColorSpaceL3(GfxState *state, + GfxDeviceNColorSpace *cs, + GBool genXform, GBool updateColors, + GBool map01) { + GString *tint; + int i; + + writePS("[/DeviceN [\n"); + for (i = 0; i < cs->getNComps(); ++i) { + writePSString(cs->getColorantName(i)); + writePS("\n"); + } + writePS("]\n"); + if ((tint = createDeviceNTintFunc(cs))) { + writePS("/DeviceCMYK\n"); + writePS(tint->getCString()); + delete tint; + } else { + dumpColorSpaceL2(state, cs->getAlt(), gFalse, gFalse, gFalse); + writePS("\n"); + cvtFunction(cs->getTintTransformFunc()); + } + writePS("]"); + if (genXform) { + writePS(" {}"); + } + if (updateColors) { + addCustomColors(state, cs); + } +} + +// If the DeviceN color space has a Colorants dictionary, and all of +// the colorants are one of: "None", "Cyan", "Magenta", "Yellow", +// "Black", or have an entry in the Colorants dict that maps to +// DeviceCMYK, then build a new tint function; else use the existing +// tint function. +GString *PSOutputDev::createDeviceNTintFunc(GfxDeviceNColorSpace *cs) { + Object *attrs; + Object colorants, sepCSObj, funcObj, obj1; + GString *name; + Function *func; + double sepIn; + double cmyk[gfxColorMaxComps][4]; + GString *tint; + GBool first; + int i, j; + + attrs = cs->getAttrs(); + if (!attrs->isDict()) { + return NULL; + } + if (!attrs->dictLookup("Colorants", &colorants)->isDict()) { + colorants.free(); + return NULL; + } + for (i = 0; i < cs->getNComps(); ++i) { + name = cs->getColorantName(i); + if (!name->cmp("None")) { + cmyk[i][0] = cmyk[i][1] = cmyk[i][2] = cmyk[i][3] = 0; + } else if (!name->cmp("Cyan")) { + cmyk[i][1] = cmyk[i][2] = cmyk[i][3] = 0; + cmyk[i][0] = 1; + } else if (!name->cmp("Magenta")) { + cmyk[i][0] = cmyk[i][2] = cmyk[i][3] = 0; + cmyk[i][1] = 1; + } else if (!name->cmp("Yellow")) { + cmyk[i][0] = cmyk[i][1] = cmyk[i][3] = 0; + cmyk[i][2] = 1; + } else if (!name->cmp("Black")) { + cmyk[i][0] = cmyk[i][1] = cmyk[i][2] = 0; + cmyk[i][3] = 1; + } else { + colorants.dictLookup(name->getCString(), &sepCSObj); + if (!sepCSObj.isArray() || sepCSObj.arrayGetLength() != 4) { + sepCSObj.free(); + colorants.free(); + return NULL; + } + if (!sepCSObj.arrayGet(0, &obj1)->isName("Separation")) { + obj1.free(); + sepCSObj.free(); + colorants.free(); + return NULL; + } + obj1.free(); + if (!sepCSObj.arrayGet(2, &obj1)->isName("DeviceCMYK")) { + obj1.free(); + sepCSObj.free(); + colorants.free(); + return NULL; + } + obj1.free(); + sepCSObj.arrayGet(3, &funcObj); + if (!(func = Function::parse(&funcObj, 1, 4))) { + funcObj.free(); + sepCSObj.free(); + colorants.free(); + return NULL; + } + funcObj.free(); + sepIn = 1; + func->transform(&sepIn, cmyk[i]); + delete func; + sepCSObj.free(); + } + } + colorants.free(); + + tint = new GString(); + tint->append("{\n"); + for (j = 0; j < 4; ++j) { // C, M, Y, K + first = gTrue; + for (i = 0; i < cs->getNComps(); ++i) { + if (cmyk[i][j] != 0) { + tint->appendf("{0:d} index {1:.4f} mul{2:s}\n", + j + cs->getNComps() - 1 - i, cmyk[i][j], + first ? "" : " add"); + first = gFalse; + } + } + if (first) { + tint->append("0\n"); + } + } + tint->appendf("{0:d} 4 roll\n", cs->getNComps() + 4); + for (i = 0; i < cs->getNComps(); ++i) { + tint->append("pop\n"); + } + tint->append("}\n"); + + return tint; +} + +#if OPI_SUPPORT +void PSOutputDev::opiBegin(GfxState *state, Dict *opiDict) { + Object dict; + + if (globalParams->getPSOPI()) { + opiDict->lookup("2.0", &dict); + if (dict.isDict()) { + opiBegin20(state, dict.getDict()); + dict.free(); + } else { + dict.free(); + opiDict->lookup("1.3", &dict); + if (dict.isDict()) { + opiBegin13(state, dict.getDict()); + } + dict.free(); + } + } +} + +void PSOutputDev::opiBegin20(GfxState *state, Dict *dict) { + Object obj1, obj2, obj3, obj4; + double width, height, left, right, top, bottom; + int w, h; + int i; + + writePS("%%BeginOPI: 2.0\n"); + writePS("%%Distilled\n"); + + dict->lookup("F", &obj1); + if (getFileSpec(&obj1, &obj2)) { + writePSFmt("%%ImageFileName: {0:t}\n", obj2.getString()); + obj2.free(); + } + obj1.free(); + + dict->lookup("MainImage", &obj1); + if (obj1.isString()) { + writePSFmt("%%MainImage: {0:t}\n", obj1.getString()); + } + obj1.free(); + + //~ ignoring 'Tags' entry + //~ need to use writePSString() and deal with >255-char lines + + dict->lookup("Size", &obj1); + if (obj1.isArray() && obj1.arrayGetLength() == 2) { + obj1.arrayGet(0, &obj2); + width = obj2.getNum(); + obj2.free(); + obj1.arrayGet(1, &obj2); + height = obj2.getNum(); + obj2.free(); + writePSFmt("%%ImageDimensions: {0:.6g} {1:.6g}\n", width, height); + } + obj1.free(); + + dict->lookup("CropRect", &obj1); + if (obj1.isArray() && obj1.arrayGetLength() == 4) { + obj1.arrayGet(0, &obj2); + left = obj2.getNum(); + obj2.free(); + obj1.arrayGet(1, &obj2); + top = obj2.getNum(); + obj2.free(); + obj1.arrayGet(2, &obj2); + right = obj2.getNum(); + obj2.free(); + obj1.arrayGet(3, &obj2); + bottom = obj2.getNum(); + obj2.free(); + writePSFmt("%%ImageCropRect: {0:.6g} {1:.6g} {2:.6g} {3:.6g}\n", + left, top, right, bottom); + } + obj1.free(); + + dict->lookup("Overprint", &obj1); + if (obj1.isBool()) { + writePSFmt("%%ImageOverprint: {0:s}\n", obj1.getBool() ? "true" : "false"); + } + obj1.free(); + + dict->lookup("Inks", &obj1); + if (obj1.isName()) { + writePSFmt("%%ImageInks: {0:s}\n", obj1.getName()); + } else if (obj1.isArray() && obj1.arrayGetLength() >= 1) { + obj1.arrayGet(0, &obj2); + if (obj2.isName()) { + writePSFmt("%%ImageInks: {0:s} {1:d}", + obj2.getName(), (obj1.arrayGetLength() - 1) / 2); + for (i = 1; i+1 < obj1.arrayGetLength(); i += 2) { + obj1.arrayGet(i, &obj3); + obj1.arrayGet(i+1, &obj4); + if (obj3.isString() && obj4.isNum()) { + writePS(" "); + writePSString(obj3.getString()); + writePSFmt(" {0:.4g}", obj4.getNum()); + } + obj3.free(); + obj4.free(); + } + writePS("\n"); + } + obj2.free(); + } + obj1.free(); + + writePS("gsave\n"); + + writePS("%%BeginIncludedImage\n"); + + dict->lookup("IncludedImageDimensions", &obj1); + if (obj1.isArray() && obj1.arrayGetLength() == 2) { + obj1.arrayGet(0, &obj2); + w = obj2.getInt(); + obj2.free(); + obj1.arrayGet(1, &obj2); + h = obj2.getInt(); + obj2.free(); + writePSFmt("%%IncludedImageDimensions: {0:d} {1:d}\n", w, h); + } + obj1.free(); + + dict->lookup("IncludedImageQuality", &obj1); + if (obj1.isNum()) { + writePSFmt("%%IncludedImageQuality: {0:.4g}\n", obj1.getNum()); + } + obj1.free(); + + ++opi20Nest; +} + +void PSOutputDev::opiBegin13(GfxState *state, Dict *dict) { + Object obj1, obj2; + int left, right, top, bottom, samples, bits, width, height; + double c, m, y, k; + double llx, lly, ulx, uly, urx, ury, lrx, lry; + double tllx, tlly, tulx, tuly, turx, tury, tlrx, tlry; + double horiz, vert; + int i, j; + + writePS("save\n"); + writePS("/opiMatrix2 matrix currentmatrix def\n"); + writePS("opiMatrix setmatrix\n"); + + dict->lookup("F", &obj1); + if (getFileSpec(&obj1, &obj2)) { + writePSFmt("%ALDImageFileName: {0:t}\n", obj2.getString()); + obj2.free(); + } + obj1.free(); + + dict->lookup("CropRect", &obj1); + if (obj1.isArray() && obj1.arrayGetLength() == 4) { + obj1.arrayGet(0, &obj2); + left = obj2.getInt(); + obj2.free(); + obj1.arrayGet(1, &obj2); + top = obj2.getInt(); + obj2.free(); + obj1.arrayGet(2, &obj2); + right = obj2.getInt(); + obj2.free(); + obj1.arrayGet(3, &obj2); + bottom = obj2.getInt(); + obj2.free(); + writePSFmt("%ALDImageCropRect: {0:d} {1:d} {2:d} {3:d}\n", + left, top, right, bottom); + } + obj1.free(); + + dict->lookup("Color", &obj1); + if (obj1.isArray() && obj1.arrayGetLength() == 5) { + obj1.arrayGet(0, &obj2); + c = obj2.getNum(); + obj2.free(); + obj1.arrayGet(1, &obj2); + m = obj2.getNum(); + obj2.free(); + obj1.arrayGet(2, &obj2); + y = obj2.getNum(); + obj2.free(); + obj1.arrayGet(3, &obj2); + k = obj2.getNum(); + obj2.free(); + obj1.arrayGet(4, &obj2); + if (obj2.isString()) { + writePSFmt("%ALDImageColor: {0:.4g} {1:.4g} {2:.4g} {3:.4g} ", + c, m, y, k); + writePSString(obj2.getString()); + writePS("\n"); + } + obj2.free(); + } + obj1.free(); + + dict->lookup("ColorType", &obj1); + if (obj1.isName()) { + writePSFmt("%ALDImageColorType: {0:s}\n", obj1.getName()); + } + obj1.free(); + + //~ ignores 'Comments' entry + //~ need to handle multiple lines + + dict->lookup("CropFixed", &obj1); + if (obj1.isArray()) { + obj1.arrayGet(0, &obj2); + ulx = obj2.getNum(); + obj2.free(); + obj1.arrayGet(1, &obj2); + uly = obj2.getNum(); + obj2.free(); + obj1.arrayGet(2, &obj2); + lrx = obj2.getNum(); + obj2.free(); + obj1.arrayGet(3, &obj2); + lry = obj2.getNum(); + obj2.free(); + writePSFmt("%ALDImageCropFixed: {0:.4g} {1:.4g} {2:.4g} {3:.4g}\n", + ulx, uly, lrx, lry); + } + obj1.free(); + + dict->lookup("GrayMap", &obj1); + if (obj1.isArray()) { + writePS("%ALDImageGrayMap:"); + for (i = 0; i < obj1.arrayGetLength(); i += 16) { + if (i > 0) { + writePS("\n%%+"); + } + for (j = 0; j < 16 && i+j < obj1.arrayGetLength(); ++j) { + obj1.arrayGet(i+j, &obj2); + writePSFmt(" {0:d}", obj2.getInt()); + obj2.free(); + } + } + writePS("\n"); + } + obj1.free(); + + dict->lookup("ID", &obj1); + if (obj1.isString()) { + writePSFmt("%ALDImageID: {0:t}\n", obj1.getString()); + } + obj1.free(); + + dict->lookup("ImageType", &obj1); + if (obj1.isArray() && obj1.arrayGetLength() == 2) { + obj1.arrayGet(0, &obj2); + samples = obj2.getInt(); + obj2.free(); + obj1.arrayGet(1, &obj2); + bits = obj2.getInt(); + obj2.free(); + writePSFmt("%ALDImageType: {0:d} {1:d}\n", samples, bits); + } + obj1.free(); + + dict->lookup("Overprint", &obj1); + if (obj1.isBool()) { + writePSFmt("%ALDImageOverprint: {0:s}\n", + obj1.getBool() ? "true" : "false"); + } + obj1.free(); + + dict->lookup("Position", &obj1); + if (obj1.isArray() && obj1.arrayGetLength() == 8) { + obj1.arrayGet(0, &obj2); + llx = obj2.getNum(); + obj2.free(); + obj1.arrayGet(1, &obj2); + lly = obj2.getNum(); + obj2.free(); + obj1.arrayGet(2, &obj2); + ulx = obj2.getNum(); + obj2.free(); + obj1.arrayGet(3, &obj2); + uly = obj2.getNum(); + obj2.free(); + obj1.arrayGet(4, &obj2); + urx = obj2.getNum(); + obj2.free(); + obj1.arrayGet(5, &obj2); + ury = obj2.getNum(); + obj2.free(); + obj1.arrayGet(6, &obj2); + lrx = obj2.getNum(); + obj2.free(); + obj1.arrayGet(7, &obj2); + lry = obj2.getNum(); + obj2.free(); + opiTransform(state, llx, lly, &tllx, &tlly); + opiTransform(state, ulx, uly, &tulx, &tuly); + opiTransform(state, urx, ury, &turx, &tury); + opiTransform(state, lrx, lry, &tlrx, &tlry); + writePSFmt("%ALDImagePosition: {0:.4g} {1:.4g} {2:.4g} {3:.4g} {4:.4g} {5:.4g} {6:.4g} {7:.4g}\n", + tllx, tlly, tulx, tuly, turx, tury, tlrx, tlry); + obj2.free(); + } + obj1.free(); + + dict->lookup("Resolution", &obj1); + if (obj1.isArray() && obj1.arrayGetLength() == 2) { + obj1.arrayGet(0, &obj2); + horiz = obj2.getNum(); + obj2.free(); + obj1.arrayGet(1, &obj2); + vert = obj2.getNum(); + obj2.free(); + writePSFmt("%ALDImageResoution: {0:.4g} {1:.4g}\n", horiz, vert); + obj2.free(); + } + obj1.free(); + + dict->lookup("Size", &obj1); + if (obj1.isArray() && obj1.arrayGetLength() == 2) { + obj1.arrayGet(0, &obj2); + width = obj2.getInt(); + obj2.free(); + obj1.arrayGet(1, &obj2); + height = obj2.getInt(); + obj2.free(); + writePSFmt("%ALDImageDimensions: {0:d} {1:d}\n", width, height); + } + obj1.free(); + + //~ ignoring 'Tags' entry + //~ need to use writePSString() and deal with >255-char lines + + dict->lookup("Tint", &obj1); + if (obj1.isNum()) { + writePSFmt("%ALDImageTint: {0:.4g}\n", obj1.getNum()); + } + obj1.free(); + + dict->lookup("Transparency", &obj1); + if (obj1.isBool()) { + writePSFmt("%ALDImageTransparency: {0:s}\n", + obj1.getBool() ? "true" : "false"); + } + obj1.free(); + + writePS("%%BeginObject: image\n"); + writePS("opiMatrix2 setmatrix\n"); + ++opi13Nest; +} + +// Convert PDF user space coordinates to PostScript default user space +// coordinates. This has to account for both the PDF CTM and the +// PSOutputDev page-fitting transform. +void PSOutputDev::opiTransform(GfxState *state, double x0, double y0, + double *x1, double *y1) { + double t; + + state->transform(x0, y0, x1, y1); + *x1 += tx; + *y1 += ty; + if (rotate == 90) { + t = *x1; + *x1 = -*y1; + *y1 = t; + } else if (rotate == 180) { + *x1 = -*x1; + *y1 = -*y1; + } else if (rotate == 270) { + t = *x1; + *x1 = *y1; + *y1 = -t; + } + *x1 *= xScale; + *y1 *= yScale; +} + +void PSOutputDev::opiEnd(GfxState *state, Dict *opiDict) { + Object dict; + + if (globalParams->getPSOPI()) { + opiDict->lookup("2.0", &dict); + if (dict.isDict()) { + writePS("%%EndIncludedImage\n"); + writePS("%%EndOPI\n"); + writePS("grestore\n"); + --opi20Nest; + dict.free(); + } else { + dict.free(); + opiDict->lookup("1.3", &dict); + if (dict.isDict()) { + writePS("%%EndObject\n"); + writePS("restore\n"); + --opi13Nest; + } + dict.free(); + } + } +} + +GBool PSOutputDev::getFileSpec(Object *fileSpec, Object *fileName) { + if (fileSpec->isString()) { + fileSpec->copy(fileName); + return gTrue; + } + if (fileSpec->isDict()) { + fileSpec->dictLookup("DOS", fileName); + if (fileName->isString()) { + return gTrue; + } + fileName->free(); + fileSpec->dictLookup("Mac", fileName); + if (fileName->isString()) { + return gTrue; + } + fileName->free(); + fileSpec->dictLookup("Unix", fileName); + if (fileName->isString()) { + return gTrue; + } + fileName->free(); + fileSpec->dictLookup("F", fileName); + if (fileName->isString()) { + return gTrue; + } + fileName->free(); + } + return gFalse; +} +#endif // OPI_SUPPORT + +void PSOutputDev::type3D0(GfxState *state, double wx, double wy) { + writePSFmt("{0:.6g} {1:.6g} setcharwidth\n", wx, wy); + writePS("q\n"); + t3NeedsRestore = gTrue; + noStateChanges = gFalse; +} + +void PSOutputDev::type3D1(GfxState *state, double wx, double wy, + double llx, double lly, double urx, double ury) { + if (t3String) { + error(errSyntaxError, -1, "Multiple 'd1' operators in Type 3 CharProc"); + return; + } + t3WX = wx; + t3WY = wy; + t3LLX = llx; + t3LLY = lly; + t3URX = urx; + t3URY = ury; + t3String = new GString(); + writePS("q\n"); + t3FillColorOnly = gTrue; + t3Cacheable = gTrue; + t3NeedsRestore = gTrue; + noStateChanges = gFalse; +} + +void PSOutputDev::drawForm(Ref id) { + writePSFmt("f_{0:d}_{1:d}\n", id.num, id.gen); + noStateChanges = gFalse; +} + +void PSOutputDev::psXObject(Stream *psStream, Stream *level1Stream) { + Stream *str; + char buf[4096]; + int n; + + if ((level == psLevel1 || level == psLevel1Sep) && level1Stream) { + str = level1Stream; + } else { + str = psStream; + } + str->reset(); + while ((n = str->getBlock(buf, sizeof(buf))) > 0) { + writePSBlock(buf, n); + } + str->close(); + noStateChanges = gFalse; +} + +//~ can nextFunc be reset to 0 -- maybe at the start of each page? +//~ or maybe at the start of each color space / pattern? +void PSOutputDev::cvtFunction(Function *func) { + SampledFunction *func0; + ExponentialFunction *func2; + StitchingFunction *func3; + PostScriptFunction *func4; + int thisFunc, m, n, nSamples, i, j, k; + + switch (func->getType()) { + + case -1: // identity + writePS("{}\n"); + break; + + case 0: // sampled + func0 = (SampledFunction *)func; + thisFunc = nextFunc++; + m = func0->getInputSize(); + n = func0->getOutputSize(); + nSamples = n; + for (i = 0; i < m; ++i) { + nSamples *= func0->getSampleSize(i); + } + writePSFmt("/xpdfSamples{0:d} [\n", thisFunc); + for (i = 0; i < nSamples; ++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:.6g} sub {1:.6g} mul {2:.6g} add\n", + func0->getDomainMin(i), + (func0->getEncodeMax(i) - func0->getEncodeMin(i)) / + (func0->getDomainMax(i) - func0->getDomainMin(i)), + func0->getEncodeMin(i)); + // [e01] [efrac] x0 x1 ... xi-1 xi' + writePSFmt("dup 0 lt {{ pop 0 }} {{ dup {0:d} gt {{ pop {1:d} }} if }} ifelse\n", + func0->getSampleSize(i) - 1, func0->getSampleSize(i) - 1); + // [e01] [efrac] x0 x1 ... xi-1 xi' + writePS("dup floor cvi exch dup ceiling cvi exch 2 index sub\n"); + // [e01] [efrac] x0 x1 ... xi-1 floor(xi') ceiling(xi') xi'-floor(xi') + writePSFmt("{0:d} index {1:d} 3 2 roll put\n", i+3, i); + // [e01] [efrac] x0 x1 ... xi-1 floor(xi') ceiling(xi') + writePSFmt("{0:d} index {1:d} 3 2 roll put\n", i+3, 2*i+1); + // [e01] [efrac] x0 x1 ... xi-1 floor(xi') + writePSFmt("{0:d} index {1:d} 3 2 roll put\n", i+2, 2*i); + // [e01] [efrac] x0 x1 ... xi-1 + } + // [e01] [efrac] + for (i = 0; i < n; ++i) { + // [e01] [efrac] y(0) ... y(i-1) + for (j = 0; j < (1<> k) & 1)); + for (k = m - 2; k >= 0; --k) { + writePSFmt("{0:d} mul {1:d} index {2:d} get add\n", + func0->getSampleSize(k), + i + j + 3, + 2 * k + ((j >> k) & 1)); + } + if (n > 1) { + writePSFmt("{0:d} mul {1:d} add ", n, i); + } + writePS("get\n"); + } + // [e01] [efrac] y(0) ... y(i-1) s(0) s(1) ... s(2^m-1) + for (j = 0; j < m; ++j) { + // [e01] [efrac] y(0) ... y(i-1) s(0) s(1) ... s(2^(m-j)-1) + for (k = 0; k < (1 << (m - j)); k += 2) { + // [e01] [efrac] y(0) ... y(i-1) <2^(m-j)-k s values> + 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); + } + // [e01] [efrac] s'(0) s'(1) ... s(2^(m-j-1)-1) + } + // [e01] [efrac] y(0) ... y(i-1) s + writePSFmt("{0:.6g} mul {1:.6g} add\n", + func0->getDecodeMax(i) - func0->getDecodeMin(i), + func0->getDecodeMin(i)); + 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) + } + // [e01] [efrac] y(0) ... y(n-1) + writePSFmt("{0:d} {1:d} roll pop pop }}\n", n+2, n); + break; + + case 2: // exponential + func2 = (ExponentialFunction *)func; + n = func2->getOutputSize(); + 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:.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:.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)); + } + } + // x y(0) .. y(n-1) + writePSFmt("{0:d} {1:d} roll pop }}\n", n+1, n); + break; + + case 3: // stitching + func3 = (StitchingFunction *)func; + thisFunc = nextFunc++; + for (i = 0; i < func3->getNumFuncs(); ++i) { + cvtFunction(func3->getFunc(i)); + writePSFmt("/xpdfFunc{0:d}_{1:d} exch def\n", thisFunc, i); + } + 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:.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:.6g} sub {1:.6g} mul {2:.6g} add xpdfFunc{3:d}_{4:d}\n", + func3->getBounds()[i], + func3->getScale()[i], + func3->getEncode()[2*i], + thisFunc, i); + for (i = 0; i < func3->getNumFuncs() - 1; ++i) { + writePS("} ifelse\n"); + } + writePS("}\n"); + break; + + case 4: // PostScript + func4 = (PostScriptFunction *)func; + writePS(func4->getCodeString()->getCString()); + writePS("\n"); + break; + } +} + +void PSOutputDev::writePSChar(char c) { + if (t3String) { + t3String->append(c); + } else { + (*outputFunc)(outputStream, &c, 1); + } +} + +void PSOutputDev::writePSBlock(char *s, int len) { + if (t3String) { + t3String->append(s, len); + } else { + (*outputFunc)(outputStream, s, len); + } +} + +void PSOutputDev::writePS(const char *s) { + if (t3String) { + t3String->append(s); + } else { + (*outputFunc)(outputStream, s, (int)strlen(s)); + } +} + +void PSOutputDev::writePSFmt(const char *fmt, ...) { + va_list args; + GString *buf; + + va_start(args, fmt); + if (t3String) { + t3String->appendfv((char *)fmt, args); + } else { + buf = GString::formatv((char *)fmt, args); + (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); + delete buf; + } + va_end(args); +} + +void PSOutputDev::writePSString(GString *s) { + Guchar *p; + int n, line; + char buf[8]; + + writePSChar('('); + line = 1; + for (p = (Guchar *)s->getCString(), n = s->getLength(); n; ++p, --n) { + if (line >= 64) { + writePSChar('\\'); + writePSChar('\n'); + line = 0; + } + if (*p == '(' || *p == ')' || *p == '\\') { + writePSChar('\\'); + writePSChar((char)*p); + line += 2; + } else if (*p < 0x20 || *p >= 0x80) { + snprintf(buf, sizeof(buf), "\\%03o", *p); + writePS(buf); + line += 4; + } else { + writePSChar((char)*p); + ++line; + } + } + writePSChar(')'); +} + +void PSOutputDev::writePSName(const char *s) { + const char *p; + char c; + + p = s; + while ((c = *p++)) { + if (c <= (char)0x20 || c >= (char)0x7f || + c == '(' || c == ')' || c == '<' || c == '>' || + c == '[' || c == ']' || c == '{' || c == '}' || + c == '/' || c == '%') { + writePSFmt("#{0:02x}", c & 0xff); + } else { + writePSChar(c); + } + } +} + +GString *PSOutputDev::filterPSName(GString *name) { + GString *name2; + char buf[8]; + int i; + char c; + + name2 = new GString(); + + // ghostscript chokes on names that begin with out-of-limits + // numbers, e.g., 1e4foo is handled correctly (as a name), but + // 1e999foo generates a limitcheck error + c = name->getChar(0); + if (c >= '0' && c <= '9') { + name2->append('f'); + } + + for (i = 0; i < name->getLength(); ++i) { + c = name->getChar(i); + if (c <= (char)0x20 || c >= (char)0x7f || + c == '(' || c == ')' || c == '<' || c == '>' || + c == '[' || c == ']' || c == '{' || c == '}' || + c == '/' || c == '%') { + snprintf(buf, sizeof(buf), "#%02x", c & 0xff); + name2->append(buf); + } else { + name2->append(c); + } + } + return name2; +} + +// Write a DSC-compliant . +void PSOutputDev::writePSTextLine(GString *s) { + TextString *ts; + Unicode *u; + int i, j; + int c; + + // - DSC comments must be printable ASCII; control chars and + // backslashes have to be escaped (we do cheap Unicode-to-ASCII + // conversion by simply ignoring the high byte) + // - lines are limited to 255 chars (we limit to 200 here to allow + // for the keyword, which was emitted by the caller) + // - lines that start with a left paren are treated as + // instead of , so we escape a leading paren + ts = new TextString(s); + u = ts->getUnicode(); + for (i = 0, j = 0; i < ts->getLength() && j < 200; ++i) { + c = u[i] & 0xff; + if (c == '\\') { + writePS("\\\\"); + j += 2; + } else if (c < 0x20 || c > 0x7e || (j == 0 && c == '(')) { + writePSFmt("\\{0:03o}", c); + j += 4; + } else { + writePSChar((char)c); + ++j; + } + } + writePS("\n"); + delete ts; +} diff --git a/xpdf/PSOutputDev.h b/xpdf/PSOutputDev.h new file mode 100644 index 0000000..b7223c6 --- /dev/null +++ b/xpdf/PSOutputDev.h @@ -0,0 +1,513 @@ +//======================================================================== +// +// PSOutputDev.h +// +// Copyright 1996-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef PSOUTPUTDEV_H +#define PSOUTPUTDEV_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include +#include "config.h" +#include "Object.h" +#include "GlobalParams.h" +#include "OutputDev.h" + +class GHash; +class PDFDoc; +class XRef; +class Function; +class GfxPath; +class GfxFont; +class GfxColorSpace; +class GfxDeviceGrayColorSpace; +class GfxCalGrayColorSpace; +class GfxDeviceRGBColorSpace; +class GfxCalRGBColorSpace; +class GfxDeviceCMYKColorSpace; +class GfxLabColorSpace; +class GfxICCBasedColorSpace; +class GfxIndexedColorSpace; +class GfxSeparationColorSpace; +class GfxDeviceNColorSpace; +class GfxFunctionShading; +class GfxAxialShading; +class GfxRadialShading; +class PDFRectangle; +class PSOutCustomColor; +class PSOutputDev; +class PSFontFileInfo; + +//------------------------------------------------------------------------ +// PSOutputDev +//------------------------------------------------------------------------ + +enum PSOutMode { + psModePS, + psModeEPS, + psModeForm +}; + +enum PSFileType { + psFile, // write to file + psPipe, // write to pipe + psStdout, // write to stdout + psGeneric // write to a generic stream +}; + +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, PDFDoc *docA, + int firstPageA, int lastPageA, PSOutMode modeA, + int imgLLXA = 0, int imgLLYA = 0, + int imgURXA = 0, int imgURYA = 0, + GBool manualCtrlA = gFalse, + PSOutCustomCodeCbk customCodeCbkA = NULL, + void *customCodeCbkDataA = NULL, + GBool honorUserUnitA = gFalse, + GBool fileNameIsUTF8 = gFalse); + + // Open a PSOutputDev that will write to a generic stream. + PSOutputDev(PSOutputFunc outputFuncA, void *outputStreamA, + PDFDoc *docA, + int firstPageA, int lastPageA, PSOutMode modeA, + int imgLLXA = 0, int imgLLYA = 0, + int imgURXA = 0, int imgURYA = 0, + GBool manualCtrlA = gFalse, + PSOutCustomCodeCbk customCodeCbkA = NULL, + void *customCodeCbkDataA = NULL, + GBool honorUserUnitA = gFalse); + + // Destructor -- writes the trailer and closes the file. + virtual ~PSOutputDev(); + + // Check if file was successfully created. + virtual GBool isOk() { return ok; } + + // Returns false if there have been any errors on the output stream. + GBool checkIO(); + + //---- get info about output device + + // Does this device use upside-down coordinates? + // (Upside-down means (0,0) is the top left corner of the page.) + virtual GBool upsideDown() { return gFalse; } + + // Does this device use drawChar() or drawString()? + virtual GBool useDrawChar() { return gFalse; } + + // 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 drawForm()? If this returns false, + // form-type XObjects will be interpreted (i.e., unrolled). + virtual GBool useDrawForm() { return preload; } + + // Does this device use beginType3Char/endType3Char? Otherwise, + // text in Type 3 fonts will be drawn with drawChar/drawString. + virtual GBool interpretType3Chars() { return gFalse; } + + //----- header/trailer (used only if manualCtrl is true) + + // Write the document-level header. + void writeHeader(PDFRectangle *mediaBox, PDFRectangle *cropBox, + int pageRotate); + + // Write the Xpdf procset. + void writeXpdfProcset(); + + // Write the document-level setup. + void writeDocSetup(Catalog *catalog); + + // Write the trailer for the current page. + void writePageTrailer(); + + // Write the document trailer. + void writeTrailer(); + + //----- initialization and control + + // Check to see if a page slice should be displayed. If this + // returns false, the page display is aborted. Typically, an + // OutputDev will use some alternate means to display the page + // before returning false. + virtual GBool checkPageSlice(Page *page, double hDPI, double vDPI, + int rotate, GBool useMediaBox, GBool crop, + int sliceX, int sliceY, int sliceW, int sliceH, + GBool printing, + GBool (*abortCheckCbk)(void *data) = NULL, + void *abortCheckCbkData = NULL); + + // Start a page. + virtual void startPage(int pageNum, GfxState *state); + + // End a page. + virtual void endPage(); + + //----- save/restore graphics state + virtual void saveState(GfxState *state); + virtual void restoreState(GfxState *state); + + //----- update graphics state + virtual void updateCTM(GfxState *state, double m11, double m12, + double m21, double m22, double m31, double m32); + virtual void updateLineDash(GfxState *state); + virtual void updateFlatness(GfxState *state); + virtual void updateLineJoin(GfxState *state); + virtual void updateLineCap(GfxState *state); + virtual void updateMiterLimit(GfxState *state); + virtual void updateLineWidth(GfxState *state); + virtual void updateFillColorSpace(GfxState *state); + virtual void updateStrokeColorSpace(GfxState *state); + virtual void updateFillColor(GfxState *state); + virtual void updateStrokeColor(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 + virtual void updateFont(GfxState *state); + virtual void updateTextMat(GfxState *state); + virtual void updateCharSpace(GfxState *state); + virtual void updateRender(GfxState *state); + virtual void updateRise(GfxState *state); + virtual void updateWordSpace(GfxState *state); + 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, Gfx *gfx, Object *strRef, + int paintType, int tilingType, Dict *resDict, + double *mat, double *bbox, + int x0, int y0, int x1, int y1, + double xStep, double yStep); + virtual GBool shadedFill(GfxState *state, GfxShading *shading); + + //----- path clipping + virtual void clip(GfxState *state); + virtual void eoClip(GfxState *state); + virtual void clipToStrokePath(GfxState *state); + + //----- text drawing + virtual void drawString(GfxState *state, GString *s); + virtual void endTextObject(GfxState *state); + + //----- image drawing + virtual void drawImageMask(GfxState *state, Object *ref, Stream *str, + int width, int height, GBool invert, + GBool inlineImg, GBool interpolate); + virtual void drawImage(GfxState *state, Object *ref, Stream *str, + int width, int height, GfxImageColorMap *colorMap, + int *maskColors, GBool inlineImg, GBool interpolate); + virtual void drawMaskedImage(GfxState *state, Object *ref, Stream *str, + int width, int height, + GfxImageColorMap *colorMap, + Object *maskRef, Stream *maskStr, + int maskWidth, int maskHeight, + GBool maskInvert, GBool interpolate); + +#if OPI_SUPPORT + //----- OPI functions + virtual void opiBegin(GfxState *state, Dict *opiDict); + virtual void opiEnd(GfxState *state, Dict *opiDict); +#endif + + //----- Type 3 font operators + virtual void type3D0(GfxState *state, double wx, double wy); + virtual void type3D1(GfxState *state, double wx, double wy, + double llx, double lly, double urx, double ury); + + //----- form XObjects + virtual void drawForm(Ref ref); + + //----- PostScript XObjects + virtual void psXObject(Stream *psStream, Stream *level1Stream); + + //----- miscellaneous + void setImageableArea(int imgLLXA, int imgLLYA, int imgURXA, int imgURYA) + { imgLLX = imgLLXA; imgLLY = imgLLYA; imgURX = imgURXA; imgURY = imgURYA; } + void setOffset(double x, double y) + { tx0 = x; ty0 = y; } + void setScale(double x, double y) + { xScale0 = x; yScale0 = y; } + void setRotate(int rotateA) + { rotate0 = rotateA; } + void setClip(double llx, double lly, double urx, double ury) + { clipLLX0 = llx; clipLLY0 = lly; clipURX0 = urx; clipURY0 = ury; } + void setExpandSmallPages(GBool expand) + { expandSmallPages = expand; } + void setUnderlayCbk(void (*cbk)(PSOutputDev *psOut, void *data), + void *data) + { underlayCbk = cbk; underlayCbkData = data; } + void setOverlayCbk(void (*cbk)(PSOutputDev *psOut, void *data), + void *data) + { overlayCbk = cbk; overlayCbkData = data; } + + void writePSChar(char c); + void writePSBlock(char *s, int len); + void writePS(const char *s); + void writePSFmt(const char *fmt, ...); + void writePSString(GString *s); + void writePSName(const char *s); + +private: + + void init(PSOutputFunc outputFuncA, void *outputStreamA, + PSFileType fileTypeA, PDFDoc *docA, + int firstPageA, int lastPageA, PSOutMode modeA, + int imgLLXA, int imgLLYA, int imgURXA, int imgURYA, + GBool manualCtrlA, GBool honorUserUnitA); + GBool checkIfPageNeedsToBeRasterized(int pg); + void setupResources(Dict *resDict); + void setupFonts(Dict *resDict); + void setupFont(GfxFont *font, Dict *parentResDict); + PSFontFileInfo *setupEmbeddedType1Font(GfxFont *font, Ref *id); + PSFontFileInfo *setupExternalType1Font(GfxFont *font, GString *fileName); + PSFontFileInfo *setupEmbeddedType1CFont(GfxFont *font, Ref *id); + PSFontFileInfo *setupEmbeddedOpenTypeT1CFont(GfxFont *font, Ref *id); + PSFontFileInfo *setupEmbeddedTrueTypeFont(GfxFont *font, Ref *id); + PSFontFileInfo *setupExternalTrueTypeFont(GfxFont *font, GString *fileName, + int fontNum); + PSFontFileInfo *setupEmbeddedCIDType0Font(GfxFont *font, Ref *id); + PSFontFileInfo *setupEmbeddedCIDTrueTypeFont(GfxFont *font, Ref *id, + GBool needVerticalMetrics); + PSFontFileInfo *setupExternalCIDTrueTypeFont(GfxFont *font, + GString *fileName, + int fontNum, + GBool needVerticalMetrics); + PSFontFileInfo *setupEmbeddedOpenTypeCFFFont(GfxFont *font, Ref *id); + PSFontFileInfo *setupExternalOpenTypeCFFFont(GfxFont *font, + GString *fileName); + PSFontFileInfo *setupType3Font(GfxFont *font, Dict *parentResDict); + GString *makePSFontName(GfxFont *font, Ref *id); + GString *fixType1Font(GString *font, int length1, int length2); + GBool splitType1PFA(Guchar *font, int fontSize, + int length1, int length2, + GString *textSection, GString *binSection); + GBool splitType1PFB(Guchar *font, int fontSize, + GString *textSection, GString *binSection); + GString *asciiHexDecodeType1EexecSection(GString *in); + GBool fixType1EexecSection(GString *binSection, GString *out); + GString *copyType1PFA(Guchar *font, int fontSize); + GString *copyType1PFB(Guchar *font, int fontSize); + void renameType1Font(GString *font, GString *name); + void setupDefaultFont(); + void setupImages(Dict *resDict); + void setupImage(Ref id, Stream *str, GBool mask, Array *colorKeyMask); + void setupForms(Dict *resDict); + void setupForm(Object *strRef, Object *strObj); + void addProcessColor(double c, double m, double y, double k); + void addCustomColor(GfxState *state, GfxSeparationColorSpace *sepCS); + void addCustomColors(GfxState *state, GfxDeviceNColorSpace *devnCS); + void tilingPatternFillL1(GfxState *state, Gfx *gfx, Object *strRef, + int paintType, int tilingType, Dict *resDict, + double *mat, double *bbox, + int x0, int y0, int x1, int y1, + double xStep, double yStep); + void tilingPatternFillL2(GfxState *state, Gfx *gfx, Object *strRef, + int paintType, int tilingType, Dict *resDict, + double *mat, double *bbox, + int x0, int y0, int x1, int y1, + double xStep, double yStep); + GBool functionShadedFill(GfxState *state, + GfxFunctionShading *shading); + GBool axialShadedFill(GfxState *state, GfxAxialShading *shading); + GBool radialShadedFill(GfxState *state, GfxRadialShading *shading); + void doPath(GfxPath *path); + void doImageL1(Object *ref, GfxState *state, + GfxImageColorMap *colorMap, + GBool invert, GBool inlineImg, + Stream *str, int width, int height, int len); + void doImageL1Sep(GfxState *state, GfxImageColorMap *colorMap, + GBool invert, GBool inlineImg, + Stream *str, int width, int height, int len); + void doImageL2(Object *ref, GfxState *state, + GfxImageColorMap *colorMap, + GBool invert, GBool inlineImg, + Stream *str, int width, int height, int len, + int *maskColors, Stream *maskStr, + int maskWidth, int maskHeight, GBool maskInvert); + void convertColorKeyMaskToClipRects(GfxImageColorMap *colorMap, + Stream *str, + int width, int height, + int *maskColors); + void convertExplicitMaskToClipRects(Stream *maskStr, + int maskWidth, int maskHeight, + GBool maskInvert); + void doImageL3(Object *ref, GfxState *state, + GfxImageColorMap *colorMap, + GBool invert, GBool inlineImg, + Stream *str, int width, int height, int len, + int *maskColors, Stream *maskStr, + int maskWidth, int maskHeight, GBool maskInvert); + void dumpColorSpaceL2(GfxState *state, GfxColorSpace *colorSpace, + GBool genXform, GBool updateColors, + GBool map01); + void dumpDeviceGrayColorSpace(GfxDeviceGrayColorSpace *cs, + GBool genXform, GBool updateColors, + GBool map01); + void dumpCalGrayColorSpace(GfxCalGrayColorSpace *cs, + GBool genXform, GBool updateColors, + GBool map01); + void dumpDeviceRGBColorSpace(GfxDeviceRGBColorSpace *cs, + GBool genXform, GBool updateColors, + GBool map01); + void dumpCalRGBColorSpace(GfxCalRGBColorSpace *cs, + GBool genXform, GBool updateColors, + GBool map01); + void dumpDeviceCMYKColorSpace(GfxDeviceCMYKColorSpace *cs, + GBool genXform, GBool updateColors, + GBool map01); + void dumpLabColorSpace(GfxLabColorSpace *cs, + GBool genXform, GBool updateColors, + GBool map01); + void dumpICCBasedColorSpace(GfxState *state, GfxICCBasedColorSpace *cs, + GBool genXform, GBool updateColors, + GBool map01); + void dumpIndexedColorSpace(GfxState *state, + GfxIndexedColorSpace *cs, + GBool genXform, GBool updateColors, + GBool map01); + void dumpSeparationColorSpace(GfxState *state, + GfxSeparationColorSpace *cs, + GBool genXform, GBool updateColors, + GBool map01); + void dumpDeviceNColorSpaceL2(GfxState *state, GfxDeviceNColorSpace *cs, + GBool genXform, GBool updateColors, + GBool map01); + void dumpDeviceNColorSpaceL3(GfxState *state, GfxDeviceNColorSpace *cs, + GBool genXform, GBool updateColors, + GBool map01); + GString *createDeviceNTintFunc(GfxDeviceNColorSpace *cs); +#if OPI_SUPPORT + void opiBegin20(GfxState *state, Dict *dict); + void opiBegin13(GfxState *state, Dict *dict); + void opiTransform(GfxState *state, double x0, double y0, + double *x1, double *y1); + GBool getFileSpec(Object *fileSpec, Object *fileName); +#endif + void cvtFunction(Function *func); + GString *filterPSName(GString *name); + void writePSTextLine(GString *s); + + PSLevel level; // PostScript level + 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 + // predefine forms + + PSOutputFunc outputFunc; + void *outputStream; + PSFileType fileType; // file / pipe / stdout + GBool manualCtrl; + int seqPage; // current sequential page number + void (*underlayCbk)(PSOutputDev *psOut, void *data); + void *underlayCbkData; + void (*overlayCbk)(PSOutputDev *psOut, void *data); + void *overlayCbkData; + GString *(*customCodeCbk)(PSOutputDev *psOut, + PSOutCustomCodeLocation loc, int n, + void *data); + void *customCodeCbkData; + GBool honorUserUnit; + + PDFDoc *doc; + XRef *xref; // the xref table for this PDF file + + int firstPage; // first output page + int lastPage; // last output page + char *rasterizePage; // boolean for each page - true if page + // needs to be rasterized + + GList *fontInfo; // info for each font [PSFontInfo] + GHash *fontFileInfo; // info for each font file [PSFontFileInfo] + Ref *imgIDs; // list of image IDs for in-memory images + int imgIDLen; // number of entries in imgIDs array + int imgIDSize; // size of imgIDs array + Ref *formIDs; // list of IDs for predefined forms + int formIDLen; // number of entries in formIDs array + int formIDSize; // size of formIDs array + char *visitedResources; // vector of resource objects already visited + GBool noStateChanges; // true if there have been no state changes + // since the last save + GList *saveStack; // "no state changes" flag for each + // pending save + 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) + double clipLLX0, clipLLY0, + clipURX0, clipURY0; + GBool expandSmallPages; // expand smaller pages to fill paper + double tx, ty; // global translation for current page + double xScale, yScale; // global scaling for current page + int rotate; // rotation angle for current page + double epsX1, epsY1, // EPS bounding box (unrotated) + epsX2, epsY2; + + GString *embFontList; // resource comments for embedded fonts + + int processColors; // used process colors + PSOutCustomColor // used custom colors + *customColors; + + GBool haveTextClip; // set if text has been drawn with a + // clipping render mode + + GBool inType3Char; // inside a Type 3 CharProc + 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 + +#if OPI_SUPPORT + int opi13Nest; // nesting level of OPI 1.3 objects + int opi20Nest; // nesting level of OPI 2.0 objects +#endif + + GBool ok; // set up ok? + + friend class WinPDFPrinter; +}; + +#endif diff --git a/xpdf/PSTokenizer.cc b/xpdf/PSTokenizer.cc new file mode 100644 index 0000000..bbdb0ec --- /dev/null +++ b/xpdf/PSTokenizer.cc @@ -0,0 +1,136 @@ +//======================================================================== +// +// PSTokenizer.cc +// +// Copyright 2002-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include +#include "gmempp.h" +#include "PSTokenizer.h" + +//------------------------------------------------------------------------ + +// A '1' in this array means the character is white space. A '1' or +// '2' means the character ends a name or command. +static char specialChars[256] = { + 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, // 0x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1x + 1, 0, 0, 0, 0, 2, 0, 0, 2, 2, 0, 0, 0, 0, 0, 2, // 2x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, // 3x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 4x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, // 5x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 6x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, // 7x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // ax + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // bx + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // cx + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // dx + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // ex + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // fx +}; + +//------------------------------------------------------------------------ + +PSTokenizer::PSTokenizer(int (*getCharFuncA)(void *), void *dataA) { + getCharFunc = getCharFuncA; + data = dataA; + charBuf = -1; +} + +PSTokenizer::~PSTokenizer() { +} + +GBool PSTokenizer::getToken(char *buf, int size, int *length) { + GBool comment, backslash; + int c; + int i; + + // skip whitespace and comments + comment = gFalse; + while (1) { + if ((c = getChar()) == EOF) { + buf[0] = '\0'; + *length = 0; + return gFalse; + } + if (comment) { + if (c == '\x0a' || c == '\x0d') { + comment = gFalse; + } + } else if (c == '%') { + comment = gTrue; + } else if (specialChars[c] != 1) { + break; + } + } + + // read a token + i = 0; + buf[i++] = (char)c; + if (c == '(') { + backslash = gFalse; + while ((c = lookChar()) != EOF) { + if (i < size - 1) { + buf[i++] = (char)c; + } + getChar(); + if (c == '\\') { + backslash = gTrue; + } else if (!backslash && c == ')') { + break; + } else { + backslash = gFalse; + } + } + } else if (c == '<') { + while ((c = lookChar()) != EOF) { + getChar(); + if (i < size - 1 && specialChars[c] != 1) { + buf[i++] = (char)c; + } + if (c == '>') { + break; + } + } + } else if (c != '[' && c != ']') { + while ((c = lookChar()) != EOF && !specialChars[c]) { + getChar(); + if (i < size - 1) { + buf[i++] = (char)c; + } + } + } + buf[i] = '\0'; + *length = i; + + return gTrue; +} + +int PSTokenizer::lookChar() { + if (charBuf < 0) { + charBuf = (*getCharFunc)(data); + } + return charBuf; +} + +int PSTokenizer::getChar() { + int c; + + if (charBuf < 0) { + charBuf = (*getCharFunc)(data); + } + c = charBuf; + charBuf = -1; + return c; +} diff --git a/xpdf/PSTokenizer.h b/xpdf/PSTokenizer.h new file mode 100644 index 0000000..4d5ee97 --- /dev/null +++ b/xpdf/PSTokenizer.h @@ -0,0 +1,41 @@ +//======================================================================== +// +// PSTokenizer.h +// +// Copyright 2002-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef PSTOKENIZER_H +#define PSTOKENIZER_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "gtypes.h" + +//------------------------------------------------------------------------ + +class PSTokenizer { +public: + + PSTokenizer(int (*getCharFuncA)(void *), void *dataA); + ~PSTokenizer(); + + // Get the next PostScript token. Returns false at end-of-stream. + GBool getToken(char *buf, int size, int *length); + +private: + + int lookChar(); + int getChar(); + + int (*getCharFunc)(void *); + void *data; + int charBuf; +}; + +#endif diff --git a/xpdf/Page.cc b/xpdf/Page.cc new file mode 100644 index 0000000..4376b5e --- /dev/null +++ b/xpdf/Page.cc @@ -0,0 +1,554 @@ +//======================================================================== +// +// Page.cc +// +// Copyright 1996-2007 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include "gmempp.h" +#include "Trace.h" +#include "GlobalParams.h" +#include "Object.h" +#include "Array.h" +#include "Dict.h" +#include "PDFDoc.h" +#include "XRef.h" +#include "Link.h" +#include "OutputDev.h" +#ifndef PDF_PARSER_ONLY +#include "Gfx.h" +#include "GfxState.h" +#include "Annot.h" +#include "AcroForm.h" +#endif +#include "Error.h" +#include "Catalog.h" +#include "Page.h" + +//------------------------------------------------------------------------ +// PDFRectangle +//------------------------------------------------------------------------ + +void PDFRectangle::clipTo(PDFRectangle *rect) { + if (x1 < rect->x1) { + x1 = rect->x1; + } else if (x1 > rect->x2) { + x1 = rect->x2; + } + if (x2 < rect->x1) { + x2 = rect->x1; + } else if (x2 > rect->x2) { + x2 = rect->x2; + } + if (y1 < rect->y1) { + y1 = rect->y1; + } else if (y1 > rect->y2) { + y1 = rect->y2; + } + if (y2 < rect->y1) { + y2 = rect->y1; + } else if (y2 > rect->y2) { + y2 = rect->y2; + } +} + +//------------------------------------------------------------------------ +// PageAttrs +//------------------------------------------------------------------------ + +PageAttrs::PageAttrs(PageAttrs *attrs, Dict *dict, XRef *xref) { + Object obj1; + + // get old/default values + if (attrs) { + mediaBox = attrs->mediaBox; + cropBox = attrs->cropBox; + haveCropBox = attrs->haveCropBox; + rotate = attrs->rotate; + } else { + // set default MediaBox to 8.5" x 11" -- this shouldn't be necessary + // but some (non-compliant) PDF files don't specify a MediaBox + mediaBox.x1 = 0; + mediaBox.y1 = 0; + mediaBox.x2 = 612; + mediaBox.y2 = 792; + cropBox.x1 = cropBox.y1 = cropBox.x2 = cropBox.y2 = 0; + haveCropBox = gFalse; + rotate = 0; + } + + // media box + readBox(dict, "MediaBox", &mediaBox); + + // crop box + if (readBox(dict, "CropBox", &cropBox)) { + haveCropBox = gTrue; + } + if (!haveCropBox) { + cropBox = mediaBox; + } + + // other boxes + bleedBox = cropBox; + readBox(dict, "BleedBox", &bleedBox); + trimBox = cropBox; + readBox(dict, "TrimBox", &trimBox); + artBox = cropBox; + readBox(dict, "ArtBox", &artBox); + + // rotate + dict->lookup("Rotate", &obj1); + if (obj1.isInt()) { + rotate = obj1.getInt(); + } + obj1.free(); + while (rotate < 0) { + rotate += 360; + } + while (rotate >= 360) { + rotate -= 360; + } + + // misc attributes + dict->lookup("LastModified", &lastModified); + dict->lookup("BoxColorInfo", &boxColorInfo); + dict->lookup("Group", &group); + dict->lookup("Metadata", &metadata); + dict->lookup("PieceInfo", &pieceInfo); + dict->lookup("SeparationInfo", &separationInfo); + if (dict->lookup("UserUnit", &obj1)->isNum()) { + userUnit = obj1.getNum(); + if (userUnit < 1) { + userUnit = 1; + } + } else { + userUnit = 1; + } + obj1.free(); + + // resource dictionary + Object childResDictObj; + dict->lookup("Resources", &childResDictObj); + if (attrs && attrs->resources.isDict() && childResDictObj.isDict()) { + // merge this node's resources into the parent's resources + // (some PDF files violate the PDF spec and expect this merging) + resources.initDict(xref); + Dict *resDict = resources.getDict(); + Dict *parentResDict = attrs->resources.getDict(); + for (int i = 0; i < parentResDict->getLength(); ++i) { + char *resType = parentResDict->getKey(i); + Object subdictObj1; + if (parentResDict->getVal(i, &subdictObj1)->isDict()) { + Dict *subdict1 = subdictObj1.getDict(); + Object subdictObj2; + subdictObj2.initDict(xref); + Dict *subdict2 = subdictObj2.getDict(); + for (int j = 0; j < subdict1->getLength(); ++j) { + subdict1->getValNF(j, &obj1); + subdict2->add(copyString(subdict1->getKey(j)), &obj1); + } + resDict->add(copyString(resType), &subdictObj2); + } + subdictObj1.free(); + } + Dict *childResDict = childResDictObj.getDict(); + for (int i = 0; i < childResDict->getLength(); ++i) { + char *resType = childResDict->getKey(i); + Object subdictObj1; + if (childResDict->getVal(i, &subdictObj1)->isDict()) { + Object subdictObj2; + if (resDict->lookup(resType, &subdictObj2)->isDict()) { + Dict *subdict1 = subdictObj1.getDict(); + Dict *subdict2 = subdictObj2.getDict(); + for (int j = 0; j < subdict1->getLength(); ++j) { + subdict1->getValNF(j, &obj1); + subdict2->add(copyString(subdict1->getKey(j)), &obj1); + } + subdictObj2.free(); + } else { + subdictObj2.free(); + resDict->add(copyString(resType), subdictObj1.copy(&subdictObj2)); + } + } + subdictObj1.free(); + } + } else if (attrs && attrs->resources.isDict()) { + attrs->resources.copy(&resources); + } else if (childResDictObj.isDict()) { + childResDictObj.copy(&resources); + } else { + resources.initNull(); + } + childResDictObj.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(); + userUnit = 1; + resources.initNull(); +} + +PageAttrs::~PageAttrs() { + lastModified.free(); + boxColorInfo.free(); + group.free(); + metadata.free(); + pieceInfo.free(); + separationInfo.free(); + resources.free(); +} + +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; + GBool ok; + + dict->lookup(key, &obj1); + if (obj1.isArray() && obj1.arrayGetLength() == 4) { + ok = gTrue; + obj1.arrayGet(0, &obj2); + if (obj2.isNum()) { + tmp.x1 = obj2.getNum(); + } else { + ok = gFalse; + } + obj2.free(); + obj1.arrayGet(1, &obj2); + if (obj2.isNum()) { + tmp.y1 = obj2.getNum(); + } else { + ok = gFalse; + } + obj2.free(); + obj1.arrayGet(2, &obj2); + if (obj2.isNum()) { + tmp.x2 = obj2.getNum(); + } else { + ok = gFalse; + } + obj2.free(); + obj1.arrayGet(3, &obj2); + if (obj2.isNum()) { + tmp.y2 = obj2.getNum(); + } else { + ok = gFalse; + } + obj2.free(); + if (ok) { + if (tmp.x1 > tmp.x2) { + t = tmp.x1; tmp.x1 = tmp.x2; tmp.x2 = t; + } + if (tmp.y1 > tmp.y2) { + t = tmp.y1; tmp.y1 = tmp.y2; tmp.y2 = t; + } + *box = tmp; + } + } else { + ok = gFalse; + } + obj1.free(); + return ok; +} + +//------------------------------------------------------------------------ +// Page +//------------------------------------------------------------------------ + +Page::Page(PDFDoc *docA, int numA, Dict *pageDict, PageAttrs *attrsA) { + ok = gTrue; + 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(errSyntaxError, -1, + "Page annotations object (page {0:d}) is wrong type ({1:s})", + num, annots.getTypeName()); + annots.free(); + goto err2; + } + + // contents + pageDict->lookupNF("Contents", &contents); + if (!(contents.isRef() || contents.isArray() || + contents.isNull())) { + error(errSyntaxError, -1, + "Page contents object (page {0:d}) is wrong type ({1:s})", + num, contents.getTypeName()); + contents.free(); + goto err1; + } + + // thumbnail + pageDict->lookupNF("Thumb", &thumbnail); + if (!thumbnail.isRef()) { + if (!thumbnail.isNull()) { + thumbnail.free(); + thumbnail.initNull(); + } + } + + return; + + err2: + annots.initNull(); + err1: + contents.initNull(); + thumbnail.initNull(); + ok = gFalse; +} + +Page::Page(PDFDoc *docA, int numA) { + doc = docA; + xref = doc->getXRef(); + num = numA; + attrs = new PageAttrs(); + annots.initNull(); + contents.initNull(); + thumbnail.initNull(); + ok = gTrue; +} + +Page::~Page() { + delete attrs; + annots.free(); + contents.free(); + thumbnail.free(); +} + +Links *Page::getLinks() { + Links *links; + Object obj; + + 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, + GBool (*abortCheckCbk)(void *data), + void *abortCheckCbkData) { + displaySlice(out, hDPI, vDPI, rotate, useMediaBox, crop, + -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, + GBool (*abortCheckCbk)(void *data), + void *abortCheckCbkData) { +#ifndef PDF_PARSER_ONLY + PDFRectangle *mediaBox, *cropBox; + PDFRectangle box; + Gfx *gfx; + Object obj; + Annots *annotList; + AcroForm *form; + int i; + + if (!out->checkPageSlice(this, hDPI, vDPI, rotate, useMediaBox, crop, + sliceX, sliceY, sliceW, sliceH, + printing, abortCheckCbk, abortCheckCbkData)) { + return; + } + + traceBegin(this, "begin page"); + + rotate += getRotate(); + if (rotate >= 360) { + rotate -= 360; + } else if (rotate < 0) { + rotate += 360; + } + + makeBox(hDPI, vDPI, rotate, useMediaBox, out->upsideDown(), + sliceX, sliceY, sliceW, sliceH, &box, &crop); + cropBox = getCropBox(); + + if (globalParams->getPrintCommands()) { + mediaBox = getMediaBox(); + printf("***** MediaBox = ll:%g,%g ur:%g,%g\n", + mediaBox->x1, mediaBox->y1, mediaBox->x2, mediaBox->y2); + printf("***** CropBox = ll:%g,%g ur:%g,%g\n", + cropBox->x1, cropBox->y1, cropBox->x2, cropBox->y2); + printf("***** Rotate = %d\n", attrs->getRotate()); + } + + gfx = new Gfx(doc, out, num, attrs->getResourceDict(), + hDPI, vDPI, &box, crop ? cropBox : (PDFRectangle *)NULL, + rotate, abortCheckCbk, abortCheckCbkData); + contents.fetch(xref, &obj); + if (!obj.isNull()) { + gfx->saveState(); + gfx->display(&contents); + gfx->endOfPage(); + } + obj.free(); + + // draw (non-form) annotations + if (globalParams->getDrawAnnotations()) { + annotList = new Annots(doc, getAnnots(&obj)); + obj.free(); + annotList->generateAnnotAppearances(); + if (annotList->getNumAnnots() > 0) { + if (globalParams->getPrintCommands()) { + printf("***** Annotations\n"); + } + for (i = 0; i < annotList->getNumAnnots(); ++i) { + if (abortCheckCbk && (*abortCheckCbk)(abortCheckCbkData)) { + break; + } + annotList->getAnnot(i)->draw(gfx, printing); + } + } + delete annotList; + } + + // draw form fields + if (globalParams->getDrawFormFields()) { + if ((form = doc->getCatalog()->getForm())) { + if (!(abortCheckCbk && (*abortCheckCbk)(abortCheckCbkData))) { + form->draw(num, gfx, printing); + } + } + } + + delete gfx; +#endif // PDF_PARSER_ONLY + + traceEnd(this, "end page"); +} + +void Page::makeBox(double hDPI, double vDPI, int rotate, + GBool useMediaBox, GBool upsideDown, + double sliceX, double sliceY, double sliceW, double sliceH, + PDFRectangle *box, GBool *crop) { + PDFRectangle *mediaBox, *cropBox, *baseBox; + double kx, ky; + + mediaBox = getMediaBox(); + cropBox = getCropBox(); + if (sliceW >= 0 && sliceH >= 0) { + baseBox = useMediaBox ? mediaBox : cropBox; + kx = 72.0 / hDPI; + ky = 72.0 / vDPI; + if (rotate == 90) { + if (upsideDown) { + box->x1 = baseBox->x1 + ky * sliceY; + box->x2 = baseBox->x1 + ky * (sliceY + sliceH); + } else { + box->x1 = baseBox->x2 - ky * (sliceY + sliceH); + box->x2 = baseBox->x2 - ky * sliceY; + } + box->y1 = baseBox->y1 + kx * sliceX; + box->y2 = baseBox->y1 + kx * (sliceX + sliceW); + } else if (rotate == 180) { + box->x1 = baseBox->x2 - kx * (sliceX + sliceW); + box->x2 = baseBox->x2 - kx * sliceX; + if (upsideDown) { + box->y1 = baseBox->y1 + ky * sliceY; + box->y2 = baseBox->y1 + ky * (sliceY + sliceH); + } else { + box->y1 = baseBox->y2 - ky * (sliceY + sliceH); + box->y2 = baseBox->y2 - ky * sliceY; + } + } else if (rotate == 270) { + if (upsideDown) { + box->x1 = baseBox->x2 - ky * (sliceY + sliceH); + box->x2 = baseBox->x2 - ky * sliceY; + } else { + box->x1 = baseBox->x1 + ky * sliceY; + box->x2 = baseBox->x1 + ky * (sliceY + sliceH); + } + box->y1 = baseBox->y2 - kx * (sliceX + sliceW); + box->y2 = baseBox->y2 - kx * sliceX; + } else { + box->x1 = baseBox->x1 + kx * sliceX; + box->x2 = baseBox->x1 + kx * (sliceX + sliceW); + if (upsideDown) { + box->y1 = baseBox->y2 - ky * (sliceY + sliceH); + box->y2 = baseBox->y2 - ky * sliceY; + } else { + box->y1 = baseBox->y1 + ky * sliceY; + box->y2 = baseBox->y1 + ky * (sliceY + sliceH); + } + } + } else if (useMediaBox) { + *box = *mediaBox; + } else { + *box = *cropBox; + *crop = gFalse; + } +} + +void Page::processLinks(OutputDev *out) { + Links *links; + int i; + + links = getLinks(); + for (i = 0; i < links->getNumLinks(); ++i) { + out->processLink(links->getLink(i)); + } + delete links; +} + +#ifndef PDF_PARSER_ONLY +void Page::getDefaultCTM(double *ctm, double hDPI, double vDPI, + int rotate, GBool useMediaBox, GBool upsideDown) { + GfxState *state; + int i; + + rotate += getRotate(); + if (rotate >= 360) { + rotate -= 360; + } else if (rotate < 0) { + rotate += 360; + } + state = new GfxState(hDPI, vDPI, + useMediaBox ? getMediaBox() : getCropBox(), + rotate, upsideDown); + for (i = 0; i < 6; ++i) { + ctm[i] = state->getCTM()[i]; + } + delete state; +} +#endif diff --git a/xpdf/Page.h b/xpdf/Page.h new file mode 100644 index 0000000..fe579e7 --- /dev/null +++ b/xpdf/Page.h @@ -0,0 +1,207 @@ +//======================================================================== +// +// Page.h +// +// Copyright 1996-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef PAGE_H +#define PAGE_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "Object.h" + +class Dict; +class PDFDoc; +class XRef; +class OutputDev; +class Links; + +//------------------------------------------------------------------------ + +class PDFRectangle { +public: + double x1, y1, x2, y2; + + PDFRectangle() { x1 = y1 = x2 = y2 = 0; } + PDFRectangle(double x1A, double y1A, double x2A, double y2A) + { x1 = x1A; y1 = y1A; x2 = x2A; y2 = y2A; } + GBool isValid() { return x1 != 0 || y1 != 0 || x2 != 0 || y2 != 0; } + void clipTo(PDFRectangle *rect); +}; + +//------------------------------------------------------------------------ +// PageAttrs +//------------------------------------------------------------------------ + +class PageAttrs { +public: + + // Construct a new PageAttrs object by merging a dictionary + // (of type Pages or Page) into another PageAttrs object. If + // is NULL, uses defaults. + PageAttrs(PageAttrs *attrs, Dict *dict, XRef *xref); + + // Construct a new PageAttrs object for an empty page (only used + // when there is an error in the page tree). + PageAttrs(); + + // Destructor. + ~PageAttrs(); + + // Accessors. + PDFRectangle *getMediaBox() { return &mediaBox; } + PDFRectangle *getCropBox() { return &cropBox; } + GBool isCropped() { return haveCropBox; } + PDFRectangle *getBleedBox() { return &bleedBox; } + PDFRectangle *getTrimBox() { return &trimBox; } + PDFRectangle *getArtBox() { return &artBox; } + int getRotate() { return rotate; } + GString *getLastModified() + { return lastModified.isString() + ? lastModified.getString() : (GString *)NULL; } + Dict *getBoxColorInfo() + { return boxColorInfo.isDict() ? boxColorInfo.getDict() : (Dict *)NULL; } + Dict *getGroup() + { return group.isDict() ? group.getDict() : (Dict *)NULL; } + Stream *getMetadata() + { return metadata.isStream() ? metadata.getStream() : (Stream *)NULL; } + Dict *getPieceInfo() + { return pieceInfo.isDict() ? pieceInfo.getDict() : (Dict *)NULL; } + Dict *getSeparationInfo() + { return separationInfo.isDict() + ? separationInfo.getDict() : (Dict *)NULL; } + double getUserUnit() { return userUnit; } + Dict *getResourceDict() + { return resources.isDict() ? resources.getDict() : (Dict *)NULL; } + + // Clip all other boxes to the MediaBox. + void clipBoxes(); + +private: + + GBool readBox(Dict *dict, const char *key, PDFRectangle *box); + + PDFRectangle mediaBox; + PDFRectangle cropBox; + GBool haveCropBox; + PDFRectangle bleedBox; + PDFRectangle trimBox; + PDFRectangle artBox; + int rotate; + Object lastModified; + Object boxColorInfo; + Object group; + Object metadata; + Object pieceInfo; + Object separationInfo; + double userUnit; + Object resources; +}; + +//------------------------------------------------------------------------ +// Page +//------------------------------------------------------------------------ + +class Page { +public: + + // Constructor. + 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(); + + // Is page valid? + GBool isOk() { return ok; } + + // Get page parameters. + int getNum() { return num; } + PageAttrs *getAttrs() { return attrs; } + PDFRectangle *getMediaBox() { return attrs->getMediaBox(); } + PDFRectangle *getCropBox() { return attrs->getCropBox(); } + GBool isCropped() { return attrs->isCropped(); } + double getMediaWidth() + { return attrs->getMediaBox()->x2 - attrs->getMediaBox()->x1; } + double getMediaHeight() + { return attrs->getMediaBox()->y2 - attrs->getMediaBox()->y1; } + double getCropWidth() + { return attrs->getCropBox()->x2 - attrs->getCropBox()->x1; } + double getCropHeight() + { return attrs->getCropBox()->y2 - attrs->getCropBox()->y1; } + PDFRectangle *getBleedBox() { return attrs->getBleedBox(); } + PDFRectangle *getTrimBox() { return attrs->getTrimBox(); } + PDFRectangle *getArtBox() { return attrs->getArtBox(); } + int getRotate() { return attrs->getRotate(); } + GString *getLastModified() { return attrs->getLastModified(); } + Dict *getBoxColorInfo() { return attrs->getBoxColorInfo(); } + Dict *getGroup() { return attrs->getGroup(); } + Stream *getMetadata() { return attrs->getMetadata(); } + Dict *getPieceInfo() { return attrs->getPieceInfo(); } + Dict *getSeparationInfo() { return attrs->getSeparationInfo(); } + double getUserUnit() { return attrs->getUserUnit(); } + + // Get resource dictionary. + Dict *getResourceDict() { return attrs->getResourceDict(); } + + // Get annotations array. + Object *getAnnots(Object *obj) { return annots.fetch(xref, obj); } + + // Return a list of links. + Links *getLinks(); + + // Get contents. + Object *getContents(Object *obj) { return contents.fetch(xref, obj); } + + // Get the page's thumbnail image. + Object *getThumbnail(Object *obj) { return thumbnail.fetch(xref, obj); } + + // Display a page. + void display(OutputDev *out, double hDPI, double vDPI, + int rotate, GBool useMediaBox, GBool crop, + GBool printing, + GBool (*abortCheckCbk)(void *data) = NULL, + void *abortCheckCbkData = NULL); + + // Display part of a page. + void displaySlice(OutputDev *out, double hDPI, double vDPI, + int rotate, GBool useMediaBox, GBool crop, + int sliceX, int sliceY, int sliceW, int sliceH, + GBool printing, + GBool (*abortCheckCbk)(void *data) = NULL, + void *abortCheckCbkData = NULL); + + void makeBox(double hDPI, double vDPI, int rotate, + GBool useMediaBox, GBool upsideDown, + double sliceX, double sliceY, double sliceW, double sliceH, + PDFRectangle *box, GBool *crop); + + void processLinks(OutputDev *out); + + // Get the page's default CTM. + void getDefaultCTM(double *ctm, double hDPI, double vDPI, + int rotate, GBool useMediaBox, GBool upsideDown); + +private: + + PDFDoc *doc; + XRef *xref; // the xref table for this PDF file + int num; // page number + PageAttrs *attrs; // page attributes + Object annots; // annotations array + Object contents; // page contents + Object thumbnail; // reference to thumbnail image + GBool ok; // true if page is valid +}; + +#endif diff --git a/xpdf/Parser.cc b/xpdf/Parser.cc new file mode 100644 index 0000000..4fad6af --- /dev/null +++ b/xpdf/Parser.cc @@ -0,0 +1,316 @@ +//======================================================================== +// +// Parser.cc +// +// Copyright 1996-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include +#include "gmempp.h" +#include "Object.h" +#include "Array.h" +#include "Dict.h" +#include "Decrypt.h" +#include "Parser.h" +#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; + inlineImg = 0; + allowStreams = allowStreamsA; + lexer->getObj(&buf1); + lexer->getObj(&buf2); +} + +Parser::~Parser() { + buf1.free(); + buf2.free(); + delete lexer; +} + +Object *Parser::getObj(Object *obj, GBool simpleOnly, + Guchar *fileKey, + CryptAlgorithm encAlgorithm, int keyLength, + int objNum, int objGen, int recursion) { + char *key; + Stream *str; + Object obj2; + int num; + DecryptStream *decrypt; + GString *s, *s2; + int c; + + // refill buffer after inline image data + if (inlineImg == 2) { + buf1.free(); + buf2.free(); + lexer->getObj(&buf1); + lexer->getObj(&buf2); + inlineImg = 0; + } + + // array + if (!simpleOnly && recursion < recursionLimit && buf1.isCmd("[")) { + shift(); + obj->initArray(xref); + while (!buf1.isCmd("]") && !buf1.isEOF()) + obj->arrayAdd(getObj(&obj2, gFalse, fileKey, encAlgorithm, keyLength, + objNum, objGen, recursion + 1)); + if (buf1.isEOF()) + error(errSyntaxError, getPos(), "End of file inside array"); + shift(); + + // dictionary or stream + } else if (!simpleOnly && recursion < recursionLimit && buf1.isCmd("<<")) { + shift(); + obj->initDict(xref); + while (!buf1.isCmd(">>") && !buf1.isEOF()) { + if (!buf1.isName()) { + error(errSyntaxError, getPos(), + "Dictionary key must be a name object"); + shift(); + } else { + key = copyString(buf1.getName()); + shift(); + if (buf1.isEOF() || buf1.isError()) { + gfree(key); + break; + } + obj->dictAdd(key, getObj(&obj2, gFalse, + fileKey, encAlgorithm, keyLength, + objNum, objGen, recursion + 1)); + } + } + if (buf1.isEOF()) + 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, recursion + 1))) { + obj->initStream(str); + } else { + obj->free(); + obj->initError(); + } + } else { + shift(); + } + + // indirect reference or integer + } else if (buf1.isInt()) { + num = buf1.getInt(); + shift(); + if (buf1.isInt() && buf2.isCmd("R")) { + obj->initRef(num, buf1.getInt()); + shift(); + shift(); + } else { + obj->initInt(num); + } + + // string + } else if (buf1.isString() && fileKey) { + s = buf1.getString(); + s2 = new GString(); + obj2.initNull(); + decrypt = new DecryptStream(new MemStream(s->getCString(), 0, + s->getLength(), &obj2), + fileKey, encAlgorithm, keyLength, + objNum, objGen); + decrypt->reset(); + while ((c = decrypt->getChar()) != EOF) { + s2->append((char)c); + } + delete decrypt; + obj->initString(s2); + shift(); + + // simple object + } else { + buf1.copy(obj); + shift(); + } + + return obj; +} + +Stream *Parser::makeStream(Object *dict, Guchar *fileKey, + CryptAlgorithm encAlgorithm, int keyLength, + int objNum, int objGen, int recursion) { + // get stream start position + lexer->skipToNextLine(); + Stream *curStr = lexer->getStream(); + if (!curStr) { + return NULL; + } + GFileOffset pos = curStr->getPos(); + + GBool haveLength = gFalse; + GFileOffset length = 0; + GFileOffset endPos; + + // check for length in damaged file + if (xref && xref->getStreamEnd(pos, &endPos)) { + length = endPos - pos; + haveLength = gTrue; + + // get length from the stream object + } else { + Object obj; + dict->dictLookup("Length", &obj, recursion); + if (obj.isInt()) { + length = (GFileOffset)(Guint)obj.getInt(); + haveLength = gTrue; + } else { + error(errSyntaxError, getPos(), + "Missing or invalid 'Length' attribute in stream"); + } + obj.free(); + } + + // in badly damaged PDF files, we can run off the end of the input + // stream immediately after the "stream" token + if (!lexer->getStream()) { + return NULL; + } + + // copy the base stream (Lexer will free stream objects when it gets + // to end of stream -- which can happen in the shift() calls below) + BaseStream *baseStr = + (BaseStream *)lexer->getStream()->getBaseStream()->copy(); + + // 'Length' attribute is missing -- search for 'endstream' + if (!haveLength) { + GBool foundEndstream = gFalse; + char endstreamBuf[8]; + if ((curStr = lexer->getStream())) { + int c; + while ((c = curStr->getChar()) != EOF) { + if (c == 'e' && + curStr->getBlock(endstreamBuf, 8) == 8 && + !memcmp(endstreamBuf, "ndstream", 8)) { + length = curStr->getPos() - 9 - pos; + foundEndstream = gTrue; + break; + } + } + } + if (!foundEndstream) { + error(errSyntaxError, getPos(), "Couldn't find 'endstream' for stream"); + delete baseStr; + return NULL; + } + } + + // make new base stream + Stream *str = baseStr->makeSubStream(pos, gTrue, length, dict); + + // look for the 'endstream' marker + if (haveLength) { + // skip over stream data + lexer->setPos(pos + length); + + // check for 'endstream' + // NB: we never reuse the Parser object to parse objects after a + // stream, and we could (if the PDF file is damaged) be in the + // middle of binary data at this point, so we check the stream + // data directly for 'endstream', rather than calling shift() to + // parse objects + GBool foundEndstream = gFalse; + char endstreamBuf[8]; + if ((curStr = lexer->getStream())) { + // skip up to 100 whitespace chars + int c; + for (int i = 0; i < 100; ++i) { + c = curStr->getChar(); + if (!Lexer::isSpace(c)) { + break; + } + } + if (c == 'e') { + if (curStr->getBlock(endstreamBuf, 8) == 8 && + !memcmp(endstreamBuf, "ndstream", 8)) { + foundEndstream = gTrue; + } + } + } + if (!foundEndstream) { + error(errSyntaxError, getPos(), "Missing 'endstream'"); + // kludge for broken PDF files: just add 5k to the length, and + // hope it's enough + // (dict is now owned by str, so we need to copy it before deleting str) + Object obj; + dict->copy(&obj); + delete str; + length += 5000; + str = baseStr->makeSubStream(pos, gTrue, length, &obj); + } + } + + // free the copied base stream + delete baseStr; + + // handle decryption + if (fileKey) { + // the 'Crypt' filter is used to mark unencrypted metadata streams + //~ this should also check for an empty DecodeParams entry + GBool encrypted = gTrue; + Object obj; + dict->dictLookup("Filter", &obj, recursion); + if (obj.isName("Crypt")) { + encrypted = gFalse; + } else if (obj.isArray() && obj.arrayGetLength() >= 1) { + Object obj2; + if (obj.arrayGet(0, &obj2)->isName("Crypt")) { + encrypted = gFalse; + } + obj2.free(); + } + obj.free(); + if (encrypted) { + str = new DecryptStream(str, fileKey, encAlgorithm, keyLength, + objNum, objGen); + } + } + + // get filters + str = str->addFilters(dict, recursion); + + return str; +} + +void Parser::shift() { + if (inlineImg > 0) { + if (inlineImg < 2) { + ++inlineImg; + } else { + // in a damaged content stream, if 'ID' shows up in the middle + // of a dictionary, we need to reset + inlineImg = 0; + } + } else if (buf2.isCmd("ID")) { + lexer->skipChar(); // skip char after 'ID' command + inlineImg = 1; + } + buf1.free(); + buf1 = buf2; + if (inlineImg > 0) // don't buffer inline image data + buf2.initNull(); + else + lexer->getObj(&buf2); +} diff --git a/xpdf/Parser.h b/xpdf/Parser.h new file mode 100644 index 0000000..bfe5a52 --- /dev/null +++ b/xpdf/Parser.h @@ -0,0 +1,65 @@ +//======================================================================== +// +// Parser.h +// +// Copyright 1996-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef PARSER_H +#define PARSER_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "Lexer.h" + +//------------------------------------------------------------------------ +// Parser +//------------------------------------------------------------------------ + +class Parser { +public: + + // Constructor. + Parser(XRef *xrefA, Lexer *lexerA, GBool allowStreamsA); + + // Destructor. + ~Parser(); + + // Get the next object from the input stream. If 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 recursion = 0); + + // Get stream index (for arrays of streams). + int getStreamIndex() { return lexer->getStreamIndex(); } + + // Get stream. + Stream *getStream() { return lexer->getStream(); } + + // Get current position in file. + GFileOffset getPos() { return lexer->getPos(); } + +private: + + XRef *xref; // the xref table for this PDF file + Lexer *lexer; // input stream + GBool allowStreams; // parse stream objects? + Object buf1, buf2; // next two tokens + int inlineImg; // set when inline image data is encountered + + Stream *makeStream(Object *dict, Guchar *fileKey, + CryptAlgorithm encAlgorithm, int keyLength, + int objNum, int objGen, int recursion); + void shift(); +}; + +#endif + diff --git a/xpdf/PreScanOutputDev.cc b/xpdf/PreScanOutputDev.cc new file mode 100644 index 0000000..29f26c0 --- /dev/null +++ b/xpdf/PreScanOutputDev.cc @@ -0,0 +1,309 @@ +//======================================================================== +// +// PreScanOutputDev.cc +// +// Copyright 2005 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include "gmempp.h" +#include "GlobalParams.h" +#include "Page.h" +#include "Gfx.h" +#include "GfxFont.h" +#include "Link.h" +#include "PreScanOutputDev.h" + +//------------------------------------------------------------------------ +// PreScanOutputDev +//------------------------------------------------------------------------ + +PreScanOutputDev::PreScanOutputDev() { + clearStats(); +} + +PreScanOutputDev::~PreScanOutputDev() { +} + +void PreScanOutputDev::startPage(int pageNum, GfxState *state) { +} + +void PreScanOutputDev::endPage() { +} + +void PreScanOutputDev::stroke(GfxState *state) { + double *dash; + int dashLen; + double dashStart; + + check(state, state->getStrokeColorSpace(), state->getStrokeColor(), + state->getStrokeOpacity(), state->getBlendMode()); + state->getLineDash(&dash, &dashLen, &dashStart); + if (dashLen != 0) { + gdi = gFalse; + } +} + +void PreScanOutputDev::fill(GfxState *state) { + check(state, state->getFillColorSpace(), state->getFillColor(), + state->getFillOpacity(), state->getBlendMode()); +} + +void PreScanOutputDev::eoFill(GfxState *state) { + check(state, state->getFillColorSpace(), state->getFillColor(), + state->getFillOpacity(), state->getBlendMode()); +} + +void PreScanOutputDev::tilingPatternFill(GfxState *state, Gfx *gfx, + Object *strRef, + int paintType, int tilingType, + Dict *resDict, + double *mat, double *bbox, + int x0, int y0, int x1, int y1, + double xStep, double yStep) { + if (paintType == 1) { + gfx->drawForm(strRef, resDict, mat, bbox); + } else { + check(state, state->getFillColorSpace(), state->getFillColor(), + state->getFillOpacity(), state->getBlendMode()); + } +} + +GBool PreScanOutputDev::shadedFill(GfxState *state, GfxShading *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 +} + +void PreScanOutputDev::eoClip(GfxState *state) { + //~ see clip() +} + +void PreScanOutputDev::beginStringOp(GfxState *state) { + int render; + GfxFont *font; + double m11, m12, m21, m22; + GBool simpleTTF; + + render = state->getRender(); + if (!(render & 1)) { + check(state, state->getFillColorSpace(), state->getFillColor(), + state->getFillOpacity(), state->getBlendMode()); + } + if ((render & 3) == 1 || (render & 3) == 2) { + check(state, state->getStrokeColorSpace(), state->getStrokeColor(), + state->getStrokeOpacity(), state->getBlendMode()); + } + + 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); + if (simpleTTF) { + //~ need to create a FoFiTrueType object, and check for a Unicode cmap + } + if (state->getRender() != 0 || !simpleTTF) { + gdi = gFalse; + } +} + +void PreScanOutputDev::endStringOp(GfxState *state) { +} + +GBool PreScanOutputDev::beginType3Char(GfxState *state, double x, double y, + double dx, double dy, + CharCode code, Unicode *u, int uLen) { + // return false so all Type 3 chars get rendered (no caching) + return gFalse; +} + +void PreScanOutputDev::endType3Char(GfxState *state) { +} + +void PreScanOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str, + int width, int height, GBool invert, + GBool inlineImg, GBool interpolate) { + check(state, state->getFillColorSpace(), state->getFillColor(), + state->getFillOpacity(), state->getBlendMode()); + if (state->getFillColorSpace()->getMode() == csPattern) { + patternImgMask = gTrue; + } + gdi = gFalse; + + if (inlineImg) { + str->reset(); + str->discardChars(height * ((width + 7) / 8)); + str->close(); + } +} + +void PreScanOutputDev::drawImage(GfxState *state, Object *ref, Stream *str, + int width, int height, + GfxImageColorMap *colorMap, + int *maskColors, GBool inlineImg, + GBool interpolate) { + GfxColorSpace *colorSpace; + + colorSpace = colorMap->getColorSpace(); + if (colorSpace->getMode() == csIndexed) { + colorSpace = ((GfxIndexedColorSpace *)colorSpace)->getBase(); + } + if (colorSpace->getMode() == csDeviceGray || + colorSpace->getMode() == csCalGray) { + if (colorMap->getBits() > 1) { + mono = gFalse; + } + } else { + gray = gFalse; + mono = gFalse; + } + if (state->getFillOpacity() != 1 || + state->getBlendMode() != gfxBlendNormal) { + transparency = gTrue; + } + gdi = gFalse; + + if (inlineImg) { + str->reset(); + str->discardChars(height * ((width * colorMap->getNumPixelComps() * + colorMap->getBits() + 7) / 8)); + str->close(); + } +} + +void PreScanOutputDev::drawMaskedImage(GfxState *state, Object *ref, + Stream *str, + int width, int height, + GfxImageColorMap *colorMap, + Object *maskRef, Stream *maskStr, + int maskWidth, int maskHeight, + GBool maskInvert, GBool interpolate) { + GfxColorSpace *colorSpace; + + colorSpace = colorMap->getColorSpace(); + if (colorSpace->getMode() == csIndexed) { + colorSpace = ((GfxIndexedColorSpace *)colorSpace)->getBase(); + } + if (colorSpace->getMode() == csDeviceGray || + colorSpace->getMode() == csCalGray) { + if (colorMap->getBits() > 1) { + mono = gFalse; + } + } else { + gray = gFalse; + mono = gFalse; + } + if (state->getFillOpacity() != 1 || + state->getBlendMode() != gfxBlendNormal) { + transparency = gTrue; + } + gdi = gFalse; +} + +void PreScanOutputDev::drawSoftMaskedImage(GfxState *state, Object *ref, + Stream *str, + int width, int height, + GfxImageColorMap *colorMap, + Object *maskRef, Stream *maskStr, + int maskWidth, int maskHeight, + GfxImageColorMap *maskColorMap, + double *matte, GBool interpolate) { + GfxColorSpace *colorSpace; + + colorSpace = colorMap->getColorSpace(); + if (colorSpace->getMode() == csIndexed) { + colorSpace = ((GfxIndexedColorSpace *)colorSpace)->getBase(); + } + if (colorSpace->getMode() != csDeviceGray && + colorSpace->getMode() != csCalGray) { + gray = gFalse; + } + mono = gFalse; + transparency = gTrue; + gdi = gFalse; +} + +GBool PreScanOutputDev::beginTransparencyGroup( + GfxState *state, double *bbox, + GfxColorSpace *blendingColorSpace, + GBool isolated, GBool knockout, + GBool forSoftMask) { + transparency = gTrue; + gdi = gFalse; + return gTrue; +} + +void PreScanOutputDev::check(GfxState *state, + GfxColorSpace *colorSpace, GfxColor *color, + double opacity, GfxBlendMode blendMode) { + GfxGray gr; + GfxCMYK cmyk; + GfxRGB rgb; + + if (colorSpace->getMode() == csPattern) { + mono = gFalse; + gray = gFalse; + gdi = gFalse; + } else if (colorSpace->getMode() == csDeviceGray || + colorSpace->getMode() == csCalGray) { + colorSpace->getGray(color, &gr, state->getRenderingIntent()); + if (!(gr == 0 || gr == gfxColorComp1)) { + mono = gFalse; + } + } else if (colorSpace->getMode() == csDeviceCMYK) { + colorSpace->getCMYK(color, &cmyk, state->getRenderingIntent()); + if (cmyk.c != 0 || cmyk.m != 0 || cmyk.y != 0) { + mono = gFalse; + gray = gFalse; + } else if (!(cmyk.k == 0 || cmyk.k == gfxColorComp1)) { + mono = gFalse; + } + } else { + colorSpace->getRGB(color, &rgb, state->getRenderingIntent()); + if (rgb.r != rgb.g || rgb.g != rgb.b || rgb.b != rgb.r) { + mono = gFalse; + gray = gFalse; + } else if (!((rgb.r == 0 && rgb.g == 0 && rgb.b == 0) || + (rgb.r == gfxColorComp1 && + rgb.g == gfxColorComp1 && + rgb.b == gfxColorComp1))) { + mono = gFalse; + } + } + if (opacity != 1 || blendMode != gfxBlendNormal) { + transparency = gTrue; + } +} + +void PreScanOutputDev::clearStats() { + mono = gTrue; + gray = gTrue; + transparency = gFalse; + patternImgMask = gFalse; + gdi = gTrue; +} diff --git a/xpdf/PreScanOutputDev.h b/xpdf/PreScanOutputDev.h new file mode 100644 index 0000000..ee21e98 --- /dev/null +++ b/xpdf/PreScanOutputDev.h @@ -0,0 +1,149 @@ +//======================================================================== +// +// PreScanOutputDev.h +// +// Copyright 2005 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef PRESCANOUTPUTDEV_H +#define PRESCANOUTPUTDEV_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "gtypes.h" +#include "GfxState.h" +#include "OutputDev.h" + +//------------------------------------------------------------------------ +// PreScanOutputDev +//------------------------------------------------------------------------ + +class PreScanOutputDev: public OutputDev { +public: + + // Constructor. + PreScanOutputDev(); + + // Destructor. + virtual ~PreScanOutputDev(); + + //----- get info about output device + + // 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; } + + // 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. + virtual void startPage(int pageNum, GfxState *state); + + // End a page. + virtual void endPage(); + + //----- path painting + virtual void stroke(GfxState *state); + virtual void fill(GfxState *state); + virtual void eoFill(GfxState *state); + virtual void tilingPatternFill(GfxState *state, Gfx *gfx, Object *strRef, + int paintType, int tilingType, Dict *resDict, + double *mat, double *bbox, + int x0, int y0, int x1, int y1, + double xStep, double yStep); + virtual GBool shadedFill(GfxState *state, GfxShading *shading); + + //----- path clipping + virtual void clip(GfxState *state); + virtual void eoClip(GfxState *state); + + //----- text drawing + virtual void beginStringOp(GfxState *state); + virtual void endStringOp(GfxState *state); + virtual GBool beginType3Char(GfxState *state, double x, double y, + double dx, double dy, + CharCode code, Unicode *u, int uLen); + virtual void endType3Char(GfxState *state); + + //----- image drawing + virtual void drawImageMask(GfxState *state, Object *ref, Stream *str, + int width, int height, GBool invert, + GBool inlineImg, GBool interpolate); + virtual void drawImage(GfxState *state, Object *ref, Stream *str, + int width, int height, GfxImageColorMap *colorMap, + int *maskColors, GBool inlineImg, GBool interpolate); + virtual void drawMaskedImage(GfxState *state, Object *ref, Stream *str, + int width, int height, + GfxImageColorMap *colorMap, + Object *maskRef, Stream *maskStr, + int maskWidth, int maskHeight, + GBool maskInvert, GBool interpolate); + virtual void drawSoftMaskedImage(GfxState *state, Object *ref, Stream *str, + int width, int height, + GfxImageColorMap *colorMap, + Object *maskRef, Stream *maskStr, + int maskWidth, int maskHeight, + GfxImageColorMap *maskColorMap, + double *matte, GBool interpolate); + + //----- transparency groups and soft masks + virtual GBool beginTransparencyGroup(GfxState *state, double *bbox, + GfxColorSpace *blendingColorSpace, + GBool isolated, GBool knockout, + GBool forSoftMask); + + //----- special access + + // Returns true if the operations performed since the last call to + // clearStats() are all monochrome (black or white). + GBool isMonochrome() { return mono; } + + // Returns true if the operations performed since the last call to + // clearStats() are all gray. + GBool isGray() { return gray; } + + // Returns true if the operations performed since the last call to + // clearStats() included any transparency. + 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; } + + // Clear the stats used by the above functions. + void clearStats(); + +private: + + void check(GfxState *state, GfxColorSpace *colorSpace, GfxColor *color, + double opacity, GfxBlendMode blendMode); + + GBool mono; + GBool gray; + GBool transparency; + GBool patternImgMask; + GBool gdi; +}; + +#endif diff --git a/xpdf/SecurityHandler.cc b/xpdf/SecurityHandler.cc new file mode 100644 index 0000000..a61a84e --- /dev/null +++ b/xpdf/SecurityHandler.cc @@ -0,0 +1,370 @@ +//======================================================================== +// +// SecurityHandler.cc +// +// Copyright 2004 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include "gmempp.h" +#include "GString.h" +#include "PDFDoc.h" +#include "Decrypt.h" +#include "Error.h" +#include "GlobalParams.h" +#include "PDFCore.h" +#include "SecurityHandler.h" + +//------------------------------------------------------------------------ +// SecurityHandler +//------------------------------------------------------------------------ + +SecurityHandler *SecurityHandler::make(PDFDoc *docA, Object *encryptDictA) { + Object filterObj; + SecurityHandler *secHdlr; + + encryptDictA->dictLookup("Filter", &filterObj); + if (filterObj.isName("Standard")) { + secHdlr = new StandardSecurityHandler(docA, encryptDictA); + } else if (filterObj.isName()) { + error(errSyntaxError, -1, "Couldn't find the '{0:s}' security handler", + filterObj.getName()); + secHdlr = NULL; + } else { + error(errSyntaxError, -1, + "Missing or invalid 'Filter' entry in encryption dictionary"); + secHdlr = NULL; + } + filterObj.free(); + return secHdlr; +} + +SecurityHandler::SecurityHandler(PDFDoc *docA) { + doc = docA; +} + +SecurityHandler::~SecurityHandler() { +} + +GBool SecurityHandler::checkEncryption(GString *ownerPassword, + GString *userPassword) { + void *authData; + GBool ok; + int i; + + if (ownerPassword || userPassword) { + authData = makeAuthData(ownerPassword, userPassword); + } else { + authData = NULL; + } + ok = authorize(authData); + if (authData) { + freeAuthData(authData); + } + for (i = 0; !ok && i < 3; ++i) { + if (!(authData = getAuthData())) { + break; + } + ok = authorize(authData); + if (authData) { + freeAuthData(authData); + } + } + if (!ok) { + error(errCommandLine, -1, "Incorrect password"); + } + return ok; +} + +//------------------------------------------------------------------------ +// StandardSecurityHandler +//------------------------------------------------------------------------ + +class StandardAuthData { +public: + + StandardAuthData(GString *ownerPasswordA, GString *userPasswordA) { + ownerPassword = ownerPasswordA; + userPassword = userPasswordA; + } + + ~StandardAuthData() { + if (ownerPassword) { + delete ownerPassword; + } + if (userPassword) { + delete userPassword; + } + } + + GString *ownerPassword; + GString *userPassword; +}; + +StandardSecurityHandler::StandardSecurityHandler(PDFDoc *docA, + Object *encryptDictA): + SecurityHandler(docA) +{ + Object versionObj, revisionObj, lengthObj; + Object ownerKeyObj, userKeyObj, ownerEncObj, userEncObj; + Object permObj, fileIDObj, fileIDObj1; + Object cryptFiltersObj, streamFilterObj, stringFilterObj; + Object cryptFilterObj, cfmObj, cfLengthObj; + Object encryptMetadataObj; + + ok = gFalse; + fileID = NULL; + ownerKey = NULL; + userKey = NULL; + ownerEnc = NULL; + userEnc = NULL; + fileKeyLength = 0; + + //--- get the main parameters + 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() || + !permObj.isInt() || + !ownerKeyObj.isString() || + !userKeyObj.isString()) { + error(errSyntaxError, -1, "Invalid encryption parameters"); + goto done; + } + 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; + + //--- check for a crypt filter (which can modify the parameters) + //~ 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 || encRevision == 6)) { + 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 + stringFilterObj.free(); + streamFilterObj.free(); + cryptFiltersObj.free(); + goto done; + } + if (cryptFiltersObj.dictLookup(streamFilterObj.getName(), + &cryptFilterObj)->isDict()) { + cryptFilterObj.dictLookup("CFM", &cfmObj); + if (cfmObj.isName("V2")) { + if (cryptFilterObj.dictLookup("Length", + &cfLengthObj)->isInt()) { + fileKeyLength = cfLengthObj.getInt(); + } + cfLengthObj.free(); + encVersion = 2; + encRevision = 3; + } else if (cfmObj.isName("AESV2")) { + if (cryptFilterObj.dictLookup("Length", + &cfLengthObj)->isInt()) { + fileKeyLength = cfLengthObj.getInt(); + } + cfLengthObj.free(); + encVersion = 2; + encRevision = 3; + encAlgorithm = cryptAES; + } else if (cfmObj.isName("AESV3")) { + if (cryptFilterObj.dictLookup("Length", + &cfLengthObj)->isInt()) { + fileKeyLength = cfLengthObj.getInt(); + } + cfLengthObj.free(); + encVersion = 5; + if (encRevision != 5 && encRevision != 6) { + encRevision = 6; + } + encAlgorithm = cryptAES256; + // The PDF 2.0 spec says Length and CF.Length are both deprecated. + // Acrobat X honors Length and ignores CF.Length. + // I think it's safest to ignore both. + fileKeyLength = 32; + } + cfmObj.free(); + } + cryptFilterObj.free(); + } + stringFilterObj.free(); + streamFilterObj.free(); + cryptFiltersObj.free(); + if (encryptDictA->dictLookup("EncryptMetadata", + &encryptMetadataObj)->isBool()) { + encryptMetadata = encryptMetadataObj.getBool(); + } + encryptMetadataObj.free(); + } + + //--- version-specific parameters + if (encRevision <= 4) { + if (ownerKeyObj.getString()->getLength() != 32 || + userKeyObj.getString()->getLength() != 32) { + error(errSyntaxError, -1, "Invalid encryption key length"); + // this is non-fatal -- see below + } + } else if (encRevision <= 6) { + // the spec says 48 bytes, but Acrobat pads them out longer + if (ownerKeyObj.getString()->getLength() < 48 || + userKeyObj.getString()->getLength() < 48 || + !ownerEncObj.isString() || + ownerEncObj.getString()->getLength() != 32 || + !userEncObj.isString() || + userEncObj.getString()->getLength() != 32) { + error(errSyntaxError, -1, "Invalid encryption key length"); + goto done; + } + } + permFlags = permObj.getInt(); + ownerKey = ownerKeyObj.getString()->copy(); + userKey = userKeyObj.getString()->copy(); + if (encRevision <= 4) { + // Adobe apparently zero-pads the U value (and maybe the O value?) + // if it's short + while (ownerKey->getLength() < 32) { + ownerKey->append((char)0x00); + } + while (userKey->getLength() < 32) { + userKey->append((char)0x00); + } + } + 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(); + } + if (fileKeyLength > 16 || fileKeyLength <= 0) { + fileKeyLength = 16; + } + ok = gTrue; + } else if (encVersion == 5 && (encRevision == 5 || encRevision == 6)) { + fileID = new GString(); // unused for V=R=5 + ownerEnc = ownerEncObj.getString()->copy(); + userEnc = userEncObj.getString()->copy(); + if (fileKeyLength > 32 || fileKeyLength <= 0) { + fileKeyLength = 32; + } + ok = gTrue; + } else { + error(errUnimplemented, -1, + "Unsupported version/revision ({0:d}/{1:d}) of Standard security handler", + encVersion, encRevision); + } + + done: + fileIDObj.free(); + permObj.free(); + userEncObj.free(); + ownerEncObj.free(); + userKeyObj.free(); + ownerKeyObj.free(); + lengthObj.free(); + revisionObj.free(); + versionObj.free(); +} + +StandardSecurityHandler::~StandardSecurityHandler() { + if (fileID) { + delete fileID; + } + if (ownerKey) { + delete ownerKey; + } + 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, + GString *userPassword) { + return new StandardAuthData(ownerPassword ? ownerPassword->copy() + : (GString *)NULL, + userPassword ? userPassword->copy() + : (GString *)NULL); +} + +void *StandardSecurityHandler::getAuthData() { + PDFCore *core; + GString *password; + + if (!(core = doc->getCore()) || + !(password = core->getPassword())) { + return NULL; + } + return new StandardAuthData(password, password->copy()); +} + +void StandardSecurityHandler::freeAuthData(void *authData) { + delete (StandardAuthData *)authData; +} + +GBool StandardSecurityHandler::authorize(void *authData) { + GString *ownerPassword, *userPassword; + + if (!ok) { + return gFalse; + } + if (authData) { + ownerPassword = ((StandardAuthData *)authData)->ownerPassword; + userPassword = ((StandardAuthData *)authData)->userPassword; + } else { + ownerPassword = NULL; + userPassword = NULL; + } + if (!Decrypt::makeFileKey(encVersion, encRevision, fileKeyLength, + ownerKey, userKey, ownerEnc, userEnc, + permFlags, fileID, + ownerPassword, userPassword, fileKey, + encryptMetadata, &ownerPasswordOk)) { + return gFalse; + } + return gTrue; +} diff --git a/xpdf/SecurityHandler.h b/xpdf/SecurityHandler.h new file mode 100644 index 0000000..6346233 --- /dev/null +++ b/xpdf/SecurityHandler.h @@ -0,0 +1,127 @@ +//======================================================================== +// +// SecurityHandler.h +// +// Copyright 2004 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef SECURITYHANDLER_H +#define SECURITYHANDLER_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "gtypes.h" +#include "Object.h" + +class GString; +class PDFDoc; +struct XpdfSecurityHandler; + +//------------------------------------------------------------------------ +// SecurityHandler +//------------------------------------------------------------------------ + +class SecurityHandler { +public: + + static SecurityHandler *make(PDFDoc *docA, Object *encryptDictA); + + 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 and (in + // "batch" mode), and if those fail, it will attempt to request a + // password from the user. This is the high-level function that + // calls the lower level functions for the specific security handler + // (requesting a password three times, etc.). Returns true if the + // document can be opened (if it's unencrypted, or if a correct + // password is obtained); false otherwise (encrypted and no correct + // password). + GBool checkEncryption(GString *ownerPassword, + GString *userPassword); + + // Create authorization data for the specified owner and user + // passwords. If the security handler doesn't support "batch" mode, + // this function should return NULL. + virtual void *makeAuthData(GString *ownerPassword, + GString *userPassword) = 0; + + // Construct authorization data, typically by prompting the user for + // a password. Returns an authorization data object, or NULL to + // cancel. + virtual void *getAuthData() = 0; + + // Free the authorization data returned by makeAuthData or + // getAuthData. + virtual void freeAuthData(void *authData) = 0; + + // Attempt to authorize the document, using the supplied + // authorization data (which may be NULL). Returns true if + // successful (i.e., if at least the right to open the document was + // granted). + virtual GBool authorize(void *authData) = 0; + + // Return the various authorization parameters. These are only + // valid after authorize has returned true. + virtual int getPermissionFlags() = 0; + virtual GBool getOwnerPasswordOk() = 0; + virtual Guchar *getFileKey() = 0; + virtual int getFileKeyLength() = 0; + virtual int getEncVersion() = 0; + virtual CryptAlgorithm getEncAlgorithm() = 0; + +protected: + + PDFDoc *doc; +}; + +//------------------------------------------------------------------------ +// StandardSecurityHandler +//------------------------------------------------------------------------ + +class StandardSecurityHandler: public SecurityHandler { +public: + + StandardSecurityHandler(PDFDoc *docA, Object *encryptDictA); + virtual ~StandardSecurityHandler(); + + virtual GBool isUnencrypted(); + virtual void *makeAuthData(GString *ownerPassword, + GString *userPassword); + virtual void *getAuthData(); + virtual void freeAuthData(void *authData); + virtual GBool authorize(void *authData); + virtual int getPermissionFlags() { return permFlags; } + virtual GBool getOwnerPasswordOk() { return ownerPasswordOk; } + virtual Guchar *getFileKey() { return fileKey; } + virtual int getFileKeyLength() { return fileKeyLength; } + virtual int getEncVersion() { return encVersion; } + virtual CryptAlgorithm getEncAlgorithm() { return encAlgorithm; } + +private: + + int permFlags; + GBool ownerPasswordOk; + Guchar fileKey[32]; + int fileKeyLength; + int encVersion; + int encRevision; + CryptAlgorithm encAlgorithm; + GBool encryptMetadata; + + GString *ownerKey, *userKey; + GString *ownerEnc, *userEnc; + GString *fileID; + GBool ok; +}; + +#endif diff --git a/xpdf/ShadingImage.cc b/xpdf/ShadingImage.cc new file mode 100644 index 0000000..d8dc24e --- /dev/null +++ b/xpdf/ShadingImage.cc @@ -0,0 +1,1327 @@ +//======================================================================== +// +// ShadingImage.cc +// +// Copyright 2020 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include "Trace.h" +#include "GfxState.h" +#include "SplashBitmap.h" +#include "SplashPattern.h" +#include "SplashPath.h" +#include "Splash.h" +#include "ShadingImage.h" + +// Max recursive depth for a patch mesh shading fill. +#define patchMaxDepth 10 + +// Max delta allowed in any color component for a patch mesh shading +// fill. +#define patchColorDelta (dblToCol(1 / 256.0)) + +SplashBitmap *ShadingImage::generateBitmap(GfxState *state, + GfxShading *shading, + SplashColorMode mode, + GBool reverseVideo, + Splash *parentSplash, + SplashBitmap *parentBitmap, + int *xOut, int *yOut) { + switch (shading->getType()) { + case 1: + return generateFunctionBitmap(state, (GfxFunctionShading *)shading, + mode, reverseVideo, + parentSplash, parentBitmap, xOut, yOut); + break; + case 2: + return generateAxialBitmap(state, (GfxAxialShading *)shading, + mode, reverseVideo, + parentSplash, parentBitmap, xOut, yOut); + break; + case 3: + return generateRadialBitmap(state, (GfxRadialShading *)shading, + mode, reverseVideo, + parentSplash, parentBitmap, xOut, yOut); + break; + case 4: + case 5: + return generateGouraudTriangleBitmap(state, + (GfxGouraudTriangleShading *)shading, + mode, reverseVideo, + parentSplash, parentBitmap, + xOut, yOut); + break; + case 6: + case 7: + return generatePatchMeshBitmap(state, (GfxPatchMeshShading *)shading, + mode, reverseVideo, + parentSplash, parentBitmap, xOut, yOut); + break; + default: + return NULL; + } +} + +SplashBitmap *ShadingImage::generateFunctionBitmap(GfxState *state, + GfxFunctionShading *shading, + SplashColorMode mode, + GBool reverseVideo, + Splash *parentSplash, + SplashBitmap *parentBitmap, + int *xOut, int *yOut) { + // get the shading parameters + double x0, y0, x1, y1; + shading->getDomain(&x0, &y0, &x1, &y1); + double *patternMat = shading->getMatrix(); + + // get the clip bbox + double fxMin, fyMin, fxMax, fyMax; + state->getClipBBox(&fxMin, &fyMin, &fxMax, &fyMax); + if (fxMin > fxMax || fyMin > fyMax) { + return NULL; + } + + // convert to integer coords + int xMin = (int)floor(fxMin); + int yMin = (int)floor(fyMin); + int xMax = (int)floor(fxMax) + 1; + int yMax = (int)floor(fyMax) + 1; + int bitmapWidth = xMax - xMin; + int bitmapHeight = yMax - yMin; + + // allocate the bitmap + traceMessage("function shading fill bitmap"); + SplashBitmap *bitmap = new SplashBitmap(bitmapWidth, bitmapHeight, 1, mode, + gTrue, gTrue, parentBitmap); + int nComps = splashColorModeNComps[mode]; + + // compute the domain -> device space transform = mat * CTM + double *ctm = state->getCTM(); + double mat[6]; + mat[0] = patternMat[0] * ctm[0] + patternMat[1] * ctm[2]; + mat[1] = patternMat[0] * ctm[1] + patternMat[1] * ctm[3]; + mat[2] = patternMat[2] * ctm[0] + patternMat[3] * ctm[2]; + mat[3] = patternMat[2] * ctm[1] + patternMat[3] * ctm[3]; + mat[4] = patternMat[4] * ctm[0] + patternMat[5] * ctm[2] + ctm[4]; + mat[5] = patternMat[4] * ctm[1] + patternMat[5] * ctm[3] + ctm[5]; + + // compute the device space -> domain transform + double det = mat[0] * mat[3] - mat[1] * mat[2]; + if (fabs(det) < 0.000001) { + return NULL; + } + det = 1 / det; + double iMat[6]; + iMat[0] = mat[3] * det; + iMat[1] = -mat[1] * det; + iMat[2] = -mat[2] * det; + iMat[3] = mat[0] * det; + iMat[4] = (mat[2] * mat[5] - mat[3] * mat[4]) * det; + iMat[5] = (mat[1] * mat[4] - mat[0] * mat[5]) * det; + + // fill the bitmap + SplashColorPtr dataPtr = bitmap->getDataPtr(); + Guchar *alphaPtr = bitmap->getAlphaPtr(); + for (int y = 0; y < bitmapHeight; ++y) { + for (int x = 0; x < bitmapWidth; ++x) { + + // convert coords to the pattern domain + double tx = xMin + x + 0.5; + double ty = yMin + y + 0.5; + double xx = tx * iMat[0] + ty * iMat[2] + iMat[4]; + double yy = tx * iMat[1] + ty * iMat[3] + iMat[5]; + + // get the color + if (xx >= x0 && xx <= x1 && yy >= y0 && yy <= y1) { + GfxColor color; + shading->getColor(xx, yy, &color); + SplashColor sColor; + computeShadingColor(state, mode, reverseVideo, &color, sColor); + for (int i = 0; i < nComps; ++i) { + *dataPtr++ = sColor[i]; + } + *alphaPtr++ = 0xff; + } else { + dataPtr += nComps; + *alphaPtr++ = 0; + } + } + } + + *xOut = xMin; + *yOut = yMin; + return bitmap; +} + +SplashBitmap *ShadingImage::generateAxialBitmap(GfxState *state, + GfxAxialShading *shading, + SplashColorMode mode, + GBool reverseVideo, + Splash *parentSplash, + SplashBitmap *parentBitmap, + int *xOut, int *yOut) { + // get the shading parameters + double x0, y0, x1, y1; + shading->getCoords(&x0, &y0, &x1, &y1); + double t0 = shading->getDomain0(); + double t1 = shading->getDomain1(); + GBool ext0 = shading->getExtend0(); + GBool ext1 = shading->getExtend1(); + double dx = x1 - x0; + double dy = y1 - y0; + double d = dx * dx + dy * dy; + GBool dZero = fabs(d) < 0.0001; + if (!dZero) { + d = 1 / d; + } + if (dZero && !ext0 && !ext1) { + return NULL; + } + + // get the clip bbox + double fxMin, fyMin, fxMax, fyMax; + state->getClipBBox(&fxMin, &fyMin, &fxMax, &fyMax); + if (fxMin > fxMax || fyMin > fyMax) { + return NULL; + } + + // convert to integer coords + int xMin = (int)floor(fxMin); + int yMin = (int)floor(fyMin); + int xMax = (int)floor(fxMax) + 1; + int yMax = (int)floor(fyMax) + 1; + int bitmapWidth = xMax - xMin; + int bitmapHeight = yMax - yMin; + + // compute the inverse CTM + double *ctm = state->getCTM(); + double det = ctm[0] * ctm[3] - ctm[1] * ctm[2]; + if (fabs(det) < 0.000001) { + return NULL; + } + det = 1 / det; + double ictm[6]; + 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; + + // convert axis endpoints to device space + double xx0, yy0, xx1, yy1; + state->transform(x0, y0, &xx0, &yy0); + state->transform(x1, y1, &xx1, &yy1); + + // allocate the bitmap + traceMessage("axial shading fill bitmap"); + SplashBitmap *bitmap = new SplashBitmap(bitmapWidth, bitmapHeight, 1, mode, + gTrue, gTrue, parentBitmap); + int nComps = splashColorModeNComps[mode]; + + // special case: zero-length axis + if (dZero) { + GfxColor color; + if (ext0) { + shading->getColor(t0, &color); + } else { + shading->getColor(t1, &color); + } + SplashColor sColor; + computeShadingColor(state, mode, reverseVideo, &color, sColor); + SplashColorPtr dataPtr = bitmap->getDataPtr(); + for (int y = 0; y < bitmapHeight; ++y) { + for (int x = 0; x < bitmapWidth; ++x) { + for (int i = 0; i < nComps; ++i) { + *dataPtr++ = sColor[i]; + } + } + } + memset(bitmap->getAlphaPtr(), 0xff, (size_t)bitmapWidth * bitmapHeight); + + // special case: horizontal axis (in device space) + } else if (fabs(yy0 - yy1) < 0.01) { + for (int x = 0; x < bitmapWidth; ++x) { + SplashColorPtr dataPtr = bitmap->getDataPtr() + x * nComps; + Guchar *alphaPtr = bitmap->getAlphaPtr() + x; + double tx = xMin + x + 0.5; + double ty = yMin + 0.5; + double xx = tx * ictm[0] + ty * ictm[2] + ictm[4]; + double yy = tx * ictm[1] + ty * ictm[3] + ictm[5]; + double s = ((xx - x0) * dx + (yy - y0) * dy) * d; + GBool go = gFalse; + if (s < 0) { + go = ext0; + } else if (s > 1) { + go = ext1; + } else { + go = gTrue; + } + if (go) { + GfxColor color; + if (s <= 0) { + shading->getColor(t0, &color); + } else if (s >= 1) { + shading->getColor(t1, &color); + } else { + double t = t0 + s * (t1 - t0); + shading->getColor(t, &color); + } + SplashColor sColor; + computeShadingColor(state, mode, reverseVideo, &color, sColor); + for (int y = 0; y < bitmapHeight; ++y) { + for (int i = 0; i < nComps; ++i) { + dataPtr[i] = sColor[i]; + } + dataPtr += bitmap->getRowSize(); + *alphaPtr = 0xff; + alphaPtr += bitmapWidth; + } + } else { + for (int y = 0; y < bitmapHeight; ++y) { + *alphaPtr = 0; + alphaPtr += bitmapWidth; + } + } + } + + // special case: vertical axis (in device space) + } else if (fabs(xx0 - xx1) < 0.01) { + for (int y = 0; y < bitmapHeight; ++y) { + SplashColorPtr dataPtr = bitmap->getDataPtr() + y * bitmap->getRowSize(); + Guchar *alphaPtr = bitmap->getAlphaPtr() + y * bitmapWidth; + double tx = xMin + 0.5; + double ty = yMin + y + 0.5; + double xx = tx * ictm[0] + ty * ictm[2] + ictm[4]; + double yy = tx * ictm[1] + ty * ictm[3] + ictm[5]; + double s = ((xx - x0) * dx + (yy - y0) * dy) * d; + GBool go = gFalse; + if (s < 0) { + go = ext0; + } else if (s > 1) { + go = ext1; + } else { + go = gTrue; + } + if (go) { + GfxColor color; + if (s <= 0) { + shading->getColor(t0, &color); + } else if (s >= 1) { + shading->getColor(t1, &color); + } else { + double t = t0 + s * (t1 - t0); + shading->getColor(t, &color); + } + SplashColor sColor; + computeShadingColor(state, mode, reverseVideo, &color, sColor); + for (int x = 0; x < bitmapWidth; ++x) { + for (int i = 0; i < nComps; ++i) { + dataPtr[i] = sColor[i]; + } + dataPtr += nComps; + } + memset(alphaPtr, 0xff, bitmapWidth); + } else { + memset(alphaPtr, 0, bitmapWidth); + } + } + + // general case + } else { + // pre-compute colors along the axis + int nColors = (int)(1.5 * sqrt((xx1 - xx0) * (xx1 - xx0) + + (yy1 - yy0) * (yy1 - yy0))); + if (nColors < 16) { + nColors = 16; + } else if (nColors > 1024) { + nColors = 1024; + } + SplashColorPtr sColors = (SplashColorPtr)gmallocn(nColors, nComps); + SplashColorPtr sColor = sColors; + for (int i = 0; i < nColors; ++i) { + double s = (double)i / (double)(nColors - 1); + double t = t0 + s * (t1 - t0); + GfxColor color; + shading->getColor(t, &color); + computeShadingColor(state, mode, reverseVideo, &color, sColor); + sColor += nComps; + } + + SplashColorPtr dataPtr = bitmap->getDataPtr(); + Guchar *alphaPtr = bitmap->getAlphaPtr(); + for (int y = 0; y < bitmapHeight; ++y) { + for (int x = 0; x < bitmapWidth; ++x) { + + // convert coords to user space + double tx = xMin + x + 0.5; + double ty = yMin + y + 0.5; + double xx = tx * ictm[0] + ty * ictm[2] + ictm[4]; + double yy = tx * ictm[1] + ty * ictm[3] + ictm[5]; + + // compute the position along the axis + double s = ((xx - x0) * dx + (yy - y0) * dy) * d; + GBool go = gFalse; + if (s < 0) { + go = ext0; + } else if (s > 1) { + go = ext1; + } else { + go = gTrue; + } + if (go) { + if (s <= 0) { + sColor = sColors; + } else if (s >= 1) { + sColor = sColors + (nColors - 1) * nComps; + } else { + int i = (int)((nColors - 1) * s + 0.5); + sColor = sColors + i * nComps; + } + for (int i = 0; i < nComps; ++i) { + *dataPtr++ = sColor[i]; + } + *alphaPtr++ = 0xff; + } else { + dataPtr += nComps; + *alphaPtr++ = 0; + } + } + } + gfree(sColors); + } + + *xOut = xMin; + *yOut = yMin; + return bitmap; +} + +SplashBitmap *ShadingImage::generateRadialBitmap(GfxState *state, + GfxRadialShading *shading, + SplashColorMode mode, + GBool reverseVideo, + Splash *parentSplash, + SplashBitmap *parentBitmap, + int *xOut, int *yOut) { + // get the shading parameters + double x0, y0, r0, x1, y1, r1; + shading->getCoords(&x0, &y0, &r0, &x1, &y1, &r1); + double t0 = shading->getDomain0(); + double t1 = shading->getDomain1(); + GBool ext0 = shading->getExtend0(); + GBool ext1 = shading->getExtend1(); + double h = sqrt((x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0)); + GBool enclosed = fabs(r1 - r0) >= h; + + // get the clip bbox + double fxMin, fyMin, fxMax, fyMax; + state->getClipBBox(&fxMin, &fyMin, &fxMax, &fyMax); + if (fxMin > fxMax || fyMin > fyMax) { + return NULL; + } + + // intersect with shading region (in user space): if the extend + // flags are false (or just the larger extend flag is false, in the + // "enclosed" case), we can use the bbox for the two circles + if ((!ext0 && !ext1) || + (enclosed && !(r0 > r1 ? ext0 : ext1))) { + double uxMin = (x0 - r0) < (x1 - r1) ? (x0 - r0) : (x1 - r1); + double uxMax = (x0 + r0) > (x1 + r1) ? (x0 + r0) : (x1 + r1); + double uyMin = (y0 - r0) < (y1 - r1) ? (y0 - r0) : (y1 - r1); + double uyMax = (y0 + r0) > (y1 + r1) ? (y0 + r0) : (y1 + r1); + double dxMin, dyMin, dxMax, dyMax; + transformBBox(state, uxMin, uyMin, uxMax, uyMax, + &dxMin, &dyMin, &dxMax, &dyMax); + if (dxMin > fxMin) { + fxMin = dxMin; + } + if (dxMax < dxMax) { + fxMax = dxMax; + } + if (dyMin > fyMin) { + fyMin = dyMin; + } + if (dyMax < fyMax) { + fyMax = dyMax; + } + if (fxMin > fxMax || fyMin > fyMax) { + return NULL; + } + } + + // convert to integer coords + int xMin = (int)floor(fxMin); + int yMin = (int)floor(fyMin); + int xMax = (int)floor(fxMax) + 1; + int yMax = (int)floor(fyMax) + 1; + int bitmapWidth = xMax - xMin; + int bitmapHeight = yMax - yMin; + + // compute the inverse CTM + double *ctm = state->getCTM(); + double det = ctm[0] * ctm[3] - ctm[1] * ctm[2]; + if (fabs(det) < 0.000001) { + return NULL; + } + det = 1 / det; + double ictm[6]; + 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; + + // allocate the bitmap + traceMessage("radial shading fill bitmap"); + SplashBitmap *bitmap = new SplashBitmap(bitmapWidth, bitmapHeight, 1, mode, + gTrue, gTrue, parentBitmap); + int nComps = splashColorModeNComps[mode]; + + // pre-compute colors along the axis + int nColors = (int)sqrt((double)(bitmapWidth * bitmapWidth + + bitmapHeight * bitmapHeight)); + if (nColors < 16) { + nColors = 16; + } else if (nColors > 1024) { + nColors = 1024; + } + SplashColorPtr sColors = (SplashColorPtr)gmallocn(nColors, nComps); + SplashColorPtr sColor = sColors; + for (int i = 0; i < nColors; ++i) { + double s = (double)i / (double)(nColors - 1); + double t = t0 + s * (t1 - t0); + GfxColor color; + shading->getColor(t, &color); + computeShadingColor(state, mode, reverseVideo, &color, sColor); + sColor += nComps; + } + + // special case: in the "enclosed" + extended case, we can fill the + // bitmap with the outer color and just render inside the larger + // circle + int bxMin, byMin, bxMax, byMax; + if (enclosed && + ((r0 > r1 && ext0) || (r1 > r0 && ext1))) { + double uxMin, uyMin, uxMax, uyMax; + if (r0 > r1) { + sColor = sColors; + uxMin = x0 - r0; + uxMax = x0 + r0; + uyMin = y0 - r0; + uyMax = y0 + r0; + } else { + sColor = sColors + (nColors - 1) * nComps; + uxMin = x1 - r1; + uxMax = x1 + r1; + uyMin = y1 - r1; + uyMax = y1 + r1; + } + + // convert bbox of larger circle to device space + double dxMin, dyMin, dxMax, dyMax; + transformBBox(state, uxMin, uyMin, uxMax, uyMax, + &dxMin, &dyMin, &dxMax, &dyMax); + bxMin = (int)floor(dxMin - xMin); + if (bxMin < 0) { + bxMin = 0; + } + byMin = (int)floor(dyMin - yMin); + if (byMin < 0) { + byMin = 0; + } + bxMax = (int)floor(dxMax - xMin) + 1; + if (bxMax > bitmapWidth) { + bxMax = bitmapWidth; + } + byMax = (int)floor(dyMax - yMin) + 1; + if (byMax > bitmapHeight) { + byMax = bitmapHeight; + } + + // fill bitmap (except for the rectangle containing the larger circle) + SplashColorPtr dataPtr = bitmap->getDataPtr(); + Guchar *alphaPtr = bitmap->getAlphaPtr(); + for (int y = 0; y < bitmapHeight; ++y) { + for (int x = 0; x < bitmapWidth; ++x) { + if (y >= byMin && y < byMax && x >= bxMin && x < bxMax) { + dataPtr += nComps; + ++alphaPtr; + } else { + for (int i = 0; i < nComps; ++i) { + *dataPtr++ = sColor[i]; + } + *alphaPtr++ = 0xff; + } + } + } + + } else { + bxMin = 0; + byMin = 0; + bxMax = bitmapWidth; + byMax = bitmapHeight; + } + + // render the shading into the bitmap + double dx = x1 - x0; + double dy = y1 - y0; + double dr = r1 - r0; + double r0dr = r0 * dr; + double r02 = r0 * r0; + double a = dx * dx + dy * dy - dr * dr; + GBool aIsZero; + double a2; + if (fabs(a) < 0.00001) { + aIsZero = gTrue; + a2 = 0; + } else { + aIsZero = gFalse; + a2 = 1 / (2 * a); + } + for (int y = byMin; y < byMax; ++y) { + SplashColorPtr dataPtr = bitmap->getDataPtr() + + y * bitmap->getRowSize() + bxMin * nComps; + Guchar *alphaPtr = bitmap->getAlphaPtr() + + y * bitmap->getAlphaRowSize() + bxMin; + for (int x = bxMin; x < bxMax; ++x) { + + // convert coords to user space + double tx = xMin + x + 0.5; + double ty = yMin + y + 0.5; + double xx = tx * ictm[0] + ty * ictm[2] + ictm[4]; + double yy = tx * ictm[1] + ty * ictm[3] + ictm[5]; + + // compute the radius of the circle at x,y + double b = 2 * ((xx - x0) * dx + (yy - y0) * dy + r0dr); + double c = (xx - x0) * (xx - x0) + (yy - y0) * (yy - y0) - r02; + double s = 0; + GBool go = gFalse; + if (aIsZero) { + if (fabs(b) < 0.000001) { + if (c <= 0) { + if (ext0) { + s = 0; + go = gTrue; + } + } else { + if (ext1) { + s = 1; + go = gTrue; + } + } + } else { + double s0 = c / b; + double rs0 = r0 + s0 * (r1 - r0); + if ((s0 >= 0 || ext0) && (s0 <= 1 || ext1) && rs0 >= 0) { + s = s0; + go = gTrue; + } + } + } else { + double e = b*b - 4*a*c; + if (e >= 0) { + double es = sqrt(e); + double s0 = (b + es) * a2; + double s1 = (b - es) * a2; + double rs0 = r0 + s0 * (r1 - r0); + double rs1 = r0 + s1 * (r1 - r0); + if (s0 > s1) { + if ((s0 >= 0 || ext0) && (s0 <= 1 || ext1) && rs0 >= 0) { + s = s0; + go = gTrue; + } else if ((s1 >= 0 || ext0) && (s1 <= 1 || ext1) && rs1 >= 0) { + s = s1; + go = gTrue; + } + } else { + if ((s1 >= 0 || ext0) && (s1 <= 1 || ext1) && rs1 >= 0) { + s = s1; + go = gTrue; + } else if ((s0 >= 0 || ext0) && (s0 <= 1 || ext1) && rs0 >= 0) { + s = s0; + go = gTrue; + } + } + } + } + if (!go) { + dataPtr += nComps; + *alphaPtr++ = 0x00; + continue; + } + if (s <= 0) { + sColor = sColors; + } else if (s >= 1) { + sColor = sColors + (nColors - 1) * nComps; + } else { + int i = (int)((nColors - 1) * s + 0.5); + sColor = sColors + i * nComps; + } + for (int i = 0; i < nComps; ++i) { + *dataPtr++ = sColor[i]; + } + *alphaPtr++ = 0xff; + } + } + + gfree(sColors); + + *xOut = xMin; + *yOut = yMin; + return bitmap; +} + +SplashBitmap *ShadingImage::generateGouraudTriangleBitmap( + GfxState *state, + GfxGouraudTriangleShading *shading, + SplashColorMode mode, + GBool reverseVideo, + Splash *parentSplash, + SplashBitmap *parentBitmap, + int *xOut, int *yOut) { + // get the clip bbox + double fxMin, fyMin, fxMax, fyMax; + state->getClipBBox(&fxMin, &fyMin, &fxMax, &fyMax); + if (fxMin > fxMax || fyMin > fyMax) { + return NULL; + } + + // get the shading bbox + double tx0, ty0, tx1, ty1, dx, dy, txMin, tyMin, txMax, tyMax; + shading->getBBox(&tx0, &ty0, &tx1, &ty1); + state->transform(tx0, ty0, &dx, &dy); + txMin = txMax = dx; + tyMin = tyMax = dy; + state->transform(tx0, ty1, &dx, &dy); + if (dx < txMin) { + txMin = dx; + } else if (dx > txMax) { + txMax = dx; + } + if (dy < tyMin) { + tyMin = dy; + } else if (dy > tyMax) { + tyMax = dy; + } + state->transform(tx1, ty0, &dx, &dy); + if (dx < txMin) { + txMin = dx; + } else if (dx > txMax) { + txMax = dx; + } + if (dy < tyMin) { + tyMin = dy; + } else if (dy > tyMax) { + tyMax = dy; + } + state->transform(tx1, ty1, &dx, &dy); + if (dx < txMin) { + txMin = dx; + } else if (dx > txMax) { + txMax = dx; + } + if (dy < tyMin) { + tyMin = dy; + } else if (dy > tyMax) { + tyMax = dy; + } + if (txMin > fxMin) { + fxMin = txMin; + } + if (txMax < fxMax) { + fxMax = txMax; + } + if (tyMin > fyMin) { + fyMin = tyMin; + } + if (tyMax < fyMax) { + fyMax = tyMax; + } + if (fxMin > fxMax || fyMin > fyMax) { + return NULL; + } + + // convert to integer coords + int xMin = (int)floor(fxMin); + int yMin = (int)floor(fyMin); + int xMax = (int)floor(fxMax) + 1; + int yMax = (int)floor(fyMax) + 1; + int bitmapWidth = xMax - xMin; + int bitmapHeight = yMax - yMin; + + // allocate the bitmap + traceMessage("Gouraud triangle shading fill bitmap"); + SplashBitmap *bitmap = new SplashBitmap(bitmapWidth, bitmapHeight, 1, mode, + gTrue, gTrue, parentBitmap); + + // clear the bitmap + memset(bitmap->getDataPtr(), 0, bitmap->getHeight() * bitmap->getRowSize()); + memset(bitmap->getAlphaPtr(), 0, bitmap->getHeight() * bitmap->getWidth()); + + // draw the triangles + for (int i = 0; i < shading->getNTriangles(); ++i) { + double x0, y0, x1, y1, x2, y2; + double color0[gfxColorMaxComps]; + double color1[gfxColorMaxComps]; + double color2[gfxColorMaxComps]; + shading->getTriangle(i, &x0, &y0, color0, + &x1, &y1, color1, + &x2, &y2, color2); + gouraudFillTriangle(state, bitmap, mode, reverseVideo, + xMin, yMin, xMax, yMax, + x0, y0, color0, x1, y1, color1, x2, y2, color2, + shading); + } + + *xOut = xMin; + *yOut = yMin; + return bitmap; +} + +void ShadingImage::gouraudFillTriangle(GfxState *state, SplashBitmap *bitmap, + SplashColorMode mode, + GBool reverseVideo, + int xMin, int yMin, int xMax, int yMax, + double x0, double y0, double *color0, + double x1, double y1, double *color1, + double x2, double y2, double *color2, + GfxGouraudTriangleShading *shading) { + int nShadingComps = shading->getNComps(); + int nBitmapComps = splashColorModeNComps[mode]; + + //--- transform the vertices to device space, sort by y + double dx0, dy0, dx1, dy1, dx2, dy2; + state->transform(x0, y0, &dx0, &dy0); + state->transform(x1, y1, &dx1, &dy1); + state->transform(x2, y2, &dx2, &dy2); + if (dy0 > dy1) { + double t = dx0; dx0 = dx1; dx1 = t; + t = dy0; dy0 = dy1; dy1 = t; + double *tc = color0; color0 = color1; color1 = tc; + } + if (dy1 > dy2) { + double t = dx1; dx1 = dx2; dx2 = t; + t = dy1; dy1 = dy2; dy2 = t; + double *tc = color1; color1 = color2; color2 = tc; + } + if (dy0 > dy1) { + double t = dx0; dx0 = dx1; dx1 = t; + t = dy0; dy0 = dy1; dy1 = t; + double *tc = color0; color0 = color1; color1 = tc; + } + + //--- y loop + int syMin = (int)floor(dy0); + if (syMin < yMin) { + syMin = yMin; + } + int syMax = (int)floor(dy2) + 1; + if (syMax > yMax) { + syMax = yMax; + } + for (int sy = syMin; sy < syMax; ++sy) { + + //--- vertical interpolation + double xx0, xx1; + double cc0[gfxColorMaxComps], cc1[gfxColorMaxComps]; + if (sy <= dy0) { + xx0 = xx1 = dx0; + for (int i = 0; i < nShadingComps; ++i) { + cc0[i] = cc1[i] = color0[i]; + } + } else if (sy >= dy2) { + xx0 = xx1 = dx2; + for (int i = 0; i < nShadingComps; ++i) { + cc0[i] = cc1[i] = color2[i]; + } + } else { + if (sy <= dy1) { + double interp = (sy - dy0) / (dy1 - dy0); + xx0 = dx0 + interp * (dx1 - dx0); + for (int i = 0; i < nShadingComps; ++i) { + cc0[i] = color0[i] + interp * (color1[i] - color0[i]); + } + } else { + double interp = (sy - dy1) / (dy2 - dy1); + xx0 = dx1 + interp * (dx2 - dx1); + for (int i = 0; i < nShadingComps; ++i) { + cc0[i] = color1[i] + interp * (color2[i] - color1[i]); + } + } + double interp = (sy - dy0) / (dy2 - dy0); + xx1 = dx0 + interp * (dx2 - dx0); + for (int i = 0; i < nShadingComps; ++i) { + cc1[i] = color0[i] + interp * (color2[i] - color0[i]); + } + } + + //--- x loop + if (xx0 > xx1) { + double t = xx0; xx0 = xx1; xx1 = t; + for (int i = 0; i < nShadingComps; ++i) { + t = cc0[i]; cc0[i] = cc1[i]; cc1[i] = t; + } + } + int sxMin = (int)floor(xx0); + if (sxMin < xMin) { + sxMin = xMin; + } + int sxMax = (int)floor(xx1) + 1; + if (sxMax > xMax) { + sxMax = xMax; + } + SplashColorPtr dataPtr = bitmap->getDataPtr() + + (sy - yMin) * bitmap->getRowSize() + + (sxMin - xMin) * nBitmapComps; + if (sxMin < sxMax) { + Guchar *alphaPtr = bitmap->getAlphaPtr() + + (sy - yMin) * bitmap->getWidth() + + (sxMin - xMin); + memset(alphaPtr, 0xff, sxMax - sxMin); + } + for (int sx = sxMin; sx < sxMax; ++sx) { + + //--- horizontal interpolation + double cc[gfxColorMaxComps]; + if (sx <= xx0) { + for (int i = 0; i < nShadingComps; ++i) { + cc[i] = cc0[i]; + } + } else if (sx >= xx1) { + for (int i = 0; i < nShadingComps; ++i) { + cc[i] = cc1[i]; + } + } else { + for (int i = 0; i < nShadingComps; ++i) { + double interp = (sx - xx0) / (xx1 - xx0); + cc[i] = cc0[i] + interp * (cc1[i] - cc0[i]); + } + } + + //--- compute color and set pixel + GfxColor gColor; + shading->getColor(cc, &gColor); + SplashColor sColor; + computeShadingColor(state, mode, reverseVideo, &gColor, sColor); + for (int i = 0; i < nBitmapComps; ++i) { + dataPtr[i] = sColor[i]; + } + dataPtr += nBitmapComps; + } + } +} + +SplashBitmap *ShadingImage::generatePatchMeshBitmap( + GfxState *state, + GfxPatchMeshShading *shading, + SplashColorMode mode, + GBool reverseVideo, + Splash *parentSplash, + SplashBitmap *parentBitmap, + int *xOut, int *yOut) { + // get the clip bbox + double fxMin, fyMin, fxMax, fyMax; + state->getClipBBox(&fxMin, &fyMin, &fxMax, &fyMax); + if (fxMin > fxMax || fyMin > fyMax) { + return NULL; + } + + // get the shading bbox + double tx0, ty0, tx1, ty1, dx, dy, txMin, tyMin, txMax, tyMax; + shading->getBBox(&tx0, &ty0, &tx1, &ty1); + state->transform(tx0, ty0, &dx, &dy); + txMin = txMax = dx; + tyMin = tyMax = dy; + state->transform(tx0, ty1, &dx, &dy); + if (dx < txMin) { + txMin = dx; + } else if (dx > txMax) { + txMax = dx; + } + if (dy < tyMin) { + tyMin = dy; + } else if (dy > tyMax) { + tyMax = dy; + } + state->transform(tx1, ty0, &dx, &dy); + if (dx < txMin) { + txMin = dx; + } else if (dx > txMax) { + txMax = dx; + } + if (dy < tyMin) { + tyMin = dy; + } else if (dy > tyMax) { + tyMax = dy; + } + state->transform(tx1, ty1, &dx, &dy); + if (dx < txMin) { + txMin = dx; + } else if (dx > txMax) { + txMax = dx; + } + if (dy < tyMin) { + tyMin = dy; + } else if (dy > tyMax) { + tyMax = dy; + } + if (txMin > fxMin) { + fxMin = txMin; + } + if (txMax < fxMax) { + fxMax = txMax; + } + if (tyMin > fyMin) { + fyMin = tyMin; + } + if (tyMax < fyMax) { + fyMax = tyMax; + } + if (fxMin > fxMax || fyMin > fyMax) { + return NULL; + } + + // convert to integer coords + int xMin = (int)floor(fxMin); + int yMin = (int)floor(fyMin); + int xMax = (int)floor(fxMax) + 1; + int yMax = (int)floor(fyMax) + 1; + int bitmapWidth = xMax - xMin; + int bitmapHeight = yMax - yMin; + + // allocate the bitmap + traceMessage("Gouraud triangle shading fill bitmap"); + SplashBitmap *bitmap = new SplashBitmap(bitmapWidth, bitmapHeight, 1, mode, + gTrue, gTrue, parentBitmap); + + // allocate a Splash object + // vector antialiasing is disabled to avoid artifacts along triangle edges + Splash *splash = new Splash(bitmap, gFalse, + parentSplash->getImageCache(), + parentSplash->getScreen()); + SplashColor zero; + for (int i = 0; i < splashColorModeNComps[mode]; ++i) { + zero[i] = 0; + } + splash->clear(zero, 0x00); + + // draw the patches + int start; + if (shading->getNPatches() > 128) { + start = 3; + } else if (shading->getNPatches() > 64) { + start = 2; + } else if (shading->getNPatches() > 16) { + start = 1; + } else { + start = 0; + } + for (int i = 0; i < shading->getNPatches(); ++i) { + fillPatch(state, splash, mode, reverseVideo, + xMin, yMin, shading->getPatch(i), shading, start); + } + + delete splash; + + *xOut = xMin; + *yOut = yMin; + return bitmap; +} + +void ShadingImage::fillPatch(GfxState *state, Splash *splash, + SplashColorMode mode, GBool reverseVideo, + int xMin, int yMin, + GfxPatch *patch, + GfxPatchMeshShading *shading, + int depth) { + GfxColor c00; + shading->getColor(patch->color[0][0], &c00); + GBool stop = gFalse; + + // stop subdivision at max depth + if (depth == patchMaxDepth) { + stop = gTrue; + } + + // stop subdivision if colors are close enough + if (!stop) { + int nComps = shading->getColorSpace()->getNComps(); + GfxColor c01, c10, c11; + shading->getColor(patch->color[0][1], &c01); + shading->getColor(patch->color[1][0], &c10); + shading->getColor(patch->color[1][1], &c11); + int i; + for (i = 0; i < nComps; ++i) { + if (abs(c00.c[i] - c01.c[i]) > patchColorDelta || + abs(c01.c[i] - c11.c[i]) > patchColorDelta || + abs(c11.c[i] - c10.c[i]) > patchColorDelta || + abs(c10.c[i] - c00.c[i]) > patchColorDelta) { + break; + } + } + if (i == nComps) { + stop = gTrue; + } + } + + // stop subdivision if patch is small enough + if (!stop) { + double xxMin = 0; + double yyMin = 0; + double xxMax = 0; + double yyMax = 0; + for (int j = 0; j < 4; ++j) { + for (int i = 0; i < 4; ++i) { + double xx, yy; + state->transformDelta(patch->x[i][j], patch->y[i][j], &xx, &yy); + if (i == 0 && j == 0) { + xxMin = xxMax = xx; + yyMin = yyMax = yy; + } else { + if (xx < xxMin) { + xxMin = xx; + } else if (xx > xxMax) { + xxMax = xx; + } + if (yy < yyMin) { + yyMin = yy; + } else if (yy > yyMax) { + yyMax = yy; + } + } + } + } + if (xxMax - xxMin < 1 && yyMax - yyMin < 1) { + stop = gTrue; + } + } + + // draw the patch + if (stop) { + SplashColor sColor; + computeShadingColor(state, mode, reverseVideo, &c00, sColor); + splash->setFillPattern(new SplashSolidColor(sColor)); + SplashPath *path = new SplashPath(); + double xx0, yy0, xx1, yy1, xx2, yy2, xx3, yy3; + state->transform(patch->x[0][0], patch->y[0][0], &xx0, &yy0); + path->moveTo(xx0 - xMin, yy0 - yMin); + state->transform(patch->x[0][1], patch->y[0][1], &xx1, &yy1); + state->transform(patch->x[0][2], patch->y[0][2], &xx2, &yy2); + state->transform(patch->x[0][3], patch->y[0][3], &xx3, &yy3); + path->curveTo(xx1 - xMin, yy1 - yMin, xx2 - xMin, yy2 - yMin, + xx3 - xMin, yy3 - yMin); + state->transform(patch->x[1][3], patch->y[1][3], &xx1, &yy1); + state->transform(patch->x[2][3], patch->y[2][3], &xx2, &yy2); + state->transform(patch->x[3][3], patch->y[3][3], &xx3, &yy3); + path->curveTo(xx1 - xMin, yy1 - yMin, xx2 - xMin, yy2 - yMin, + xx3 - xMin, yy3 - yMin); + state->transform(patch->x[3][2], patch->y[3][2], &xx1, &yy1); + state->transform(patch->x[3][1], patch->y[3][1], &xx2, &yy2); + state->transform(patch->x[3][0], patch->y[3][0], &xx3, &yy3); + path->curveTo(xx1 - xMin, yy1 - yMin, xx2 - xMin, yy2 - yMin, + xx3 - xMin, yy3 - yMin); + state->transform(patch->x[2][0], patch->y[2][0], &xx1, &yy1); + state->transform(patch->x[1][0], patch->y[1][0], &xx2, &yy2); + path->curveTo(xx1 - xMin, yy1 - yMin, xx2 - xMin, yy2 - yMin, + xx0 - xMin, yy0 - yMin); + path->close(); + splash->fill(path, gFalse); + delete path; + + // subdivide the patch + } else { + double xx[4][8], yy[4][8]; + for (int i = 0; i < 4; ++i) { + xx[i][0] = patch->x[i][0]; + yy[i][0] = patch->y[i][0]; + xx[i][1] = 0.5 * (patch->x[i][0] + patch->x[i][1]); + yy[i][1] = 0.5 * (patch->y[i][0] + patch->y[i][1]); + double xxm = 0.5 * (patch->x[i][1] + patch->x[i][2]); + double yym = 0.5 * (patch->y[i][1] + patch->y[i][2]); + xx[i][6] = 0.5 * (patch->x[i][2] + patch->x[i][3]); + yy[i][6] = 0.5 * (patch->y[i][2] + patch->y[i][3]); + xx[i][2] = 0.5 * (xx[i][1] + xxm); + yy[i][2] = 0.5 * (yy[i][1] + yym); + xx[i][5] = 0.5 * (xxm + xx[i][6]); + yy[i][5] = 0.5 * (yym + yy[i][6]); + xx[i][3] = xx[i][4] = 0.5 * (xx[i][2] + xx[i][5]); + yy[i][3] = yy[i][4] = 0.5 * (yy[i][2] + yy[i][5]); + xx[i][7] = patch->x[i][3]; + yy[i][7] = patch->y[i][3]; + } + GfxPatch patch00, patch01, patch10, patch11; + for (int i = 0; i < 4; ++i) { + patch00.x[0][i] = xx[0][i]; + patch00.y[0][i] = yy[0][i]; + patch00.x[1][i] = 0.5 * (xx[0][i] + xx[1][i]); + patch00.y[1][i] = 0.5 * (yy[0][i] + yy[1][i]); + double xxm = 0.5 * (xx[1][i] + xx[2][i]); + double yym = 0.5 * (yy[1][i] + yy[2][i]); + patch10.x[2][i] = 0.5 * (xx[2][i] + xx[3][i]); + patch10.y[2][i] = 0.5 * (yy[2][i] + yy[3][i]); + patch00.x[2][i] = 0.5 * (patch00.x[1][i] + xxm); + patch00.y[2][i] = 0.5 * (patch00.y[1][i] + yym); + patch10.x[1][i] = 0.5 * (xxm + patch10.x[2][i]); + patch10.y[1][i] = 0.5 * (yym + patch10.y[2][i]); + patch00.x[3][i] = 0.5 * (patch00.x[2][i] + patch10.x[1][i]); + patch00.y[3][i] = 0.5 * (patch00.y[2][i] + patch10.y[1][i]); + patch10.x[0][i] = patch00.x[3][i]; + patch10.y[0][i] = patch00.y[3][i]; + patch10.x[3][i] = xx[3][i]; + patch10.y[3][i] = yy[3][i]; + } + for (int i = 4; i < 8; ++i) { + patch01.x[0][i-4] = xx[0][i]; + patch01.y[0][i-4] = yy[0][i]; + patch01.x[1][i-4] = 0.5 * (xx[0][i] + xx[1][i]); + patch01.y[1][i-4] = 0.5 * (yy[0][i] + yy[1][i]); + double xxm = 0.5 * (xx[1][i] + xx[2][i]); + double yym = 0.5 * (yy[1][i] + yy[2][i]); + patch11.x[2][i-4] = 0.5 * (xx[2][i] + xx[3][i]); + patch11.y[2][i-4] = 0.5 * (yy[2][i] + yy[3][i]); + patch01.x[2][i-4] = 0.5 * (patch01.x[1][i-4] + xxm); + patch01.y[2][i-4] = 0.5 * (patch01.y[1][i-4] + yym); + patch11.x[1][i-4] = 0.5 * (xxm + patch11.x[2][i-4]); + patch11.y[1][i-4] = 0.5 * (yym + patch11.y[2][i-4]); + patch01.x[3][i-4] = 0.5 * (patch01.x[2][i-4] + patch11.x[1][i-4]); + patch01.y[3][i-4] = 0.5 * (patch01.y[2][i-4] + patch11.y[1][i-4]); + patch11.x[0][i-4] = patch01.x[3][i-4]; + patch11.y[0][i-4] = patch01.y[3][i-4]; + patch11.x[3][i-4] = xx[3][i]; + patch11.y[3][i-4] = yy[3][i]; + } + for (int i = 0; i < shading->getNComps(); ++i) { + patch00.color[0][0][i] = patch->color[0][0][i]; + patch00.color[0][1][i] = 0.5 * (patch->color[0][0][i] + + patch->color[0][1][i]); + patch01.color[0][0][i] = patch00.color[0][1][i]; + patch01.color[0][1][i] = patch->color[0][1][i]; + patch01.color[1][1][i] = 0.5 * (patch->color[0][1][i] + + patch->color[1][1][i]); + patch11.color[0][1][i] = patch01.color[1][1][i]; + patch11.color[1][1][i] = patch->color[1][1][i]; + patch11.color[1][0][i] = 0.5 * (patch->color[1][1][i] + + patch->color[1][0][i]); + patch10.color[1][1][i] = patch11.color[1][0][i]; + patch10.color[1][0][i] = patch->color[1][0][i]; + patch10.color[0][0][i] = 0.5 * (patch->color[1][0][i] + + patch->color[0][0][i]); + patch00.color[1][0][i] = patch10.color[0][0][i]; + patch00.color[1][1][i] = 0.5 * (patch00.color[1][0][i] + + patch01.color[1][1][i]); + patch01.color[1][0][i] = patch00.color[1][1][i]; + patch11.color[0][0][i] = patch00.color[1][1][i]; + patch10.color[0][1][i] = patch00.color[1][1][i]; + } + fillPatch(state, splash, mode, reverseVideo, xMin, yMin, &patch00, + shading, depth + 1); + fillPatch(state, splash, mode, reverseVideo, xMin, yMin, &patch10, + shading, depth + 1); + fillPatch(state, splash, mode, reverseVideo, xMin, yMin, &patch01, + shading, depth + 1); + fillPatch(state, splash, mode, reverseVideo, xMin, yMin, &patch11, + shading, depth + 1); + } +} + +void ShadingImage::computeShadingColor(GfxState *state, + SplashColorMode mode, + GBool reverseVideo, + GfxColor *color, + SplashColorPtr sColor) { + GfxGray gray; + GfxRGB rgb; +#if SPLASH_CMYK + GfxCMYK cmyk; +#endif + + state->setFillColor(color); + switch (mode) { + case splashModeMono8: + state->getFillGray(&gray); + if (reverseVideo) { + gray = gfxColorComp1 - gray; + } + sColor[0] = colToByte(gray); + break; + case splashModeRGB8: + state->getFillRGB(&rgb); + if (reverseVideo) { + rgb.r = gfxColorComp1 - rgb.r; + rgb.g = gfxColorComp1 - rgb.g; + rgb.b = gfxColorComp1 - rgb.b; + } + sColor[0] = colToByte(rgb.r); + sColor[1] = colToByte(rgb.g); + sColor[2] = colToByte(rgb.b); + break; +#if SPLASH_CMYK + case splashModeCMYK8: + state->getFillCMYK(&cmyk); + sColor[0] = colToByte(cmyk.c); + sColor[1] = colToByte(cmyk.m); + sColor[2] = colToByte(cmyk.y); + sColor[3] = colToByte(cmyk.k); + break; +#endif + case splashModeMono1: + case splashModeBGR8: + // mode cannot be Mono1 or BGR8 + break; + } +} + +// Transform a user space bbox to a device space bbox. +void ShadingImage::transformBBox(GfxState *state, + double uxMin, double uyMin, + double uxMax, double uyMax, + double *dxMin, double *dyMin, + double *dxMax, double *dyMax) { + double tx, ty; + state->transform(uxMin, uyMin, &tx, &ty); + *dxMin = *dxMax = tx; + *dyMin = *dyMax = ty; + state->transform(uxMin, uyMax, &tx, &ty); + if (tx < *dxMin) { + *dxMin = tx; + } else if (tx > *dxMax) { + *dxMax = tx; + } + if (ty < *dyMin) { + *dyMin = ty; + } else if (ty > *dyMax) { + *dyMax = ty; + } + state->transform(uxMax, uyMin, &tx, &ty); + if (tx < *dxMin) { + *dxMin = tx; + } else if (tx > *dxMax) { + *dxMax = tx; + } + if (ty < *dyMin) { + *dyMin = ty; + } else if (ty > *dyMax) { + *dyMax = ty; + } + state->transform(uxMax, uyMax, &tx, &ty); + if (tx < *dxMin) { + *dxMin = tx; + } else if (tx > *dxMax) { + *dxMax = tx; + } + if (ty < *dyMin) { + *dyMin = ty; + } else if (ty > *dyMax) { + *dyMax = ty; + } +} + diff --git a/xpdf/ShadingImage.h b/xpdf/ShadingImage.h new file mode 100644 index 0000000..3bbff69 --- /dev/null +++ b/xpdf/ShadingImage.h @@ -0,0 +1,106 @@ +//======================================================================== +// +// ShadingImage.h +// +// Convert shading patterns to bitmaps. +// +// Copyright 2020 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef SHADINGIMAGE_H +#define SHADINGIMAGE_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "SplashTypes.h" + +class GfxState; +class GfxShading; +class SplashBitmap; +class Splash; + +class ShadingImage { +public: + + // Generate a [mode] bitmap for [shading], using the clipping and + // CTM info from [state]. Returns the bitmap and sets [xOut],[yOut] + // to the upper-left corner of the region in device space. Returns + // NULL if the clip region is empty. + static SplashBitmap *generateBitmap(GfxState *state, GfxShading *shading, + SplashColorMode mode, + GBool reverseVideo, + Splash *parentSplash, + SplashBitmap *parentBitmap, + int *xOut, int *yOut); + + +private: + + static SplashBitmap *generateFunctionBitmap(GfxState *state, + GfxFunctionShading *shading, + SplashColorMode mode, + GBool reverseVideo, + Splash *parentSplash, + SplashBitmap *parentBitmap, + int *xOut, int *yOut); + static SplashBitmap *generateAxialBitmap(GfxState *state, + GfxAxialShading *shading, + SplashColorMode mode, + GBool reverseVideo, + Splash *parentSplash, + SplashBitmap *parentBitmap, + int *xOut, int *yOut); + static SplashBitmap *generateRadialBitmap(GfxState *state, + GfxRadialShading *shading, + SplashColorMode mode, + GBool reverseVideo, + Splash *parentSplash, + SplashBitmap *parentBitmap, + int *xOut, int *yOut); + static SplashBitmap *generateGouraudTriangleBitmap( + GfxState *state, + GfxGouraudTriangleShading *shading, + SplashColorMode mode, + GBool reverseVideo, + Splash *parentSplash, + SplashBitmap *parentBitmap, + int *xOut, int *yOut); + static void gouraudFillTriangle(GfxState *state, SplashBitmap *bitmap, + SplashColorMode mode, + GBool reverseVideo, + int xMin, int yMin, int xMax, int yMax, + double x0, double y0, double *color0, + double x1, double y1, double *color1, + double x2, double y2, double *color2, + GfxGouraudTriangleShading *shading); + static SplashBitmap *generatePatchMeshBitmap(GfxState *state, + GfxPatchMeshShading *shading, + SplashColorMode mode, + GBool reverseVideo, + Splash *parentSplash, + SplashBitmap *parentBitmap, + int *xOut, int *yOut); + static void fillPatch(GfxState *state, Splash *splash, + SplashColorMode mode, GBool reverseVideo, + int xMin, int yMin, + GfxPatch *patch, + GfxPatchMeshShading *shading, + int depth); + static void computeShadingColor(GfxState *state, + SplashColorMode mode, + GBool reverseVideo, + GfxColor *color, + SplashColorPtr sColor); + static void transformBBox(GfxState *state, + double uxMin, double uyMin, + double uxMax, double uyMax, + double *dxMin, double *dyMin, + double *dxMax, double *dyMax); +}; + +#endif diff --git a/xpdf/SplashOutputDev.cc b/xpdf/SplashOutputDev.cc new file mode 100644 index 0000000..d758e25 --- /dev/null +++ b/xpdf/SplashOutputDev.cc @@ -0,0 +1,4550 @@ +//======================================================================== +// +// SplashOutputDev.cc +// +// Copyright 2003-2013 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include +#include +#include "gmempp.h" +#include "gfile.h" +#include "Trace.h" +#include "GlobalParams.h" +#include "Error.h" +#include "Object.h" +#include "Gfx.h" +#include "GfxFont.h" +#include "ShadingImage.h" +#include "Link.h" +#include "CharCodeToUnicode.h" +#include "FontEncodingTables.h" +#include "BuiltinFont.h" +#include "BuiltinFontTables.h" +#include "FoFiTrueType.h" +#include "FoFiType1C.h" +#include "JPXStream.h" +#include "SplashBitmap.h" +#include "SplashGlyphBitmap.h" +#include "SplashPattern.h" +#include "SplashScreen.h" +#include "SplashPath.h" +#include "SplashState.h" +#include "SplashErrorCodes.h" +#include "SplashFontEngine.h" +#include "SplashFont.h" +#include "SplashFontFile.h" +#include "SplashFontFileID.h" +#include "Splash.h" +#include "SplashOutputDev.h" + +#ifdef VMS +#if (__VMS_VER < 70000000) +extern "C" int unlink(char *filename); +#endif +#endif + +//------------------------------------------------------------------------ + +// max tile size (used in tilingPatternFill()) +// - Adobe uses a resolution-independent threshold here, of 6M sq pts +// - xpdf uses a resolution-dependent max, but with different values +// on 32-bit and 64-bit systems +#if SplashBitmapRowSizeMax == INT_MAX +# define maxTileSize 200000000 +#else +# define maxTileSize 2000000000 +#endif + +//------------------------------------------------------------------------ + +// Type 3 font cache size parameters +#define type3FontCacheAssoc 8 +#define type3FontCacheMaxSets 8 +#define type3FontCacheSize (128*1024) + +// Map StrokeAdjustMode (from GlobalParams) to SplashStrokeAdjustMode +// (for Splash). +static SplashStrokeAdjustMode mapStrokeAdjustMode[3] = { + splashStrokeAdjustOff, + splashStrokeAdjustNormal, + splashStrokeAdjustCAD +}; + +//------------------------------------------------------------------------ + +// 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); +} + +// Clip x to lie in [0, 255]. +static inline Guchar clip255(int x) { + return x < 0 ? 0 : x > 255 ? 255 : (Guchar)x; +} + + +//------------------------------------------------------------------------ +// Blend functions +//------------------------------------------------------------------------ + +static void splashOutBlendMultiply(SplashColorPtr src, SplashColorPtr dest, + SplashColorPtr blend, SplashColorMode cm) { + int i; + + for (i = 0; i < splashColorModeNComps[cm]; ++i) { + blend[i] = (Guchar)((dest[i] * src[i]) / 255); + } +} + +static void splashOutBlendScreen(SplashColorPtr src, SplashColorPtr dest, + SplashColorPtr blend, SplashColorMode cm) { + int i; + + for (i = 0; i < splashColorModeNComps[cm]; ++i) { + blend[i] = (Guchar)(dest[i] + src[i] - (dest[i] * src[i]) / 255); + } +} + +// note: this is the same as HardLight, with src/dest reversed +static void splashOutBlendOverlay(SplashColorPtr src, SplashColorPtr dest, + SplashColorPtr blend, SplashColorMode cm) { + int i; + + for (i = 0; i < splashColorModeNComps[cm]; ++i) { + // the spec says "if Cs <= 0.5" -- note that 0x80 is 128/255=0.5020 + blend[i] = dest[i] < 0x80 + ? (Guchar)((src[i] * 2 * dest[i]) / 255) + : (Guchar)(255 - 2 * ((255 - src[i]) * (255 - dest[i])) / 255); + } +} + +static void splashOutBlendDarken(SplashColorPtr src, SplashColorPtr dest, + SplashColorPtr blend, SplashColorMode cm) { + int i; + + for (i = 0; i < splashColorModeNComps[cm]; ++i) { + blend[i] = dest[i] < src[i] ? dest[i] : src[i]; + } +} + +static void splashOutBlendLighten(SplashColorPtr src, SplashColorPtr dest, + SplashColorPtr blend, SplashColorMode cm) { + int i; + + for (i = 0; i < splashColorModeNComps[cm]; ++i) { + blend[i] = dest[i] > src[i] ? dest[i] : src[i]; + } +} + +static void splashOutBlendColorDodge(SplashColorPtr src, SplashColorPtr dest, + SplashColorPtr blend, + SplashColorMode cm) { + int i; + + for (i = 0; i < splashColorModeNComps[cm]; ++i) { + if (dest[i] == 0) { + blend[i] = 0; + } else if (dest[i] >= 255 - src[i]) { + blend[i] = 255; + } else { + blend[i] = (Guchar)((dest[i] * 255) / (255 - src[i])); + } + } +} + +static void splashOutBlendColorBurn(SplashColorPtr src, SplashColorPtr dest, + SplashColorPtr blend, SplashColorMode cm) { + int i; + + for (i = 0; i < splashColorModeNComps[cm]; ++i) { + if (dest[i] == 255) { + blend[i] = 255; + } else if (255 - dest[i] >= src[i]) { + blend[i] = 0; + } else { + blend[i] = (Guchar)(255 - (((255 - dest[i]) * 255) / src[i])); + } + } +} + +static void splashOutBlendHardLight(SplashColorPtr src, SplashColorPtr dest, + SplashColorPtr blend, SplashColorMode cm) { + int i; + + for (i = 0; i < splashColorModeNComps[cm]; ++i) { + // the spec says "if Cs <= 0.5" -- note that 0x80 is 128/255=0.5020 + blend[i] = src[i] < 0x80 + ? (Guchar)((dest[i] * 2 * src[i]) / 255) + : (Guchar)(255 - 2 * ((255 - dest[i]) * (255 - src[i])) / 255); + } +} + +static void splashOutBlendSoftLight(SplashColorPtr src, SplashColorPtr dest, + SplashColorPtr blend, SplashColorMode cm) { + int i, x; + + for (i = 0; i < splashColorModeNComps[cm]; ++i) { + // the spec says "if Cs <= 0.5" -- note that 0x80 is 128/255=0.5020 + if (src[i] < 0x80) { + blend[i] = (Guchar)(dest[i] - + (255 - 2 * src[i]) * dest[i] * (255 - dest[i]) / + (255 * 255)); + } else { + // the spec says "if Cb <= 0.25" -- note that 0x40 is 64/255=0.2510 + if (dest[i] < 0x40) { + x = (((((16 * dest[i] - 12 * 255) * dest[i]) / 255) + + 4 * 255) * dest[i]) / 255; + } else { + x = (int)sqrt(255.0 * dest[i]); + } + blend[i] = (Guchar)(dest[i] + (2 * src[i] - 255) * (x - dest[i]) / 255); + } + } +} + +static void splashOutBlendDifference(SplashColorPtr src, SplashColorPtr dest, + SplashColorPtr blend, + SplashColorMode cm) { + int i; + + for (i = 0; i < splashColorModeNComps[cm]; ++i) { + blend[i] = dest[i] < src[i] ? (Guchar)(src[i] - dest[i]) + : (Guchar)(dest[i] - src[i]); + } +} + +static void splashOutBlendExclusion(SplashColorPtr src, SplashColorPtr dest, + SplashColorPtr blend, SplashColorMode cm) { + int i; + + for (i = 0; i < splashColorModeNComps[cm]; ++i) { + blend[i] = (Guchar)(dest[i] + src[i] - (2 * dest[i] * src[i]) / 255); + } +} + +static int getLum(int r, int g, int b) { + return (int)(0.3 * r + 0.59 * g + 0.11 * b); +} + +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, r, g, b; + + 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; + } + r = rIn; + g = gIn; + b = bIn; + if (rgbMin < 0) { + r = lum + ((r - lum) * lum) / (lum - rgbMin); + g = lum + ((g - lum) * lum) / (lum - rgbMin); + b = lum + ((b - lum) * lum) / (lum - rgbMin); + } + if (rgbMax > 255) { + r = lum + ((r - lum) * (255 - lum)) / (rgbMax - lum); + g = lum + ((g - lum) * (255 - lum)) / (rgbMax - lum); + b = lum + ((b - lum) * (255 - lum)) / (rgbMax - lum); + } + *rOut = (Guchar)r; + *gOut = (Guchar)g; + *bOut = (Guchar)b; +} + +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 (rIn < gIn) { + rgbMin = rIn; minOut = rOut; + rgbMid = gIn; midOut = gOut; + } else { + 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) { + Guchar r0, g0, b0; + + switch (cm) { + case splashModeMono1: + case splashModeMono8: + blend[0] = dest[0]; + break; + case splashModeRGB8: + case splashModeBGR8: + 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: + // 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]), + &blend[0], &blend[1], &blend[2]); + blend[3] = dest[3]; + break; +#endif + } +} + +static void splashOutBlendSaturation(SplashColorPtr src, SplashColorPtr dest, + SplashColorPtr blend, + SplashColorMode cm) { + Guchar r0, g0, b0; + + switch (cm) { + case splashModeMono1: + case splashModeMono8: + blend[0] = dest[0]; + break; + case splashModeRGB8: + case splashModeBGR8: + 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: + // 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]), + &blend[0], &blend[1], &blend[2]); + blend[3] = dest[3]; + break; +#endif + } +} + +static void splashOutBlendColor(SplashColorPtr src, SplashColorPtr dest, + SplashColorPtr blend, SplashColorMode cm) { + + switch (cm) { + case splashModeMono1: + case splashModeMono8: + blend[0] = dest[0]; + break; + case splashModeRGB8: + case splashModeBGR8: + 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: + // NB: inputs have already been converted to additive mode + setLum(src[0], src[1], src[2], getLum(dest[0], dest[1], dest[2]), + &blend[0], &blend[1], &blend[2]); + blend[3] = dest[3]; + break; +#endif + } +} + +static void splashOutBlendLuminosity(SplashColorPtr src, SplashColorPtr dest, + SplashColorPtr blend, + SplashColorMode cm) { + + switch (cm) { + case splashModeMono1: + case splashModeMono8: + blend[0] = dest[0]; + break; + case splashModeRGB8: + case splashModeBGR8: + 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: + // NB: inputs have already been converted to additive mode + setLum(dest[0], dest[1], dest[2], getLum(src[0], src[1], src[2]), + &blend[0], &blend[1], &blend[2]); + blend[3] = src[3]; + break; +#endif + } +} + +// NB: This must match the GfxBlendMode enum defined in GfxState.h. +SplashBlendFunc splashOutBlendFuncs[] = { + NULL, + &splashOutBlendMultiply, + &splashOutBlendScreen, + &splashOutBlendOverlay, + &splashOutBlendDarken, + &splashOutBlendLighten, + &splashOutBlendColorDodge, + &splashOutBlendColorBurn, + &splashOutBlendHardLight, + &splashOutBlendSoftLight, + &splashOutBlendDifference, + &splashOutBlendExclusion, + &splashOutBlendHue, + &splashOutBlendSaturation, + &splashOutBlendColor, + &splashOutBlendLuminosity +}; + + +//------------------------------------------------------------------------ +// SplashOutFontFileID +//------------------------------------------------------------------------ + +class SplashOutFontFileID: public SplashFontFileID { +public: + + SplashOutFontFileID(Ref *rA) { + r = *rA; + substIdx = -1; + oblique = 0; + } + + ~SplashOutFontFileID() {} + + GBool matches(SplashFontFileID *id) { + return ((SplashOutFontFileID *)id)->r.num == r.num && + ((SplashOutFontFileID *)id)->r.gen == r.gen; + } + + void setOblique(double obliqueA) { oblique = obliqueA; } + double getOblique() { return oblique; } + void setSubstIdx(int substIdxA) { substIdx = substIdxA; } + int getSubstIdx() { return substIdx; } + +private: + + Ref r; + double oblique; + int substIdx; +}; + +//------------------------------------------------------------------------ +// T3FontCache +//------------------------------------------------------------------------ + +struct T3FontCacheTag { + Gushort code; + Gushort mru; // valid bit (0x8000) and MRU index +}; + +class T3FontCache { +public: + + T3FontCache(Ref *fontID, double m11A, double m12A, + double m21A, double m22A, + int glyphXA, int glyphYA, int glyphWA, int glyphHA, + GBool validBBoxA, GBool aa); + ~T3FontCache(); + GBool matches(Ref *idA, double m11A, double m12A, + double m21A, double m22A) + { return fontID.num == idA->num && fontID.gen == idA->gen && + m11 == m11A && m12 == m12A && m21 == m21A && m22 == m22A; } + + Ref fontID; // PDF font ID + double m11, m12, m21, m22; // transform matrix + int glyphX, glyphY; // pixel offset of glyph bitmaps + int glyphW, glyphH; // size of glyph bitmaps, in pixels + GBool validBBox; // false if the bbox was [0 0 0 0] + int glyphSize; // size of glyph bitmaps, in bytes + int cacheSets; // number of sets in cache + int cacheAssoc; // cache associativity (glyphs per set) + Guchar *cacheData; // glyph pixmap cache + T3FontCacheTag *cacheTags; // cache tags, i.e., char codes + int refCount; // active reference count for this T3 font +}; + +T3FontCache::T3FontCache(Ref *fontIDA, double m11A, double m12A, + double m21A, double m22A, + int glyphXA, int glyphYA, int glyphWA, int glyphHA, + GBool validBBoxA, GBool aa) { + int i; + + fontID = *fontIDA; + m11 = m11A; + m12 = m12A; + m21 = m21A; + m22 = m22A; + glyphX = glyphXA; + glyphY = glyphYA; + 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 = 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)); + for (i = 0; i < cacheSets * cacheAssoc; ++i) { + cacheTags[i].mru = (Gushort)(i & (cacheAssoc - 1)); + } + refCount = 0; +} + +T3FontCache::~T3FontCache() { + gfree(cacheData); + gfree(cacheTags); +} + +struct T3GlyphStack { + Gushort code; // character code + + GBool haveDx; // set after seeing a d0/d1 operator + GBool doNotCache; // set if we see a gsave/grestore before + // the d0/d1 + + //----- cache info + T3FontCache *cache; // font cache for the current font + T3FontCacheTag *cacheTag; // pointer to cache tag for the glyph + Guchar *cacheData; // pointer to cache data for the glyph + + //----- saved state + SplashBitmap *origBitmap; + Splash *origSplash; + double origCTM4, origCTM5; + SplashStrokeAdjustMode savedStrokeAdjust; + + T3GlyphStack *next; // next object on stack +}; + +//------------------------------------------------------------------------ +// SplashTransparencyGroup +//------------------------------------------------------------------------ + +struct SplashTransparencyGroup { + int tx, ty; // translation coordinates + SplashBitmap *tBitmap; // bitmap for transparency group + GfxColorSpace *blendingColorSpace; + GBool isolated; + + //----- modified region in tBitmap + int modXMin, modYMin, modXMax, modYMax; + + //----- saved state + SplashBitmap *origBitmap; + Splash *origSplash; + SplashBitmap *backdropBitmap; + + SplashTransparencyGroup *next; +}; + +//------------------------------------------------------------------------ +// SplashOutputDev +//------------------------------------------------------------------------ + +SplashOutputDev::SplashOutputDev(SplashColorMode colorModeA, + int bitmapRowPadA, + GBool reverseVideoA, + SplashColorPtr paperColorA, + GBool bitmapTopDownA, + GBool allowAntialiasA) { + colorMode = colorModeA; + bitmapRowPad = bitmapRowPadA; + bitmapTopDown = bitmapTopDownA; + bitmapUpsideDown = gFalse; + noComposite = gFalse; + allowAntialias = allowAntialiasA; + vectorAntialias = allowAntialias && + globalParams->getVectorAntialias() && + colorMode != splashModeMono1; + 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, NULL); + splash = new Splash(bitmap, vectorAntialias, NULL, &screenParams); + splash->setMinLineWidth(globalParams->getMinLineWidth()); + splash->setStrokeAdjust( + mapStrokeAdjustMode[globalParams->getStrokeAdjust()]); + splash->setEnablePathSimplification( + globalParams->getEnablePathSimplification()); + splash->clear(paperColor, 0); + + fontEngine = NULL; + + nT3Fonts = 0; + t3GlyphStack = NULL; + + font = NULL; + needFontUpdate = gFalse; + textClipPath = NULL; + + transpGroupStack = NULL; + + nestCount = 0; + + startPageCbk = NULL; + startPageCbkData = NULL; +} + + +void SplashOutputDev::setupScreenParams(double hDPI, double vDPI) { + screenParams.size = globalParams->getScreenSize(); + screenParams.dotRadius = globalParams->getScreenDotRadius(); + screenParams.gamma = (SplashCoord)globalParams->getScreenGamma(); + screenParams.blackThreshold = + (SplashCoord)globalParams->getScreenBlackThreshold(); + screenParams.whiteThreshold = + (SplashCoord)globalParams->getScreenWhiteThreshold(); + switch (globalParams->getScreenType()) { + case screenDispersed: + screenParams.type = splashScreenDispersed; + if (screenParams.size < 0) { + screenParams.size = 4; + } + break; + case screenClustered: + screenParams.type = splashScreenClustered; + if (screenParams.size < 0) { + screenParams.size = 10; + } + break; + case screenStochasticClustered: + screenParams.type = splashScreenStochasticClustered; + if (screenParams.size < 0) { + screenParams.size = 64; + } + if (screenParams.dotRadius < 0) { + screenParams.dotRadius = 2; + } + break; + case screenUnset: + default: + // use clustered dithering for resolution >= 300 dpi + // (compare to 299.9 to avoid floating point issues) + if (hDPI > 299.9 && vDPI > 299.9) { + screenParams.type = splashScreenStochasticClustered; + if (screenParams.size < 0) { + screenParams.size = 64; + } + if (screenParams.dotRadius < 0) { + screenParams.dotRadius = 2; + } + } else { + screenParams.type = splashScreenDispersed; + if (screenParams.size < 0) { + screenParams.size = 4; + } + } + } +} + +SplashOutputDev::~SplashOutputDev() { + int i; + + for (i = 0; i < nT3Fonts; ++i) { + delete t3FontCache[i]; + } + if (fontEngine) { + delete fontEngine; + } + if (splash) { + delete splash; + } + if (bitmap) { + delete bitmap; + } + if (textClipPath) { + delete textClipPath; + } +} + +void SplashOutputDev::startDoc(XRef *xrefA) { + int i; + + xref = xrefA; + if (fontEngine) { + delete fontEngine; + } + fontEngine = new SplashFontEngine( +#if HAVE_FREETYPE_H + globalParams->getEnableFreeType(), + globalParams->getDisableFreeTypeHinting() + ? splashFTNoHinting : 0, +#endif + allowAntialias && + globalParams->getAntialias() && + colorMode != splashModeMono1); + for (i = 0; i < nT3Fonts; ++i) { + delete t3FontCache[i]; + } + nT3Fonts = 0; +} + +void SplashOutputDev::startPage(int pageNum, GfxState *state) { + int w, h; + double *ctm; + SplashCoord mat[6]; + SplashColor color; + + if (state) { + setupScreenParams(state->getHDPI(), state->getVDPI()); + w = (int)(state->getPageWidth() + 0.5); + if (w <= 0) { + w = 1; + } + h = (int)(state->getPageHeight() + 0.5); + if (h <= 0) { + h = 1; + } + } else { + w = h = 1; + } + if (splash) { + delete splash; + splash = NULL; + } + if (!bitmap || w != bitmap->getWidth() || h != bitmap->getHeight()) { + if (bitmap) { + delete bitmap; + bitmap = NULL; + } + traceMessage("page bitmap"); + bitmap = new SplashBitmap(w, h, bitmapRowPad, colorMode, + colorMode != splashModeMono1, bitmapTopDown, + NULL); + } + splash = new Splash(bitmap, vectorAntialias, NULL, &screenParams); + splash->setMinLineWidth(globalParams->getMinLineWidth()); + splash->setEnablePathSimplification( + globalParams->getEnablePathSimplification()); + if (state) { + ctm = state->getCTM(); + mat[0] = (SplashCoord)ctm[0]; + mat[1] = (SplashCoord)ctm[1]; + mat[2] = (SplashCoord)ctm[2]; + mat[3] = (SplashCoord)ctm[3]; + mat[4] = (SplashCoord)ctm[4]; + mat[5] = (SplashCoord)ctm[5]; + splash->setMatrix(mat); + } + 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 + } + splash->setStrokePattern(new SplashSolidColor(color)); + splash->setFillPattern(new SplashSolidColor(color)); + splash->setLineCap(splashLineCapButt); + splash->setLineJoin(splashLineJoinMiter); + splash->setLineDash(NULL, 0, 0); + splash->setMiterLimit(10); + splash->setFlatness(1); + // the SA parameter supposedly defaults to false, but Acrobat + // apparently hardwires it to true + splash->setStrokeAdjust( + mapStrokeAdjustMode[globalParams->getStrokeAdjust()]); + splash->clear(paperColor, 0); + reverseVideoInvertImages = globalParams->getReverseVideoInvertImages(); + if (startPageCbk) { + (*startPageCbk)(startPageCbkData); + } +} + +void SplashOutputDev::endPage() { + if (colorMode != splashModeMono1 && !noComposite) { + splash->compositeBackground(paperColor); + } +} + +void SplashOutputDev::saveState(GfxState *state) { + splash->saveState(); + if (t3GlyphStack && !t3GlyphStack->haveDx) { + t3GlyphStack->doNotCache = gTrue; + error(errSyntaxWarning, -1, + "Save (q) operator before d0/d1 in Type 3 glyph"); + } +} + +void SplashOutputDev::restoreState(GfxState *state) { + splash->restoreState(); + needFontUpdate = gTrue; + if (t3GlyphStack && !t3GlyphStack->haveDx) { + t3GlyphStack->doNotCache = gTrue; + error(errSyntaxWarning, -1, + "Restore (Q) operator before d0/d1 in Type 3 glyph"); + } +} + +void SplashOutputDev::updateAll(GfxState *state) { + updateLineDash(state); + updateLineJoin(state); + updateLineCap(state); + updateLineWidth(state); + updateFlatness(state); + updateMiterLimit(state); + updateStrokeAdjust(state); + updateFillColor(state); + updateStrokeColor(state); + needFontUpdate = gTrue; +} + +void SplashOutputDev::updateCTM(GfxState *state, double m11, double m12, + double m21, double m22, + double m31, double m32) { + double *ctm; + SplashCoord mat[6]; + + ctm = state->getCTM(); + mat[0] = (SplashCoord)ctm[0]; + mat[1] = (SplashCoord)ctm[1]; + mat[2] = (SplashCoord)ctm[2]; + mat[3] = (SplashCoord)ctm[3]; + mat[4] = (SplashCoord)ctm[4]; + mat[5] = (SplashCoord)ctm[5]; + splash->setMatrix(mat); +} + +void SplashOutputDev::updateLineDash(GfxState *state) { + double *dashPattern; + int dashLength; + double dashStart; + SplashCoord dash[20]; + int i; + + state->getLineDash(&dashPattern, &dashLength, &dashStart); + if (dashLength > 20) { + dashLength = 20; + } + for (i = 0; i < dashLength; ++i) { + dash[i] = (SplashCoord)dashPattern[i]; + if (dash[i] < 0) { + dash[i] = 0; + } + } + splash->setLineDash(dash, dashLength, (SplashCoord)dashStart); +} + +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) { + splash->setLineJoin(state->getLineJoin()); +} + +void SplashOutputDev::updateLineCap(GfxState *state) { + splash->setLineCap(state->getLineCap()); +} + +void SplashOutputDev::updateMiterLimit(GfxState *state) { + splash->setMiterLimit(state->getMiterLimit()); +} + +void SplashOutputDev::updateLineWidth(GfxState *state) { + splash->setLineWidth(state->getLineWidth()); +} + +void SplashOutputDev::updateStrokeAdjust(GfxState *state) { +#if 0 // the SA parameter supposedly defaults to false, but Acrobat + // apparently hardwires it to true + if (state->getStrokeAdjust()) { + if (globalParams->getStrokeAdjustMode() == strokeAdjustCAD) { + splash->setStrokeAdjust(splashStrokeAdjustCAD); + } else { + splash->setStrokeAdjust(splashStrokeAdjustNormal); + } + } else { + splash->setStrokeAdjust(splashStrokeAdjustOff); + } +#endif +} + + +void SplashOutputDev::updateFillColor(GfxState *state) { + GfxGray gray; + GfxRGB rgb; +#if SPLASH_CMYK + GfxCMYK cmyk; +#endif + + 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 + case splashModeCMYK8: + state->getFillCMYK(&cmyk); + splash->setFillPattern(getColor(&cmyk)); + break; +#endif + } +} + +void SplashOutputDev::updateStrokeColor(GfxState *state) { + GfxGray gray; + GfxRGB rgb; +#if SPLASH_CMYK + GfxCMYK cmyk; +#endif + + 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 + case splashModeCMYK8: + state->getStrokeCMYK(&cmyk); + splash->setStrokePattern(getColor(&cmyk)); + break; +#endif + } +} + + +SplashPattern *SplashOutputDev::getColor(GfxGray gray) { + SplashColor color; + + getColor(gray, color); + return new SplashSolidColor(color); +} + +SplashPattern *SplashOutputDev::getColor(GfxRGB *rgb) { + SplashColor color; + + getColor(rgb, color); + return new SplashSolidColor(color); +} + +#if SPLASH_CMYK +SplashPattern *SplashOutputDev::getColor(GfxCMYK *cmyk) { + SplashColor color; + + getColor(cmyk, color); + return new SplashSolidColor(color); +} +#endif + + +void SplashOutputDev::getColor(GfxGray gray, SplashColorPtr color) { + if (reverseVideo) { + gray = gfxColorComp1 - gray; + } + color[0] = colToByte(gray); +} + +void SplashOutputDev::getColor(GfxRGB *rgb, SplashColorPtr color) { + GfxColorComp r, g, b; + + if (reverseVideo) { + r = gfxColorComp1 - rgb->r; + g = gfxColorComp1 - rgb->g; + b = gfxColorComp1 - rgb->b; + } else { + r = rgb->r; + g = rgb->g; + b = rgb->b; + } + color[0] = colToByte(r); + color[1] = colToByte(g); + color[2] = colToByte(b); +} + +#if SPLASH_CMYK +void SplashOutputDev::getColor(GfxCMYK *cmyk, SplashColorPtr color) { + color[0] = colToByte(cmyk->c); + color[1] = colToByte(cmyk->m); + color[2] = colToByte(cmyk->y); + color[3] = colToByte(cmyk->k); +} +#endif + + + +void SplashOutputDev::setOverprintMask(GfxState *state, + GfxColorSpace *colorSpace, + GBool overprintFlag, + int overprintMode, + GfxColor *singleColor) { +#if SPLASH_CMYK + Guint mask; + GfxCMYK cmyk; + + if (overprintFlag && globalParams->getOverprintPreview()) { + mask = colorSpace->getOverprintMask(); + // The OPM (overprintMode) setting is only relevant when the color + // space is DeviceCMYK or is "implicitly converted to DeviceCMYK". + // Per the PDF spec, this happens with ICCBased color spaces only + // if the profile matches the output device. + if (singleColor && overprintMode && + colorSpace->getMode() == csDeviceCMYK) { + colorSpace->getCMYK(singleColor, &cmyk, state->getRenderingIntent()); + 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) { + splash->setBlendFunc(splashOutBlendFuncs[state->getBlendMode()]); +} + +void SplashOutputDev::updateFillOpacity(GfxState *state) { + splash->setFillAlpha((SplashCoord)state->getFillOpacity()); +} + +void SplashOutputDev::updateStrokeOpacity(GfxState *state) { + splash->setStrokeAlpha((SplashCoord)state->getStrokeOpacity()); +} + +void SplashOutputDev::updateRenderingIntent(GfxState *state) { + updateFillColor(state); + updateStrokeColor(state); +} + +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; + FoFiType1C *ffT1C; + Ref embRef; + Object refObj, strObj; +#if LOAD_FONTS_FROM_MEM + GString *fontBuf; + FILE *extFontFile; +#else + GString *tmpFileName, *fileName; + FILE *tmpFile; +#endif + char blk[4096]; + int *codeToGID; + CharCodeToUnicode *ctu; + double *textMat; + double m11, m12, m21, m22, fontSize, oblique; + double fsx, fsy, w, fontScaleMin, fontScaleAvg, fontScale; + Gushort ww; + SplashCoord mat[4]; + char *name, *start; + Unicode uBuf[8]; + int substIdx, n, code, cmap, cmapPlatform, cmapEncoding, length, i; + + needFontUpdate = gFalse; + font = NULL; +#if LOAD_FONTS_FROM_MEM + fontBuf = NULL; +#else + tmpFileName = NULL; + fileName = NULL; +#endif + substIdx = -1; + + if (!(gfxFont = state->getFont())) { + goto err1; + } + fontType = gfxFont->getType(); + if (fontType == fontType3) { + goto err1; + } + + // sanity-check the font size: skip anything larger than 10k x 10k, + // to avoid problems allocating a bitmap (note that code in + // SplashFont disables caching at a smaller size than this) + state->textTransformDelta(state->getFontSize(), state->getFontSize(), + &fsx, &fsy); + state->transformDelta(fsx, fsy, &fsx, &fsy); + if (fabs(fsx) > 20000 || fabs(fsy) > 20000) { + goto err1; + } + + // check the font file cache + id = new SplashOutFontFileID(gfxFont->getID()); + if (fontEngine->checkForBadFontFile(id)) { + goto err2; + } + if ((fontFile = fontEngine->getFontFile(id))) { + delete id; + + } else { + + 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 LOAD_FONTS_FROM_MEM + fontBuf = new GString(); + refObj.initRef(embRef.num, embRef.gen); + refObj.fetch(xref, &strObj); + refObj.free(); + if (!strObj.isStream()) { + error(errSyntaxError, -1, "Embedded font object is wrong type"); + strObj.free(); + delete fontLoc; + goto err2; + } + strObj.streamReset(); + while ((n = strObj.streamGetBlock(blk, sizeof(blk))) > 0) { + fontBuf->append(blk, n); + } + strObj.streamClose(); + strObj.free(); +#else + if (!openTempFile(&tmpFileName, &tmpFile, "wb", NULL)) { + error(errIO, -1, "Couldn't create temporary font file"); + delete fontLoc; + goto err2; + } + refObj.initRef(embRef.num, embRef.gen); + refObj.fetch(xref, &strObj); + refObj.free(); + if (!strObj.isStream()) { + error(errSyntaxError, -1, "Embedded font object is wrong type"); + strObj.free(); + fclose(tmpFile); + delete fontLoc; + goto err2; + } + strObj.streamReset(); + while ((n = strObj.streamGetBlock(blk, sizeof(blk))) > 0) { + fwrite(blk, 1, n, tmpFile); + } + strObj.streamClose(); + strObj.free(); + fclose(tmpFile); + fileName = tmpFileName; +#endif + + // external font + } else { // gfxFontLocExternal +#if LOAD_FONTS_FROM_MEM + if (!(extFontFile = fopen(fontLoc->path->getCString(), "rb"))) { + error(errSyntaxError, -1, "Couldn't open external font file '{0:t}'", + fontLoc->path); + delete fontLoc; + goto err2; + } + fontBuf = new GString(); + while ((n = fread(blk, 1, sizeof(blk), extFontFile)) > 0) { + fontBuf->append(blk, n); + } + fclose(extFontFile); +#else + fileName = fontLoc->path; +#endif + fontNum = fontLoc->fontNum; + if (fontLoc->substIdx >= 0) { + id->setSubstIdx(fontLoc->substIdx); + } + if (fontLoc->oblique != 0) { + id->setOblique(fontLoc->oblique); + } + } + + // load the font file + switch (fontLoc->fontType) { + case fontType1: + if (!(fontFile = fontEngine->loadType1Font( + id, +#if LOAD_FONTS_FROM_MEM + fontBuf, +#else + fileName->getCString(), + fileName == tmpFileName, +#endif + (const char **)((Gfx8BitFont *)gfxFont)->getEncoding()))) { + error(errSyntaxError, -1, "Couldn't create a font for '{0:s}'", + gfxFont->getName() ? gfxFont->getName()->getCString() + : "(unnamed)"); + delete fontLoc; + goto err1; + } + break; + case fontType1C: +#if LOAD_FONTS_FROM_MEM + if ((ffT1C = FoFiType1C::make(fontBuf->getCString(), + fontBuf->getLength()))) { +#else + if ((ffT1C = FoFiType1C::load(fileName->getCString()))) { +#endif + codeToGID = ((Gfx8BitFont *)gfxFont)->getCodeToGIDMap(ffT1C); + delete ffT1C; + } else { + codeToGID = NULL; + } + if (!(fontFile = fontEngine->loadType1CFont( + id, +#if LOAD_FONTS_FROM_MEM + fontBuf, +#else + fileName->getCString(), + fileName == tmpFileName, +#endif + codeToGID, + (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 err1; + } + break; + case fontType1COT: + codeToGID = NULL; +#if LOAD_FONTS_FROM_MEM + if ((ff = FoFiTrueType::make(fontBuf->getCString(), fontBuf->getLength(), + fontNum, gTrue))) { +#else + if ((ff = FoFiTrueType::load(fileName->getCString(), + fontNum, gTrue))) { +#endif + if (ff->getCFFBlock(&start, &length) && + (ffT1C = FoFiType1C::make(start, length))) { + codeToGID = ((Gfx8BitFont *)gfxFont)->getCodeToGIDMap(ffT1C); + delete ffT1C; + } + delete ff; + } + if (!(fontFile = fontEngine->loadOpenTypeT1CFont( + id, +#if LOAD_FONTS_FROM_MEM + fontBuf, +#else + fileName->getCString(), + fileName == tmpFileName, +#endif + codeToGID, + (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 err1; + } + break; + case fontTrueType: + case fontTrueTypeOT: +#if LOAD_FONTS_FROM_MEM + if ((ff = FoFiTrueType::make(fontBuf->getCString(), fontBuf->getLength(), + fontNum))) { +#else + if ((ff = FoFiTrueType::load(fileName->getCString(), fontNum))) { +#endif + codeToGID = ((Gfx8BitFont *)gfxFont)->getCodeToGIDMap(ff); + n = 256; + delete ff; + // 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, +#if LOAD_FONTS_FROM_MEM + fontBuf, +#else + fileName->getCString(), + fileName == tmpFileName, +#endif + fontNum, 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 err1; + } + break; + case fontCIDType0: + case fontCIDType0C: + 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->loadCIDFont( + id, +#if LOAD_FONTS_FROM_MEM + fontBuf, +#else + fileName->getCString(), + fileName == tmpFileName, +#endif + codeToGID, n))) { + + error(errSyntaxError, -1, "Couldn't create a font for '{0:s}'", + gfxFont->getName() ? gfxFont->getName()->getCString() + : "(unnamed)"); + delete fontLoc; + goto err1; + } + break; + case fontCIDType0COT: + codeToGID = NULL; + n = 0; + 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 if (globalParams->getMapExtTrueTypeFontsViaUnicode()) { + // create a CID-to-GID mapping, via Unicode + if ((ctu = ((GfxCIDFont *)gfxFont)->getToUnicode())) { +#if LOAD_FONTS_FROM_MEM + if ((ff = FoFiTrueType::make(fontBuf->getCString(), + fontBuf->getLength(), fontNum))) { +#else + if ((ff = FoFiTrueType::load(fileName->getCString(), fontNum))) { +#endif + // look for a Unicode cmap + for (cmap = 0; cmap < ff->getNumCmaps(); ++cmap) { + cmapPlatform = ff->getCmapPlatform(cmap); + cmapEncoding = ff->getCmapEncoding(cmap); + if ((cmapPlatform == 3 && cmapEncoding == 1) || + (cmapPlatform == 0 && cmapEncoding <= 4)) { + break; + } + } + if (cmap < ff->getNumCmaps()) { + // map CID -> Unicode -> GID + if (ctu->isIdentity()) { + n = 65536; + } else { + n = ctu->getLength(); + } + codeToGID = (int *)gmallocn(n, sizeof(int)); + for (code = 0; code < n; ++code) { + if (ctu->mapToUnicode(code, uBuf, 8) > 0) { + codeToGID[code] = ff->mapCodeToGID(cmap, uBuf[0]); + } else { + codeToGID[code] = -1; + } + } + } + delete ff; + } + ctu->decRefCnt(); + } else { + error(errSyntaxError, -1, + "Couldn't find a mapping to Unicode for font '{0:s}'", + gfxFont->getName() ? gfxFont->getName()->getCString() + : "(unnamed)"); + } + } + if (!(fontFile = fontEngine->loadOpenTypeCFFFont( + id, +#if LOAD_FONTS_FROM_MEM + fontBuf, +#else + fileName->getCString(), + fileName == tmpFileName, +#endif + codeToGID, n))) { + error(errSyntaxError, -1, "Couldn't create a font for '{0:s}'", + gfxFont->getName() ? gfxFont->getName()->getCString() + : "(unnamed)"); + delete fontLoc; + goto err1; + } + break; + case fontCIDType2: + case fontCIDType2OT: + codeToGID = NULL; + n = 0; + 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 if (globalParams->getMapExtTrueTypeFontsViaUnicode() && + !((GfxCIDFont *)gfxFont)->usesIdentityEncoding()) { + // create a CID-to-GID mapping, via Unicode + if ((ctu = ((GfxCIDFont *)gfxFont)->getToUnicode())) { +#if LOAD_FONTS_FROM_MEM + if ((ff = FoFiTrueType::make(fontBuf->getCString(), + fontBuf->getLength(), fontNum))) { +#else + if ((ff = FoFiTrueType::load(fileName->getCString(), fontNum))) { +#endif + // look for a Unicode cmap + for (cmap = 0; cmap < ff->getNumCmaps(); ++cmap) { + cmapPlatform = ff->getCmapPlatform(cmap); + cmapEncoding = ff->getCmapEncoding(cmap); + if ((cmapPlatform == 3 && cmapEncoding == 1) || + (cmapPlatform == 0 && cmapEncoding <= 4)) { + break; + } + } + if (cmap < ff->getNumCmaps()) { + // map CID -> Unicode -> GID + if (ctu->isIdentity()) { + n = 65536; + } else { + n = ctu->getLength(); + } + codeToGID = (int *)gmallocn(n, sizeof(int)); + for (code = 0; code < n; ++code) { + if (ctu->mapToUnicode(code, uBuf, 8) > 0) { + codeToGID[code] = ff->mapCodeToGID(cmap, uBuf[0]); + } else { + codeToGID[code] = -1; + } + } + } + delete ff; + } + ctu->decRefCnt(); + } else { + error(errSyntaxError, -1, + "Couldn't find a mapping to Unicode for font '{0:s}'", + gfxFont->getName() ? gfxFont->getName()->getCString() + : "(unnamed)"); + } + } + if (!(fontFile = fontEngine->loadTrueTypeFont( + id, +#if LOAD_FONTS_FROM_MEM + fontBuf, +#else + fileName->getCString(), + fileName == tmpFileName, +#endif + fontNum, 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 err1; + } + break; + default: + // this shouldn't happen + delete fontLoc; + goto err2; + } + + delete fontLoc; + } + + // get the font matrix + textMat = state->getTextMat(); + fontSize = state->getFontSize(); + oblique = ((SplashOutFontFileID *)fontFile->getID())->getOblique(); + m11 = state->getHorizScaling() * textMat[0]; + m12 = state->getHorizScaling() * textMat[1]; + m21 = oblique * m11 + textMat[2]; + m22 = oblique * m12 + textMat[3]; + m11 *= fontSize; + m12 *= fontSize; + m21 *= fontSize; + m22 *= fontSize; + + // for substituted fonts: adjust the font matrix -- compare the + // widths of letters and digits (A-Z, a-z, 0-9) in the original font + // and the substituted font + substIdx = ((SplashOutFontFileID *)fontFile->getID())->getSubstIdx(); + 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] && !name[1] && + ((name[0] >= 'A' && name[0] <= 'Z') || + (name[0] >= 'a' && name[0] <= 'z') || + (name[0] >= '0' && name[0] <= '9'))) { + w = ((Gfx8BitFont *)gfxFont)->getWidth((Guchar)code); + if (builtinFontSubst[substIdx]->widths->getWidth(name, &ww) && + w > 0.01 && ww > 10) { + w /= ww * 0.001; + if (w < fontScaleMin) { + fontScaleMin = w; + } + fontScaleAvg += w; + ++n; + } + } + } + // 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; + } + } + } + + // create the scaled font + mat[0] = m11; mat[1] = m12; + mat[2] = m21; mat[3] = m22; + font = fontEngine->getFont(fontFile, mat, splash->getMatrix()); + +#if !LOAD_FONTS_FROM_MEM + if (tmpFileName) { + delete tmpFileName; + } +#endif + return; + + err2: + delete id; + err1: +#if LOAD_FONTS_FROM_MEM + if (fontBuf) { + delete fontBuf; + } +#else + if (tmpFileName) { + unlink(tmpFileName->getCString()); + delete tmpFileName; + } +#endif + return; +} + +void SplashOutputDev::stroke(GfxState *state) { + SplashPath *path; + + if (state->getStrokeColorSpace()->isNonMarking()) { + return; + } + setOverprintMask(state, state->getStrokeColorSpace(), + state->getStrokeOverprint(), state->getOverprintMode(), + state->getStrokeColor()); + path = convertPath(state, state->getPath(), gFalse); + splash->stroke(path); + delete path; +} + +void SplashOutputDev::fill(GfxState *state) { + SplashPath *path; + + if (state->getFillColorSpace()->isNonMarking()) { + return; + } + setOverprintMask(state, state->getFillColorSpace(), + state->getFillOverprint(), state->getOverprintMode(), + state->getFillColor()); + path = convertPath(state, state->getPath(), gTrue); + splash->fill(path, gFalse); + delete path; +} + +void SplashOutputDev::eoFill(GfxState *state) { + SplashPath *path; + + if (state->getFillColorSpace()->isNonMarking()) { + return; + } + setOverprintMask(state, 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 *strRef, + int paintType, int tilingType, + Dict *resDict, + double *mat, double *bbox, + int x0, int y0, int x1, int y1, + double xStep, double yStep) { + SplashBitmap *origBitmap, *tileBitmap; + Splash *origSplash; + SplashColor color; + Guint *overprintMaskBitmap; + double *ctm; + double ictm[6], tileMat[6], mat1[6], mat2[6]; + double tileXMin, tileYMin, tileXMax, tileYMax; + double xStepX, xStepY, yStepX, yStepY; + double adjXMin, adjYMin; + double sx, sy; + double clipXMin, clipYMin, clipXMax, clipYMax, clipXC, clipYC; + double tx, ty, idet, txMin, tyMin, txMax, tyMax; + int tileW, tileH, tileSize; + int ixMin, ixMax, iyMin, iyMax, ix, iy, x, y; + int i; + + // Notes: + // - PTM = pattern matrix = transform from pattern space to default + // user space (default for most recent page or form) + // - BTM = transform from default user space to device space + // + // This function is called with: + // - mat = PTM * BTM * iCTM = transform from pattern space to + // current user space + + // transform the four corners of the pattern 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; + } + tileW = (int)(tileXMax - tileXMin + 0.5); + tileH = (int)(tileYMax - tileYMin + 0.5); + if (tileW < 1) { + tileW = 1; + } + if (tileH < 1) { + tileH = 1; + } + + // check for an excessively large tile size + tileSize = tileW * tileH; + if (tileXMax - tileXMin + 0.5 > (double)INT_MAX || + tileYMax - tileYMin + 0.5 > (double)INT_MAX || + tileW > INT_MAX / tileH || + tileSize > maxTileSize) { + mat1[0] = mat[0]; + mat1[1] = mat[1]; + mat1[2] = mat[2]; + mat1[3] = mat[3]; + for (iy = y0; iy < y1; ++iy) { + for (ix = x0; ix < x1; ++ix) { + tx = ix * xStep; + ty = iy * yStep; + mat1[4] = tx * mat[0] + ty * mat[2] + mat[4]; + mat1[5] = tx * mat[1] + ty * mat[3] + mat[5]; + gfx->drawForm(strRef, resDict, mat1, bbox); + } + } + return; + } + + // transform XStep and YStep to device space + state->transformDelta(xStep * mat[0], xStep * mat[1], &xStepX, &xStepY); + state->transformDelta(yStep * mat[2], yStep * mat[3], &yStepX, &yStepY); + + // get the clipping bbox (in device space) + state->getClipBBox(&clipXMin, &clipYMin, &clipXMax, &clipYMax); + + // compute tiling parameters + idet = xStepX * yStepY - yStepX * xStepY; + if (tilingType == 2 || idet == 0) { + adjXMin = tileXMin; + adjYMin = tileYMin; + sx = 1; + sy = 1; + } else { + // reposition the pattern origin to the center of the clipping bbox + idet = 1 / idet; + clipXC = 0.5 * (clipXMin + clipXMax); + clipYC = 0.5 * (clipYMin + clipYMax); + ix = (int)floor((yStepX * (tileYMin - clipYC) + - (tileXMin - clipXC) * yStepY) * idet + 0.5); + iy = (int)floor((xStepX * (clipYC - tileYMin) + - (clipXC - tileXMin) * xStepY) * idet + 0.5); + adjXMin = (int)floor(tileXMin + ix * xStepX + iy * yStepX + 0.5); + adjYMin = (int)floor(tileYMin + ix * xStepY + iy * yStepY + 0.5); + sx = tileW / (tileXMax - tileXMin); + sy = tileH / (tileYMax - tileYMin); + xStepX = (int)floor(sx * xStepX + 0.5); + xStepY = (int)floor(sy * xStepY + 0.5); + yStepX = (int)floor(sx * yStepX + 0.5); + yStepY = (int)floor(sy * yStepY + 0.5); + } + + // compute tiling range: + // - look at the four corners of the clipping bbox + // - solve for the (ix,iy) tile position at each corner + // - take the min and max values for ix, iy + idet = xStepX * yStepY - xStepY * yStepX; + if (idet == 0) { + return; + } + idet = 1 / idet; + // LL corner + tx = idet * (yStepY * (clipXMin - tileW - 1 - adjXMin) + - yStepX * (clipYMax + 1 - adjYMin)); + ty = idet * (xStepX * (clipYMax + 1 - adjYMin) + - xStepY * (clipXMin - tileW - 1 - adjXMin)); + txMin = txMax = tx; + tyMin = tyMax = ty; + // LR corner + tx = idet * (yStepY * (clipXMax + 1 - adjXMin) + - yStepX * (clipYMax + 1 - adjYMin)); + ty = idet * (xStepX * (clipYMax + 1 - adjYMin) + - xStepY * (clipXMax + 1 - adjXMin)); + if (tx < txMin) { + txMin = tx; + } else if (tx > txMax) { + txMax = tx; + } + if (ty < tyMin) { + tyMin = ty; + } else if (ty > tyMax) { + tyMax = ty; + } + // UL corner + tx = idet * (yStepY * (clipXMin - tileW - 1 - adjXMin) + - yStepX * (clipYMin - tileH - 1 - adjYMin)); + ty = idet * (xStepX * (clipYMin - tileH - 1 - adjYMin) + - xStepY * (clipXMin - tileW - 1 - adjXMin)); + if (tx < txMin) { + txMin = tx; + } else if (tx > txMax) { + txMax = tx; + } + if (ty < tyMin) { + tyMin = ty; + } else if (ty > tyMax) { + tyMax = ty; + } + // UR corner + tx = idet * (yStepY * (clipXMax + 1 - adjXMin) + - yStepX * (clipYMin - tileH - 1 - adjYMin)); + ty = idet * (xStepX * (clipYMin - tileH - 1 - adjYMin) + - xStepY * (clipXMax + 1 - adjXMin)); + if (tx < txMin) { + txMin = tx; + } else if (tx > txMax) { + txMax = tx; + } + if (ty < tyMin) { + tyMin = ty; + } else if (ty > tyMax) { + tyMax = ty; + } + ixMin = (int)ceil(txMin); + ixMax = (int)floor(txMax) + 1; + iyMin = (int)ceil(tyMin); + iyMax = (int)floor(tyMax) + 1; + + // special case: pattern tile is larger than clipping bbox + if (ixMax - ixMin == 1 && iyMax - iyMin == 1) { + // reduce the tile size to just the clipping bbox -- this improves + // performance in cases where just a small portion of one tile is + // needed + tileW = (int)(clipXMax - clipXMin + 0.5); + tileH = (int)(clipYMax - clipYMin + 0.5); + if (tileW < 1) { + tileW = 1; + } + if (tileH < 1) { + tileH = 1; + } + tileXMin += clipXMin - (adjXMin + ixMin * xStepX + iyMin * yStepX); + tileYMin += clipYMin - (adjYMin + ixMin * xStepY + iyMin * yStepY); + ixMin = 0; + iyMin = 0; + ixMax = 1; + iyMax = 1; + adjXMin = clipXMin; + adjYMin = clipYMin; + } + + // compute tile matrix = PTM * BTM * Mtranslate * Mscale * iCTM + // = mat * CTM * Mtranslate * Mscale * iCTM + ctm = state->getCTM(); + idet = 1 / (ctm[0] * ctm[3] - ctm[1] * ctm[2]); + ictm[0] = ctm[3] * idet; + ictm[1] = -ctm[1] * idet; + ictm[2] = -ctm[2] * idet; + ictm[3] = ctm[0] * idet; + ictm[4] = (ctm[2] * ctm[5] - ctm[3] * ctm[4]) * idet; + ictm[5] = (ctm[1] * ctm[4] - ctm[0] * ctm[5]) * idet; + // mat * CTM + mat1[0] = mat[0] * ctm[0] + mat[1] * ctm[2]; + mat1[1] = mat[0] * ctm[1] + mat[1] * ctm[3]; + mat1[2] = mat[2] * ctm[0] + mat[3] * ctm[2]; + mat1[3] = mat[2] * ctm[1] + mat[3] * ctm[3]; + mat1[4] = mat[4] * ctm[0] + mat[5] * ctm[2] + ctm[4]; + mat1[5] = mat[4] * ctm[1] + mat[5] * ctm[3] + ctm[5]; + // mat * CTM * (Mtranslate * Mscale) + mat2[0] = mat1[0] * sx; + mat2[1] = mat1[1] * sy; + mat2[2] = mat1[2] * sx; + mat2[3] = mat1[3] * sy; + mat2[4] = mat1[4] * sx - sx * tileXMin; + mat2[5] = mat1[5] * sy - sy * tileYMin; + // mat * CTM * (Mtranslate * Mscale) * iCTM + tileMat[0] = mat2[0] * ictm[0] + mat2[1] * ictm[2]; + tileMat[1] = mat2[0] * ictm[1] + mat2[1] * ictm[3]; + tileMat[2] = mat2[2] * ictm[0] + mat2[3] * ictm[2]; + tileMat[3] = mat2[2] * ictm[1] + mat2[3] * ictm[3]; + tileMat[4] = mat2[4] * ictm[0] + mat2[5] * ictm[2] + ictm[4]; + tileMat[5] = mat2[4] * ictm[1] + mat2[5] * ictm[3] + ictm[5]; + + // create a temporary bitmap + origBitmap = bitmap; + origSplash = splash; + traceMessage("tiling pattern bitmap"); + bitmap = tileBitmap = new SplashBitmap(tileW, tileH, bitmapRowPad, + colorMode, gTrue, bitmapTopDown, + origBitmap); + splash = new Splash(bitmap, vectorAntialias, + origSplash->getImageCache(), origSplash->getScreen()); + for (i = 0; i < splashMaxColorComps; ++i) { + color[i] = 0; + } + splash->clear(color); +#if SPLASH_CMYK + // if we're doing overprint preview, we need to track the overprint + // mask at each pixel in the tile bitmap + if (globalParams->getOverprintPreview() && + colorMode == splashModeCMYK8) { + overprintMaskBitmap = (Guint *)gmallocn(tileH, tileW * (int)sizeof(Guint)); + memset(overprintMaskBitmap, 0, tileH * tileW * sizeof(Guint)); + splash->setOverprintMaskBitmap(overprintMaskBitmap); + } else { + overprintMaskBitmap = NULL; + } +#else // SPLASH_CMYK + overprintMaskBitmap = NULL; +#endif // SPLASH_CMYK + splash->setMinLineWidth(globalParams->getMinLineWidth()); + splash->setStrokeAdjust( + mapStrokeAdjustMode[globalParams->getStrokeAdjust()]); + splash->setEnablePathSimplification( + globalParams->getEnablePathSimplification()); + ++nestCount; + + // copy the fill color (for uncolored tiling patterns) + // (and stroke color, to handle buggy PDF files) + // -- Acrobat apparently doesn't copy the full state here + splash->setFillPattern(origSplash->getFillPattern()->copy()); + splash->setStrokePattern(origSplash->getStrokePattern()->copy()); + + // reset the clip rectangle + state->resetDevClipRect(0, 0, tileW, tileH); + + // render the tile + gfx->drawForm(strRef, resDict, tileMat, bbox); + + // restore the original bitmap + --nestCount; + delete splash; + bitmap = origBitmap; + splash = origSplash; + splash->setOverprintMask(0xffffffff); + + // draw the tiles + if (tileW == 1 && tileH == 1 && + fabs(xStepX * yStepY - xStepY * yStepX) < 0.9) { + // if the tile is 1x1 pixel, and the stepping completely fills the + // area, just composite the 1x1 image across the clip region + // (this avoids performance problems in cases where the step size + // is very small) (we compare to 0.9 instead of 1.0 to avoid fp + // jitter issues) + ixMin = (int)floor(clipXMin); + ixMax = (int)floor(clipXMax) + 1; + iyMin = (int)floor(clipYMin); + iyMax = (int)floor(clipYMax) + 1; + for (iy = iyMin; iy < iyMax; ++iy) { + for (ix = ixMin; ix < ixMax; ++ix) { + splash->composite(tileBitmap, 0, 0, ix, iy, tileW, tileH, + gFalse, gFalse); + } + } + } else { + for (iy = iyMin; iy < iyMax; ++iy) { + for (ix = ixMin; ix < ixMax; ++ix) { + x = (int)floor(adjXMin + ix * xStepX + iy * yStepX + 0.5); + y = (int)floor(adjYMin + ix * xStepY + iy * yStepY + 0.5); + if (overprintMaskBitmap) { + splash->compositeWithOverprint(tileBitmap, overprintMaskBitmap, + 0, 0, x, y, tileW, tileH, + gFalse, gFalse); + } else { + splash->composite(tileBitmap, 0, 0, x, y, tileW, tileH, + gFalse, gFalse); + } + } + } + } + + gfree(overprintMaskBitmap); + delete tileBitmap; +} + +GBool SplashOutputDev::shadedFill(GfxState *state, GfxShading *shading) { + + // generate the bitmap + SplashColorMode srcMode; + if (colorMode == splashModeMono1) { + srcMode = splashModeMono8; + } else if (colorMode == splashModeBGR8) { + srcMode = splashModeRGB8; + } else { + srcMode = colorMode; + } + int x, y; + SplashBitmap *tBitmap = ShadingImage::generateBitmap(state, shading, srcMode, + reverseVideo, + splash, bitmap, &x, &y); + if (!tBitmap) { + // clip region is empty - nothing to draw + return gTrue; + } + + // check clipping and composite the bitmap + int xMin = x; + int yMin = y; + int xMax = x + tBitmap->getWidth(); + int yMax = y + tBitmap->getHeight(); + SplashClipResult clipRes = splash->limitRectToClipRect(&xMin, &yMin, + &xMax, &yMax); + if (clipRes != splashClipAllOutside) { + setOverprintMask(state, state->getFillColorSpace(), + state->getFillOverprint(), state->getOverprintMode(), + NULL); + splash->composite(tBitmap, xMin - x, yMin - y, xMin, yMin, + xMax - xMin, yMax - yMin, + clipRes == splashClipAllInside, gFalse); + } + + delete tBitmap; + + return gTrue; +} + +void SplashOutputDev::clip(GfxState *state) { + SplashPath *path; + + path = convertPath(state, state->getPath(), gTrue); + splash->clipToPath(path, gFalse); + delete path; +} + +void SplashOutputDev::eoClip(GfxState *state) { + SplashPath *path; + + path = convertPath(state, state->getPath(), gTrue); + splash->clipToPath(path, gTrue); + delete path; +} + +void SplashOutputDev::clipToStrokePath(GfxState *state) { + SplashPath *path, *path2; + + path = convertPath(state, state->getPath(), gFalse); + path2 = splash->makeStrokePath(path, state->getLineWidth(), + state->getLineCap(), state->getLineJoin()); + delete path; + splash->clipToPath(path2, gFalse); + delete path2; +} + +SplashPath *SplashOutputDev::convertPath(GfxState *state, GfxPath *path, + GBool dropEmptySubpaths) { + SplashPath *sPath; + GfxSubpath *subpath; + 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() > n) { + sPath->moveTo((SplashCoord)subpath->getX(0), + (SplashCoord)subpath->getY(0)); + j = 1; + while (j < subpath->getNumPoints()) { + if (subpath->getCurve(j)) { + sPath->curveTo((SplashCoord)subpath->getX(j), + (SplashCoord)subpath->getY(j), + (SplashCoord)subpath->getX(j+1), + (SplashCoord)subpath->getY(j+1), + (SplashCoord)subpath->getX(j+2), + (SplashCoord)subpath->getY(j+2)); + j += 3; + } else { + sPath->lineTo((SplashCoord)subpath->getX(j), + (SplashCoord)subpath->getY(j)); + ++j; + } + } + if (subpath->isClosed()) { + sPath->close(); + } + } + } + return sPath; +} + +void SplashOutputDev::drawChar(GfxState *state, double x, double y, + double dx, double dy, + double originX, double originY, + CharCode code, int nBytes, + Unicode *u, int uLen) { + SplashPath *path; + int render; + GBool doFill, doStroke, doClip; + SplashStrokeAdjustMode strokeAdjust; + double m[4]; + GBool horiz; + + if (skipHorizText || skipRotatedText) { + state->getFontTransMat(&m[0], &m[1], &m[2], &m[3]); + // this matches the 'diagonal' test in TextPage::updateFont() + 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(); + if (render == 3) { + return; + } + + if (needFontUpdate) { + doUpdateFont(state); + } + if (!font) { + return; + } + + x -= originX; + y -= originY; + + 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 = splashStrokeAdjustOff; // make gcc happy + if (doStroke) { + strokeAdjust = splash->getStrokeAdjust(); + splash->setStrokeAdjust(splashStrokeAdjustOff); + } + + // fill and stroke + if (doFill && doStroke) { + if (path) { + setOverprintMask(state, state->getFillColorSpace(), + state->getFillOverprint(), state->getOverprintMode(), + state->getFillColor()); + splash->fill(path, gFalse); + setOverprintMask(state, state->getStrokeColorSpace(), + state->getStrokeOverprint(), state->getOverprintMode(), + state->getStrokeColor()); + splash->stroke(path); + } + + // fill + } else if (doFill) { + setOverprintMask(state, state->getFillColorSpace(), + state->getFillOverprint(), state->getOverprintMode(), + state->getFillColor()); + splash->fillChar((SplashCoord)x, (SplashCoord)y, code, font); + + // stroke + } else if (doStroke) { + if (path) { + setOverprintMask(state, state->getStrokeColorSpace(), + state->getStrokeOverprint(), state->getOverprintMode(), + state->getStrokeColor()); + splash->stroke(path); + } + } + + // clip + if (doClip) { + if (path) { + if (textClipPath) { + textClipPath->append(path); + } else { + textClipPath = path; + path = NULL; + } + } + } + + if (doStroke) { + splash->setStrokeAdjust(strokeAdjust); + } + + if (path) { + delete path; + } +} + +GBool SplashOutputDev::beginType3Char(GfxState *state, double x, double y, + double dx, double dy, + CharCode code, Unicode *u, int uLen) { + GfxFont *gfxFont; + Ref *fontID; + double *ctm, *bbox; + T3FontCache *t3Font; + T3GlyphStack *t3gs; + GBool validBBox; + double m[4]; + GBool horiz; + double x1, y1, xMin, yMin, xMax, yMax, xt, yt; + int render, 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; + } + } + + // check for invisible text + render = state->getRender(); + if (render == 3 || render == 7) { + return gTrue; + } + + if (!(gfxFont = state->getFont())) { + return gTrue; + } + fontID = gfxFont->getID(); + ctm = state->getCTM(); + state->transform(0, 0, &xt, &yt); + + // is it the first (MRU) font in the cache? + if (!(nT3Fonts > 0 && + t3FontCache[0]->matches(fontID, ctm[0], ctm[1], ctm[2], ctm[3]))) { + + // is the font elsewhere in the cache? + for (i = 1; i < nT3Fonts; ++i) { + if (t3FontCache[i]->matches(fontID, ctm[0], ctm[1], ctm[2], ctm[3])) { + t3Font = t3FontCache[i]; + for (j = i; j > 0; --j) { + t3FontCache[j] = t3FontCache[j - 1]; + } + t3FontCache[0] = t3Font; + break; + } + } + if (i >= nT3Fonts) { + + // create new entry in the font cache + if (nT3Fonts < splashOutT3FontCacheSize) { + for (j = nT3Fonts; j > 0; --j) { + t3FontCache[j] = t3FontCache[j - 1]; + } + } else { + for (j = nT3Fonts - 1; j >= 0; --j) { + if (t3FontCache[j]->refCount == 0) { + break; + } + } + if (j < 0) { + error(errSyntaxError, -1, "Type 3 fonts nested too deeply"); + return gTrue; + } + delete t3FontCache[j]; + --nT3Fonts; + for (; j > 0; --j) { + t3FontCache[j] = t3FontCache[j - 1]; + } + } + ++nT3Fonts; + bbox = gfxFont->getFontBBox(); + if (bbox[0] == 0 && bbox[1] == 0 && bbox[2] == 0 && bbox[3] == 0) { + // unspecified bounding box -- just take a guess + xMin = xt - 5; + xMax = xMin + 30; + yMax = yt + 15; + yMin = yMax - 45; + validBBox = gFalse; + } else { + state->transform(bbox[0], bbox[1], &x1, &y1); + xMin = xMax = x1; + yMin = yMax = y1; + state->transform(bbox[0], bbox[3], &x1, &y1); + if (x1 < xMin) { + xMin = x1; + } else if (x1 > xMax) { + xMax = x1; + } + if (y1 < yMin) { + yMin = y1; + } else if (y1 > yMax) { + yMax = y1; + } + state->transform(bbox[2], bbox[1], &x1, &y1); + if (x1 < xMin) { + xMin = x1; + } else if (x1 > xMax) { + xMax = x1; + } + if (y1 < yMin) { + yMin = y1; + } else if (y1 > yMax) { + yMax = y1; + } + state->transform(bbox[2], bbox[3], &x1, &y1); + if (x1 < xMin) { + xMin = x1; + } else if (x1 > xMax) { + xMax = x1; + } + if (y1 < yMin) { + yMin = y1; + } else if (y1 > yMax) { + yMax = y1; + } + validBBox = gTrue; + } + t3FontCache[0] = new T3FontCache(fontID, ctm[0], ctm[1], ctm[2], ctm[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); + } + } + t3Font = t3FontCache[0]; + + // is the glyph in the cache? + i = (code & (t3Font->cacheSets - 1)) * t3Font->cacheAssoc; + for (j = 0; j < t3Font->cacheAssoc; ++j) { + if ((t3Font->cacheTags[i+j].mru & 0x8000) && + t3Font->cacheTags[i+j].code == code) { + drawType3Glyph(state, t3Font, &t3Font->cacheTags[i+j], + t3Font->cacheData + (i+j) * t3Font->glyphSize); + return gTrue; + } + } + + if (t3Font->refCount > 1000) { + error(errSyntaxError, -1, "Type 3 CharProcs nested too deeply"); + return gTrue; + } + ++t3Font->refCount; + + // push a new Type 3 glyph record + t3gs = new T3GlyphStack(); + t3gs->next = t3GlyphStack; + t3GlyphStack = t3gs; + t3GlyphStack->code = (Gushort)code; + t3GlyphStack->cache = t3Font; + t3GlyphStack->cacheTag = NULL; + t3GlyphStack->cacheData = NULL; + t3GlyphStack->haveDx = gFalse; + t3GlyphStack->doNotCache = gFalse; +#if 1 //~t3-sa + t3GlyphStack->savedStrokeAdjust = splash->getStrokeAdjust(); + splash->setStrokeAdjust(splashStrokeAdjustOff); +#endif + + return gFalse; +} + +void SplashOutputDev::endType3Char(GfxState *state) { + T3GlyphStack *t3gs; + double *ctm; + + if (t3GlyphStack->cacheTag) { + --nestCount; + memcpy(t3GlyphStack->cacheData, bitmap->getDataPtr(), + t3GlyphStack->cache->glyphSize); + delete bitmap; + delete splash; + bitmap = t3GlyphStack->origBitmap; + colorMode = bitmap->getMode(); + splash = t3GlyphStack->origSplash; + ctm = state->getCTM(); + state->setCTM(ctm[0], ctm[1], ctm[2], ctm[3], + t3GlyphStack->origCTM4, t3GlyphStack->origCTM5); + updateCTM(state, 0, 0, 0, 0, 0, 0); + drawType3Glyph(state, t3GlyphStack->cache, + t3GlyphStack->cacheTag, t3GlyphStack->cacheData); + } +#if 1 //~t3-sa + splash->setStrokeAdjust(t3GlyphStack->savedStrokeAdjust); +#endif + t3gs = t3GlyphStack; + t3GlyphStack = t3gs->next; + --t3gs->cache->refCount; + delete t3gs; +} + +void SplashOutputDev::type3D0(GfxState *state, double wx, double wy) { + if (!t3GlyphStack) { + error(errSyntaxError, -1, + "Encountered d0 operator outside of Type 3 CharProc"); + return; + } + t3GlyphStack->haveDx = gTrue; +} + +void SplashOutputDev::type3D1(GfxState *state, double wx, double wy, + double llx, double lly, double urx, double ury) { + double *ctm; + T3FontCache *t3Font; + SplashColor color; + double xt, yt, xMin, xMax, yMin, yMax, x1, y1; + int i, j; + + if (!t3GlyphStack) { + error(errSyntaxError, -1, + "Encountered d1 operator outside of Type 3 CharProc"); + return; + } + + // ignore multiple d0/d1 operators + if (t3GlyphStack->haveDx) { + return; + } + t3GlyphStack->haveDx = gTrue; + // don't cache if we got a gsave/grestore before the d1 + if (t3GlyphStack->doNotCache) { + return; + } + + t3Font = t3GlyphStack->cache; + + // check for a valid bbox + state->transform(0, 0, &xt, &yt); + state->transform(llx, lly, &x1, &y1); + xMin = xMax = x1; + yMin = yMax = y1; + state->transform(llx, ury, &x1, &y1); + if (x1 < xMin) { + xMin = x1; + } else if (x1 > xMax) { + xMax = x1; + } + if (y1 < yMin) { + yMin = y1; + } else if (y1 > yMax) { + yMax = y1; + } + state->transform(urx, lly, &x1, &y1); + if (x1 < xMin) { + xMin = x1; + } else if (x1 > xMax) { + xMax = x1; + } + if (y1 < yMin) { + yMin = y1; + } else if (y1 > yMax) { + yMax = y1; + } + state->transform(urx, ury, &x1, &y1); + if (x1 < xMin) { + xMin = x1; + } else if (x1 > xMax) { + xMax = x1; + } + if (y1 < yMin) { + yMin = y1; + } else if (y1 > yMax) { + yMax = y1; + } + if (xMin - xt < t3Font->glyphX || + yMin - yt < t3Font->glyphY || + xMax - xt > t3Font->glyphX + t3Font->glyphW || + yMax - yt > t3Font->glyphY + t3Font->glyphH) { + if (t3Font->validBBox) { + error(errSyntaxWarning, -1, "Bad bounding box in Type 3 glyph"); + } + return; + } + + // allocate a cache entry + i = (t3GlyphStack->code & (t3Font->cacheSets - 1)) * t3Font->cacheAssoc; + for (j = 0; j < t3Font->cacheAssoc; ++j) { + if ((t3Font->cacheTags[i+j].mru & 0x7fff) == t3Font->cacheAssoc - 1) { + t3Font->cacheTags[i+j].mru = 0x8000; + t3Font->cacheTags[i+j].code = t3GlyphStack->code; + t3GlyphStack->cacheTag = &t3Font->cacheTags[i+j]; + t3GlyphStack->cacheData = t3Font->cacheData + (i+j) * t3Font->glyphSize; + } else { + ++t3Font->cacheTags[i+j].mru; + } + } + + // save state + t3GlyphStack->origBitmap = bitmap; + t3GlyphStack->origSplash = splash; + ctm = state->getCTM(); + t3GlyphStack->origCTM4 = ctm[4]; + t3GlyphStack->origCTM5 = ctm[5]; + + // create the temporary bitmap + if (colorMode == splashModeMono1) { + colorMode = splashModeMono1; + traceMessage("T3 glyph bitmap"); + bitmap = new SplashBitmap(t3Font->glyphW, t3Font->glyphH, 1, + splashModeMono1, gFalse, gTrue, bitmap); + splash = new Splash(bitmap, gFalse, + t3GlyphStack->origSplash->getImageCache(), + t3GlyphStack->origSplash->getScreen()); + color[0] = 0; + splash->clear(color); + color[0] = 0xff; + } else { + colorMode = splashModeMono8; + traceMessage("T3 glyph bitmap"); + bitmap = new SplashBitmap(t3Font->glyphW, t3Font->glyphH, 1, + splashModeMono8, gFalse, gTrue, bitmap); + splash = new Splash(bitmap, vectorAntialias, + t3GlyphStack->origSplash->getImageCache(), + t3GlyphStack->origSplash->getScreen()); + color[0] = 0x00; + splash->clear(color); + color[0] = 0xff; + } + splash->setMinLineWidth(globalParams->getMinLineWidth()); + splash->setStrokeAdjust(t3GlyphStack->origSplash->getStrokeAdjust()); + splash->setEnablePathSimplification( + globalParams->getEnablePathSimplification()); + copyState(t3GlyphStack->origSplash, gFalse); + splash->setFillPattern(new SplashSolidColor(color)); + splash->setStrokePattern(new SplashSolidColor(color)); + 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(GfxState *state, T3FontCache *t3Font, + T3FontCacheTag *tag, Guchar *data) { + SplashGlyphBitmap glyph; + + setOverprintMask(state, state->getFillColorSpace(), + state->getFillOverprint(), state->getOverprintMode(), + state->getFillColor()); + glyph.x = -t3Font->glyphX; + glyph.y = -t3Font->glyphY; + glyph.w = t3Font->glyphW; + glyph.h = t3Font->glyphH; + glyph.aa = colorMode != splashModeMono1; + glyph.data = data; + glyph.freeData = gFalse; + splash->fillGlyph(0, 0, &glyph); +} + +void SplashOutputDev::endTextObject(GfxState *state) { + if (textClipPath) { + splash->clipToPath(textClipPath, gFalse); + delete textClipPath; + textClipPath = NULL; + } +} + +struct SplashOutImageMaskData { + ImageStream *imgStr; + Guchar invert; + int width, height, y; +}; + +GBool SplashOutputDev::imageMaskSrc(void *data, Guchar *line) { + SplashOutImageMaskData *imgMaskData = (SplashOutImageMaskData *)data; + Guchar *p; + SplashColorPtr q; + int x; + + if (imgMaskData->y == imgMaskData->height || + !(p = imgMaskData->imgStr->getLine())) { + memset(line, 0, imgMaskData->width); + return gFalse; + } + for (x = 0, q = line; x < imgMaskData->width; ++x) { + *q++ = *p++ ^ imgMaskData->invert; + } + ++imgMaskData->y; + return gTrue; +} + +void SplashOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str, + int width, int height, GBool invert, + GBool inlineImg, GBool interpolate) { + double *ctm; + SplashCoord mat[6]; + SplashOutImageMaskData imgMaskData; + GString *imgTag; + + if (state->getFillColorSpace()->isNonMarking()) { + return; + } + setOverprintMask(state, state->getFillColorSpace(), + state->getFillOverprint(), state->getOverprintMode(), + state->getFillColor()); + + 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]; + + reduceImageResolution(str, ctm, &width, &height); + + 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; + + imgTag = makeImageTag(ref, gfxRenderingIntentRelativeColorimetric, NULL); + splash->fillImageMask(imgTag, + &imageMaskSrc, &imgMaskData, width, height, mat, + t3GlyphStack != NULL, interpolate, + globalParams->getImageMaskAntialias()); + + if (inlineImg) { + while (imgMaskData.y < height) { + imgMaskData.imgStr->getLine(); + ++imgMaskData.y; + } + } + + delete imgTag; + delete imgMaskData.imgStr; + str->close(); +} + +void SplashOutputDev::setSoftMaskFromImageMask(GfxState *state, + Object *ref, Stream *str, + int width, int height, + GBool invert, + GBool inlineImg, + GBool interpolate) { + double *ctm; + SplashCoord mat[6]; + SplashOutImageMaskData imgMaskData; + SplashBitmap *maskBitmap; + Splash *maskSplash; + SplashColor maskColor; + GString *imgTag; + + 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]; + reduceImageResolution(str, ctm, &width, &height); + 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; + traceMessage("image mask soft mask bitmap"); + maskBitmap = new SplashBitmap(bitmap->getWidth(), bitmap->getHeight(), + 1, splashModeMono8, gFalse, gTrue, bitmap); + maskSplash = new Splash(maskBitmap, gTrue, splash->getImageCache()); + maskSplash->setStrokeAdjust( + mapStrokeAdjustMode[globalParams->getStrokeAdjust()]); + maskSplash->setEnablePathSimplification( + globalParams->getEnablePathSimplification()); + if (splash->getSoftMask()) { + maskSplash->setSoftMask(splash->getSoftMask(), gFalse); + } + clearMaskRegion(state, maskSplash, 0, 0, 1, 1); + maskColor[0] = 0xff; + maskSplash->setFillPattern(new SplashSolidColor(maskColor)); + imgTag = makeImageTag(ref, gfxRenderingIntentRelativeColorimetric, NULL); + maskSplash->fillImageMask(imgTag, &imageMaskSrc, &imgMaskData, + width, height, mat, gFalse, interpolate, + globalParams->getImageMaskAntialias()); + delete imgTag; + delete imgMaskData.imgStr; + str->close(); + delete maskSplash; + splash->setSoftMask(maskBitmap); +} + +struct SplashOutImageData { + ImageStream *imgStr; + GfxImageColorMap *colorMap; + GfxRenderingIntent ri; + SplashColorPtr lookup; + int *maskColors; + SplashColorMode colorMode; + GBool invert; + int width, height, y; +}; + +GBool SplashOutputDev::imageSrc(void *data, SplashColorPtr colorLine, + Guchar *alphaLine) { + SplashOutImageData *imgData = (SplashOutImageData *)data; + Guchar *p; + SplashColorPtr q, col; + int n, x; + + if (imgData->y == imgData->height || + !(p = imgData->imgStr->getLine())) { + memset(colorLine, 0, + imgData->width * splashColorModeNComps[imgData->colorMode]); + return gFalse; + } + + if (imgData->lookup) { + switch (imgData->colorMode) { + case splashModeMono1: + case splashModeMono8: + for (x = 0, q = colorLine; x < imgData->width; ++x, ++p) { + *q++ = imgData->lookup[*p]; + } + break; + case splashModeRGB8: + case splashModeBGR8: + for (x = 0, q = colorLine; x < imgData->width; ++x, ++p) { + col = &imgData->lookup[3 * *p]; + *q++ = col[0]; + *q++ = col[1]; + *q++ = col[2]; + } + break; +#if SPLASH_CMYK + case splashModeCMYK8: + for (x = 0, q = colorLine; x < imgData->width; ++x, ++p) { + col = &imgData->lookup[4 * *p]; + *q++ = col[0]; + *q++ = col[1]; + *q++ = col[2]; + *q++ = col[3]; + } + break; +#endif + } + } else { + switch (imgData->colorMode) { + case splashModeMono1: + case splashModeMono8: + imgData->colorMap->getGrayByteLine(p, colorLine, imgData->width, + imgData->ri); + break; + case splashModeRGB8: + case splashModeBGR8: + imgData->colorMap->getRGBByteLine(p, colorLine, imgData->width, + imgData->ri); + break; +#if SPLASH_CMYK + case splashModeCMYK8: + imgData->colorMap->getCMYKByteLine(p, colorLine, imgData->width, + imgData->ri); + break; +#endif + } + } + + if (imgData->invert) { + n = imgData->width * splashColorModeNComps[imgData->colorMode]; + for (x = 0, p = colorLine; x < n; ++x, ++p) { + *p ^= 0xff; + } + } + + ++imgData->y; + return gTrue; +} + +GBool SplashOutputDev::alphaImageSrc(void *data, SplashColorPtr colorLine, + Guchar *alphaLine) { + SplashOutImageData *imgData = (SplashOutImageData *)data; + Guchar *p0, *p, *aq; + SplashColorPtr q, col; + Guchar alpha; + int nComps, x, n, i; + + if (imgData->y == imgData->height || + !(p0 = imgData->imgStr->getLine())) { + memset(colorLine, 0, + imgData->width * splashColorModeNComps[imgData->colorMode]); + memset(alphaLine, 0, imgData->width); + return gFalse; + } + + nComps = imgData->colorMap->getNumPixelComps(); + + if (imgData->lookup) { + switch (imgData->colorMode) { + case splashModeMono1: + case splashModeMono8: + for (x = 0, p = p0, q = colorLine; x < imgData->width; ++x, ++p) { + *q++ = imgData->lookup[*p]; + } + break; + case splashModeRGB8: + case splashModeBGR8: + for (x = 0, p = p0, q = colorLine; x < imgData->width; ++x, ++p) { + col = &imgData->lookup[3 * *p]; + *q++ = col[0]; + *q++ = col[1]; + *q++ = col[2]; + } + break; +#if SPLASH_CMYK + case splashModeCMYK8: + for (x = 0, p = p0, q = colorLine; x < imgData->width; ++x, ++p) { + col = &imgData->lookup[4 * *p]; + *q++ = col[0]; + *q++ = col[1]; + *q++ = col[2]; + *q++ = col[3]; + } + break; +#endif + } + } else { + switch (imgData->colorMode) { + case splashModeMono1: + case splashModeMono8: + imgData->colorMap->getGrayByteLine(p0, colorLine, imgData->width, + imgData->ri); + break; + case splashModeRGB8: + case splashModeBGR8: + imgData->colorMap->getRGBByteLine(p0, colorLine, imgData->width, + imgData->ri); + break; +#if SPLASH_CMYK + case splashModeCMYK8: + imgData->colorMap->getCMYKByteLine(p0, colorLine, imgData->width, + imgData->ri); + break; +#endif + } + } + + for (x = 0, p = p0, aq = alphaLine; x < imgData->width; ++x, p += nComps) { + alpha = 0; + for (i = 0; i < nComps; ++i) { + if (p[i] < imgData->maskColors[2*i] || + p[i] > imgData->maskColors[2*i+1]) { + alpha = 0xff; + break; + } + } + *aq++ = alpha; + } + + if (imgData->invert) { + n = imgData->width * splashColorModeNComps[imgData->colorMode]; + for (x = 0, p = colorLine; x < n; ++x, ++p) { + *p ^= 0xff; + } + } + + ++imgData->y; + return gTrue; +} + + +void SplashOutputDev::drawImage(GfxState *state, Object *ref, Stream *str, + int width, int height, + GfxImageColorMap *colorMap, + int *maskColors, GBool inlineImg, + GBool interpolate) { + double *ctm; + SplashCoord mat[6]; + SplashOutImageData imgData; + SplashColorMode srcMode; + SplashImageSource src; + GString *imgTag; + GfxGray gray; + GfxRGB rgb; +#if SPLASH_CMYK + GfxCMYK cmyk; +#endif + Guchar pix; + int n, i; + + setOverprintMask(state, colorMap->getColorSpace(), + state->getFillOverprint(), state->getOverprintMode(), + NULL); + + 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]; + + reduceImageResolution(str, ctm, &width, &height); + + imgData.imgStr = new ImageStream(str, width, + colorMap->getNumPixelComps(), + colorMap->getBits()); + imgData.imgStr->reset(); + imgData.colorMap = colorMap; + imgData.ri = state->getRenderingIntent(); + imgData.maskColors = maskColors; + imgData.colorMode = colorMode; + imgData.invert = reverseVideo && reverseVideoInvertImages; + imgData.width = width; + imgData.height = height; + imgData.y = 0; + + // special case for one-channel (monochrome/gray/separation) images: + // build a lookup table here + imgData.lookup = NULL; + if (colorMap->getNumPixelComps() == 1) { + if (colorMap->getBits() <= 8) { + n = 1 << colorMap->getBits(); + } else { + // GfxImageColorMap and ImageStream compress 16-bit samples to 8-bit + n = 1 << 8; + } + switch (colorMode) { + case splashModeMono1: + case splashModeMono8: + imgData.lookup = (SplashColorPtr)gmalloc(n); + for (i = 0; i < n; ++i) { + pix = (Guchar)i; + colorMap->getGray(&pix, &gray, state->getRenderingIntent()); + imgData.lookup[i] = colToByte(gray); + } + break; + case splashModeRGB8: + case splashModeBGR8: + imgData.lookup = (SplashColorPtr)gmallocn(n, 3); + for (i = 0; i < n; ++i) { + pix = (Guchar)i; + colorMap->getRGB(&pix, &rgb, state->getRenderingIntent()); + imgData.lookup[3*i] = colToByte(rgb.r); + imgData.lookup[3*i+1] = colToByte(rgb.g); + imgData.lookup[3*i+2] = colToByte(rgb.b); + } + break; +#if SPLASH_CMYK + case splashModeCMYK8: + imgData.lookup = (SplashColorPtr)gmallocn(n, 4); + for (i = 0; i < n; ++i) { + pix = (Guchar)i; + colorMap->getCMYK(&pix, &cmyk, state->getRenderingIntent()); + imgData.lookup[4*i] = colToByte(cmyk.c); + imgData.lookup[4*i+1] = colToByte(cmyk.m); + imgData.lookup[4*i+2] = colToByte(cmyk.y); + imgData.lookup[4*i+3] = colToByte(cmyk.k); + } + break; +#endif + } + } + + if (colorMode == splashModeMono1) { + srcMode = splashModeMono8; + } else if (colorMode == splashModeBGR8) { + srcMode = splashModeRGB8; + } else { + srcMode = colorMode; + } + src = maskColors ? &alphaImageSrc : &imageSrc; + imgTag = makeImageTag(ref, state->getRenderingIntent(), + colorMap->getColorSpace()); + splash->drawImage(imgTag, + src, &imgData, srcMode, maskColors ? gTrue : gFalse, + width, height, mat, interpolate); + if (inlineImg) { + while (imgData.y < height) { + imgData.imgStr->getLine(); + ++imgData.y; + } + } + + delete imgTag; + gfree(imgData.lookup); + delete imgData.imgStr; + str->close(); +} + +struct SplashOutMaskedImageData { + ImageStream *imgStr; + GfxImageColorMap *colorMap; + GfxRenderingIntent ri; + SplashBitmap *mask; + SplashColorPtr lookup; + SplashColorMode colorMode; + GBool invert; + int width, height, y; +}; + +GBool SplashOutputDev::maskedImageSrc(void *data, SplashColorPtr colorLine, + Guchar *alphaLine) { + SplashOutMaskedImageData *imgData = (SplashOutMaskedImageData *)data; + Guchar *p, *aq; + SplashColorPtr q, col; + static Guchar bitToByte[2] = {0x00, 0xff}; + Guchar *maskPtr; + int maskShift; + int n, x; + + if (imgData->y == imgData->height || + !(p = imgData->imgStr->getLine())) { + memset(colorLine, 0, + imgData->width * splashColorModeNComps[imgData->colorMode]); + memset(alphaLine, 0, imgData->width); + return gFalse; + } + + maskPtr = imgData->mask->getDataPtr() + + imgData->y * imgData->mask->getRowSize(); + aq = alphaLine; + for (x = 0; x <= imgData->width - 8; x += 8) { + aq[0] = bitToByte[(*maskPtr >> 7) & 1]; + aq[1] = bitToByte[(*maskPtr >> 6) & 1]; + aq[2] = bitToByte[(*maskPtr >> 5) & 1]; + aq[3] = bitToByte[(*maskPtr >> 4) & 1]; + aq[4] = bitToByte[(*maskPtr >> 3) & 1]; + aq[5] = bitToByte[(*maskPtr >> 2) & 1]; + aq[6] = bitToByte[(*maskPtr >> 1) & 1]; + aq[7] = bitToByte[*maskPtr & 1]; + aq += 8; + ++maskPtr; + } + maskShift = 7; + for (; x < imgData->width; ++x) { + *aq++ = bitToByte[(*maskPtr >> maskShift) & 1]; + --maskShift; + } + + if (imgData->lookup) { + switch (imgData->colorMode) { + case splashModeMono1: + case splashModeMono8: + for (x = 0, q = colorLine; x < imgData->width; ++x, ++p) { + *q++ = imgData->lookup[*p]; + } + break; + case splashModeRGB8: + case splashModeBGR8: + for (x = 0, q = colorLine; x < imgData->width; ++x, ++p) { + col = &imgData->lookup[3 * *p]; + *q++ = col[0]; + *q++ = col[1]; + *q++ = col[2]; + } + break; +#if SPLASH_CMYK + case splashModeCMYK8: + for (x = 0, q = colorLine; x < imgData->width; ++x, ++p) { + col = &imgData->lookup[4 * *p]; + *q++ = col[0]; + *q++ = col[1]; + *q++ = col[2]; + *q++ = col[3]; + } + break; +#endif + } + } else { + switch (imgData->colorMode) { + case splashModeMono1: + case splashModeMono8: + imgData->colorMap->getGrayByteLine(p, colorLine, imgData->width, + imgData->ri); + break; + case splashModeRGB8: + case splashModeBGR8: + imgData->colorMap->getRGBByteLine(p, colorLine, imgData->width, + imgData->ri); + break; +#if SPLASH_CMYK + case splashModeCMYK8: + imgData->colorMap->getCMYKByteLine(p, colorLine, imgData->width, + imgData->ri); + break; +#endif + } + } + + if (imgData->invert) { + n = imgData->width * splashColorModeNComps[imgData->colorMode]; + for (x = 0, p = colorLine; x < n; ++x, ++p) { + *p ^= 0xff; + } + } + + ++imgData->y; + return gTrue; +} + + +void SplashOutputDev::drawMaskedImage(GfxState *state, Object *ref, + Stream *str, int width, int height, + GfxImageColorMap *colorMap, + Object *maskRef, Stream *maskStr, + int maskWidth, int maskHeight, + GBool maskInvert, GBool interpolate) { + GfxImageColorMap *maskColorMap; + Object maskDecode, decodeLow, decodeHigh; + double *ctm; + SplashCoord mat[6]; + SplashOutMaskedImageData imgData; + SplashOutImageMaskData imgMaskData; + SplashColorMode srcMode; + SplashBitmap *maskBitmap; + Splash *maskSplash; + GString *imgTag; + SplashColor maskColor; + GfxGray gray; + GfxRGB rgb; +#if SPLASH_CMYK + GfxCMYK cmyk; +#endif + Guchar pix; + int n, i; + + setOverprintMask(state, colorMap->getColorSpace(), + state->getFillOverprint(), state->getOverprintMode(), + NULL); + + ctm = state->getCTM(); + reduceImageResolution(str, ctm, &width, &height); + reduceImageResolution(maskStr, ctm, &maskWidth, &maskHeight); + + // If the mask is higher resolution than the image, use + // drawSoftMaskedImage() instead. + if (maskWidth > width || maskHeight > height) { + decodeLow.initInt(maskInvert ? 0 : 1); + decodeHigh.initInt(maskInvert ? 1 : 0); + maskDecode.initArray(xref); + maskDecode.arrayAdd(&decodeLow); + maskDecode.arrayAdd(&decodeHigh); + maskColorMap = new GfxImageColorMap(1, &maskDecode, + new GfxDeviceGrayColorSpace()); + maskDecode.free(); + drawSoftMaskedImage(state, ref, str, width, height, colorMap, + maskRef, maskStr, maskWidth, maskHeight, maskColorMap, + NULL, interpolate); + delete maskColorMap; + + } else { + + //----- scale the mask image to the same size as the source image + + mat[0] = (SplashCoord)width; + mat[1] = 0; + mat[2] = 0; + mat[3] = (SplashCoord)height; + mat[4] = 0; + mat[5] = 0; + imgMaskData.imgStr = new ImageStream(maskStr, maskWidth, 1, 1); + imgMaskData.imgStr->reset(); + imgMaskData.invert = maskInvert ? 0 : 1; + imgMaskData.width = maskWidth; + imgMaskData.height = maskHeight; + imgMaskData.y = 0; + traceMessage("masked image bitmap"); + maskBitmap = new SplashBitmap(width, height, 1, splashModeMono1, + gFalse, gTrue, bitmap); + maskSplash = new Splash(maskBitmap, gFalse, splash->getImageCache()); + maskSplash->setStrokeAdjust( + mapStrokeAdjustMode[globalParams->getStrokeAdjust()]); + maskSplash->setEnablePathSimplification( + globalParams->getEnablePathSimplification()); + maskColor[0] = 0; + maskSplash->clear(maskColor); + maskColor[0] = 0xff; + maskSplash->setFillPattern(new SplashSolidColor(maskColor)); + // use "glyph mode" here to get the correct scaled size + maskSplash->fillImageMask(NULL, &imageMaskSrc, &imgMaskData, + maskWidth, maskHeight, mat, gTrue, interpolate, + globalParams->getImageMaskAntialias()); + delete imgMaskData.imgStr; + maskStr->close(); + delete maskSplash; + + //----- draw the source image + + 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]; + + imgData.imgStr = new ImageStream(str, width, + colorMap->getNumPixelComps(), + colorMap->getBits()); + imgData.imgStr->reset(); + imgData.colorMap = colorMap; + imgData.ri = state->getRenderingIntent(); + imgData.mask = maskBitmap; + imgData.colorMode = colorMode; + imgData.invert = reverseVideo && reverseVideoInvertImages; + imgData.width = width; + imgData.height = height; + imgData.y = 0; + + // special case for one-channel (monochrome/gray/separation) images: + // build a lookup table here + imgData.lookup = NULL; + if (colorMap->getNumPixelComps() == 1) { + if (colorMap->getBits() <= 8) { + n = 1 << colorMap->getBits(); + } else { + // GfxImageColorMap and ImageStream compress 16-bit samples to 8-bit + n = 1 << 8; + } + switch (colorMode) { + case splashModeMono1: + case splashModeMono8: + imgData.lookup = (SplashColorPtr)gmalloc(n); + for (i = 0; i < n; ++i) { + pix = (Guchar)i; + colorMap->getGray(&pix, &gray, state->getRenderingIntent()); + imgData.lookup[i] = colToByte(gray); + } + break; + case splashModeRGB8: + case splashModeBGR8: + imgData.lookup = (SplashColorPtr)gmallocn(n, 3); + for (i = 0; i < n; ++i) { + pix = (Guchar)i; + colorMap->getRGB(&pix, &rgb, state->getRenderingIntent()); + imgData.lookup[3*i] = colToByte(rgb.r); + imgData.lookup[3*i+1] = colToByte(rgb.g); + imgData.lookup[3*i+2] = colToByte(rgb.b); + } + break; +#if SPLASH_CMYK + case splashModeCMYK8: + imgData.lookup = (SplashColorPtr)gmallocn(n, 4); + for (i = 0; i < n; ++i) { + pix = (Guchar)i; + colorMap->getCMYK(&pix, &cmyk, state->getRenderingIntent()); + imgData.lookup[4*i] = colToByte(cmyk.c); + imgData.lookup[4*i+1] = colToByte(cmyk.m); + imgData.lookup[4*i+2] = colToByte(cmyk.y); + imgData.lookup[4*i+3] = colToByte(cmyk.k); + } + break; +#endif + } + } + + if (colorMode == splashModeMono1) { + srcMode = splashModeMono8; + } else if (colorMode == splashModeBGR8) { + srcMode = splashModeRGB8; + } else { + srcMode = colorMode; + } + imgTag = makeImageTag(ref, state->getRenderingIntent(), + colorMap->getColorSpace()); + splash->drawImage(imgTag, + &maskedImageSrc, &imgData, srcMode, gTrue, + width, height, mat, interpolate); + + delete imgTag; + delete maskBitmap; + gfree(imgData.lookup); + delete imgData.imgStr; + str->close(); + } +} + +struct SplashOutSoftMaskMatteImageData { + ImageStream *imgStr; + ImageStream *maskStr; + GfxImageColorMap *colorMap; + GfxRenderingIntent ri; + Guchar matte[gfxColorMaxComps]; + SplashColorMode colorMode; + GBool invert; + int width, height, y; +}; + +GBool SplashOutputDev::softMaskMatteImageSrc(void *data, + SplashColorPtr colorLine, + Guchar *alphaLine) { + SplashOutSoftMaskMatteImageData *imgData = + (SplashOutSoftMaskMatteImageData *)data; + Guchar *p, *ap, *aq; + SplashColorPtr q; + GfxRGB rgb; + GfxGray gray; +#if SPLASH_CMYK + GfxCMYK cmyk; +#endif + Guchar alpha; + int nComps, n, x; + + if (imgData->y == imgData->height || + !(p = imgData->imgStr->getLine()) || + !(ap = imgData->maskStr->getLine())) { + memset(colorLine, 0, + imgData->width * splashColorModeNComps[imgData->colorMode]); + memset(alphaLine, 0, imgData->width); + return gFalse; + } + + nComps = imgData->colorMap->getNumPixelComps(); + + for (x = 0, q = colorLine, aq = alphaLine; + x < imgData->width; + ++x, p += nComps, ++ap) { + alpha = *ap; + switch (imgData->colorMode) { + case splashModeMono1: + case splashModeMono8: + if (alpha) { + imgData->colorMap->getGray(p, &gray, imgData->ri); + *q++ = clip255(imgData->matte[0] + + (255 * (colToByte(gray) - imgData->matte[0])) / alpha); + } else { + *q++ = 0; + } + break; + case splashModeRGB8: + case splashModeBGR8: + if (alpha) { + imgData->colorMap->getRGB(p, &rgb, imgData->ri); + *q++ = clip255(imgData->matte[0] + + (255 * (colToByte(rgb.r) - imgData->matte[0])) / alpha); + *q++ = clip255(imgData->matte[1] + + (255 * (colToByte(rgb.g) - imgData->matte[1])) / alpha); + *q++ = clip255(imgData->matte[2] + + (255 * (colToByte(rgb.b) - imgData->matte[2])) / alpha); + } else { + *q++ = 0; + *q++ = 0; + *q++ = 0; + } + break; +#if SPLASH_CMYK + case splashModeCMYK8: + if (alpha) { + imgData->colorMap->getCMYK(p, &cmyk, imgData->ri); + *q++ = clip255(imgData->matte[0] + + (255 * (colToByte(cmyk.c) - imgData->matte[0])) + / alpha); + *q++ = clip255(imgData->matte[1] + + (255 * (colToByte(cmyk.m) - imgData->matte[1])) + / alpha); + *q++ = clip255(imgData->matte[2] + + (255 * (colToByte(cmyk.y) - imgData->matte[2])) + / alpha); + *q++ = clip255(imgData->matte[3] + + (255 * (colToByte(cmyk.k) - imgData->matte[3])) + / alpha); + } else { + *q++ = 0; + *q++ = 0; + *q++ = 0; + *q++ = 0; + } + break; +#endif + } + *aq++ = alpha; + } + + if (imgData->invert) { + n = imgData->width * splashColorModeNComps[imgData->colorMode]; + for (x = 0, p = colorLine; x < n; ++x, ++p) { + *p ^= 0xff; + } + } + + ++imgData->y; + return gTrue; +} + + +void SplashOutputDev::drawSoftMaskedImage(GfxState *state, Object *ref, + Stream *str, int width, int height, + GfxImageColorMap *colorMap, + Object *maskRef, Stream *maskStr, + int maskWidth, int maskHeight, + GfxImageColorMap *maskColorMap, + double *matte, GBool interpolate) { + double *ctm; + SplashCoord mat[6]; + SplashOutImageData imgData; + SplashOutImageData imgMaskData; + SplashOutSoftMaskMatteImageData matteImgData; + GString *imgTag; + SplashColorMode srcMode; + SplashBitmap *maskBitmap; + Splash *maskSplash; + GfxColor matteColor; + GfxGray gray; + GfxRGB rgb; +#if SPLASH_CMYK + GfxCMYK cmyk; +#endif + Guchar pix; + int n, i; + + setOverprintMask(state, colorMap->getColorSpace(), + state->getFillOverprint(), state->getOverprintMode(), + NULL); + + 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]; + + if (colorMode == splashModeMono1) { + srcMode = splashModeMono8; + } else if (colorMode == splashModeBGR8) { + srcMode = splashModeRGB8; + } else { + srcMode = colorMode; + } + + //----- handle a preblended image + + if (matte && width == maskWidth && height == maskHeight) { + + // the image and mask must be the same size, so don't call + // reduceImageResolution(), which might result in different + // reductions (e.g., if the image filter supports resolution + // reduction but the mask filter doesn't) + + matteImgData.imgStr = new ImageStream(str, width, + colorMap->getNumPixelComps(), + colorMap->getBits()); + matteImgData.imgStr->reset(); + matteImgData.maskStr = new ImageStream(maskStr, maskWidth, + maskColorMap->getNumPixelComps(), + maskColorMap->getBits()); + matteImgData.maskStr->reset(); + matteImgData.colorMap = colorMap; + matteImgData.ri = state->getRenderingIntent(); + n = colorMap->getNumPixelComps(); + for (i = 0; i < n; ++i) { + matteColor.c[i] = dblToCol(matte[i]); + } + switch (colorMode) { + case splashModeMono1: + case splashModeMono8: + colorMap->getColorSpace()->getGray(&matteColor, &gray, + state->getRenderingIntent()); + matteImgData.matte[0] = colToByte(gray); + break; + case splashModeRGB8: + case splashModeBGR8: + colorMap->getColorSpace()->getRGB(&matteColor, &rgb, + state->getRenderingIntent()); + matteImgData.matte[0] = colToByte(rgb.r); + matteImgData.matte[1] = colToByte(rgb.g); + matteImgData.matte[2] = colToByte(rgb.b); + break; +#if SPLASH_CMYK + case splashModeCMYK8: + colorMap->getColorSpace()->getCMYK(&matteColor, &cmyk, + state->getRenderingIntent()); + matteImgData.matte[0] = colToByte(cmyk.c); + matteImgData.matte[1] = colToByte(cmyk.m); + matteImgData.matte[2] = colToByte(cmyk.y); + matteImgData.matte[3] = colToByte(cmyk.k); + break; +#endif + } + //~ could add the matteImgData.lookup special case + matteImgData.colorMode = colorMode; + matteImgData.invert = reverseVideo && reverseVideoInvertImages; + matteImgData.width = width; + matteImgData.height = height; + matteImgData.y = 0; + imgTag = makeImageTag(ref, state->getRenderingIntent(), + colorMap->getColorSpace()); + splash->drawImage(imgTag, &softMaskMatteImageSrc, &matteImgData, + srcMode, gTrue, width, height, mat, interpolate); + delete imgTag; + delete matteImgData.maskStr; + delete matteImgData.imgStr; + maskStr->close(); + str->close(); + + } else { + + reduceImageResolution(str, ctm, &width, &height); + reduceImageResolution(maskStr, ctm, &maskWidth, &maskHeight); + + //----- set up the soft mask + + imgMaskData.imgStr = new ImageStream(maskStr, maskWidth, + maskColorMap->getNumPixelComps(), + maskColorMap->getBits()); + imgMaskData.imgStr->reset(); + imgMaskData.colorMap = maskColorMap; + imgMaskData.ri = state->getRenderingIntent(); + imgMaskData.maskColors = NULL; + imgMaskData.colorMode = splashModeMono8; + imgMaskData.invert = gFalse; + imgMaskData.width = maskWidth; + imgMaskData.height = maskHeight; + imgMaskData.y = 0; + if (maskColorMap->getBits() <= 8) { + n = 1 << maskColorMap->getBits(); + } else { + // GfxImageColorMap and ImageStream compress 16-bit samples to 8-bit + n = 1 << 8; + } + imgMaskData.lookup = (SplashColorPtr)gmalloc(n); + for (i = 0; i < n; ++i) { + pix = (Guchar)i; + maskColorMap->getGray(&pix, &gray, state->getRenderingIntent()); + imgMaskData.lookup[i] = colToByte(gray); + } + traceMessage("soft masked image bitmap"); + maskBitmap = new SplashBitmap(bitmap->getWidth(), bitmap->getHeight(), + 1, splashModeMono8, gFalse, gTrue, bitmap); + maskSplash = new Splash(maskBitmap, vectorAntialias, + splash->getImageCache()); + maskSplash->setStrokeAdjust( + mapStrokeAdjustMode[globalParams->getStrokeAdjust()]); + maskSplash->setEnablePathSimplification( + globalParams->getEnablePathSimplification()); + clearMaskRegion(state, maskSplash, 0, 0, 1, 1); + maskSplash->drawImage(NULL, + &imageSrc, &imgMaskData, splashModeMono8, gFalse, + maskWidth, maskHeight, mat, interpolate); + delete imgMaskData.imgStr; + maskStr->close(); + gfree(imgMaskData.lookup); + delete maskSplash; + splash->setSoftMask(maskBitmap); + + //----- draw the source image + + imgData.imgStr = new ImageStream(str, width, + colorMap->getNumPixelComps(), + colorMap->getBits()); + imgData.imgStr->reset(); + imgData.colorMap = colorMap; + imgData.ri = state->getRenderingIntent(); + imgData.maskColors = NULL; + imgData.colorMode = colorMode; + imgData.invert = reverseVideo && reverseVideoInvertImages; + imgData.width = width; + imgData.height = height; + imgData.y = 0; + + // special case for one-channel (monochrome/gray/separation) images: + // build a lookup table here + imgData.lookup = NULL; + if (colorMap->getNumPixelComps() == 1) { + if (colorMap->getBits() <= 8) { + n = 1 << colorMap->getBits(); + } else { + // GfxImageColorMap and ImageStream compress 16-bit samples to 8-bit + n = 1 << 8; + } + switch (colorMode) { + case splashModeMono1: + case splashModeMono8: + imgData.lookup = (SplashColorPtr)gmalloc(n); + for (i = 0; i < n; ++i) { + pix = (Guchar)i; + colorMap->getGray(&pix, &gray, state->getRenderingIntent()); + imgData.lookup[i] = colToByte(gray); + } + break; + case splashModeRGB8: + case splashModeBGR8: + imgData.lookup = (SplashColorPtr)gmallocn(n, 3); + for (i = 0; i < n; ++i) { + pix = (Guchar)i; + colorMap->getRGB(&pix, &rgb, state->getRenderingIntent()); + imgData.lookup[3*i] = colToByte(rgb.r); + imgData.lookup[3*i+1] = colToByte(rgb.g); + imgData.lookup[3*i+2] = colToByte(rgb.b); + } + break; +#if SPLASH_CMYK + case splashModeCMYK8: + imgData.lookup = (SplashColorPtr)gmallocn(n, 4); + for (i = 0; i < n; ++i) { + pix = (Guchar)i; + colorMap->getCMYK(&pix, &cmyk, state->getRenderingIntent()); + imgData.lookup[4*i] = colToByte(cmyk.c); + imgData.lookup[4*i+1] = colToByte(cmyk.m); + imgData.lookup[4*i+2] = colToByte(cmyk.y); + imgData.lookup[4*i+3] = colToByte(cmyk.k); + } + break; +#endif + } + } + + imgTag = makeImageTag(ref, state->getRenderingIntent(), + colorMap->getColorSpace()); + splash->drawImage(imgTag, + &imageSrc, &imgData, srcMode, gFalse, width, height, mat, + interpolate); + + splash->setSoftMask(NULL); + delete imgTag; + gfree(imgData.lookup); + delete imgData.imgStr; + + + str->close(); + } +} + +GString *SplashOutputDev::makeImageTag(Object *ref, GfxRenderingIntent ri, + GfxColorSpace *colorSpace) { + if (!ref || !ref->isRef() || + (colorSpace && colorSpace->isDefaultColorSpace())) { + return NULL; + } + return GString::format("{0:d}_{1:d}_{2:d}", + ref->getRefNum(), ref->getRefGen(), (int)ri); +} + +void SplashOutputDev::reduceImageResolution(Stream *str, double *ctm, + int *width, int *height) { + double sw, sh; + int reduction; + + if (str->getKind() == strJPX && + *width >= 256 && + *height >= 256 && + *width * *height > 10000000) { + sw = (double)*width / (fabs(ctm[0]) + fabs(ctm[1])); + sh = (double)*height / (fabs(ctm[2]) + fabs(ctm[3])); + if (sw > 8 && sh > 8) { + reduction = 3; + } else if (sw > 4 && sh > 4) { + reduction = 2; + } else if (sw > 2 && sh > 2) { + reduction = 1; + } else { + reduction = 0; + } + if (reduction > 0) { + ((JPXStream *)str)->reduceResolution(reduction); + *width >>= reduction; + *height >>= reduction; + } + } +} + +void SplashOutputDev::clearMaskRegion(GfxState *state, + Splash *maskSplash, + double xMin, double yMin, + double xMax, double yMax) { + SplashBitmap *maskBitmap; + double xxMin, yyMin, xxMax, yyMax, xx, yy; + int xxMinI, yyMinI, xxMaxI, yyMaxI, y, n; + Guchar *p; + + maskBitmap = maskSplash->getBitmap(); + xxMin = maskBitmap->getWidth(); + xxMax = 0; + yyMin = maskBitmap->getHeight(); + yyMax = 0; + state->transform(xMin, yMin, &xx, &yy); + if (xx < xxMin) { xxMin = xx; } + if (xx > xxMax) { xxMax = xx; } + if (yy < yyMin) { yyMin = yy; } + if (yy > yyMax) { yyMax = yy; } + state->transform(xMin, yMax, &xx, &yy); + if (xx < xxMin) { xxMin = xx; } + if (xx > xxMax) { xxMax = xx; } + if (yy < yyMin) { yyMin = yy; } + if (yy > yyMax) { yyMax = yy; } + state->transform(xMax, yMin, &xx, &yy); + if (xx < xxMin) { xxMin = xx; } + if (xx > xxMax) { xxMax = xx; } + if (yy < yyMin) { yyMin = yy; } + if (yy > yyMax) { yyMax = yy; } + state->transform(xMax, yMax, &xx, &yy); + if (xx < xxMin) { xxMin = xx; } + if (xx > xxMax) { xxMax = xx; } + if (yy < yyMin) { yyMin = yy; } + if (yy > yyMax) { yyMax = yy; } + xxMinI = (int)floor(xxMin); + if (xxMinI < 0) { + xxMinI = 0; + } + xxMaxI = (int)ceil(xxMax); + if (xxMaxI > maskBitmap->getWidth()) { + xxMaxI = maskBitmap->getWidth(); + } + yyMinI = (int)floor(yyMin); + if (yyMinI < 0) { + yyMinI = 0; + } + yyMaxI = (int)ceil(yyMax); + if (yyMaxI > maskBitmap->getHeight()) { + yyMaxI = maskBitmap->getHeight(); + } + p = maskBitmap->getDataPtr() + yyMinI * maskBitmap->getRowSize(); + if (maskBitmap->getMode() == splashModeMono1) { + n = (xxMaxI + 7) / 8 - xxMinI / 8; + p += xxMinI / 8; + } else { + n = xxMaxI - xxMinI; + p += xxMinI; + } + if (xxMaxI > xxMinI) { + for (y = yyMinI; y < yyMaxI; ++y) { + memset(p, 0, n); + p += maskBitmap->getRowSize(); + } + } +} + +GBool SplashOutputDev::beginTransparencyGroup(GfxState *state, double *bbox, + GfxColorSpace *blendingColorSpace, + GBool isolated, GBool knockout, + GBool forSoftMask) { + SplashTransparencyGroup *transpGroup; + SplashBitmap *backdropBitmap; + SplashColor color; + double xMin, yMin, xMax, yMax, x, y; + int bw, bh, tx, ty, w, h, i; + + // transform the bbox + state->transform(bbox[0], bbox[1], &x, &y); + xMin = xMax = x; + yMin = yMax = y; + state->transform(bbox[0], bbox[3], &x, &y); + if (x < xMin) { + xMin = x; + } else if (x > xMax) { + xMax = x; + } + if (y < yMin) { + yMin = y; + } else if (y > yMax) { + yMax = y; + } + state->transform(bbox[2], bbox[1], &x, &y); + if (x < xMin) { + xMin = x; + } else if (x > xMax) { + xMax = x; + } + if (y < yMin) { + yMin = y; + } else if (y > yMax) { + yMax = y; + } + state->transform(bbox[2], bbox[3], &x, &y); + if (x < xMin) { + xMin = x; + } else if (x > xMax) { + xMax = x; + } + if (y < yMin) { + yMin = y; + } else if (y > yMax) { + yMax = y; + } + + // clip the box + x = splash->getClip()->getXMin(); + if (x > xMin) { + xMin = x; + } + x = splash->getClip()->getXMax(); + if (x < xMax) { + xMax = x; + } + y = splash->getClip()->getYMin(); + if (y > yMin) { + yMin = y; + } + y = splash->getClip()->getYMax(); + if (y < yMax) { + yMax = y; + } + + // convert box coords to integers + bw = bitmap->getWidth(); + bh = bitmap->getHeight(); + tx = (int)floor(xMin); + if (tx < 0) { + tx = 0; + } else if (tx >= bw) { + tx = bw - 1; + } + ty = (int)floor(yMin); + if (ty < 0) { + ty = 0; + } else if (ty >= bh) { + ty = bh - 1; + } + w = (int)ceil(xMax) - tx + 1; + // NB bw and tx are both non-negative, so 'bw - tx' can't overflow + if (bw - tx < w) { + w = bw - tx; + } + if (w < 1) { + w = 1; + } + h = (int)ceil(yMax) - ty + 1; + // NB bh and ty are both non-negative, so 'bh - ty' can't overflow + if (bh - ty < h) { + h = bh - ty; + } + if (h < 1) { + h = 1; + } + + // optimization: a non-isolated group drawn with alpha=1 and + // Blend=Normal and backdrop alpha=0 is equivalent to drawing + // directly onto the backdrop (i.e., a regular non-t-group Form) + // notes: + // - if we are already in a non-isolated group, it means the + // backdrop alpha is non-zero (otherwise the parent non-isolated + // group would have been optimized away) + // - if there is a soft mask in place, then source alpha is not 1 + // (i.e., source alpha = fillOpacity * softMask) + // - both the parent and child groups must be non-knockout + if (!isolated && + !splash->getInNonIsolatedGroup() && + !knockout && + !splash->getInKnockoutGroup() && + !forSoftMask && + !splash->getSoftMask() && + state->getFillOpacity() == 1 && + state->getBlendMode() == gfxBlendNormal && + splash->checkTransparentRect(tx, ty, w, h)) { + return gFalse; + } + + // push a new stack entry + transpGroup = new SplashTransparencyGroup(); + transpGroup->tx = tx; + transpGroup->ty = ty; + transpGroup->blendingColorSpace = blendingColorSpace; + transpGroup->isolated = isolated; + transpGroup->next = transpGroupStack; + transpGroupStack = transpGroup; + + // save state + transpGroup->origBitmap = bitmap; + transpGroup->origSplash = splash; + + //~ this handles the blendingColorSpace arg for soft masks, but + //~ not yet for transparency groups + + // switch to the blending color space + if (forSoftMask && isolated && !knockout && 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 + traceMessage("t-group bitmap"); + bitmap = new SplashBitmap(w, h, bitmapRowPad, colorMode, gTrue, + bitmapTopDown, transpGroup->origBitmap); + splash = new Splash(bitmap, vectorAntialias, + transpGroup->origSplash->getImageCache(), + transpGroup->origSplash->getScreen()); + splash->setMinLineWidth(globalParams->getMinLineWidth()); + splash->setStrokeAdjust( + mapStrokeAdjustMode[globalParams->getStrokeAdjust()]); + splash->setEnablePathSimplification( + globalParams->getEnablePathSimplification()); + copyState(transpGroup->origSplash, gTrue); + if (!isolated || knockout) { + // non-isolated and knockout groups nested in another group will + // read the parent group bitmap, so we need to force any deferred + // initialization on the parent + transpGroup->origSplash->forceDeferredInit(ty, h); + } + if (isolated) { + // isolated group + backdropBitmap = transpGroup->origBitmap; + transpGroup->backdropBitmap = NULL; + if (forSoftMask) { + // setSoftMask uses the whole bitmap, not just the mod region, + // so we can't use the deferred initialization optimization + for (i = 0; i < splashMaxColorComps; ++i) { + color[i] = 0; + } + splash->clear(color, 0); + splash->setInTransparencyGroup(backdropBitmap, tx, ty, + splashGroupDestPreInit, + gFalse, knockout); + } else { + splash->setInTransparencyGroup(backdropBitmap, tx, ty, + splashGroupDestInitZero, + gFalse, knockout); + } + } else if (transpGroup->origBitmap->getAlphaPtr() && + transpGroup->origSplash->getInNonIsolatedGroup() && + colorMode != splashModeMono1) { + // non-isolated group drawn in another non-isolated group: + // compute a backdrop bitmap with corrected alpha values + traceMessage("t-group backdrop bitmap"); + backdropBitmap = new SplashBitmap(w, h, bitmapRowPad, colorMode, gTrue, + bitmapTopDown, transpGroup->origBitmap); + transpGroup->origSplash->blitCorrectedAlpha(backdropBitmap, + tx, ty, 0, 0, w, h); + transpGroup->backdropBitmap = backdropBitmap; + if (forSoftMask) { + // setSoftMask uses the whole bitmap, not just the mod region, + // so we can't use the deferred initialization optimization + splash->blitTransparent(transpGroup->origBitmap, tx, ty, 0, 0, w, h); + splash->setInTransparencyGroup(backdropBitmap, 0, 0, + splashGroupDestPreInit, + gTrue, knockout); + } else { + splash->setInTransparencyGroup(backdropBitmap, 0, 0, + splashGroupDestInitCopy, + gTrue, knockout); + } + } else { + // other non-isolated group + backdropBitmap = transpGroup->origBitmap; + transpGroup->backdropBitmap = NULL; + if (forSoftMask) { + // setSoftMask uses the whole bitmap, not just the mod region, + // so we can't use the deferred initialization optimization + splash->blitTransparent(transpGroup->origBitmap, tx, ty, 0, 0, w, h); + splash->setInTransparencyGroup(backdropBitmap, tx, ty, + splashGroupDestPreInit, + gTrue, knockout); + } else { + splash->setInTransparencyGroup(backdropBitmap, tx, ty, + splashGroupDestInitCopy, + gTrue, knockout); + } + } + splash->clearModRegion(); + transpGroup->tBitmap = bitmap; +#if 1 //~tmp + if (knockout) { + splash->setInShading(gTrue); + } +#endif + state->shiftCTM(-tx, -ty); + updateCTM(state, 0, 0, 0, 0, 0, 0); + ++nestCount; + + return gTrue; +} + +void SplashOutputDev::endTransparencyGroup(GfxState *state) { + splash->getModRegion(&transpGroupStack->modXMin, &transpGroupStack->modYMin, + &transpGroupStack->modXMax, &transpGroupStack->modYMax); + + // restore state + --nestCount; + delete splash; + bitmap = transpGroupStack->origBitmap; + colorMode = bitmap->getMode(); + splash = transpGroupStack->origSplash; + state->shiftCTM(transpGroupStack->tx, transpGroupStack->ty); + updateCTM(state, 0, 0, 0, 0, 0, 0); +} + +void SplashOutputDev::paintTransparencyGroup(GfxState *state, double *bbox) { + SplashBitmap *tBitmap; + SplashTransparencyGroup *transpGroup; + GBool isolated; + int xSrc, ySrc, xDest, yDest, w, h; + + xSrc = transpGroupStack->modXMin; + ySrc = transpGroupStack->modYMin; + xDest = transpGroupStack->tx + transpGroupStack->modXMin; + yDest = transpGroupStack->ty + transpGroupStack->modYMin; + w = transpGroupStack->modXMax - transpGroupStack->modXMin + 1; + h = transpGroupStack->modYMax - transpGroupStack->modYMin + 1; + tBitmap = transpGroupStack->tBitmap; + isolated = transpGroupStack->isolated; + + // paint the transparency group onto the parent bitmap + // - the clip path was set in the parent's state) + if (xDest < bitmap->getWidth() && yDest < bitmap->getHeight() && + w > 0 && h > 0) { + splash->setOverprintMask(0xffffffff); + splash->composite(tBitmap, xSrc, ySrc, xDest, yDest, w, h, + gFalse, !isolated); + } + + // free the temporary backdrop bitmap + if (transpGroupStack->backdropBitmap) { + delete transpGroupStack->backdropBitmap; + } + + // pop the stack + transpGroup = transpGroupStack; + transpGroupStack = transpGroup->next; + delete transpGroup; + + delete tBitmap; +} + +void SplashOutputDev::setSoftMask(GfxState *state, double *bbox, + GBool alpha, Function *transferFunc, + GfxColor *backdropColor) { + SplashBitmap *softMask, *tBitmap; + Splash *tSplash; + SplashTransparencyGroup *transpGroup; + SplashColor color; + SplashColorPtr p, colorPtr, colorPtr2; + Guchar *alphaPtr; + GfxGray gray; + GfxRGB rgb; +#if SPLASH_CMYK + GfxCMYK cmyk; +#endif + double backdrop, backdrop2, lum, lum2; + Guchar lum8; + SplashBitmapRowSize rowSize; + int tw, th, tNComps, tx, ty, x, y; + + tx = transpGroupStack->tx; + ty = transpGroupStack->ty; + tBitmap = transpGroupStack->tBitmap; + + // composite with backdrop color + backdrop = 0; + if (!alpha && tBitmap->getMode() != splashModeMono1) { + //~ need to correctly handle the case where no blending color + //~ space is given + if (transpGroupStack->blendingColorSpace) { + tSplash = new Splash(tBitmap, vectorAntialias, + transpGroupStack->origSplash->getImageCache(), + transpGroupStack->origSplash->getScreen()); + tSplash->setStrokeAdjust( + mapStrokeAdjustMode[globalParams->getStrokeAdjust()]); + tSplash->setEnablePathSimplification( + globalParams->getEnablePathSimplification()); + switch (tBitmap->getMode()) { + case splashModeMono1: + // transparency is not supported in mono1 mode + break; + case splashModeMono8: + transpGroupStack->blendingColorSpace->getGray( + backdropColor, &gray, state->getRenderingIntent()); + backdrop = colToDbl(gray); + color[0] = colToByte(gray); + tSplash->compositeBackground(color); + break; + case splashModeRGB8: + case splashModeBGR8: + transpGroupStack->blendingColorSpace->getRGB( + backdropColor, &rgb, state->getRenderingIntent()); + backdrop = 0.3 * colToDbl(rgb.r) + + 0.59 * colToDbl(rgb.g) + + 0.11 * colToDbl(rgb.b); + color[0] = colToByte(rgb.r); + color[1] = colToByte(rgb.g); + color[2] = colToByte(rgb.b); + tSplash->compositeBackground(color); + break; +#if SPLASH_CMYK + case splashModeCMYK8: + transpGroupStack->blendingColorSpace->getCMYK( + backdropColor, &cmyk, state->getRenderingIntent()); + backdrop = (1 - colToDbl(cmyk.k)) + - 0.3 * colToDbl(cmyk.c) + - 0.59 * colToDbl(cmyk.m) + - 0.11 * colToDbl(cmyk.y); + if (backdrop < 0) { + backdrop = 0; + } + color[0] = colToByte(cmyk.c); + color[1] = colToByte(cmyk.m); + color[2] = colToByte(cmyk.y); + color[3] = colToByte(cmyk.k); + tSplash->compositeBackground(color); + break; +#endif + } + delete tSplash; + } + } + if (transferFunc) { + transferFunc->transform(&backdrop, &backdrop2); + } else { + backdrop2 = backdrop; + } + + traceMessage("soft mask bitmap"); + softMask = new SplashBitmap(bitmap->getWidth(), bitmap->getHeight(), + 1, splashModeMono8, gFalse, gTrue, bitmap); + memset(softMask->getDataPtr(), (int)(backdrop2 * 255.0 + 0.5), + softMask->getRowSize() * softMask->getHeight()); + if (tx < softMask->getWidth() && ty < softMask->getHeight()) { + p = softMask->getDataPtr() + ty * softMask->getRowSize() + tx; + tw = tBitmap->getWidth(); + th = tBitmap->getHeight(); + rowSize = softMask->getRowSize(); + if (alpha) { + alphaPtr = tBitmap->getAlphaPtr(); + for (y = 0; y < th; ++y) { + for (x = 0; x < tw; ++x) { + lum = *alphaPtr++ / 255.0; + if (transferFunc) { + transferFunc->transform(&lum, &lum2); + } else { + lum2 = lum; + } + p[x] = (Guchar)(lum2 * 255.0 + 0.5); + } + p += rowSize; + } + } else { + colorPtr = tBitmap->getDataPtr(); + tNComps = splashColorModeNComps[tBitmap->getMode()]; + lum8 = 0; // make gcc happy + for (y = 0; y < th; ++y) { + colorPtr2 = colorPtr; + for (x = 0; x < tw; ++x) { + // convert to luminosity + switch (tBitmap->getMode()) { + case splashModeMono1: + lum8 = 0; + break; + case splashModeMono8: + lum8 = colorPtr2[0]; + break; + case splashModeRGB8: + case splashModeBGR8: + // [0.3, 0.59, 0.11] * 255 = [77, 150, 28] + lum8 = div255(77 * colorPtr2[0] + + 150 * colorPtr2[1] + + 28 * colorPtr2[1]); + break; +#if SPLASH_CMYK + case splashModeCMYK8: + lum8 = clip255(255 - colorPtr2[3] + - div255(77 * colorPtr2[0] + + 150 * colorPtr2[1] + + 28 * colorPtr2[2])); + break; +#endif + } + if (transferFunc) { + lum = lum8 / 255.0; + transferFunc->transform(&lum, &lum2); + lum8 = (Guchar)(lum2 * 255.0 + 0.5); + } + p[x] = lum8; + colorPtr2 += tNComps; + } + p += rowSize; + colorPtr += tBitmap->getRowSize(); + } + } + } + splash->setSoftMask(softMask); + + // free the temporary backdrop bitmap + if (transpGroupStack->backdropBitmap) { + delete transpGroupStack->backdropBitmap; + } + + // pop the stack + transpGroup = transpGroupStack; + transpGroupStack = transpGroup->next; + delete transpGroup; + + delete tBitmap; +} + +void SplashOutputDev::clearSoftMask(GfxState *state) { + splash->setSoftMask(NULL); +} + +void SplashOutputDev::setPaperColor(SplashColorPtr paperColorA) { + splashColorCopy(paperColor, paperColorA); +} + +int SplashOutputDev::getBitmapWidth() { + return bitmap->getWidth(); +} + +int SplashOutputDev::getBitmapHeight() { + return bitmap->getHeight(); +} + +SplashBitmap *SplashOutputDev::takeBitmap() { + SplashBitmap *ret; + + ret = bitmap; + bitmap = new SplashBitmap(1, 1, bitmapRowPad, colorMode, + colorMode != splashModeMono1, bitmapTopDown, NULL); + return ret; +} + +void SplashOutputDev::getModRegion(int *xMin, int *yMin, + int *xMax, int *yMax) { + splash->getModRegion(xMin, yMin, xMax, yMax); +} + +void SplashOutputDev::clearModRegion() { + splash->clearModRegion(); +} + +void SplashOutputDev::setFillColor(int r, int g, int b) { + GfxRGB rgb; + GfxGray gray; +#if SPLASH_CMYK + GfxCMYK cmyk; +#endif + + rgb.r = byteToCol((Guchar)r); + rgb.g = byteToCol((Guchar)g); + rgb.b = byteToCol((Guchar)b); + 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 + 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, SplashCoord *textMatA) { + Ref ref; + SplashOutFontFileID *id; + GfxFontLoc *fontLoc; +#if LOAD_FONTS_FROM_MEM + GString *fontBuf; + FILE *extFontFile; + char blk[4096]; + int n; +#endif + SplashFontFile *fontFile; + SplashFont *fontObj; + FoFiTrueType *ff; + int *codeToGID; + Unicode u; + SplashCoord textMat[4]; + SplashCoord oblique; + int cmap, cmapPlatform, cmapEncoding, i; + + for (i = 0; i < nBuiltinFonts; ++i) { + if (!name->cmp(builtinFonts[i].name)) { + break; + } + } + if (i == nBuiltinFonts) { + return NULL; + } + ref.num = i; + ref.gen = -1; + id = new SplashOutFontFileID(&ref); + + // check the font file cache + if ((fontFile = fontEngine->getFontFile(id))) { + delete id; + + // load the font file + } else { + if (!(fontLoc = GfxFont::locateBase14Font(name))) { + return NULL; + } +#if LOAD_FONTS_FROM_MEM + fontBuf = NULL; + if (fontLoc->fontType == fontType1 || + fontLoc->fontType == fontTrueType) { + if (!(extFontFile = fopen(fontLoc->path->getCString(), "rb"))) { + delete fontLoc; + delete id; + return NULL; + } + fontBuf = new GString(); + while ((n = fread(blk, 1, sizeof(blk), extFontFile)) > 0) { + fontBuf->append(blk, n); + } + fclose(extFontFile); + } +#endif + if (fontLoc->fontType == fontType1) { + fontFile = fontEngine->loadType1Font(id, +#if LOAD_FONTS_FROM_MEM + fontBuf, +#else + fontLoc->path->getCString(), + gFalse, +#endif + winAnsiEncoding); + } else if (fontLoc->fontType == fontTrueType) { +#if LOAD_FONTS_FROM_MEM + if (!(ff = FoFiTrueType::make(fontBuf->getCString(), + fontBuf->getLength(), + fontLoc->fontNum))) { +#else + if (!(ff = FoFiTrueType::load(fontLoc->path->getCString(), + fontLoc->fontNum))) { +#endif + delete fontLoc; + delete id; + return NULL; + } + for (cmap = 0; cmap < ff->getNumCmaps(); ++cmap) { + cmapPlatform = ff->getCmapPlatform(cmap); + cmapEncoding = ff->getCmapEncoding(cmap); + if ((cmapPlatform == 3 && cmapEncoding == 1) || + (cmapPlatform == 0 && cmapEncoding <= 4)) { + break; + } + } + if (cmap == ff->getNumCmaps()) { + delete ff; + delete fontLoc; + delete id; + return NULL; + } + codeToGID = (int *)gmallocn(256, sizeof(int)); + for (i = 0; i < 256; ++i) { + codeToGID[i] = 0; + if (winAnsiEncoding[i] && + (u = globalParams->mapNameToUnicode(winAnsiEncoding[i]))) { + codeToGID[i] = ff->mapCodeToGID(cmap, u); + } + } + delete ff; + fontFile = fontEngine->loadTrueTypeFont(id, +#if LOAD_FONTS_FROM_MEM + fontBuf, +#else + fontLoc->path->getCString(), + gFalse, +#endif + fontLoc->fontNum, + codeToGID, 256, NULL); + } else { + delete fontLoc; + delete id; + return NULL; + } + delete fontLoc; + } + if (!fontFile) { + return NULL; + } + + // create the scaled font + oblique = (SplashCoord) + ((SplashOutFontFileID *)fontFile->getID())->getOblique(); + textMat[0] = (SplashCoord)textMatA[0]; + textMat[1] = (SplashCoord)textMatA[1]; + textMat[2] = oblique * textMatA[0] + textMatA[2]; + textMat[3] = oblique * textMatA[1] + textMatA[3]; + fontObj = fontEngine->getFont(fontFile, textMat, splash->getMatrix()); + + return fontObj; +} + +// This is called when initializing a temporary Splash object for Type +// 3 characters and transparency groups. Acrobat apparently copies at +// least the fill and stroke colors, and the line parameters. +//~ not sure what else should be copied -- the PDF spec is unclear +//~ - fill and stroke alpha? +void SplashOutputDev::copyState(Splash *oldSplash, GBool copyColors) { + // cached Type 3 chars set a color, so no need to copy the color here + if (copyColors) { + splash->setFillPattern(oldSplash->getFillPattern()->copy()); + splash->setStrokePattern(oldSplash->getStrokePattern()->copy()); + } + splash->setLineDash(oldSplash->getLineDash(), + oldSplash->getLineDashLength(), + oldSplash->getLineDashPhase()); + splash->setLineCap(oldSplash->getLineCap()); + splash->setLineJoin(oldSplash->getLineJoin()); + splash->setLineWidth(oldSplash->getLineWidth()); +} + +#if 1 //~tmp: turn off anti-aliasing temporarily +// This was originally used with gradient shadings -- that's no longer +// necessary, now that shadings are all converted to device space +// images. It's still used with knockout groups, however, because the +// rasterizer doesn't properly separate opacity and shape. +void SplashOutputDev::setInShading(GBool sh) { + splash->setInShading(sh); +} +#endif diff --git a/xpdf/SplashOutputDev.h b/xpdf/SplashOutputDev.h new file mode 100644 index 0000000..5ec70e9 --- /dev/null +++ b/xpdf/SplashOutputDev.h @@ -0,0 +1,320 @@ +//======================================================================== +// +// SplashOutputDev.h +// +// Copyright 2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef SPLASHOUTPUTDEV_H +#define SPLASHOUTPUTDEV_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "gtypes.h" +#include "SplashTypes.h" +#include "config.h" +#include "OutputDev.h" +#include "GfxState.h" + +class Gfx8BitFont; +class SplashBitmap; +class Splash; +class SplashPath; +class SplashPattern; +class SplashFontEngine; +class SplashFont; +class T3FontCache; +struct T3FontCacheTag; +struct T3GlyphStack; +struct SplashTransparencyGroup; + +//------------------------------------------------------------------------ + +// number of Type 3 fonts to cache +#define splashOutT3FontCacheSize 8 + +//------------------------------------------------------------------------ +// SplashOutputDev +//------------------------------------------------------------------------ + +class SplashOutputDev: public OutputDev { +public: + + // Constructor. + SplashOutputDev(SplashColorMode colorModeA, int bitmapRowPadA, + GBool reverseVideoA, SplashColorPtr paperColorA, + GBool bitmapTopDownA = gTrue, + GBool allowAntialiasA = gTrue); + + + // Destructor. + virtual ~SplashOutputDev(); + + //----- get info about output device + + // Does this device use upside-down coordinates? + // (Upside-down means (0,0) is the top left corner of the page.) + 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. + virtual void startPage(int pageNum, GfxState *state); + + // End a page. + virtual void endPage(); + + //----- save/restore graphics state + virtual void saveState(GfxState *state); + virtual void restoreState(GfxState *state); + + //----- update graphics state + virtual void updateAll(GfxState *state); + virtual void updateCTM(GfxState *state, double m11, double m12, + double m21, double m22, double m31, double m32); + virtual void updateLineDash(GfxState *state); + virtual void updateFlatness(GfxState *state); + virtual void updateLineJoin(GfxState *state); + virtual void updateLineCap(GfxState *state); + virtual void updateMiterLimit(GfxState *state); + virtual void updateLineWidth(GfxState *state); + virtual void updateStrokeAdjust(GfxState *state); + virtual void updateFillColor(GfxState *state); + virtual void updateStrokeColor(GfxState *state); + virtual void updateBlendMode(GfxState *state); + virtual void updateFillOpacity(GfxState *state); + virtual void updateStrokeOpacity(GfxState *state); + virtual void updateRenderingIntent(GfxState *state); + virtual void updateTransfer(GfxState *state); + + //----- update text state + virtual void updateFont(GfxState *state); + + //----- path painting + virtual void stroke(GfxState *state); + virtual void fill(GfxState *state); + virtual void eoFill(GfxState *state); + virtual void tilingPatternFill(GfxState *state, Gfx *gfx, Object *strRef, + int paintType, int tilingType, Dict *resDict, + double *mat, double *bbox, + int x0, int y0, int x1, int y1, + double xStep, double yStep); + virtual GBool shadedFill(GfxState *state, GfxShading *shading); + + //----- path clipping + virtual void clip(GfxState *state); + virtual void eoClip(GfxState *state); + virtual void clipToStrokePath(GfxState *state); + + //----- text drawing + virtual void drawChar(GfxState *state, double x, double y, + double dx, double dy, + double originX, double originY, + CharCode code, int nBytes, Unicode *u, int uLen); + virtual GBool beginType3Char(GfxState *state, double x, double y, + double dx, double dy, + CharCode code, Unicode *u, int uLen); + virtual void endType3Char(GfxState *state); + virtual void endTextObject(GfxState *state); + + //----- image drawing + virtual void drawImageMask(GfxState *state, Object *ref, Stream *str, + int width, int height, GBool invert, + GBool inlineImg, GBool interpolate); + virtual void setSoftMaskFromImageMask(GfxState *state, + Object *ref, Stream *str, + int width, int height, GBool invert, + GBool inlineImg, GBool interpolate); + virtual void drawImage(GfxState *state, Object *ref, Stream *str, + int width, int height, GfxImageColorMap *colorMap, + int *maskColors, GBool inlineImg, GBool interpolate); + virtual void drawMaskedImage(GfxState *state, Object *ref, Stream *str, + int width, int height, + GfxImageColorMap *colorMap, + Object *maskRef, Stream *maskStr, + int maskWidth, int maskHeight, + GBool maskInvert, GBool interpolate); + virtual void drawSoftMaskedImage(GfxState *state, Object *ref, Stream *str, + int width, int height, + GfxImageColorMap *colorMap, + Object *maskRef, Stream *maskStr, + int maskWidth, int maskHeight, + GfxImageColorMap *maskColorMap, + double *matte, GBool interpolate); + + //----- Type 3 font operators + virtual void type3D0(GfxState *state, double wx, double wy); + virtual void type3D1(GfxState *state, double wx, double wy, + double llx, double lly, double urx, double ury); + + //----- transparency groups and soft masks + virtual GBool beginTransparencyGroup(GfxState *state, double *bbox, + GfxColorSpace *blendingColorSpace, + GBool isolated, GBool knockout, + GBool forSoftMask); + virtual void endTransparencyGroup(GfxState *state); + virtual void paintTransparencyGroup(GfxState *state, double *bbox); + virtual void setSoftMask(GfxState *state, double *bbox, GBool alpha, + Function *transferFunc, GfxColor *backdropColor); + virtual void clearSoftMask(GfxState *state); + + //----- special access + + // Called to indicate that a new PDF document has been loaded. + void startDoc(XRef *xrefA); + + void setStartPageCallback(void (*cbk)(void *data), void *data) + { startPageCbk = cbk; startPageCbkData = data; } + + void setPaperColor(SplashColorPtr paperColorA); + + GBool isReverseVideo() { return reverseVideo; } + void setReverseVideo(GBool reverseVideoA) { reverseVideo = reverseVideoA; } + + // Get the bitmap and its size. + SplashBitmap *getBitmap() { return bitmap; } + int getBitmapWidth(); + int getBitmapHeight(); + + // Returns the last rasterized bitmap, transferring ownership to the + // 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; } + + // Setting this to true disables the final composite (with the + // opaque paper color), resulting in transparent output. + void setNoComposite(GBool f) { noComposite = f; } + + // Get the Splash object. + Splash *getSplash() { return splash; } + + // Get the modified region. + void getModRegion(int *xMin, int *yMin, int *xMax, int *yMax); + + // Clear the modified region. + void clearModRegion(); + + // Set the Splash fill color. + 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, SplashCoord *textMatA); + + SplashFont *getCurrentFont() { return font; } + + // If is true, don't draw horizontal text. + // If is true, don't draw rotated (non-horizontal) text. + void setSkipText(GBool skipHorizTextA, GBool skipRotatedTextA) + { skipHorizText = skipHorizTextA; skipRotatedText = skipRotatedTextA; } + + int getNestCount() { return nestCount; } + + + // Get the screen parameters. + SplashScreenParams *getScreenParams() { return &screenParams; } + +private: + + void setupScreenParams(double hDPI, double vDPI); + SplashPattern *getColor(GfxGray gray); + SplashPattern *getColor(GfxRGB *rgb); +#if SPLASH_CMYK + SplashPattern *getColor(GfxCMYK *cmyk); +#endif + void getColor(GfxGray gray, SplashColorPtr color); + void getColor(GfxRGB *rgb, SplashColorPtr color); +#if SPLASH_CMYK + void getColor(GfxCMYK *cmyk, SplashColorPtr color); +#endif + void setOverprintMask(GfxState *state, GfxColorSpace *colorSpace, + GBool overprintFlag, int overprintMode, + GfxColor *singleColor); + SplashPath *convertPath(GfxState *state, GfxPath *path, + GBool dropEmptySubpaths); + void doUpdateFont(GfxState *state); + void drawType3Glyph(GfxState *state, T3FontCache *t3Font, + T3FontCacheTag *tag, Guchar *data); + static GBool imageMaskSrc(void *data, Guchar *line); + static GBool imageSrc(void *data, SplashColorPtr colorLine, + Guchar *alphaLine); + static GBool alphaImageSrc(void *data, SplashColorPtr line, + Guchar *alphaLine); + static GBool maskedImageSrc(void *data, SplashColorPtr line, + Guchar *alphaLine); + static GBool softMaskMatteImageSrc(void *data, + SplashColorPtr colorLine, + Guchar *alphaLine); + GString *makeImageTag(Object *ref, GfxRenderingIntent ri, + GfxColorSpace *colorSpace); + void reduceImageResolution(Stream *str, double *mat, + int *width, int *height); + void clearMaskRegion(GfxState *state, + Splash *maskSplash, + double xMin, double yMin, + double xMax, double yMax); + void copyState(Splash *oldSplash, GBool copyColors); +#if 1 //~tmp: turn off anti-aliasing temporarily + void setInShading(GBool sh); +#endif + + SplashColorMode colorMode; + int bitmapRowPad; + GBool bitmapTopDown; + GBool bitmapUpsideDown; + GBool noComposite; + GBool allowAntialias; + GBool vectorAntialias; + GBool reverseVideo; // reverse video mode + GBool reverseVideoInvertImages; + SplashColor paperColor; // paper color + SplashScreenParams screenParams; + GBool skipHorizText; + GBool skipRotatedText; + + XRef *xref; // xref table for current document + + SplashBitmap *bitmap; + Splash *splash; + SplashFontEngine *fontEngine; + + T3FontCache * // Type 3 font cache + t3FontCache[splashOutT3FontCacheSize]; + int nT3Fonts; // number of valid entries in t3FontCache + T3GlyphStack *t3GlyphStack; // Type 3 glyph context stack + + SplashFont *font; // current font + GBool needFontUpdate; // set when the font needs to be updated + SplashPath *textClipPath; // clipping path built with text object + + SplashTransparencyGroup * // transparency group stack + transpGroupStack; + + int nestCount; + + void (*startPageCbk)(void *data); + void *startPageCbkData; +}; + +#endif diff --git a/xpdf/Stream-CCITT.h b/xpdf/Stream-CCITT.h new file mode 100644 index 0000000..f82150a --- /dev/null +++ b/xpdf/Stream-CCITT.h @@ -0,0 +1,464 @@ +//======================================================================== +// +// Stream-CCITT.h +// +// Tables for CCITT Fax decoding. +// +// Copyright 1996-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef STREAM_CCITT_H +#define STREAM_CCITT_H + +struct CCITTCode { + short bits; + short n; +}; + +#define ccittEOL -2 + +//------------------------------------------------------------------------ +// 2D codes +//------------------------------------------------------------------------ + +#define twoDimPass 0 +#define twoDimHoriz 1 +#define twoDimVert0 2 +#define twoDimVertR1 3 +#define twoDimVertL1 4 +#define twoDimVertR2 5 +#define twoDimVertL2 6 +#define twoDimVertR3 7 +#define twoDimVertL3 8 + +// 1-7 bit codes +static CCITTCode twoDimTab1[128] = { + {-1, -1}, {-1, -1}, // 000000x + {7, twoDimVertL3}, // 0000010 + {7, twoDimVertR3}, // 0000011 + {6, twoDimVertL2}, {6, twoDimVertL2}, // 000010x + {6, twoDimVertR2}, {6, twoDimVertR2}, // 000011x + {4, twoDimPass}, {4, twoDimPass}, // 0001xxx + {4, twoDimPass}, {4, twoDimPass}, + {4, twoDimPass}, {4, twoDimPass}, + {4, twoDimPass}, {4, twoDimPass}, + {3, twoDimHoriz}, {3, twoDimHoriz}, // 001xxxx + {3, twoDimHoriz}, {3, twoDimHoriz}, + {3, twoDimHoriz}, {3, twoDimHoriz}, + {3, twoDimHoriz}, {3, twoDimHoriz}, + {3, twoDimHoriz}, {3, twoDimHoriz}, + {3, twoDimHoriz}, {3, twoDimHoriz}, + {3, twoDimHoriz}, {3, twoDimHoriz}, + {3, twoDimHoriz}, {3, twoDimHoriz}, + {3, twoDimVertL1}, {3, twoDimVertL1}, // 010xxxx + {3, twoDimVertL1}, {3, twoDimVertL1}, + {3, twoDimVertL1}, {3, twoDimVertL1}, + {3, twoDimVertL1}, {3, twoDimVertL1}, + {3, twoDimVertL1}, {3, twoDimVertL1}, + {3, twoDimVertL1}, {3, twoDimVertL1}, + {3, twoDimVertL1}, {3, twoDimVertL1}, + {3, twoDimVertL1}, {3, twoDimVertL1}, + {3, twoDimVertR1}, {3, twoDimVertR1}, // 011xxxx + {3, twoDimVertR1}, {3, twoDimVertR1}, + {3, twoDimVertR1}, {3, twoDimVertR1}, + {3, twoDimVertR1}, {3, twoDimVertR1}, + {3, twoDimVertR1}, {3, twoDimVertR1}, + {3, twoDimVertR1}, {3, twoDimVertR1}, + {3, twoDimVertR1}, {3, twoDimVertR1}, + {3, twoDimVertR1}, {3, twoDimVertR1}, + {1, twoDimVert0}, {1, twoDimVert0}, // 1xxxxxx + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0} +}; + +//------------------------------------------------------------------------ +// white run lengths +//------------------------------------------------------------------------ + +// 11-12 bit codes (upper 7 bits are 0) +static CCITTCode whiteTab1[32] = { + {-1, -1}, // 00000 + {12, ccittEOL}, // 00001 + {-1, -1}, {-1, -1}, // 0001x + {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, // 001xx + {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, // 010xx + {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, // 011xx + {11, 1792}, {11, 1792}, // 1000x + {12, 1984}, // 10010 + {12, 2048}, // 10011 + {12, 2112}, // 10100 + {12, 2176}, // 10101 + {12, 2240}, // 10110 + {12, 2304}, // 10111 + {11, 1856}, {11, 1856}, // 1100x + {11, 1920}, {11, 1920}, // 1101x + {12, 2368}, // 11100 + {12, 2432}, // 11101 + {12, 2496}, // 11110 + {12, 2560} // 11111 +}; + +// 1-9 bit codes +static CCITTCode whiteTab2[512] = { + {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, // 0000000xx + {8, 29}, {8, 29}, // 00000010x + {8, 30}, {8, 30}, // 00000011x + {8, 45}, {8, 45}, // 00000100x + {8, 46}, {8, 46}, // 00000101x + {7, 22}, {7, 22}, {7, 22}, {7, 22}, // 0000011xx + {7, 23}, {7, 23}, {7, 23}, {7, 23}, // 0000100xx + {8, 47}, {8, 47}, // 00001010x + {8, 48}, {8, 48}, // 00001011x + {6, 13}, {6, 13}, {6, 13}, {6, 13}, // 000011xxx + {6, 13}, {6, 13}, {6, 13}, {6, 13}, + {7, 20}, {7, 20}, {7, 20}, {7, 20}, // 0001000xx + {8, 33}, {8, 33}, // 00010010x + {8, 34}, {8, 34}, // 00010011x + {8, 35}, {8, 35}, // 00010100x + {8, 36}, {8, 36}, // 00010101x + {8, 37}, {8, 37}, // 00010110x + {8, 38}, {8, 38}, // 00010111x + {7, 19}, {7, 19}, {7, 19}, {7, 19}, // 0001100xx + {8, 31}, {8, 31}, // 00011010x + {8, 32}, {8, 32}, // 00011011x + {6, 1}, {6, 1}, {6, 1}, {6, 1}, // 000111xxx + {6, 1}, {6, 1}, {6, 1}, {6, 1}, + {6, 12}, {6, 12}, {6, 12}, {6, 12}, // 001000xxx + {6, 12}, {6, 12}, {6, 12}, {6, 12}, + {8, 53}, {8, 53}, // 00100100x + {8, 54}, {8, 54}, // 00100101x + {7, 26}, {7, 26}, {7, 26}, {7, 26}, // 0010011xx + {8, 39}, {8, 39}, // 00101000x + {8, 40}, {8, 40}, // 00101001x + {8, 41}, {8, 41}, // 00101010x + {8, 42}, {8, 42}, // 00101011x + {8, 43}, {8, 43}, // 00101100x + {8, 44}, {8, 44}, // 00101101x + {7, 21}, {7, 21}, {7, 21}, {7, 21}, // 0010111xx + {7, 28}, {7, 28}, {7, 28}, {7, 28}, // 0011000xx + {8, 61}, {8, 61}, // 00110010x + {8, 62}, {8, 62}, // 00110011x + {8, 63}, {8, 63}, // 00110100x + {8, 0}, {8, 0}, // 00110101x + {8, 320}, {8, 320}, // 00110110x + {8, 384}, {8, 384}, // 00110111x + {5, 10}, {5, 10}, {5, 10}, {5, 10}, // 00111xxxx + {5, 10}, {5, 10}, {5, 10}, {5, 10}, + {5, 10}, {5, 10}, {5, 10}, {5, 10}, + {5, 10}, {5, 10}, {5, 10}, {5, 10}, + {5, 11}, {5, 11}, {5, 11}, {5, 11}, // 01000xxxx + {5, 11}, {5, 11}, {5, 11}, {5, 11}, + {5, 11}, {5, 11}, {5, 11}, {5, 11}, + {5, 11}, {5, 11}, {5, 11}, {5, 11}, + {7, 27}, {7, 27}, {7, 27}, {7, 27}, // 0100100xx + {8, 59}, {8, 59}, // 01001010x + {8, 60}, {8, 60}, // 01001011x + {9, 1472}, // 010011000 + {9, 1536}, // 010011001 + {9, 1600}, // 010011010 + {9, 1728}, // 010011011 + {7, 18}, {7, 18}, {7, 18}, {7, 18}, // 0100111xx + {7, 24}, {7, 24}, {7, 24}, {7, 24}, // 0101000xx + {8, 49}, {8, 49}, // 01010010x + {8, 50}, {8, 50}, // 01010011x + {8, 51}, {8, 51}, // 01010100x + {8, 52}, {8, 52}, // 01010101x + {7, 25}, {7, 25}, {7, 25}, {7, 25}, // 0101011xx + {8, 55}, {8, 55}, // 01011000x + {8, 56}, {8, 56}, // 01011001x + {8, 57}, {8, 57}, // 01011010x + {8, 58}, {8, 58}, // 01011011x + {6, 192}, {6, 192}, {6, 192}, {6, 192}, // 010111xxx + {6, 192}, {6, 192}, {6, 192}, {6, 192}, + {6, 1664}, {6, 1664}, {6, 1664}, {6, 1664}, // 011000xxx + {6, 1664}, {6, 1664}, {6, 1664}, {6, 1664}, + {8, 448}, {8, 448}, // 01100100x + {8, 512}, {8, 512}, // 01100101x + {9, 704}, // 011001100 + {9, 768}, // 011001101 + {8, 640}, {8, 640}, // 01100111x + {8, 576}, {8, 576}, // 01101000x + {9, 832}, // 011010010 + {9, 896}, // 011010011 + {9, 960}, // 011010100 + {9, 1024}, // 011010101 + {9, 1088}, // 011010110 + {9, 1152}, // 011010111 + {9, 1216}, // 011011000 + {9, 1280}, // 011011001 + {9, 1344}, // 011011010 + {9, 1408}, // 011011011 + {7, 256}, {7, 256}, {7, 256}, {7, 256}, // 0110111xx + {4, 2}, {4, 2}, {4, 2}, {4, 2}, // 0111xxxxx + {4, 2}, {4, 2}, {4, 2}, {4, 2}, + {4, 2}, {4, 2}, {4, 2}, {4, 2}, + {4, 2}, {4, 2}, {4, 2}, {4, 2}, + {4, 2}, {4, 2}, {4, 2}, {4, 2}, + {4, 2}, {4, 2}, {4, 2}, {4, 2}, + {4, 2}, {4, 2}, {4, 2}, {4, 2}, + {4, 2}, {4, 2}, {4, 2}, {4, 2}, + {4, 3}, {4, 3}, {4, 3}, {4, 3}, // 1000xxxxx + {4, 3}, {4, 3}, {4, 3}, {4, 3}, + {4, 3}, {4, 3}, {4, 3}, {4, 3}, + {4, 3}, {4, 3}, {4, 3}, {4, 3}, + {4, 3}, {4, 3}, {4, 3}, {4, 3}, + {4, 3}, {4, 3}, {4, 3}, {4, 3}, + {4, 3}, {4, 3}, {4, 3}, {4, 3}, + {4, 3}, {4, 3}, {4, 3}, {4, 3}, + {5, 128}, {5, 128}, {5, 128}, {5, 128}, // 10010xxxx + {5, 128}, {5, 128}, {5, 128}, {5, 128}, + {5, 128}, {5, 128}, {5, 128}, {5, 128}, + {5, 128}, {5, 128}, {5, 128}, {5, 128}, + {5, 8}, {5, 8}, {5, 8}, {5, 8}, // 10011xxxx + {5, 8}, {5, 8}, {5, 8}, {5, 8}, + {5, 8}, {5, 8}, {5, 8}, {5, 8}, + {5, 8}, {5, 8}, {5, 8}, {5, 8}, + {5, 9}, {5, 9}, {5, 9}, {5, 9}, // 10100xxxx + {5, 9}, {5, 9}, {5, 9}, {5, 9}, + {5, 9}, {5, 9}, {5, 9}, {5, 9}, + {5, 9}, {5, 9}, {5, 9}, {5, 9}, + {6, 16}, {6, 16}, {6, 16}, {6, 16}, // 101010xxx + {6, 16}, {6, 16}, {6, 16}, {6, 16}, + {6, 17}, {6, 17}, {6, 17}, {6, 17}, // 101011xxx + {6, 17}, {6, 17}, {6, 17}, {6, 17}, + {4, 4}, {4, 4}, {4, 4}, {4, 4}, // 1011xxxxx + {4, 4}, {4, 4}, {4, 4}, {4, 4}, + {4, 4}, {4, 4}, {4, 4}, {4, 4}, + {4, 4}, {4, 4}, {4, 4}, {4, 4}, + {4, 4}, {4, 4}, {4, 4}, {4, 4}, + {4, 4}, {4, 4}, {4, 4}, {4, 4}, + {4, 4}, {4, 4}, {4, 4}, {4, 4}, + {4, 4}, {4, 4}, {4, 4}, {4, 4}, + {4, 5}, {4, 5}, {4, 5}, {4, 5}, // 1100xxxxx + {4, 5}, {4, 5}, {4, 5}, {4, 5}, + {4, 5}, {4, 5}, {4, 5}, {4, 5}, + {4, 5}, {4, 5}, {4, 5}, {4, 5}, + {4, 5}, {4, 5}, {4, 5}, {4, 5}, + {4, 5}, {4, 5}, {4, 5}, {4, 5}, + {4, 5}, {4, 5}, {4, 5}, {4, 5}, + {4, 5}, {4, 5}, {4, 5}, {4, 5}, + {6, 14}, {6, 14}, {6, 14}, {6, 14}, // 110100xxx + {6, 14}, {6, 14}, {6, 14}, {6, 14}, + {6, 15}, {6, 15}, {6, 15}, {6, 15}, // 110101xxx + {6, 15}, {6, 15}, {6, 15}, {6, 15}, + {5, 64}, {5, 64}, {5, 64}, {5, 64}, // 11011xxxx + {5, 64}, {5, 64}, {5, 64}, {5, 64}, + {5, 64}, {5, 64}, {5, 64}, {5, 64}, + {5, 64}, {5, 64}, {5, 64}, {5, 64}, + {4, 6}, {4, 6}, {4, 6}, {4, 6}, // 1110xxxxx + {4, 6}, {4, 6}, {4, 6}, {4, 6}, + {4, 6}, {4, 6}, {4, 6}, {4, 6}, + {4, 6}, {4, 6}, {4, 6}, {4, 6}, + {4, 6}, {4, 6}, {4, 6}, {4, 6}, + {4, 6}, {4, 6}, {4, 6}, {4, 6}, + {4, 6}, {4, 6}, {4, 6}, {4, 6}, + {4, 6}, {4, 6}, {4, 6}, {4, 6}, + {4, 7}, {4, 7}, {4, 7}, {4, 7}, // 1111xxxxx + {4, 7}, {4, 7}, {4, 7}, {4, 7}, + {4, 7}, {4, 7}, {4, 7}, {4, 7}, + {4, 7}, {4, 7}, {4, 7}, {4, 7}, + {4, 7}, {4, 7}, {4, 7}, {4, 7}, + {4, 7}, {4, 7}, {4, 7}, {4, 7}, + {4, 7}, {4, 7}, {4, 7}, {4, 7}, + {4, 7}, {4, 7}, {4, 7}, {4, 7} +}; + +//------------------------------------------------------------------------ +// black run lengths +//------------------------------------------------------------------------ + +// 10-13 bit codes (upper 6 bits are 0) +static CCITTCode blackTab1[128] = { + {-1, -1}, {-1, -1}, // 000000000000x + {12, ccittEOL}, {12, ccittEOL}, // 000000000001x + {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, // 00000000001xx + {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, // 00000000010xx + {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, // 00000000011xx + {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, // 00000000100xx + {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, // 00000000101xx + {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, // 00000000110xx + {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, // 00000000111xx + {11, 1792}, {11, 1792}, {11, 1792}, {11, 1792}, // 00000001000xx + {12, 1984}, {12, 1984}, // 000000010010x + {12, 2048}, {12, 2048}, // 000000010011x + {12, 2112}, {12, 2112}, // 000000010100x + {12, 2176}, {12, 2176}, // 000000010101x + {12, 2240}, {12, 2240}, // 000000010110x + {12, 2304}, {12, 2304}, // 000000010111x + {11, 1856}, {11, 1856}, {11, 1856}, {11, 1856}, // 00000001100xx + {11, 1920}, {11, 1920}, {11, 1920}, {11, 1920}, // 00000001101xx + {12, 2368}, {12, 2368}, // 000000011100x + {12, 2432}, {12, 2432}, // 000000011101x + {12, 2496}, {12, 2496}, // 000000011110x + {12, 2560}, {12, 2560}, // 000000011111x + {10, 18}, {10, 18}, {10, 18}, {10, 18}, // 0000001000xxx + {10, 18}, {10, 18}, {10, 18}, {10, 18}, + {12, 52}, {12, 52}, // 000000100100x + {13, 640}, // 0000001001010 + {13, 704}, // 0000001001011 + {13, 768}, // 0000001001100 + {13, 832}, // 0000001001101 + {12, 55}, {12, 55}, // 000000100111x + {12, 56}, {12, 56}, // 000000101000x + {13, 1280}, // 0000001010010 + {13, 1344}, // 0000001010011 + {13, 1408}, // 0000001010100 + {13, 1472}, // 0000001010101 + {12, 59}, {12, 59}, // 000000101011x + {12, 60}, {12, 60}, // 000000101100x + {13, 1536}, // 0000001011010 + {13, 1600}, // 0000001011011 + {11, 24}, {11, 24}, {11, 24}, {11, 24}, // 00000010111xx + {11, 25}, {11, 25}, {11, 25}, {11, 25}, // 00000011000xx + {13, 1664}, // 0000001100100 + {13, 1728}, // 0000001100101 + {12, 320}, {12, 320}, // 000000110011x + {12, 384}, {12, 384}, // 000000110100x + {12, 448}, {12, 448}, // 000000110101x + {13, 512}, // 0000001101100 + {13, 576}, // 0000001101101 + {12, 53}, {12, 53}, // 000000110111x + {12, 54}, {12, 54}, // 000000111000x + {13, 896}, // 0000001110010 + {13, 960}, // 0000001110011 + {13, 1024}, // 0000001110100 + {13, 1088}, // 0000001110101 + {13, 1152}, // 0000001110110 + {13, 1216}, // 0000001110111 + {10, 64}, {10, 64}, {10, 64}, {10, 64}, // 0000001111xxx + {10, 64}, {10, 64}, {10, 64}, {10, 64} +}; + +// 7-12 bit codes (upper 4 bits are 0) +static CCITTCode blackTab2[192] = { + {8, 13}, {8, 13}, {8, 13}, {8, 13}, // 00000100xxxx + {8, 13}, {8, 13}, {8, 13}, {8, 13}, + {8, 13}, {8, 13}, {8, 13}, {8, 13}, + {8, 13}, {8, 13}, {8, 13}, {8, 13}, + {11, 23}, {11, 23}, // 00000101000x + {12, 50}, // 000001010010 + {12, 51}, // 000001010011 + {12, 44}, // 000001010100 + {12, 45}, // 000001010101 + {12, 46}, // 000001010110 + {12, 47}, // 000001010111 + {12, 57}, // 000001011000 + {12, 58}, // 000001011001 + {12, 61}, // 000001011010 + {12, 256}, // 000001011011 + {10, 16}, {10, 16}, {10, 16}, {10, 16}, // 0000010111xx + {10, 17}, {10, 17}, {10, 17}, {10, 17}, // 0000011000xx + {12, 48}, // 000001100100 + {12, 49}, // 000001100101 + {12, 62}, // 000001100110 + {12, 63}, // 000001100111 + {12, 30}, // 000001101000 + {12, 31}, // 000001101001 + {12, 32}, // 000001101010 + {12, 33}, // 000001101011 + {12, 40}, // 000001101100 + {12, 41}, // 000001101101 + {11, 22}, {11, 22}, // 00000110111x + {8, 14}, {8, 14}, {8, 14}, {8, 14}, // 00000111xxxx + {8, 14}, {8, 14}, {8, 14}, {8, 14}, + {8, 14}, {8, 14}, {8, 14}, {8, 14}, + {8, 14}, {8, 14}, {8, 14}, {8, 14}, + {7, 10}, {7, 10}, {7, 10}, {7, 10}, // 0000100xxxxx + {7, 10}, {7, 10}, {7, 10}, {7, 10}, + {7, 10}, {7, 10}, {7, 10}, {7, 10}, + {7, 10}, {7, 10}, {7, 10}, {7, 10}, + {7, 10}, {7, 10}, {7, 10}, {7, 10}, + {7, 10}, {7, 10}, {7, 10}, {7, 10}, + {7, 10}, {7, 10}, {7, 10}, {7, 10}, + {7, 10}, {7, 10}, {7, 10}, {7, 10}, + {7, 11}, {7, 11}, {7, 11}, {7, 11}, // 0000101xxxxx + {7, 11}, {7, 11}, {7, 11}, {7, 11}, + {7, 11}, {7, 11}, {7, 11}, {7, 11}, + {7, 11}, {7, 11}, {7, 11}, {7, 11}, + {7, 11}, {7, 11}, {7, 11}, {7, 11}, + {7, 11}, {7, 11}, {7, 11}, {7, 11}, + {7, 11}, {7, 11}, {7, 11}, {7, 11}, + {7, 11}, {7, 11}, {7, 11}, {7, 11}, + {9, 15}, {9, 15}, {9, 15}, {9, 15}, // 000011000xxx + {9, 15}, {9, 15}, {9, 15}, {9, 15}, + {12, 128}, // 000011001000 + {12, 192}, // 000011001001 + {12, 26}, // 000011001010 + {12, 27}, // 000011001011 + {12, 28}, // 000011001100 + {12, 29}, // 000011001101 + {11, 19}, {11, 19}, // 00001100111x + {11, 20}, {11, 20}, // 00001101000x + {12, 34}, // 000011010010 + {12, 35}, // 000011010011 + {12, 36}, // 000011010100 + {12, 37}, // 000011010101 + {12, 38}, // 000011010110 + {12, 39}, // 000011010111 + {11, 21}, {11, 21}, // 00001101100x + {12, 42}, // 000011011010 + {12, 43}, // 000011011011 + {10, 0}, {10, 0}, {10, 0}, {10, 0}, // 0000110111xx + {7, 12}, {7, 12}, {7, 12}, {7, 12}, // 0000111xxxxx + {7, 12}, {7, 12}, {7, 12}, {7, 12}, + {7, 12}, {7, 12}, {7, 12}, {7, 12}, + {7, 12}, {7, 12}, {7, 12}, {7, 12}, + {7, 12}, {7, 12}, {7, 12}, {7, 12}, + {7, 12}, {7, 12}, {7, 12}, {7, 12}, + {7, 12}, {7, 12}, {7, 12}, {7, 12}, + {7, 12}, {7, 12}, {7, 12}, {7, 12} +}; + +// 2-6 bit codes +static CCITTCode blackTab3[64] = { + {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, // 0000xx + {6, 9}, // 000100 + {6, 8}, // 000101 + {5, 7}, {5, 7}, // 00011x + {4, 6}, {4, 6}, {4, 6}, {4, 6}, // 0010xx + {4, 5}, {4, 5}, {4, 5}, {4, 5}, // 0011xx + {3, 1}, {3, 1}, {3, 1}, {3, 1}, // 010xxx + {3, 1}, {3, 1}, {3, 1}, {3, 1}, + {3, 4}, {3, 4}, {3, 4}, {3, 4}, // 011xxx + {3, 4}, {3, 4}, {3, 4}, {3, 4}, + {2, 3}, {2, 3}, {2, 3}, {2, 3}, // 10xxxx + {2, 3}, {2, 3}, {2, 3}, {2, 3}, + {2, 3}, {2, 3}, {2, 3}, {2, 3}, + {2, 3}, {2, 3}, {2, 3}, {2, 3}, + {2, 2}, {2, 2}, {2, 2}, {2, 2}, // 11xxxx + {2, 2}, {2, 2}, {2, 2}, {2, 2}, + {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 new file mode 100644 index 0000000..383ac54 --- /dev/null +++ b/xpdf/Stream.cc @@ -0,0 +1,6064 @@ +//======================================================================== +// +// Stream.cc +// +// Copyright 1996-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include +#include +#include +#ifdef _WIN32 +#include +#else +#include +#endif +#include +#include +#include "gmem.h" +#include "gmempp.h" +#include "gfile.h" +#if MULTITHREADED +#include "GMutex.h" +#endif +#include "config.h" +#include "Error.h" +#include "Object.h" +#include "Lexer.h" +#include "GfxState.h" +#include "Stream.h" +#include "JBIG2Stream.h" +#include "JPXStream.h" +#include "Stream-CCITT.h" + +#ifdef __DJGPP__ +static GBool setDJSYSFLAGS = gFalse; +#endif + +#ifdef VMS +#ifdef __GNUC__ +#define SEEK_SET 0 +#define SEEK_CUR 1 +#define SEEK_END 2 +#endif +#endif + +//------------------------------------------------------------------------ + +// An LZW/Flate decompression bomb is detected if the output size +// exceeds decompressionBombSizeThreshold and the decompression ratio +// exceeds decompressionBombRatioThreshold. +#define decompressionBombSizeThreshold 50000000 +#define decompressionBombRatioThreshold 200 + +//------------------------------------------------------------------------ +// Stream (base class) +//------------------------------------------------------------------------ + +Stream::Stream() { +} + +Stream::~Stream() { +} + +void Stream::close() { +} + +int Stream::getRawChar() { + 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 || size < 0) + return NULL; + for (i = 0; i < size - 1; ++i) { + c = getChar(); + if (c == EOF || c == '\n') + break; + if (c == '\r') { + if ((c = lookChar()) == '\n') + getChar(); + break; + } + buf[i] = (char)c; + } + buf[i] = '\0'; + return buf; +} + +Guint Stream::discardChars(Guint n) { + char buf[4096]; + Guint count, i, j; + + count = 0; + while (count < n) { + if ((i = n - count) > sizeof(buf)) { + i = (Guint)sizeof(buf); + } + j = (Guint)getBlock(buf, (int)i); + count += j; + if (j != i) { + break; + } + } + return count; +} + +GString *Stream::getPSFilter(int psLevel, const char *indent, + GBool okToReadStream) { + return new GString(); +} + +Stream *Stream::addFilters(Object *dict, int recursion) { + Object obj, obj2; + Object params, params2; + Stream *str; + int i; + + str = this; + dict->dictLookup("Filter", &obj, recursion); + if (obj.isNull()) { + obj.free(); + dict->dictLookup("F", &obj, recursion); + } + dict->dictLookup("DecodeParms", ¶ms, recursion); + if (params.isNull()) { + params.free(); + dict->dictLookup("DP", ¶ms, recursion); + } + if (obj.isName()) { + str = makeFilter(obj.getName(), str, ¶ms, recursion); + } else if (obj.isArray()) { + for (i = 0; i < obj.arrayGetLength(); ++i) { + obj.arrayGet(i, &obj2, recursion); + if (params.isArray() && i < params.arrayGetLength()) + params.arrayGet(i, ¶ms2, recursion); + else + params2.initNull(); + if (obj2.isName()) { + str = makeFilter(obj2.getName(), str, ¶ms2, recursion); + } else { + error(errSyntaxError, getPos(), "Bad filter name"); + str = new EOFStream(str); + } + obj2.free(); + params2.free(); + } + } else if (!obj.isNull()) { + error(errSyntaxError, getPos(), "Bad 'Filter' attribute in stream"); + } + obj.free(); + params.free(); + + return str; +} + +Stream *Stream::makeFilter(char *name, Stream *str, Object *params, + int recursion) { + int pred; // parameters + int colors; + int bits; + int early; + int encoding; + GBool endOfLine, byteAlign, endOfBlock, black; + int columns, rows; + int colorXform; + Object globals, obj; + + if (!strcmp(name, "ASCIIHexDecode") || !strcmp(name, "AHx")) { + str = new ASCIIHexStream(str); + } else if (!strcmp(name, "ASCII85Decode") || !strcmp(name, "A85")) { + str = new ASCII85Stream(str); + } else if (!strcmp(name, "LZWDecode") || !strcmp(name, "LZW")) { + pred = 1; + columns = 1; + colors = 1; + bits = 8; + early = 1; + if (params->isDict()) { + params->dictLookup("Predictor", &obj, recursion); + if (obj.isInt()) + pred = obj.getInt(); + obj.free(); + params->dictLookup("Columns", &obj, recursion); + if (obj.isInt()) + columns = obj.getInt(); + obj.free(); + params->dictLookup("Colors", &obj, recursion); + if (obj.isInt()) + colors = obj.getInt(); + obj.free(); + params->dictLookup("BitsPerComponent", &obj, recursion); + if (obj.isInt()) + bits = obj.getInt(); + obj.free(); + params->dictLookup("EarlyChange", &obj, recursion); + if (obj.isInt()) + early = obj.getInt(); + obj.free(); + } + str = new LZWStream(str, pred, columns, colors, bits, early); + } else if (!strcmp(name, "RunLengthDecode") || !strcmp(name, "RL")) { + str = new RunLengthStream(str); + } else if (!strcmp(name, "CCITTFaxDecode") || !strcmp(name, "CCF")) { + encoding = 0; + endOfLine = gFalse; + byteAlign = gFalse; + columns = 1728; + rows = 0; + endOfBlock = gTrue; + black = gFalse; + if (params->isDict()) { + params->dictLookup("K", &obj, recursion); + if (obj.isInt()) { + encoding = obj.getInt(); + } + obj.free(); + params->dictLookup("EndOfLine", &obj, recursion); + if (obj.isBool()) { + endOfLine = obj.getBool(); + } + obj.free(); + params->dictLookup("EncodedByteAlign", &obj, recursion); + if (obj.isBool()) { + byteAlign = obj.getBool(); + } + obj.free(); + params->dictLookup("Columns", &obj, recursion); + if (obj.isInt()) { + columns = obj.getInt(); + } + obj.free(); + params->dictLookup("Rows", &obj, recursion); + if (obj.isInt()) { + rows = obj.getInt(); + } + obj.free(); + params->dictLookup("EndOfBlock", &obj, recursion); + if (obj.isBool()) { + endOfBlock = obj.getBool(); + } + obj.free(); + params->dictLookup("BlackIs1", &obj, recursion); + if (obj.isBool()) { + black = obj.getBool(); + } + obj.free(); + } + str = new CCITTFaxStream(str, encoding, endOfLine, byteAlign, + columns, rows, endOfBlock, black); + } else if (!strcmp(name, "DCTDecode") || !strcmp(name, "DCT")) { + colorXform = -1; + if (params->isDict()) { + if (params->dictLookup("ColorTransform", &obj, recursion)->isInt()) { + colorXform = obj.getInt(); + } + obj.free(); + } + str = new DCTStream(str, colorXform); + } else if (!strcmp(name, "FlateDecode") || !strcmp(name, "Fl")) { + pred = 1; + columns = 1; + colors = 1; + bits = 8; + if (params->isDict()) { + params->dictLookup("Predictor", &obj, recursion); + if (obj.isInt()) + pred = obj.getInt(); + obj.free(); + params->dictLookup("Columns", &obj, recursion); + if (obj.isInt()) + columns = obj.getInt(); + obj.free(); + params->dictLookup("Colors", &obj, recursion); + if (obj.isInt()) + colors = obj.getInt(); + obj.free(); + params->dictLookup("BitsPerComponent", &obj, recursion); + if (obj.isInt()) + bits = obj.getInt(); + obj.free(); + } + str = new FlateStream(str, pred, columns, colors, bits); + } else if (!strcmp(name, "JBIG2Decode")) { + if (params->isDict()) { + params->dictLookup("JBIG2Globals", &globals, recursion); + } + str = new JBIG2Stream(str, &globals); + globals.free(); + } else if (!strcmp(name, "JPXDecode")) { + str = new JPXStream(str); + } else if (!strcmp(name, "Crypt")) { + // this is handled in Parser::makeStream() + } else { + error(errSyntaxError, getPos(), "Unknown filter '{0:s}'", name); + str = new EOFStream(str); + } + return str; +} + +//------------------------------------------------------------------------ +// BaseStream +//------------------------------------------------------------------------ + +BaseStream::BaseStream(Object *dictA) { + dict = *dictA; +} + +BaseStream::~BaseStream() { + dict.free(); +} + +//------------------------------------------------------------------------ +// FilterStream +//------------------------------------------------------------------------ + +FilterStream::FilterStream(Stream *strA) { + str = strA; +} + +FilterStream::~FilterStream() { +} + +void FilterStream::close() { + str->close(); +} + +void FilterStream::setPos(GFileOffset pos, int dir) { + error(errInternal, -1, "Called setPos() on FilterStream"); +} + +//------------------------------------------------------------------------ +// ImageStream +//------------------------------------------------------------------------ + +ImageStream::ImageStream(Stream *strA, int widthA, int nCompsA, int nBitsA) { + int imgLineSize; + + str = strA; + width = widthA; + nComps = nCompsA; + nBits = nBitsA; + + nVals = width * nComps; + inputLineSize = (nVals * nBits + 7) >> 3; + if (width > INT_MAX / nComps || + nVals > (INT_MAX - 7) / nBits) { + // 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 { + if (nBits == 1) { + imgLineSize = (nVals + 7) & ~7; + } else { + imgLineSize = nVals; + } + imgLine = (Guchar *)gmallocn(imgLineSize, sizeof(Guchar)); + } + imgIdx = nVals; +} + +ImageStream::~ImageStream() { + if (imgLine != (Guchar *)inputLine) { + gfree(imgLine); + } + gfree(inputLine); +} + +void ImageStream::reset() { + str->disableDecompressionBombChecking(); + str->reset(); +} + +void ImageStream::close() { + str->close(); +} + +GBool ImageStream::getPixel(Guchar *pix) { + int i; + + if (imgIdx >= nVals) { + if (!getLine()) { + return gFalse; + } + imgIdx = 0; + } + for (i = 0; i < nComps; ++i) { + pix[i] = imgLine[imgIdx++]; + } + return gTrue; +} + +Guchar *ImageStream::getLine() { + Gulong buf, bitMask; + 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 = *p++; + imgLine[i+0] = (Guchar)((c >> 7) & 1); + imgLine[i+1] = (Guchar)((c >> 6) & 1); + imgLine[i+2] = (Guchar)((c >> 5) & 1); + imgLine[i+3] = (Guchar)((c >> 4) & 1); + imgLine[i+4] = (Guchar)((c >> 3) & 1); + imgLine[i+5] = (Guchar)((c >> 2) & 1); + imgLine[i+6] = (Guchar)((c >> 1) & 1); + imgLine[i+7] = (Guchar)(c & 1); + } + } else if (nBits == 8) { + // special case: imgLine == inputLine + } else if (nBits == 16) { + for (i = 0; i < nVals; ++i) { + imgLine[i] = (Guchar)inputLine[2*i]; + } + } else { + bitMask = (1 << nBits) - 1; + buf = 0; + bits = 0; + p = inputLine; + for (i = 0; i < nVals; ++i) { + if (bits < nBits) { + buf = (buf << 8) | (*p++ & 0xff); + bits += 8; + } + imgLine[i] = (Guchar)((buf >> (bits - nBits)) & bitMask); + bits -= nBits; + } + } + return imgLine; +} + +void ImageStream::skipLine() { + str->getBlock(inputLine, inputLineSize); +} + + +//------------------------------------------------------------------------ +// StreamPredictor +//------------------------------------------------------------------------ + +StreamPredictor::StreamPredictor(Stream *strA, int predictorA, + int widthA, int nCompsA, int nBitsA) { + str = strA; + predictor = predictorA; + width = widthA; + nComps = nCompsA; + nBits = nBitsA; + predLine = NULL; + ok = gFalse; + + nVals = width * nComps; + pixBytes = (nComps * nBits + 7) >> 3; + rowBytes = ((nVals * nBits + 7) >> 3) + pixBytes; + 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); + + reset(); + + ok = gTrue; +} + +StreamPredictor::~StreamPredictor() { + gfree(predLine); +} + +void StreamPredictor::reset() { + memset(predLine, 0, rowBytes); + predIdx = rowBytes; +} + +int StreamPredictor::lookChar() { + if (predIdx >= rowBytes) { + if (!getNextLine()) { + return EOF; + } + } + return predLine[predIdx]; +} + +int StreamPredictor::getChar() { + if (predIdx >= rowBytes) { + if (!getNextLine()) { + return EOF; + } + } + 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]; + int left, up, upLeft, p, pa, pb, pc; + int c; + Gulong inBuf, outBuf, bitMask; + int inBits, outBits; + int i, j, k, kk; + + // get PNG optimum predictor number + if (predictor >= 10) { + if ((curPred = str->getRawChar()) == EOF) { + return gFalse; + } + curPred += 10; + } else { + curPred = predictor; + } + + // read the raw line, apply PNG (byte) predictor + memset(upLeftBuf, 0, pixBytes + 1); + for (i = pixBytes; i < rowBytes; ++i) { + for (j = pixBytes; j > 0; --j) { + upLeftBuf[j] = upLeftBuf[j-1]; + } + upLeftBuf[0] = predLine[i]; + if ((c = str->getRawChar()) == EOF) { + if (i > pixBytes) { + // this ought to return false, but some (broken) PDF files + // contain truncated image data, and Adobe apparently reads the + // last partial line + break; + } + return gFalse; + } + switch (curPred) { + case 11: // PNG sub + predLine[i] = (Guchar)(predLine[i - pixBytes] + c); + break; + case 12: // PNG up + predLine[i] = (Guchar)(predLine[i] + c); + break; + case 13: // PNG average + predLine[i] = (Guchar)(((predLine[i - pixBytes] + predLine[i]) >> 1) + c); + break; + case 14: // PNG Paeth + left = predLine[i - pixBytes]; + up = predLine[i]; + upLeft = upLeftBuf[pixBytes]; + p = left + up - upLeft; + if ((pa = p - left) < 0) + pa = -pa; + if ((pb = p - up) < 0) + pb = -pb; + if ((pc = p - upLeft) < 0) + pc = -pc; + if (pa <= pb && pa <= pc) + predLine[i] = (Guchar)(left + c); + else if (pb <= pc) + predLine[i] = (Guchar)(up + c); + else + predLine[i] = (Guchar)(upLeft + c); + break; + case 10: // PNG none + default: // no predictor or TIFF predictor + predLine[i] = (Guchar)c; + break; + } + } + + // apply TIFF (component) predictor + if (predictor == 2) { + if (nBits == 8) { + for (i = pixBytes; i < rowBytes; ++i) { + predLine[i] = (Guchar)(predLine[i] + predLine[i - nComps]); + } + } else if (nBits == 16) { + for (i = pixBytes; i < rowBytes; i += 2) { + c = ((predLine[i] + predLine[i - 2*nComps]) << 8) + + predLine[i + 1] + predLine[i + 1 - 2*nComps]; + predLine[i] = (Guchar)(c >> 8); + predLine[i+1] = (Guchar)(c & 0xff); + } + } else { + memset(upLeftBuf, 0, nComps); + bitMask = (1 << nBits) - 1; + inBuf = outBuf = 0; + inBits = outBits = 0; + j = k = pixBytes; + for (i = 0; i < width; ++i) { + for (kk = 0; kk < nComps; ++kk) { + if (inBits < nBits) { + inBuf = (inBuf << 8) | (predLine[j++] & 0xff); + inBits += 8; + } + upLeftBuf[kk] = (Guchar)((upLeftBuf[kk] + + (inBuf >> (inBits - nBits))) & bitMask); + inBits -= nBits; + outBuf = (outBuf << nBits) | upLeftBuf[kk]; + outBits += nBits; + if (outBits >= 8) { + predLine[k++] = (Guchar)(outBuf >> (outBits - 8)); + outBits -= 8; + } + } + } + if (outBits > 0) { + predLine[k++] = (Guchar)((outBuf << (8 - outBits)) + + (inBuf & ((1 << (8 - outBits)) - 1))); + } + } + } + + // reset to start of line + predIdx = pixBytes; + + return gTrue; +} + +//------------------------------------------------------------------------ +// SharedFile +//------------------------------------------------------------------------ + +class SharedFile { +public: + + SharedFile(FILE *fA); + SharedFile *copy(); + void free(); + int readBlock(char *buf, GFileOffset pos, int size); + GFileOffset getSize(); + +private: + + ~SharedFile(); + + FILE *f; + int refCnt; +#if MULTITHREADED + GMutex mutex; +#endif +}; + +SharedFile::SharedFile(FILE *fA) { + f = fA; + refCnt = 1; +#if MULTITHREADED + gInitMutex(&mutex); +#endif +} + +SharedFile::~SharedFile() { +#if MULTITHREADED + gDestroyMutex(&mutex); +#endif +} + +SharedFile *SharedFile::copy() { +#if MULTITHREADED + gLockMutex(&mutex); +#endif + ++refCnt; +#if MULTITHREADED + gUnlockMutex(&mutex); +#endif + return this; +} + +void SharedFile::free() { + int newCount; + +#if MULTITHREADED + gLockMutex(&mutex); +#endif + newCount = --refCnt; +#if MULTITHREADED + gUnlockMutex(&mutex); +#endif + if (newCount == 0) { + delete this; + } +} + +int SharedFile::readBlock(char *buf, GFileOffset pos, int size) { + int n; + +#if MULTITHREADED + gLockMutex(&mutex); +#endif + gfseek(f, pos, SEEK_SET); + n = (int)fread(buf, 1, size, f); +#if MULTITHREADED + gUnlockMutex(&mutex); +#endif + return n; +} + +GFileOffset SharedFile::getSize() { + GFileOffset size; + +#if MULTITHREADED + gLockMutex(&mutex); +#endif + gfseek(f, 0, SEEK_END); + size = gftell(f); +#if MULTITHREADED + gUnlockMutex(&mutex); +#endif + return size; +} + +//------------------------------------------------------------------------ +// FileStream +//------------------------------------------------------------------------ + +FileStream::FileStream(FILE *fA, GFileOffset startA, GBool limitedA, + GFileOffset lengthA, Object *dictA): + BaseStream(dictA) { + f = new SharedFile(fA); + start = startA; + limited = limitedA; + length = lengthA; + bufPtr = bufEnd = buf; + bufPos = start; +} + +FileStream::FileStream(SharedFile *fA, GFileOffset startA, GBool limitedA, + GFileOffset lengthA, Object *dictA): + BaseStream(dictA) { + f = fA->copy(); + start = startA; + limited = limitedA; + length = lengthA; + bufPtr = bufEnd = buf; + bufPos = start; +} + +FileStream::~FileStream() { + f->free(); +} + +Stream *FileStream::copy() { + Object dictA; + + dict.copy(&dictA); + return new FileStream(f, start, limited, length, &dictA); +} + +Stream *FileStream::makeSubStream(GFileOffset startA, GBool limitedA, + GFileOffset lengthA, Object *dictA) { + return new FileStream(f, startA, limitedA, lengthA, dictA); +} + +void FileStream::reset() { + bufPtr = bufEnd = buf; + bufPos = start; +} + +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 += (int)(bufEnd - buf); + bufPtr = bufEnd = buf; + if (limited && bufPos >= start + length) { + return gFalse; + } + if (limited && bufPos + fileStreamBufSize > start + length) { + n = (int)(start + length - bufPos); + } else { + n = fileStreamBufSize; + } + n = f->readBlock(buf, bufPos, n); + bufEnd = buf + n; + if (bufPtr >= bufEnd) { + return gFalse; + } + return gTrue; +} + +void FileStream::setPos(GFileOffset pos, int dir) { + GFileOffset size; + + if (dir >= 0) { + bufPos = pos; + } else { + size = f->getSize(); + if (pos <= size) { + bufPos = size - pos; + } else { + bufPos = 0; + } + } + bufPtr = bufEnd = buf; +} + +void FileStream::moveStart(int delta) { + start += delta; + bufPtr = bufEnd = buf; + bufPos = start; +} + +//------------------------------------------------------------------------ +// MemStream +//------------------------------------------------------------------------ + +MemStream::MemStream(char *bufA, Guint startA, Guint lengthA, Object *dictA): + BaseStream(dictA) { + buf = bufA; + start = startA; + length = lengthA; + bufEnd = buf + start + length; + bufPtr = buf + start; + needFree = gFalse; +} + +MemStream::~MemStream() { + if (needFree) { + gfree(buf); + } +} + +Stream *MemStream::copy() { + Object dictA; + + dict.copy(&dictA); + return new MemStream(buf, start, length, &dictA); +} + +Stream *MemStream::makeSubStream(GFileOffset startA, GBool limited, + GFileOffset lengthA, Object *dictA) { + MemStream *subStr; + Guint newStart, newLength; + + if (startA < start) { + newStart = start; + } else if (startA > start + length) { + newStart = start + (int)length; + } else { + newStart = (int)startA; + } + if (!limited || newStart + lengthA > start + length) { + newLength = start + length - newStart; + } else { + newLength = (Guint)lengthA; + } + subStr = new MemStream(buf, newStart, newLength, dictA); + return subStr; +} + +void MemStream::reset() { + bufPtr = buf + start; +} + +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(GFileOffset pos, int dir) { + Guint i; + + if (dir >= 0) { + i = (Guint)pos; + } else { + if (pos > start + length) { + i = 0; + } else { + i = (Guint)(start + length - pos); + } + } + if (i < start) { + i = start; + } else if (i > start + length) { + i = start + length; + } + bufPtr = buf + i; +} + +void MemStream::moveStart(int delta) { + start += delta; + length -= delta; + bufPtr = buf + start; +} + +//------------------------------------------------------------------------ +// EmbedStream +//------------------------------------------------------------------------ + +EmbedStream::EmbedStream(Stream *strA, Object *dictA, + GBool limitedA, GFileOffset lengthA): + BaseStream(dictA) { + str = strA; + limited = limitedA; + length = lengthA; +} + +EmbedStream::~EmbedStream() { +} + +Stream *EmbedStream::copy() { + Object dictA; + + dict.copy(&dictA); + return new EmbedStream(str, &dictA, limited, length); +} + +Stream *EmbedStream::makeSubStream(GFileOffset start, GBool limitedA, + GFileOffset lengthA, Object *dictA) { + error(errInternal, -1, "Called makeSubStream() on EmbedStream"); + return NULL; +} + +int EmbedStream::getChar() { + if (limited && !length) { + return EOF; + } + --length; + return str->getChar(); +} + +int EmbedStream::lookChar() { + if (limited && !length) { + return EOF; + } + return str->lookChar(); +} + +int EmbedStream::getBlock(char *blk, int size) { + if (size <= 0) { + return 0; + } + if (limited && length < (Guint)size) { + size = (int)length; + } + length -= size; + return str->getBlock(blk, size); +} + +void EmbedStream::setPos(GFileOffset pos, int dir) { + error(errInternal, -1, "Called setPos() on EmbedStream"); +} + +GFileOffset EmbedStream::getStart() { + error(errInternal, -1, "Called getStart() on EmbedStream"); + return 0; +} + +void EmbedStream::moveStart(int delta) { + error(errInternal, -1, "Called moveStart() on EmbedStream"); +} + +//------------------------------------------------------------------------ +// ASCIIHexStream +//------------------------------------------------------------------------ + +ASCIIHexStream::ASCIIHexStream(Stream *strA): + FilterStream(strA) { + buf = EOF; + eof = gFalse; +} + +ASCIIHexStream::~ASCIIHexStream() { + delete str; +} + +Stream *ASCIIHexStream::copy() { + return new ASCIIHexStream(str->copy()); +} + +void ASCIIHexStream::reset() { + str->reset(); + buf = EOF; + eof = gFalse; +} + +int ASCIIHexStream::lookChar() { + int c1, c2, x; + + if (buf != EOF) + return buf; + if (eof) { + buf = EOF; + return EOF; + } + do { + c1 = str->getChar(); + } while (isspace(c1)); + if (c1 == '>') { + eof = gTrue; + buf = EOF; + return buf; + } + do { + c2 = str->getChar(); + } while (isspace(c2)); + if (c2 == '>') { + eof = gTrue; + c2 = '0'; + } + if (c1 >= '0' && c1 <= '9') { + x = (c1 - '0') << 4; + } else if (c1 >= 'A' && c1 <= 'F') { + x = (c1 - 'A' + 10) << 4; + } else if (c1 >= 'a' && c1 <= 'f') { + x = (c1 - 'a' + 10) << 4; + } else if (c1 == EOF) { + eof = gTrue; + x = 0; + } else { + error(errSyntaxError, getPos(), + "Illegal character <{0:02x}> in ASCIIHex stream", c1); + x = 0; + } + if (c2 >= '0' && c2 <= '9') { + x += c2 - '0'; + } else if (c2 >= 'A' && c2 <= 'F') { + x += c2 - 'A' + 10; + } else if (c2 >= 'a' && c2 <= 'f') { + x += c2 - 'a' + 10; + } else if (c2 == EOF) { + eof = gTrue; + x = 0; + } else { + error(errSyntaxError, getPos(), + "Illegal character <{0:02x}> in ASCIIHex stream", c2); + } + buf = x & 0xff; + return buf; +} + +GString *ASCIIHexStream::getPSFilter(int psLevel, const char *indent, + GBool okToReadStream) { + GString *s; + + if (psLevel < 2) { + return NULL; + } + if (!(s = str->getPSFilter(psLevel, indent, okToReadStream))) { + return NULL; + } + s->append(indent)->append("/ASCIIHexDecode filter\n"); + return s; +} + +GBool ASCIIHexStream::isBinary(GBool last) { + return str->isBinary(gFalse); +} + +//------------------------------------------------------------------------ +// ASCII85Stream +//------------------------------------------------------------------------ + +ASCII85Stream::ASCII85Stream(Stream *strA): + FilterStream(strA) { + index = n = 0; + eof = gFalse; +} + +ASCII85Stream::~ASCII85Stream() { + delete str; +} + +Stream *ASCII85Stream::copy() { + return new ASCII85Stream(str->copy()); +} + +void ASCII85Stream::reset() { + str->reset(); + index = n = 0; + eof = gFalse; +} + +int ASCII85Stream::lookChar() { + int k; + Gulong t; + + if (index >= n) { + if (eof) + return EOF; + index = 0; + do { + c[0] = str->getChar(); + } while (Lexer::isSpace(c[0])); + if (c[0] == '~' || c[0] == EOF) { + eof = gTrue; + n = 0; + return EOF; + } else if (c[0] == 'z') { + b[0] = b[1] = b[2] = b[3] = 0; + n = 4; + } else { + for (k = 1; k < 5; ++k) { + do { + c[k] = str->getChar(); + } while (Lexer::isSpace(c[k])); + if (c[k] == '~' || c[k] == EOF) + break; + } + n = k - 1; + if (k < 5 && (c[k] == '~' || c[k] == EOF)) { + for (++k; k < 5; ++k) + c[k] = 0x21 + 84; + eof = gTrue; + } + t = 0; + for (k = 0; k < 5; ++k) + t = t * 85 + (c[k] - 0x21); + for (k = 3; k >= 0; --k) { + b[k] = (int)(t & 0xff); + t >>= 8; + } + } + } + return b[index]; +} + +GString *ASCII85Stream::getPSFilter(int psLevel, const char *indent, + GBool okToReadStream) { + GString *s; + + if (psLevel < 2) { + return NULL; + } + if (!(s = str->getPSFilter(psLevel, indent, okToReadStream))) { + return NULL; + } + s->append(indent)->append("/ASCII85Decode filter\n"); + return s; +} + +GBool ASCII85Stream::isBinary(GBool last) { + return str->isBinary(gFalse); +} + +//------------------------------------------------------------------------ +// LZWStream +//------------------------------------------------------------------------ + +LZWStream::LZWStream(Stream *strA, int predictor, int columns, int colors, + int bits, int earlyA): + FilterStream(strA) { + if (predictor != 1) { + pred = new StreamPredictor(this, predictor, columns, colors, bits); + if (!pred->isOk()) { + delete pred; + pred = NULL; + } + } else { + pred = NULL; + } + early = earlyA; + eof = gFalse; + inputBits = 0; + clearTable(); + checkForDecompressionBombs = gTrue; +} + +LZWStream::~LZWStream() { + if (pred) { + delete pred; + } + delete str; +} + +Stream *LZWStream::copy() { + if (pred) { + return new LZWStream(str->copy(), pred->getPredictor(), + pred->getWidth(), pred->getNComps(), + pred->getNBits(), early); + } else { + return new LZWStream(str->copy(), 1, 0, 0, 0, early); + } +} + +void LZWStream::disableDecompressionBombChecking() { + checkForDecompressionBombs = gFalse; + FilterStream::disableDecompressionBombChecking(); +} + +int LZWStream::getChar() { + if (pred) { + return pred->getChar(); + } + if (eof) { + return EOF; + } + if (seqIndex >= seqLength) { + if (!processNextCode()) { + return EOF; + } + } + return seqBuf[seqIndex++]; +} + +int LZWStream::lookChar() { + if (pred) { + return pred->lookChar(); + } + if (eof) { + return EOF; + } + if (seqIndex >= seqLength) { + if (!processNextCode()) { + return EOF; + } + } + return seqBuf[seqIndex]; +} + +int LZWStream::getRawChar() { + if (eof) { + return EOF; + } + if (seqIndex >= seqLength) { + if (!processNextCode()) { + return EOF; + } + } + 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(); + if (pred) { + pred->reset(); + } + eof = gFalse; + inputBits = 0; + clearTable(); + totalIn = totalOut = 0; +} + +GBool LZWStream::processNextCode() { + int code; + int nextLength; + int i, j; + + // check for EOF + if (eof) { + return gFalse; + } + + // check for eod and clear-table codes + start: + code = getCode(); + if (code == EOF || code == 257) { + eof = gTrue; + return gFalse; + } + if (code == 256) { + clearTable(); + goto start; + } + if (nextCode >= 4097) { + error(errSyntaxError, getPos(), + "Bad LZW stream - expected clear-table code"); + clearTable(); + } + + // process the next code + nextLength = seqLength + 1; + if (code < 256) { + seqBuf[0] = (Guchar)code; + seqLength = 1; + } else if (code < nextCode) { + seqLength = table[code].length; + for (i = seqLength - 1, j = code; i > 0; --i) { + seqBuf[i] = table[j].tail; + j = table[j].head; + } + seqBuf[0] = (Guchar)j; + } else if (code == nextCode) { + seqBuf[seqLength] = (Guchar)newChar; + ++seqLength; + } else { + error(errSyntaxError, getPos(), "Bad LZW stream - unexpected code"); + eof = gTrue; + return gFalse; + } + newChar = seqBuf[0]; + if (first) { + first = gFalse; + } else { + table[nextCode].length = nextLength; + table[nextCode].head = prevCode; + table[nextCode].tail = (Guchar)newChar; + ++nextCode; + if (nextCode + early == 512) + nextBits = 10; + else if (nextCode + early == 1024) + nextBits = 11; + else if (nextCode + early == 2048) + nextBits = 12; + } + prevCode = code; + totalOut += seqLength; + + // check for a 'decompression bomb' + if (checkForDecompressionBombs && + totalOut > decompressionBombSizeThreshold && + totalIn < totalOut / decompressionBombRatioThreshold) { + error(errSyntaxError, getPos(), "Decompression bomb in LZW stream"); + eof = gTrue; + return gFalse; + } + + // reset buffer + seqIndex = 0; + + return gTrue; +} + +void LZWStream::clearTable() { + nextCode = 258; + nextBits = 9; + seqIndex = seqLength = 0; + first = gTrue; +} + +int LZWStream::getCode() { + int c; + int code; + + while (inputBits < nextBits) { + if ((c = str->getChar()) == EOF) + return EOF; + inputBuf = (inputBuf << 8) | (c & 0xff); + inputBits += 8; + ++totalIn; + } + code = (inputBuf >> (inputBits - nextBits)) & ((1 << nextBits) - 1); + inputBits -= nextBits; + return code; +} + +GString *LZWStream::getPSFilter(int psLevel, const char *indent, + GBool okToReadStream) { + GString *s; + + if (psLevel < 2 || pred) { + return NULL; + } + if (!(s = str->getPSFilter(psLevel, indent, okToReadStream))) { + return NULL; + } + s->append(indent)->append("<< "); + if (!early) { + s->append("/EarlyChange 0 "); + } + s->append(">> /LZWDecode filter\n"); + return s; +} + +GBool LZWStream::isBinary(GBool last) { + return str->isBinary(gTrue); +} + +//------------------------------------------------------------------------ +// RunLengthStream +//------------------------------------------------------------------------ + +RunLengthStream::RunLengthStream(Stream *strA): + FilterStream(strA) { + bufPtr = bufEnd = buf; + eof = gFalse; +} + +RunLengthStream::~RunLengthStream() { + delete str; +} + +Stream *RunLengthStream::copy() { + return new RunLengthStream(str->copy()); +} + +void RunLengthStream::reset() { + str->reset(); + bufPtr = bufEnd = buf; + eof = gFalse; +} + +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, + GBool okToReadStream) { + GString *s; + + if (psLevel < 2) { + return NULL; + } + if (!(s = str->getPSFilter(psLevel, indent, okToReadStream))) { + return NULL; + } + s->append(indent)->append("/RunLengthDecode filter\n"); + return s; +} + +GBool RunLengthStream::isBinary(GBool last) { + return str->isBinary(gTrue); +} + +GBool RunLengthStream::fillBuf() { + int c; + int n, i; + + if (eof) + return gFalse; + c = str->getChar(); + if (c == 0x80 || c == EOF) { + eof = gTrue; + return gFalse; + } + if (c < 0x80) { + n = c + 1; + for (i = 0; i < n; ++i) + buf[i] = (char)str->getChar(); + } else { + n = 0x101 - c; + c = str->getChar(); + for (i = 0; i < n; ++i) + buf[i] = (char)c; + } + bufPtr = buf; + bufEnd = buf + n; + return gTrue; +} + +//------------------------------------------------------------------------ +// CCITTFaxStream +//------------------------------------------------------------------------ + +CCITTFaxStream::CCITTFaxStream(Stream *strA, int encodingA, GBool endOfLineA, + GBool byteAlignA, int columnsA, int rowsA, + GBool endOfBlockA, GBool blackA): + FilterStream(strA) { + encoding = encodingA; + endOfLine = endOfLineA; + byteAlign = byteAlignA; + columns = columnsA; + if (columns < 1) { + columns = 1; + } else if (columns > INT_MAX - 3) { + columns = INT_MAX - 3; + } + rows = rowsA; + endOfBlock = endOfBlockA; + black = blackA; + blackXOR = black ? 0xff : 0x00; + // 0 <= codingLine[0] < codingLine[1] < ... < codingLine[n] = columns + // ---> max codingLine size = columns + 1 + // refLine has two extra guard entries at the end + // ---> max refLine size = columns + 3 + codingLine = (int *)gmallocn(columns + 1, sizeof(int)); + refLine = (int *)gmallocn(columns + 3, sizeof(int)); + + eof = gFalse; + row = 0; + nextLine2D = encoding < 0; + inputBits = 0; + codingLine[0] = columns; + nextCol = columns; + a0i = 0; + err = gFalse; + nErrors = 0; +} + +CCITTFaxStream::~CCITTFaxStream() { + delete str; + gfree(refLine); + gfree(codingLine); +} + +Stream *CCITTFaxStream::copy() { + return new CCITTFaxStream(str->copy(), encoding, endOfLine, + byteAlign, columns, rows, endOfBlock, black); +} + +void CCITTFaxStream::reset() { + int code1; + + str->reset(); + eof = gFalse; + row = 0; + nextLine2D = encoding < 0; + inputBits = 0; + codingLine[0] = columns; + nextCol = columns; + a0i = 0; + + // skip any initial zero bits and end-of-line marker, and get the 2D + // encoding tag + while ((code1 = lookBits(12)) == 0) { + eatBits(1); + } + if (code1 == 0x001) { + eatBits(12); + endOfLine = gTrue; + } + if (encoding > 0) { + nextLine2D = !lookBits(1); + eatBits(1); + } +} + +int CCITTFaxStream::getChar() { + int c, bitsNeeded, bitsAvail, bitsUsed; + + if (nextCol >= columns) { + if (eof) { + return EOF; + } + if (!readRow()) { + return EOF; + } + } + bitsAvail = codingLine[a0i] - nextCol; + if (bitsAvail > 8) { + c = (a0i & 1) ? 0x00 : 0xff; + } else { + c = 0; + bitsNeeded = 8; + do { + bitsUsed = (bitsAvail < bitsNeeded) ? bitsAvail : bitsNeeded; + c <<= bitsUsed; + if (!(a0i & 1)) { + c |= 0xff >> (8 - bitsUsed); + } + bitsAvail -= bitsUsed; + bitsNeeded -= bitsUsed; + if (bitsAvail == 0) { + if (codingLine[a0i] >= columns) { + c <<= bitsNeeded; + break; + } + ++a0i; + bitsAvail = codingLine[a0i] - codingLine[a0i - 1]; + } + } while (bitsNeeded > 0); + } + nextCol += 8; + c ^= blackXOR; + return c; +} + +int CCITTFaxStream::lookChar() { + int c, bitsNeeded, bitsAvail, bitsUsed, i; + + if (nextCol >= columns) { + if (eof) { + return EOF; + } + if (!readRow()) { + return EOF; + } + } + bitsAvail = codingLine[a0i] - nextCol; + if (bitsAvail >= 8) { + c = (a0i & 1) ? 0x00 : 0xff; + } else { + i = a0i; + c = 0; + bitsNeeded = 8; + do { + bitsUsed = (bitsAvail < bitsNeeded) ? bitsAvail : bitsNeeded; + c <<= bitsUsed; + if (!(i & 1)) { + c |= 0xff >> (8 - bitsUsed); + } + bitsAvail -= bitsUsed; + bitsNeeded -= bitsUsed; + if (bitsAvail == 0) { + if (codingLine[i] >= columns) { + c <<= bitsNeeded; + break; + } + ++i; + bitsAvail = codingLine[i] - codingLine[i - 1]; + } + } while (bitsNeeded > 0); + } + c ^= blackXOR; + return c; +} + +int CCITTFaxStream::getBlock(char *blk, int size) { + int bytesRead, bitsAvail, bitsNeeded, bitsUsed, byte, c; + + bytesRead = 0; + while (bytesRead < size) { + if (nextCol >= columns) { + if (eof) { + break; + } + if (!readRow()) { + break; + } + } + bitsAvail = codingLine[a0i] - nextCol; + byte = (a0i & 1) ? 0x00 : 0xff; + if (bitsAvail > 8) { + c = byte; + bitsAvail -= 8; + } else { + c = 0; + bitsNeeded = 8; + do { + bitsUsed = (bitsAvail < bitsNeeded) ? bitsAvail : bitsNeeded; + c <<= bitsUsed; + c |= byte >> (8 - bitsUsed); + bitsAvail -= bitsUsed; + bitsNeeded -= bitsUsed; + if (bitsAvail == 0) { + if (codingLine[a0i] >= columns) { + c <<= bitsNeeded; + break; + } + ++a0i; + bitsAvail = codingLine[a0i] - codingLine[a0i - 1]; + byte ^= 0xff; + } + } while (bitsNeeded > 0); + } + nextCol += 8; + blk[bytesRead++] = (char)(c ^ blackXOR); + } + return bytesRead; +} + +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; + ++nErrors; + 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; + ++nErrors; + 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; + ++nErrors; + a1 = 0; + } + while (a0i > 0 && a1 <= codingLine[a0i - 1]) { + --a0i; + } + codingLine[a0i] = a1; + } +} + +GBool CCITTFaxStream::readRow() { + int code1, code2, code3; + int b1i, blackPixels, i; + GBool gotEOL; + + // if at eof just return EOF + if (eof) { + return gFalse; + } + + err = gFalse; + + // 2-D encoding + if (nextLine2D) { + for (i = 0; codingLine[i] < columns; ++i) { + refLine[i] = codingLine[i]; + } + refLine[i++] = columns; + 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: + addPixels(refLine[b1i + 1], blackPixels); + if (refLine[b1i + 1] < columns) { + b1i += 2; + } + break; + case twoDimHoriz: + code1 = code2 = 0; + if (blackPixels) { + do { + code1 += code3 = getBlackCode(); + } while (code3 >= 64); + do { + code2 += code3 = getWhiteCode(); + } while (code3 >= 64); + } else { + do { + code1 += code3 = getWhiteCode(); + } while (code3 >= 64); + do { + code2 += code3 = getBlackCode(); + } while (code3 >= 64); + } + 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 twoDimVertR2: + addPixels(refLine[b1i] + 2, blackPixels); + blackPixels ^= 1; + if (codingLine[a0i] < columns) { + ++b1i; + while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) { + b1i += 2; + } + } + break; + case twoDimVertR1: + addPixels(refLine[b1i] + 1, blackPixels); + blackPixels ^= 1; + if (codingLine[a0i] < columns) { + ++b1i; + while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) { + b1i += 2; + } + } + break; + 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 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; + } + } + break; + case twoDimVertL2: + addPixelsNeg(refLine[b1i] - 2, 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 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); + err = gTrue; + break; + default: + error(errSyntaxError, getPos(), + "Bad 2D code {0:04x} in CCITTFax stream", code1); + addPixels(columns, 0); + err = gTrue; + ++nErrors; + break; + } + } + + // 1-D encoding + } else { + codingLine[0] = 0; + a0i = 0; + blackPixels = 0; + while (codingLine[a0i] < columns) { + code1 = 0; + if (blackPixels) { + do { + code1 += code3 = getBlackCode(); + } while (code3 >= 64); + } else { + do { + code1 += code3 = getWhiteCode(); + } while (code3 >= 64); + } + addPixels(codingLine[a0i] + code1, blackPixels); + blackPixels ^= 1; + } + } + + // 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 if (endOfLine || !byteAlign) { + 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; + } + } + + // 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); + eatBits(1); + } + + // 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) { + eatBits(12); + if (encoding > 0) { + lookBits(1); + eatBits(1); + } + if (encoding > 0) { + for (i = 0; i < 4; ++i) { + code1 = lookBits(12); + if (code1 != 0x001) { + error(errSyntaxError, getPos(), + "Bad RTC code in CCITTFax stream"); + ++nErrors; + } + eatBits(12); + if (encoding > 0) { + lookBits(1); + eatBits(1); + } + } + } + eof = gTrue; + } + + // look for an end-of-line marker after an error -- we only do + // 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) { + while (1) { + code1 = lookBits(13); + if (code1 == EOF) { + eof = gTrue; + return gFalse; + } + if ((code1 >> 1) == 0x001) { + break; + } + eatBits(1); + } + eatBits(12); + if (encoding > 0) { + eatBits(1); + nextLine2D = !(code1 & 1); + } + } + + // corrupt CCITTFax streams can generate huge data expansion -- we + // avoid that case by aborting decode after 1000 errors + if (nErrors > 1000) { + error(errSyntaxError, getPos(), "Too many errors in CCITTFaxStream - aborting decode"); + eof = gTrue; + return gFalse; + } + + // set up for output + nextCol = 0; + a0i = (codingLine[0] > 0) ? 0 : 1; + + ++row; + + return gTrue; +} + +short CCITTFaxStream::getTwoDimCode() { + int code; + CCITTCode *p; + int n; + + code = 0; // make gcc happy + if (endOfBlock) { + 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) { + if ((code = lookBits(n)) == EOF) { + break; + } + if (n < 7) { + code <<= 7 - n; + } + p = &twoDimTab1[code]; + if (p->bits == n) { + eatBits(n); + return p->n; + } + } + } + error(errSyntaxError, getPos(), + "Bad two dim code ({0:04x}) in CCITTFax stream", code); + ++nErrors; + return EOF; +} + +short CCITTFaxStream::getWhiteCode() { + short code; + CCITTCode *p; + int n; + + code = 0; // make gcc happy + if (endOfBlock) { + code = lookBits(12); + if (code == EOF) { + return 1; + } + if ((code >> 5) == 0) { + p = &whiteTab1[code]; + } else { + p = &whiteTab2[code >> 3]; + } + if (p->bits > 0) { + eatBits(p->bits); + return p->n; + } + } else { + for (n = 1; n <= 9; ++n) { + code = lookBits(n); + if (code == EOF) { + return 1; + } + if (n < 9) { + code = (short)(code << (9 - n)); + } + p = &whiteTab2[code]; + if (p->bits == n) { + eatBits(n); + return p->n; + } + } + for (n = 11; n <= 12; ++n) { + code = lookBits(n); + if (code == EOF) { + return 1; + } + if (n < 12) { + code = (short)(code << (12 - n)); + } + p = &whiteTab1[code]; + if (p->bits == n) { + eatBits(n); + return p->n; + } + } + } + error(errSyntaxError, getPos(), + "Bad white code ({0:04x}) in CCITTFax stream", code); + ++nErrors; + // eat a bit and return a positive number so that the caller doesn't + // go into an infinite loop + eatBits(1); + return 1; +} + +short CCITTFaxStream::getBlackCode() { + short code; + CCITTCode *p; + int n; + + 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 && (code >> 7) != 0) { + p = &blackTab2[(code >> 1) - 64]; + } else { + p = &blackTab3[code >> 7]; + } + if (p->bits > 0) { + eatBits(p->bits); + return p->n; + } + } else { + for (n = 2; n <= 6; ++n) { + code = lookBits(n); + if (code == EOF) { + return 1; + } + if (n < 6) { + code = (short)(code << (6 - n)); + } + p = &blackTab3[code]; + if (p->bits == n) { + eatBits(n); + return p->n; + } + } + for (n = 7; n <= 12; ++n) { + code = lookBits(n); + if (code == EOF) { + return 1; + } + if (n < 12) { + code = (short)(code << (12 - n)); + } + if (code >= 64) { + p = &blackTab2[code - 64]; + if (p->bits == n) { + eatBits(n); + return p->n; + } + } + } + for (n = 10; n <= 13; ++n) { + code = lookBits(n); + if (code == EOF) { + return 1; + } + if (n < 13) { + code = (short)(code << (13 - n)); + } + p = &blackTab1[code]; + if (p->bits == n) { + eatBits(n); + return p->n; + } + } + } + error(errSyntaxError, getPos(), + "Bad black code ({0:04x}) in CCITTFax stream", code); + ++nErrors; + // eat a bit and return a positive number so that the caller doesn't + // go into an infinite loop + eatBits(1); + return 1; +} + +short CCITTFaxStream::lookBits(int n) { + int c; + + while (inputBits < n) { + if ((c = str->getChar()) == EOF) { + if (inputBits == 0) { + return EOF; + } + // near the end of the stream, the caller may ask for more bits + // 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 (short)((inputBuf << (n - inputBits)) & (0xffffffff >> (32 - n))); + } + inputBuf = (inputBuf << 8) + c; + inputBits += 8; + } + return (short)((inputBuf >> (inputBits - n)) & (0xffffffff >> (32 - n))); +} + +GString *CCITTFaxStream::getPSFilter(int psLevel, const char *indent, + GBool okToReadStream) { + GString *s; + + if (psLevel < 2) { + return NULL; + } + if (!(s = str->getPSFilter(psLevel, indent, okToReadStream))) { + return NULL; + } + s->append(indent)->append("<< "); + if (encoding != 0) { + s->appendf("/K {0:d} ", encoding); + } + if (endOfLine) { + s->append("/EndOfLine true "); + } + if (byteAlign) { + s->append("/EncodedByteAlign true "); + } + s->appendf("/Columns {0:d} ", columns); + if (rows != 0) { + s->appendf("/Rows {0:d} ", rows); + } + if (!endOfBlock) { + s->append("/EndOfBlock false "); + } + if (black) { + s->append("/BlackIs1 true "); + } + s->append(">> /CCITTFaxDecode filter\n"); + return s; +} + +GBool CCITTFaxStream::isBinary(GBool last) { + return str->isBinary(gTrue); +} + +//------------------------------------------------------------------------ +// DCTStream +//------------------------------------------------------------------------ + +#if HAVE_JPEGLIB + +DCTStream::DCTStream(Stream *strA, GBool colorXformA): + FilterStream(strA) { + colorXform = colorXformA; + lineBuf = NULL; + inlineImage = str->isEmbedStream(); +} + +DCTStream::~DCTStream() { + delete str; +} + +Stream *DCTStream::copy() { + return new DCTStream(str->copy(), colorXform); +} + +void DCTStream::reset() { + int i; + + lineBuf = NULL; + error = gFalse; + + str->reset(); + + // initialize the libjpeg decompression object + decomp.err = jpeg_std_error(&errorMgr.err); + errorMgr.err.error_exit = &errorExit; + errorMgr.err.output_message = &errorMessage; + if (setjmp(errorMgr.setjmpBuf)) { + error = gTrue; + return; + } + jpeg_create_decompress(&decomp); + + // set up the data source manager + sourceMgr.src.next_input_byte = NULL; + sourceMgr.src.bytes_in_buffer = 0; + sourceMgr.src.init_source = &initSourceCbk; + sourceMgr.src.fill_input_buffer = &fillInputBufferCbk; + sourceMgr.src.skip_input_data = &skipInputDataCbk; + sourceMgr.src.resync_to_restart = &jpeg_resync_to_restart; + sourceMgr.src.term_source = &termSourceCbk; + sourceMgr.str = this; + decomp.src = &sourceMgr.src; + + // read the header + jpeg_read_header(&decomp, TRUE); + jpeg_calc_output_dimensions(&decomp); + + // set up the color transform + if (!decomp.saw_Adobe_marker && colorXform >= 0) { + if (decomp.num_components == 3) { + decomp.jpeg_color_space = colorXform ? JCS_YCbCr : JCS_RGB; + decomp.out_color_space = JCS_RGB; + decomp.out_color_components = 3; + } else if (decomp.num_components == 4) { + decomp.jpeg_color_space = colorXform ? JCS_YCCK : JCS_CMYK; + decomp.out_color_space = JCS_CMYK; + decomp.out_color_components = 4; + } + } + + // allocate a line buffer + if ((lineBufHeight = decomp.rec_outbuf_height) > 4) { + lineBufHeight = 4; + } + lineBuf = (char *)gmallocn(lineBufHeight * decomp.out_color_components, + decomp.output_width); + for (i = 0; i < lineBufHeight; ++i) { + lineBufRows[i] = lineBuf + + i * decomp.out_color_components * decomp.output_width; + } + bufPtr = bufEnd = lineBuf; + + // start up the decompression process + jpeg_start_decompress(&decomp); +} + +GBool DCTStream::checkSequentialInterleaved() { + //~ this is unimplemented + return gTrue; +} + +void DCTStream::close() { + // we don't call jpeg_finish_decompress() here because it will report + // an error if the full image wasn't read + if (setjmp(errorMgr.setjmpBuf)) { + goto skip; + } + jpeg_destroy_decompress(&decomp); + skip: + gfree(lineBuf); + FilterStream::close(); +} + +int DCTStream::getChar() { + if (error) { + return EOF; + } + if (bufPtr == bufEnd) { + if (!fillBuf()) { + return EOF; + } + } + return *bufPtr++ & 0xff; +} + +int DCTStream::lookChar() { + if (error) { + return EOF; + } + if (bufPtr == bufEnd) { + if (!fillBuf()) { + return EOF; + } + } + return *bufPtr & 0xff; +} + +int DCTStream::getBlock(char *blk, int size) { + int nRead, nAvail, n; + + if (error) { + return 0; + } + nRead = 0; + while (nRead < size) { + if (bufPtr == bufEnd) { + if (!fillBuf()) { + break; + } + } + nAvail = bufEnd - bufPtr; + n = (nAvail < size - nRead) ? nAvail : size - nRead; + memcpy(blk + nRead, bufPtr, n); + bufPtr += n; + nRead += n; + } + return nRead; +} + +GBool DCTStream::fillBuf() { + int nLines; + + if (setjmp(errorMgr.setjmpBuf)) { + error = gTrue; + return gFalse; + } + nLines = jpeg_read_scanlines(&decomp, (JSAMPARRAY)lineBufRows, + lineBufHeight); + bufPtr = lineBuf; + bufEnd = lineBuf + + nLines * decomp.out_color_components * decomp.output_width; + return nLines > 0; +} + +void DCTStream::errorExit(j_common_ptr d) { + DCTErrorMgr *errMgr = (DCTErrorMgr *)d->err; + longjmp(errMgr->setjmpBuf, 1); +} + +void DCTStream::errorMessage(j_common_ptr d) { +#if 0 // for debugging + char buf[JMSG_LENGTH_MAX]; + + (*d->err->format_message)(d, buf); + fprintf(stderr, "%s\n", buf); +#endif +} + +void DCTStream::initSourceCbk(j_decompress_ptr d) { + DCTSourceMgr *sourceMgr = (DCTSourceMgr *)d->src; + + sourceMgr->src.next_input_byte = NULL; + sourceMgr->src.bytes_in_buffer = 0; +} + +boolean DCTStream::fillInputBufferCbk(j_decompress_ptr d) { + DCTSourceMgr *sourceMgr = (DCTSourceMgr *)d->src; + int c, n; + + // for inline images, we need to read one byte at a time so we don't + // read past the end of the input data + if (sourceMgr->str->inlineImage) { + c = sourceMgr->str->str->getChar(); + if (c == EOF) { + sourceMgr->buf[0] = (char)0xff; + sourceMgr->buf[1] = (char)JPEG_EOI; + sourceMgr->src.bytes_in_buffer = 2; + } else { + sourceMgr->buf[0] = (char)c; + sourceMgr->src.bytes_in_buffer = 1; + } + } else { + n = sourceMgr->str->str->getBlock(sourceMgr->buf, dctStreamBufSize); + if (n > 0) { + sourceMgr->src.bytes_in_buffer = (size_t)n; + } else { + sourceMgr->buf[0] = (char)0xff; + sourceMgr->buf[1] = (char)JPEG_EOI; + sourceMgr->src.bytes_in_buffer = 2; + } + } + sourceMgr->src.next_input_byte = (JOCTET *)sourceMgr->buf; + return TRUE; +} + +void DCTStream::skipInputDataCbk(j_decompress_ptr d, long numBytes) { + DCTSourceMgr *sourceMgr = (DCTSourceMgr *)d->src; + + if (numBytes > 0) { + if ((long)sourceMgr->src.bytes_in_buffer < numBytes) { + sourceMgr->str->str->discardChars( + (Guint)(numBytes - sourceMgr->src.bytes_in_buffer)); + sourceMgr->src.bytes_in_buffer = 0; + } else { + sourceMgr->src.bytes_in_buffer -= numBytes; + sourceMgr->src.next_input_byte += numBytes; + } + } +} + +void DCTStream::termSourceCbk(j_decompress_ptr d) { +} + +#else // HAVE_JPEGLIB + +#define idctScaleA 1024 +#define idctScaleB 1138 +#define idctScaleC 1730 +#define idctScaleD 1609 +#define idctScaleE 1264 +#define idctScaleF 1922 +#define idctScaleG 1788 +#define idctScaleH 2923 +#define idctScaleI 2718 +#define idctScaleJ 2528 + +static int idctScaleMat[64] = { + idctScaleA, idctScaleB, idctScaleC, idctScaleD, idctScaleA, idctScaleD, idctScaleC, idctScaleB, + idctScaleB, idctScaleE, idctScaleF, idctScaleG, idctScaleB, idctScaleG, idctScaleF, idctScaleE, + idctScaleC, idctScaleF, idctScaleH, idctScaleI, idctScaleC, idctScaleI, idctScaleH, idctScaleF, + idctScaleD, idctScaleG, idctScaleI, idctScaleJ, idctScaleD, idctScaleJ, idctScaleI, idctScaleG, + idctScaleA, idctScaleB, idctScaleC, idctScaleD, idctScaleA, idctScaleD, idctScaleC, idctScaleB, + idctScaleD, idctScaleG, idctScaleI, idctScaleJ, idctScaleD, idctScaleJ, idctScaleI, idctScaleG, + idctScaleC, idctScaleF, idctScaleH, idctScaleI, idctScaleC, idctScaleI, idctScaleH, idctScaleF, + idctScaleB, idctScaleE, idctScaleF, idctScaleG, idctScaleB, idctScaleG, idctScaleF, idctScaleE +}; + +// color conversion parameters (16.16 fixed point format) +#define dctCrToR 91881 // 1.4020 +#define dctCbToG -22553 // -0.3441363 +#define dctCrToG -46802 // -0.71413636 +#define dctCbToB 116130 // 1.772 + +// The dctClip function clips signed integers to the [0,255] range. +// To handle valid DCT inputs, this must support an input range of at +// least [-256,511]. Invalid DCT inputs (e.g., from damaged PDF +// files) can result in arbitrary values, so we want to mask those +// out. We round the input range size up to a power of 2 (so we can +// use a bit mask), which gives us an input range of [-384,639]. The +// end result is: +// input output +// ---------- ------ +// <-384 X invalid inputs -> output is "don't care" +// -384..-257 0 invalid inputs, clipped +// -256..-1 0 valid inputs, need to be clipped +// 0..255 0..255 +// 256..511 255 valid inputs, need to be clipped +// 512..639 255 invalid inputs, clipped +// >=512 X invalid inputs -> output is "don't care" + +#define dctClipOffset 384 +#define dctClipMask 1023 +static Guchar dctClipData[1024]; + +static inline void dctClipInit() { + static int initDone = 0; + int i; + if (!initDone) { + for (i = -384; i < 0; ++i) { + dctClipData[dctClipOffset + i] = 0; + } + for (i = 0; i < 256; ++i) { + dctClipData[dctClipOffset + i] = (Guchar)i; + } + for (i = 256; i < 639; ++i) { + dctClipData[dctClipOffset + i] = 255; + } + initDone = 1; + } +} + +static inline Guchar dctClip(int x) { + return dctClipData[(dctClipOffset + x) & dctClipMask]; +} + +// zig zag decode map +static int dctZigZag[64] = { + 0, + 1, 8, + 16, 9, 2, + 3, 10, 17, 24, + 32, 25, 18, 11, 4, + 5, 12, 19, 26, 33, 40, + 48, 41, 34, 27, 20, 13, 6, + 7, 14, 21, 28, 35, 42, 49, 56, + 57, 50, 43, 36, 29, 22, 15, + 23, 30, 37, 44, 51, 58, + 59, 52, 45, 38, 31, + 39, 46, 53, 60, + 61, 54, 47, + 55, 62, + 63 +}; + +DCTStream::DCTStream(Stream *strA, GBool colorXformA): + FilterStream(strA) { + int i; + + prepared = gFalse; + colorXform = colorXformA; + progressive = interleaved = gFalse; + width = height = 0; + mcuWidth = mcuHeight = 0; + numComps = 0; + comp = 0; + x = y = 0; + for (i = 0; i < 4; ++i) { + frameBuf[i] = NULL; + } + rowBuf = NULL; + memset(dcHuffTables, 0, sizeof(dcHuffTables)); + memset(acHuffTables, 0, sizeof(acHuffTables)); + + dctClipInit(); +} + +DCTStream::~DCTStream() { + close(); + delete str; +} + +Stream *DCTStream::copy() { + return new DCTStream(str->copy(), colorXform); +} + +void DCTStream::reset() { + int i; + + str->reset(); + + progressive = interleaved = gFalse; + width = height = 0; + numComps = 0; + numQuantTables = 0; + numDCHuffTables = 0; + numACHuffTables = 0; + gotJFIFMarker = gFalse; + gotAdobeMarker = gFalse; + restartInterval = 0; + + if (!readHeader(gTrue)) { + // force an EOF condition + progressive = gTrue; + y = height; + prepared = gTrue; + return; + } + + // compute MCU size + if (numComps == 1) { + compInfo[0].hSample = compInfo[0].vSample = 1; + } + mcuWidth = compInfo[0].hSample; + mcuHeight = compInfo[0].vSample; + for (i = 1; i < numComps; ++i) { + if (compInfo[i].hSample > mcuWidth) { + mcuWidth = compInfo[i].hSample; + } + if (compInfo[i].vSample > mcuHeight) { + mcuHeight = compInfo[i].vSample; + } + } + mcuWidth *= 8; + mcuHeight *= 8; + + // figure out color transform + if (colorXform == -1) { + if (numComps == 3) { + if (gotJFIFMarker) { + colorXform = 1; + } else if (compInfo[0].id == 82 && compInfo[1].id == 71 && + compInfo[2].id == 66) { // ASCII "RGB" + colorXform = 0; + } else { + colorXform = 1; + } + } else { + colorXform = 0; + } + } + + prepared = gFalse; +} + +GBool DCTStream::checkSequentialInterleaved() { + GBool headerOk; + + str->reset(); + + progressive = interleaved = gFalse; + width = height = 0; + numComps = 0; + numQuantTables = 0; + numDCHuffTables = 0; + numACHuffTables = 0; + gotJFIFMarker = gFalse; + gotAdobeMarker = gFalse; + restartInterval = 0; + + headerOk = readHeader(gTrue); + + FilterStream::close(); + + return headerOk && !progressive && interleaved; +} + +void DCTStream::close() { + int i; + + for (i = 0; i < 4; ++i) { + gfree(frameBuf[i]); + frameBuf[i] = NULL; + } + gfree(rowBuf); + rowBuf = NULL; + FilterStream::close(); +} + +int DCTStream::getChar() { + int c; + + if (!prepared) { + prepare(); + } + if (progressive || !interleaved) { + if (y >= height) { + return EOF; + } + c = frameBuf[comp][y * bufWidth + x]; + if (++comp == numComps) { + comp = 0; + if (++x == width) { + x = 0; + ++y; + } + } + } else { + if (rowBufPtr == rowBufEnd) { + if (y + mcuHeight >= height) { + return EOF; + } + y += mcuHeight; + if (!readMCURow()) { + y = height; + return EOF; + } + } + c = *rowBufPtr++; + } + return c; +} + +int DCTStream::lookChar() { + if (!prepared) { + prepare(); + } + if (progressive || !interleaved) { + if (y >= height) { + return EOF; + } + return frameBuf[comp][y * bufWidth + x]; + } else { + if (rowBufPtr == rowBufEnd) { + if (y + mcuHeight >= height) { + return EOF; + } + if (!readMCURow()) { + y = height; + return EOF; + } + } + return *rowBufPtr; + } +} + +int DCTStream::getBlock(char *blk, int size) { + int nRead, nAvail, n; + + if (!prepared) { + prepare(); + } + if (progressive || !interleaved) { + if (y >= height) { + return 0; + } + for (nRead = 0; nRead < size; ++nRead) { + blk[nRead] = (char)frameBuf[comp][y * bufWidth + x]; + if (++comp == numComps) { + comp = 0; + if (++x == width) { + x = 0; + ++y; + if (y >= height) { + ++nRead; + break; + } + } + } + } + } else { + nRead = 0; + while (nRead < size) { + if (rowBufPtr == rowBufEnd) { + if (y + mcuHeight >= height) { + break; + } + y += mcuHeight; + if (!readMCURow()) { + y = height; + break; + } + } + nAvail = (int)(rowBufEnd - rowBufPtr); + n = (nAvail < size - nRead) ? nAvail : size - nRead; + memcpy(blk + nRead, rowBufPtr, n); + rowBufPtr += n; + nRead += n; + } + } + return nRead; +} + +void DCTStream::prepare() { + int i; + + if (progressive || !interleaved) { + + // allocate a buffer for the whole image + bufWidth = ((width + mcuWidth - 1) / mcuWidth) * mcuWidth; + bufHeight = ((height + mcuHeight - 1) / mcuHeight) * mcuHeight; + if (bufWidth <= 0 || bufHeight <= 0 || + bufWidth > INT_MAX / bufWidth / (int)sizeof(int)) { + error(errSyntaxError, getPos(), "Invalid image size in DCT stream"); + y = height; + prepared = gTrue; + return; + } +#if USE_EXCEPTIONS + try { +#endif + for (i = 0; i < numComps; ++i) { + frameBuf[i] = (int *)gmallocn(bufWidth * bufHeight, sizeof(int)); + memset(frameBuf[i], 0, bufWidth * bufHeight * sizeof(int)); + } +#if USE_EXCEPTIONS + } catch (GMemException) { + error(errSyntaxError, getPos(), "Out of memory in DCT stream"); + y = height; + prepared = gTrue; + return; + } +#endif + + // read the image data + do { + restartMarker = 0xd0; + restart(); + readScan(); + } while (readHeader(gFalse)); + + // decode + decodeImage(); + + // initialize counters + comp = 0; + x = 0; + y = 0; + + } else { + + if (scanInfo.numComps != numComps) { + error(errSyntaxError, getPos(), "Invalid scan in sequential DCT stream"); + y = height; + prepared = gTrue; + return; + } + + // allocate a buffer for one row of MCUs + bufWidth = ((width + mcuWidth - 1) / mcuWidth) * mcuWidth; + rowBuf = (Guchar *)gmallocn(numComps * mcuHeight, bufWidth); + rowBufPtr = rowBufEnd = rowBuf; + + // initialize counters + y = -mcuHeight; + + restartMarker = 0xd0; + restart(); + } + + prepared = gTrue; +} + +void DCTStream::restart() { + int i; + + inputBits = 0; + restartCtr = restartInterval; + for (i = 0; i < numComps; ++i) { + compInfo[i].prevDC = 0; + } + eobRun = 0; +} + +// Read one row of MCUs from a sequential JPEG stream. +GBool DCTStream::readMCURow() { + int data1[64]; + Guchar data2[64]; + Guchar *p1, *p2; + int pY, pCb, pCr, pR, pG, pB; + int h, v, horiz, vert, hSub, vSub; + int x1, x2, y2, x3, y3, x4, y4, x5, y5, cc, i; + int c; + + for (cc = 0; cc < numComps; ++cc) { + if (scanInfo.dcHuffTable[cc] >= numDCHuffTables || + scanInfo.acHuffTable[cc] >= numACHuffTables) { + error(errSyntaxError, getPos(), + "Bad DCT data: invalid Huffman table index"); + return gFalse; + } + if (compInfo[cc].quantTable > numQuantTables) { + error(errSyntaxError, getPos(), + "Bad DCT data: invalid quant table index"); + return gFalse; + } + } + + for (x1 = 0; x1 < width; x1 += mcuWidth) { + + // deal with restart marker + if (restartInterval > 0 && restartCtr == 0) { + c = readMarker(); + if (c != restartMarker) { + error(errSyntaxError, getPos(), + "Bad DCT data: incorrect restart marker"); + return gFalse; + } + if (++restartMarker == 0xd8) + restartMarker = 0xd0; + restart(); + } + + // read one MCU + for (cc = 0; cc < numComps; ++cc) { + h = compInfo[cc].hSample; + v = compInfo[cc].vSample; + horiz = mcuWidth / h; + vert = mcuHeight / v; + hSub = horiz / 8; + vSub = vert / 8; + for (y2 = 0; y2 < mcuHeight; y2 += vert) { + for (x2 = 0; x2 < mcuWidth; x2 += horiz) { + if (!readDataUnit(&dcHuffTables[scanInfo.dcHuffTable[cc]], + &acHuffTables[scanInfo.acHuffTable[cc]], + &compInfo[cc].prevDC, + data1)) { + return gFalse; + } + transformDataUnit(quantTables[compInfo[cc].quantTable], + data1, data2); + if (hSub == 1 && vSub == 1 && x1+x2+8 <= width) { + for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) { + p1 = &rowBuf[((y2+y3) * width + (x1+x2)) * numComps + cc]; + p1[0] = data2[i]; + p1[ numComps] = data2[i+1]; + p1[2*numComps] = data2[i+2]; + p1[3*numComps] = data2[i+3]; + p1[4*numComps] = data2[i+4]; + p1[5*numComps] = data2[i+5]; + p1[6*numComps] = data2[i+6]; + p1[7*numComps] = data2[i+7]; + } + } else if (hSub == 2 && vSub == 2 && x1+x2+16 <= width) { + for (y3 = 0, i = 0; y3 < 16; y3 += 2, i += 8) { + p1 = &rowBuf[((y2+y3) * width + (x1+x2)) * numComps + cc]; + p2 = p1 + width * numComps; + p1[0] = p1[numComps] = + p2[0] = p2[numComps] = data2[i]; + p1[2*numComps] = p1[3*numComps] = + p2[2*numComps] = p2[3*numComps] = data2[i+1]; + p1[4*numComps] = p1[5*numComps] = + p2[4*numComps] = p2[5*numComps] = data2[i+2]; + p1[6*numComps] = p1[7*numComps] = + p2[6*numComps] = p2[7*numComps] = data2[i+3]; + p1[8*numComps] = p1[9*numComps] = + p2[8*numComps] = p2[9*numComps] = data2[i+4]; + p1[10*numComps] = p1[11*numComps] = + p2[10*numComps] = p2[11*numComps] = data2[i+5]; + p1[12*numComps] = p1[13*numComps] = + p2[12*numComps] = p2[13*numComps] = data2[i+6]; + p1[14*numComps] = p1[15*numComps] = + p2[14*numComps] = p2[15*numComps] = data2[i+7]; + } + } else { + p1 = &rowBuf[(y2 * width + (x1+x2)) * numComps + cc]; + i = 0; + for (y3 = 0, y4 = 0; y3 < 8; ++y3, y4 += vSub) { + for (x3 = 0, x4 = 0; x3 < 8; ++x3, x4 += hSub) { + for (y5 = 0; y5 < vSub; ++y5) { + for (x5 = 0; x5 < hSub && x1+x2+x4+x5 < width; ++x5) { + p1[((y4+y5) * width + (x4+x5)) * numComps] = data2[i]; + } + } + ++i; + } + } + } + } + } + } + --restartCtr; + } + + // color space conversion + if (colorXform) { + // convert YCbCr to RGB + if (numComps == 3) { + for (i = 0, p1 = rowBuf; i < width * mcuHeight; ++i, p1 += 3) { + pY = p1[0]; + pCb = p1[1] - 128; + pCr = p1[2] - 128; + pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16; + p1[0] = dctClip(pR); + pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + 32768) >> 16; + p1[1] = dctClip(pG); + pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16; + p1[2] = dctClip(pB); + } + // convert YCbCrK to CMYK (K is passed through unchanged) + } else if (numComps == 4) { + for (i = 0, p1 = rowBuf; i < width * mcuHeight; ++i, p1 += 4) { + pY = p1[0]; + pCb = p1[1] - 128; + pCr = p1[2] - 128; + pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16; + p1[0] = (Guchar)(255 - dctClip(pR)); + pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + 32768) >> 16; + p1[1] = (Guchar)(255 - dctClip(pG)); + pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16; + p1[2] = (Guchar)(255 - dctClip(pB)); + } + } + } + + rowBufPtr = rowBuf; + if (y + mcuHeight <= height) { + rowBufEnd = rowBuf + numComps * width * mcuHeight; + } else { + rowBufEnd = rowBuf + numComps * width * (height - y); + } + + return gTrue; +} + +// Read one scan from a progressive or non-interleaved JPEG stream. +void DCTStream::readScan() { + int data[64]; + int x1, y1, dx1, dy1, x2, y2, y3, cc, i; + int h, v, horiz, vert, vSub; + int *p1; + int c; + + for (cc = 0; cc < numComps; ++cc) { + if (scanInfo.comp[cc] && + (scanInfo.dcHuffTable[cc] >= numDCHuffTables || + ((!progressive || scanInfo.lastCoeff > 0) && + scanInfo.acHuffTable[cc] >= numACHuffTables))) { + error(errSyntaxError, getPos(), + "Bad DCT data: invalid Huffman table index"); + return; + } + if (compInfo[cc].quantTable > numQuantTables) { + error(errSyntaxError, getPos(), + "Bad DCT data: invalid quant table index"); + return; + } + } + + if (scanInfo.numComps == 1) { + for (cc = 0; cc < numComps; ++cc) { + if (scanInfo.comp[cc]) { + break; + } + } + dx1 = mcuWidth / compInfo[cc].hSample; + dy1 = mcuHeight / compInfo[cc].vSample; + } else { + dx1 = mcuWidth; + dy1 = mcuHeight; + } + + for (y1 = 0; y1 < height; y1 += dy1) { + for (x1 = 0; x1 < width; x1 += dx1) { + + // deal with restart marker + if (restartInterval > 0 && restartCtr == 0) { + c = readMarker(); + if (c != restartMarker) { + error(errSyntaxError, getPos(), + "Bad DCT data: incorrect restart marker"); + return; + } + if (++restartMarker == 0xd8) { + restartMarker = 0xd0; + } + restart(); + } + + // read one MCU + for (cc = 0; cc < numComps; ++cc) { + if (!scanInfo.comp[cc]) { + continue; + } + + h = compInfo[cc].hSample; + v = compInfo[cc].vSample; + horiz = mcuWidth / h; + vert = mcuHeight / v; + vSub = vert / 8; + for (y2 = 0; y2 < dy1; y2 += vert) { + for (x2 = 0; x2 < dx1; x2 += horiz) { + + // pull out the current values + p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)]; + for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) { + data[i] = p1[0]; + data[i+1] = p1[1]; + data[i+2] = p1[2]; + data[i+3] = p1[3]; + data[i+4] = p1[4]; + data[i+5] = p1[5]; + data[i+6] = p1[6]; + data[i+7] = p1[7]; + p1 += bufWidth * vSub; + } + + // read one data unit + if (progressive) { + if (!readProgressiveDataUnit( + &dcHuffTables[scanInfo.dcHuffTable[cc]], + &acHuffTables[scanInfo.acHuffTable[cc]], + &compInfo[cc].prevDC, + data)) { + return; + } + } else { + if (!readDataUnit(&dcHuffTables[scanInfo.dcHuffTable[cc]], + &acHuffTables[scanInfo.acHuffTable[cc]], + &compInfo[cc].prevDC, + data)) { + return; + } + } + + // add the data unit into frameBuf + p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)]; + for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) { + p1[0] = data[i]; + p1[1] = data[i+1]; + p1[2] = data[i+2]; + p1[3] = data[i+3]; + p1[4] = data[i+4]; + p1[5] = data[i+5]; + p1[6] = data[i+6]; + p1[7] = data[i+7]; + p1 += bufWidth * vSub; + } + } + } + } + --restartCtr; + } + } +} + +// Read one data unit from a sequential JPEG stream. +GBool DCTStream::readDataUnit(DCTHuffTable *dcHuffTable, + DCTHuffTable *acHuffTable, + int *prevDC, int data[64]) { + int run, size, amp; + int c; + int i, j; + + if ((size = readHuffSym(dcHuffTable)) == 9999) { + return gFalse; + } + if (size > 0) { + if ((amp = readAmp(size)) == 9999) { + return gFalse; + } + } else { + amp = 0; + } + data[0] = *prevDC += amp; + for (i = 1; i < 64; ++i) { + data[i] = 0; + } + i = 1; + while (i < 64) { + run = 0; + while ((c = readHuffSym(acHuffTable)) == 0xf0 && run < 0x30) { + run += 0x10; + } + if (c == 9999) { + return gFalse; + } + if (c == 0x00) { + break; + } else { + run += (c >> 4) & 0x0f; + size = c & 0x0f; + amp = readAmp(size); + if (amp == 9999) { + return gFalse; + } + i += run; + if (i < 64) { + j = dctZigZag[i++]; + data[j] = amp; + } + } + } + return gTrue; +} + +// Read one data unit from a progressive JPEG stream. +GBool DCTStream::readProgressiveDataUnit(DCTHuffTable *dcHuffTable, + DCTHuffTable *acHuffTable, + int *prevDC, int data[64]) { + int run, size, amp, bit, c; + int i, j, k; + + // get the DC coefficient + i = scanInfo.firstCoeff; + if (i == 0) { + if (scanInfo.ah == 0) { + if ((size = readHuffSym(dcHuffTable)) == 9999) { + return gFalse; + } + if (size > 0) { + if ((amp = readAmp(size)) == 9999) { + return gFalse; + } + } else { + amp = 0; + } + data[0] += (*prevDC += amp) << scanInfo.al; + } else { + if ((bit = readBit()) == 9999) { + return gFalse; + } + if (bit) { + data[0] += 1 << scanInfo.al; + } + } + ++i; + } + if (scanInfo.lastCoeff == 0) { + return gTrue; + } + + // check for an EOB run + if (eobRun > 0) { + while (i <= scanInfo.lastCoeff) { + j = dctZigZag[i++]; + if (data[j] != 0) { + if ((bit = readBit()) == EOF) { + return gFalse; + } + if (bit) { + if (data[j] >= 0) { + data[j] += 1 << scanInfo.al; + } else { + data[j] -= 1 << scanInfo.al; + } + } + } + } + --eobRun; + return gTrue; + } + + // read the AC coefficients + while (i <= scanInfo.lastCoeff) { + if ((c = readHuffSym(acHuffTable)) == 9999) { + return gFalse; + } + + // ZRL + if (c == 0xf0) { + k = 0; + while (k < 16 && i <= scanInfo.lastCoeff) { + j = dctZigZag[i++]; + if (data[j] == 0) { + ++k; + } else { + if ((bit = readBit()) == EOF) { + return gFalse; + } + if (bit) { + if (data[j] >= 0) { + data[j] += 1 << scanInfo.al; + } else { + data[j] -= 1 << scanInfo.al; + } + } + } + } + + // EOB run + } else if ((c & 0x0f) == 0x00) { + j = c >> 4; + eobRun = 0; + for (k = 0; k < j; ++k) { + if ((bit = readBit()) == EOF) { + return gFalse; + } + eobRun = (eobRun << 1) | bit; + } + eobRun += 1 << j; + while (i <= scanInfo.lastCoeff) { + j = dctZigZag[i++]; + if (data[j] != 0) { + if ((bit = readBit()) == EOF) { + return gFalse; + } + if (bit) { + if (data[j] >= 0) { + data[j] += 1 << scanInfo.al; + } else { + data[j] -= 1 << scanInfo.al; + } + } + } + } + --eobRun; + break; + + // zero run and one AC coefficient + } else { + run = (c >> 4) & 0x0f; + size = c & 0x0f; + if ((amp = readAmp(size)) == 9999) { + return gFalse; + } + j = 0; // make gcc happy + for (k = 0; k <= run && i <= scanInfo.lastCoeff; ++k) { + j = dctZigZag[i++]; + while (data[j] != 0 && i <= scanInfo.lastCoeff) { + if ((bit = readBit()) == EOF) { + return gFalse; + } + if (bit) { + if (data[j] >= 0) { + data[j] += 1 << scanInfo.al; + } else { + data[j] -= 1 << scanInfo.al; + } + } + j = dctZigZag[i++]; + } + } + data[j] = amp << scanInfo.al; + } + } + + return gTrue; +} + +// Decode a progressive JPEG image. +void DCTStream::decodeImage() { + int dataIn[64]; + Guchar dataOut[64]; + Gushort *quantTable; + int pY, pCb, pCr, pR, pG, pB; + int x1, y1, x2, y2, x3, y3, x4, y4, x5, y5, cc, i; + int h, v, horiz, vert, hSub, vSub; + int *p0, *p1, *p2; + + for (y1 = 0; y1 < bufHeight; y1 += mcuHeight) { + for (x1 = 0; x1 < bufWidth; x1 += mcuWidth) { + for (cc = 0; cc < numComps; ++cc) { + quantTable = quantTables[compInfo[cc].quantTable]; + h = compInfo[cc].hSample; + v = compInfo[cc].vSample; + horiz = mcuWidth / h; + vert = mcuHeight / v; + hSub = horiz / 8; + vSub = vert / 8; + for (y2 = 0; y2 < mcuHeight; y2 += vert) { + for (x2 = 0; x2 < mcuWidth; x2 += horiz) { + + // pull out the coded data unit + p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)]; + for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) { + dataIn[i] = p1[0]; + dataIn[i+1] = p1[1]; + dataIn[i+2] = p1[2]; + dataIn[i+3] = p1[3]; + dataIn[i+4] = p1[4]; + dataIn[i+5] = p1[5]; + dataIn[i+6] = p1[6]; + dataIn[i+7] = p1[7]; + p1 += bufWidth * vSub; + } + + // transform + transformDataUnit(quantTable, dataIn, dataOut); + + // store back into frameBuf, doing replication for + // subsampled components + p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)]; + if (hSub == 1 && vSub == 1) { + for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) { + p1[0] = dataOut[i] & 0xff; + p1[1] = dataOut[i+1] & 0xff; + p1[2] = dataOut[i+2] & 0xff; + p1[3] = dataOut[i+3] & 0xff; + p1[4] = dataOut[i+4] & 0xff; + p1[5] = dataOut[i+5] & 0xff; + p1[6] = dataOut[i+6] & 0xff; + p1[7] = dataOut[i+7] & 0xff; + p1 += bufWidth; + } + } else if (hSub == 2 && vSub == 2) { + p2 = p1 + bufWidth; + for (y3 = 0, i = 0; y3 < 16; y3 += 2, i += 8) { + p1[0] = p1[1] = p2[0] = p2[1] = dataOut[i] & 0xff; + p1[2] = p1[3] = p2[2] = p2[3] = dataOut[i+1] & 0xff; + p1[4] = p1[5] = p2[4] = p2[5] = dataOut[i+2] & 0xff; + p1[6] = p1[7] = p2[6] = p2[7] = dataOut[i+3] & 0xff; + p1[8] = p1[9] = p2[8] = p2[9] = dataOut[i+4] & 0xff; + p1[10] = p1[11] = p2[10] = p2[11] = dataOut[i+5] & 0xff; + p1[12] = p1[13] = p2[12] = p2[13] = dataOut[i+6] & 0xff; + p1[14] = p1[15] = p2[14] = p2[15] = dataOut[i+7] & 0xff; + p1 += bufWidth * 2; + p2 += bufWidth * 2; + } + } else { + i = 0; + for (y3 = 0, y4 = 0; y3 < 8; ++y3, y4 += vSub) { + for (x3 = 0, x4 = 0; x3 < 8; ++x3, x4 += hSub) { + p2 = p1 + x4; + for (y5 = 0; y5 < vSub; ++y5) { + for (x5 = 0; x5 < hSub; ++x5) { + p2[x5] = dataOut[i] & 0xff; + } + p2 += bufWidth; + } + ++i; + } + p1 += bufWidth * vSub; + } + } + } + } + } + + // color space conversion + if (colorXform) { + // convert YCbCr to RGB + if (numComps == 3) { + for (y2 = 0; y2 < mcuHeight; ++y2) { + p0 = &frameBuf[0][(y1+y2) * bufWidth + x1]; + p1 = &frameBuf[1][(y1+y2) * bufWidth + x1]; + p2 = &frameBuf[2][(y1+y2) * bufWidth + x1]; + for (x2 = 0; x2 < mcuWidth; ++x2) { + pY = *p0; + pCb = *p1 - 128; + pCr = *p2 - 128; + pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16; + *p0++ = dctClip(pR); + pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + + 32768) >> 16; + *p1++ = dctClip(pG); + pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16; + *p2++ = dctClip(pB); + } + } + // convert YCbCrK to CMYK (K is passed through unchanged) + } else if (numComps == 4) { + for (y2 = 0; y2 < mcuHeight; ++y2) { + p0 = &frameBuf[0][(y1+y2) * bufWidth + x1]; + p1 = &frameBuf[1][(y1+y2) * bufWidth + x1]; + p2 = &frameBuf[2][(y1+y2) * bufWidth + x1]; + for (x2 = 0; x2 < mcuWidth; ++x2) { + pY = *p0; + pCb = *p1 - 128; + pCr = *p2 - 128; + pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16; + *p0++ = 255 - dctClip(pR); + pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + + 32768) >> 16; + *p1++ = 255 - dctClip(pG); + pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16; + *p2++ = 255 - dctClip(pB); + } + } + } + } + } + } +} + +// Transform one data unit -- this performs the dequantization and +// IDCT steps. This IDCT algorithm is taken from: +// Y. A. Reznik, A. T. Hinds, L. Yu, Z. Ni, and C-X. Zhang, +// "Efficient fixed-point approximations of the 8x8 inverse discrete +// cosine transform" (invited paper), Proc. SPIE Vol. 6696, Sep. 24, +// 2007. +// which is based on: +// Christoph Loeffler, Adriaan Ligtenberg, George S. Moschytz, +// "Practical Fast 1-D DCT Algorithms with 11 Multiplications", +// IEEE Intl. Conf. on Acoustics, Speech & Signal Processing, 1989, +// 988-991. +// The stage numbers mentioned in the comments refer to Figure 1 in the +// Loeffler paper. +void DCTStream::transformDataUnit(Gushort *quantTable, + int dataIn[64], Guchar dataOut[64]) { + int v0, v1, v2, v3, v4, v5, v6, v7; + int t0, t1, t2, t3, t4, t5, t6, t7; + int *p, *scale; + Gushort *q; + int i; + + // dequant; inverse DCT on rows + for (i = 0; i < 64; i += 8) { + p = dataIn + i; + q = quantTable + i; + scale = idctScaleMat + i; + + // check for all-zero AC coefficients + if (p[1] == 0 && p[2] == 0 && p[3] == 0 && + p[4] == 0 && p[5] == 0 && p[6] == 0 && p[7] == 0) { + t0 = p[0] * q[0] * scale[0]; + if (i == 0) { + t0 += 1 << 12; // rounding bias + } + p[0] = t0; + p[1] = t0; + p[2] = t0; + p[3] = t0; + p[4] = t0; + p[5] = t0; + p[6] = t0; + p[7] = t0; + continue; + } + + // stage 4 + v0 = p[0] * q[0] * scale[0]; + if (i == 0) { + v0 += 1 << 12; // rounding bias + } + v1 = p[4] * q[4] * scale[4]; + v2 = p[2] * q[2] * scale[2]; + v3 = p[6] * q[6] * scale[6]; + t0 = p[1] * q[1] * scale[1]; + t1 = p[7] * q[7] * scale[7]; + v4 = t0 - t1; + v7 = t0 + t1; + v5 = p[3] * q[3] * scale[3]; + v6 = p[5] * q[5] * scale[5]; + + // stage 3 + t0 = v0 - v1; + v0 = v0 + v1; + v1 = t0; + t0 = v2 + (v2 >> 5); + t1 = t0 >> 2; + t2 = t1 + (v2 >> 4); // 41/128 * v2 + t3 = t0 - t1; // 99/128 * v2 + t4 = v3 + (v3 >> 5); + t5 = t4 >> 2; + t6 = t5 + (v3 >> 4); // 41/128 * v3 + t7 = t4 - t5; // 99/128 * v3 + v2 = t2 - t7; + v3 = t3 + t6; + t0 = v4 - v6; + v4 = v4 + v6; + v6 = t0; + t0 = v7 + v5; + v5 = v7 - v5; + v7 = t0; + + // stage 2 + t0 = v0 - v3; + v0 = v0 + v3; + v3 = t0; + t0 = v1 - v2; + v1 = v1 + v2; + v2 = t0; + t0 = (v4 >> 9) - v4; + t1 = v4 >> 1; // 1/2 * v4 + t2 = (t0 >> 2) - t0; // 1533/2048 * v4 + t3 = (v7 >> 9) - v7; + t4 = v7 >> 1; // 1/2 * v7 + t5 = (t3 >> 2) - t3; // 1533/2048 * v7 + v4 = t2 - t4; + v7 = t1 + t5; + t0 = (v5 >> 3) - (v5 >> 7); + t1 = t0 - (v5 >> 11); + t2 = t0 + (t1 >> 1); // 719/4096 * v5 + t3 = v5 - t0; // 113/256 * v5 + t4 = (v6 >> 3) - (v6 >> 7); + t5 = t4 - (v6 >> 11); + t6 = t4 + (t5 >> 1); // 719/4096 * v6 + t7 = v6 - t4; // 113/256 * v6 + v5 = t3 - t6; + v6 = t2 + t7; + + // stage 1 + p[0] = v0 + v7; + p[7] = v0 - v7; + p[1] = v1 + v6; + p[6] = v1 - v6; + p[2] = v2 + v5; + p[5] = v2 - v5; + p[3] = v3 + v4; + p[4] = v3 - v4; + } + + // inverse DCT on columns + for (i = 0; i < 8; ++i) { + p = dataIn + i; + + // check for all-zero AC coefficients + if (p[1*8] == 0 && p[2*8] == 0 && p[3*8] == 0 && + p[4*8] == 0 && p[5*8] == 0 && p[6*8] == 0 && p[7*8] == 0) { + t0 = p[0*8]; + p[1*8] = t0; + p[2*8] = t0; + p[3*8] = t0; + p[4*8] = t0; + p[5*8] = t0; + p[6*8] = t0; + p[7*8] = t0; + continue; + } + + // stage 4 + v0 = p[0*8]; + v1 = p[4*8]; + v2 = p[2*8]; + v3 = p[6*8]; + t0 = p[1*8]; + t1 = p[7*8]; + v4 = t0 - t1; + v7 = t0 + t1; + v5 = p[3*8]; + v6 = p[5*8]; + + // stage 3 + t0 = v0 - v1; + v0 = v0 + v1; + v1 = t0; + t0 = v2 + (v2 >> 5); + t1 = t0 >> 2; + t2 = t1 + (v2 >> 4); // 41/128 * v2 + t3 = t0 - t1; // 99/128 * v2 + t4 = v3 + (v3 >> 5); + t5 = t4 >> 2; + t6 = t5 + (v3 >> 4); // 41/128 * v3 + t7 = t4 - t5; // 99/128 * v3 + v2 = t2 - t7; + v3 = t3 + t6; + t0 = v4 - v6; + v4 = v4 + v6; + v6 = t0; + t0 = v7 + v5; + v5 = v7 - v5; + v7 = t0; + + // stage 2 + t0 = v0 - v3; + v0 = v0 + v3; + v3 = t0; + t0 = v1 - v2; + v1 = v1 + v2; + v2 = t0; + t0 = (v4 >> 9) - v4; + t1 = v4 >> 1; // 1/2 * v4 + t2 = (t0 >> 2) - t0; // 1533/2048 * v4 + t3 = (v7 >> 9) - v7; + t4 = v7 >> 1; // 1/2 * v7 + t5 = (t3 >> 2) - t3; // 1533/2048 * v7 + v4 = t2 - t4; + v7 = t1 + t5; + t0 = (v5 >> 3) - (v5 >> 7); + t1 = t0 - (v5 >> 11); + t2 = t0 + (t1 >> 1); // 719/4096 * v5 + t3 = v5 - t0; // 113/256 * v5 + t4 = (v6 >> 3) - (v6 >> 7); + t5 = t4 - (v6 >> 11); + t6 = t4 + (t5 >> 1); // 719/4096 * v6 + t7 = v6 - t4; // 113/256 * v6 + v5 = t3 - t6; + v6 = t2 + t7; + + // stage 1 + p[0*8] = v0 + v7; + p[7*8] = v0 - v7; + p[1*8] = v1 + v6; + p[6*8] = v1 - v6; + p[2*8] = v2 + v5; + p[5*8] = v2 - v5; + p[3*8] = v3 + v4; + p[4*8] = v3 - v4; + } + + // convert to 8-bit integers + for (i = 0; i < 64; ++i) { + dataOut[i] = dctClip(128 + (dataIn[i] >> 13)); + } +} + +int DCTStream::readHuffSym(DCTHuffTable *table) { + Gushort code; + int bit; + int codeBits; + + code = 0; + codeBits = 0; + do { + // add a bit to the code + if ((bit = readBit()) == EOF) { + return 9999; + } + code = (Gushort)((code << 1) + bit); + ++codeBits; + + // look up code + if (code < table->firstCode[codeBits]) { + break; + } + if (code - table->firstCode[codeBits] < table->numCodes[codeBits]) { + code = (Gushort)(code - table->firstCode[codeBits]); + return table->sym[table->firstSym[codeBits] + code]; + } + } while (codeBits < 16); + + error(errSyntaxError, getPos(), "Bad Huffman code in DCT stream"); + return 9999; +} + +int DCTStream::readAmp(int size) { + int amp, bit; + int bits; + + amp = 0; + for (bits = 0; bits < size; ++bits) { + if ((bit = readBit()) == EOF) + return 9999; + amp = (amp << 1) + bit; + } + if (amp < (1 << (size - 1))) + amp -= (1 << size) - 1; + return amp; +} + +int DCTStream::readBit() { + int bit; + int c, c2; + + if (inputBits == 0) { + if ((c = str->getChar()) == EOF) + return EOF; + if (c == 0xff) { + do { + c2 = str->getChar(); + } while (c2 == 0xff); + if (c2 != 0x00) { + error(errSyntaxError, getPos(), "Bad DCT data: missing 00 after ff"); + return EOF; + } + } + inputBuf = c; + inputBits = 8; + } + bit = (inputBuf >> (inputBits - 1)) & 1; + --inputBits; + return bit; +} + +GBool DCTStream::readHeader(GBool frame) { + GBool doScan; + int n, i; + int c = 0; + + // read headers + doScan = gFalse; + while (!doScan) { + c = readMarker(); + switch (c) { + case 0xc0: // SOF0 (sequential) + case 0xc1: // SOF1 (extended sequential) + if (!frame) { + error(errSyntaxError, getPos(), + "Invalid DCT marker in scan <{0:02x}>", c); + return gFalse; + } + if (!readBaselineSOF()) { + return gFalse; + } + break; + case 0xc2: // SOF2 (progressive) + if (!frame) { + error(errSyntaxError, getPos(), + "Invalid DCT marker in scan <{0:02x}>", c); + return gFalse; + } + if (!readProgressiveSOF()) { + return gFalse; + } + break; + case 0xc4: // DHT + if (!readHuffmanTables()) { + return gFalse; + } + break; + case 0xd8: // SOI + if (!frame) { + error(errSyntaxError, getPos(), + "Invalid DCT marker in scan <{0:02x}>", c); + return gFalse; + } + break; + case 0xd9: // EOI + return gFalse; + case 0xda: // SOS + if (!readScanInfo()) { + return gFalse; + } + if (frame) { + interleaved = scanInfo.numComps == numComps; + } + doScan = gTrue; + break; + case 0xdb: // DQT + if (!readQuantTables()) { + return gFalse; + } + break; + case 0xdd: // DRI + if (!readRestartInterval()) { + return gFalse; + } + break; + case 0xe0: // APP0 + if (!frame) { + error(errSyntaxError, getPos(), + "Invalid DCT marker in scan <{0:02x}>", c); + return gFalse; + } + if (!readJFIFMarker()) { + return gFalse; + } + break; + case 0xee: // APP14 + if (!frame) { + error(errSyntaxError, getPos(), + "Invalid DCT marker in scan <{0:02x}>", c); + return gFalse; + } + if (!readAdobeMarker()) { + return gFalse; + } + break; + case EOF: + error(errSyntaxError, getPos(), "Bad DCT header"); + return gFalse; + default: + // skip APPn / COM / etc. + if (c >= 0xe0) { + n = read16() - 2; + str->discardChars(n); + } else { + error(errSyntaxError, getPos(), "Unknown DCT marker <{0:02x}>", c); + return gFalse; + } + break; + } + } + + for (i = 0; i < numComps; ++i) { + if (compInfo[i].quantTable >= numQuantTables) { + error(errSyntaxError, getPos(), "Invalid DCT quant table selector"); + return gFalse; + } + } + + return gTrue; +} + +GBool DCTStream::readBaselineSOF() { + int prec; + int i; + int c; + + read16(); // length + prec = str->getChar(); + height = read16(); + width = read16(); + numComps = str->getChar(); + if (numComps <= 0 || numComps > 4) { + error(errSyntaxError, getPos(), "Bad number of components in DCT stream"); + numComps = 0; + return gFalse; + } + if (prec != 8) { + error(errSyntaxError, getPos(), "Bad DCT precision {0:d}", prec); + return gFalse; + } + for (i = 0; i < numComps; ++i) { + compInfo[i].id = str->getChar(); + c = str->getChar(); + compInfo[i].hSample = (c >> 4) & 0x0f; + compInfo[i].vSample = c & 0x0f; + compInfo[i].quantTable = str->getChar(); + // a sampling factor of 3 is allowed by the spec, but requires + // messy upsampling, and appears not to be used in practice + if (!(compInfo[i].hSample == 1 || + compInfo[i].hSample == 2 || + compInfo[i].hSample == 4) || + !(compInfo[i].vSample == 1 || + compInfo[i].vSample == 2 || + 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; +} + +GBool DCTStream::readProgressiveSOF() { + int prec; + int i; + int c; + + read16(); // length + prec = str->getChar(); + height = read16(); + width = read16(); + numComps = str->getChar(); + if (numComps <= 0 || numComps > 4) { + error(errSyntaxError, getPos(), "Bad number of components in DCT stream"); + numComps = 0; + return gFalse; + } + if (prec != 8) { + error(errSyntaxError, getPos(), "Bad DCT precision {0:d}", prec); + return gFalse; + } + for (i = 0; i < numComps; ++i) { + compInfo[i].id = str->getChar(); + c = str->getChar(); + compInfo[i].hSample = (c >> 4) & 0x0f; + compInfo[i].vSample = c & 0x0f; + compInfo[i].quantTable = str->getChar(); + // a sampling factor of 3 is allowed by the spec, but requires + // messy upsampling, and appears not to be used in practice + if (!(compInfo[i].hSample == 1 || + compInfo[i].hSample == 2 || + compInfo[i].hSample == 4) || + !(compInfo[i].vSample == 1 || + compInfo[i].vSample == 2 || + 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; +} + +GBool DCTStream::readScanInfo() { + int length; + int id, c; + int i, j; + + length = read16() - 2; + scanInfo.numComps = str->getChar(); + if (scanInfo.numComps <= 0 || scanInfo.numComps > 4) { + error(errSyntaxError, getPos(), "Bad number of components in DCT stream"); + scanInfo.numComps = 0; + return gFalse; + } + --length; + if (length != 2 * scanInfo.numComps + 3) { + error(errSyntaxError, getPos(), "Bad DCT scan info block"); + return gFalse; + } + for (j = 0; j < numComps; ++j) { + scanInfo.comp[j] = gFalse; + } + for (i = 0; i < scanInfo.numComps; ++i) { + id = str->getChar(); + // some (broken) DCT streams reuse ID numbers, but at least they + // keep the components in order, so we check compInfo[i] first to + // work around the problem + if (id == compInfo[i].id) { + j = i; + } else { + for (j = 0; j < numComps; ++j) { + if (id == compInfo[j].id) { + break; + } + } + if (j == numComps) { + error(errSyntaxError, getPos(), + "Bad DCT component ID in scan info block"); + return gFalse; + } + } + if (scanInfo.comp[j]) { + error(errSyntaxError, getPos(), + "Invalid DCT component ID in scan info block"); + return gFalse; + } + scanInfo.comp[j] = gTrue; + c = str->getChar(); + scanInfo.dcHuffTable[j] = (c >> 4) & 0x0f; + scanInfo.acHuffTable[j] = c & 0x0f; + } + 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; + return gTrue; +} + +GBool DCTStream::readQuantTables() { + int length, prec, i, index; + + length = read16() - 2; + while (length > 0) { + index = str->getChar(); + prec = (index >> 4) & 0x0f; + index &= 0x0f; + if (prec > 1 || index >= 4) { + error(errSyntaxError, getPos(), "Bad DCT quantization table"); + return gFalse; + } + if (index >= numQuantTables) { + numQuantTables = index + 1; + } + for (i = 0; i < 64; ++i) { + if (prec) { + quantTables[index][dctZigZag[i]] = (Gushort)read16(); + } else { + quantTables[index][dctZigZag[i]] = (Gushort)str->getChar(); + } + } + if (prec) { + length -= 129; + } else { + length -= 65; + } + } + return gTrue; +} + +GBool DCTStream::readHuffmanTables() { + DCTHuffTable *tbl; + int length; + int index; + Gushort code; + Guchar sym; + int i; + int c; + + length = read16() - 2; + while (length > 0) { + index = str->getChar(); + --length; + if ((index & 0x0f) >= 4) { + error(errSyntaxError, getPos(), "Bad DCT Huffman table"); + return gFalse; + } + if (index & 0x10) { + index &= 0x0f; + if (index >= numACHuffTables) + numACHuffTables = index+1; + tbl = &acHuffTables[index]; + } else { + index &= 0x0f; + if (index >= numDCHuffTables) + numDCHuffTables = index+1; + tbl = &dcHuffTables[index]; + } + sym = 0; + code = 0; + for (i = 1; i <= 16; ++i) { + c = str->getChar(); + tbl->firstSym[i] = sym; + tbl->firstCode[i] = code; + tbl->numCodes[i] = (Gushort)c; + sym = (Guchar)(sym + c); + code = (Gushort)((code + c) << 1); + } + length -= 16; + for (i = 0; i < sym; ++i) + tbl->sym[i] = (Guchar)str->getChar(); + length -= sym; + } + return gTrue; +} + +GBool DCTStream::readRestartInterval() { + int length; + + length = read16(); + if (length != 4) { + error(errSyntaxError, getPos(), "Bad DCT restart interval"); + return gFalse; + } + restartInterval = read16(); + return gTrue; +} + +GBool DCTStream::readJFIFMarker() { + int length, i; + char buf[5]; + int c; + + length = read16(); + length -= 2; + if (length >= 5) { + for (i = 0; i < 5; ++i) { + if ((c = str->getChar()) == EOF) { + error(errSyntaxError, getPos(), "Bad DCT APP0 marker"); + return gFalse; + } + buf[i] = (char)c; + } + length -= 5; + if (!memcmp(buf, "JFIF\0", 5)) { + gotJFIFMarker = gTrue; + } + } + while (length > 0) { + if (str->getChar() == EOF) { + error(errSyntaxError, getPos(), "Bad DCT APP0 marker"); + return gFalse; + } + --length; + } + return gTrue; +} + +GBool DCTStream::readAdobeMarker() { + int length, i; + char buf[12]; + int c; + + length = read16(); + if (length < 14) { + goto err; + } + for (i = 0; i < 12; ++i) { + if ((c = str->getChar()) == EOF) { + goto err; + } + buf[i] = (char)c; + } + if (!strncmp(buf, "Adobe", 5)) { + colorXform = buf[11]; + gotAdobeMarker = gTrue; + } + for (i = 14; i < length; ++i) { + if (str->getChar() == EOF) { + goto err; + } + } + return gTrue; + + err: + error(errSyntaxError, getPos(), "Bad DCT Adobe APP14 marker"); + return gFalse; +} + +GBool DCTStream::readTrailer() { + int c; + + c = readMarker(); + if (c != 0xd9) { // EOI + error(errSyntaxError, getPos(), "Bad DCT trailer"); + return gFalse; + } + return gTrue; +} + +int DCTStream::readMarker() { + int c; + + do { + do { + c = str->getChar(); + } while (c != 0xff && c != EOF); + do { + c = str->getChar(); + } while (c == 0xff); + } while (c == 0x00); + return c; +} + +int DCTStream::read16() { + int c1, c2; + + if ((c1 = str->getChar()) == EOF) + return EOF; + if ((c2 = str->getChar()) == EOF) + return EOF; + return (c1 << 8) + c2; +} + +#endif // HAVE_JPEGLIB + +GString *DCTStream::getPSFilter(int psLevel, const char *indent, + GBool okToReadStream) { + GString *s; + + if (psLevel < 2) { + return NULL; + } + if (!(s = str->getPSFilter(psLevel, indent, okToReadStream))) { + return NULL; + } + if (okToReadStream && !checkSequentialInterleaved()) { + // PostScript does not allow progressive or interleaved JPEG + delete s; + return NULL; + } + s->append(indent)->append("<< >> /DCTDecode filter\n"); + return s; +} + +GBool DCTStream::isBinary(GBool last) { + return str->isBinary(gTrue); +} + +//------------------------------------------------------------------------ +// FlateStream +//------------------------------------------------------------------------ + +int FlateStream::codeLenCodeMap[flateMaxCodeLenCodes] = { + 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 +}; + +FlateDecode FlateStream::lengthDecode[flateMaxLitCodes-257] = { + {0, 3}, + {0, 4}, + {0, 5}, + {0, 6}, + {0, 7}, + {0, 8}, + {0, 9}, + {0, 10}, + {1, 11}, + {1, 13}, + {1, 15}, + {1, 17}, + {2, 19}, + {2, 23}, + {2, 27}, + {2, 31}, + {3, 35}, + {3, 43}, + {3, 51}, + {3, 59}, + {4, 67}, + {4, 83}, + {4, 99}, + {4, 115}, + {5, 131}, + {5, 163}, + {5, 195}, + {5, 227}, + {0, 258}, + {0, 258}, + {0, 258} +}; + +FlateDecode FlateStream::distDecode[flateMaxDistCodes] = { + { 0, 1}, + { 0, 2}, + { 0, 3}, + { 0, 4}, + { 1, 5}, + { 1, 7}, + { 2, 9}, + { 2, 13}, + { 3, 17}, + { 3, 25}, + { 4, 33}, + { 4, 49}, + { 5, 65}, + { 5, 97}, + { 6, 129}, + { 6, 193}, + { 7, 257}, + { 7, 385}, + { 8, 513}, + { 8, 769}, + { 9, 1025}, + { 9, 1537}, + {10, 2049}, + {10, 3073}, + {11, 4097}, + {11, 6145}, + {12, 8193}, + {12, 12289}, + {13, 16385}, + {13, 24577} +}; + +static FlateCode flateFixedLitCodeTabCodes[512] = { + {7, 0x0100}, + {8, 0x0050}, + {8, 0x0010}, + {8, 0x0118}, + {7, 0x0110}, + {8, 0x0070}, + {8, 0x0030}, + {9, 0x00c0}, + {7, 0x0108}, + {8, 0x0060}, + {8, 0x0020}, + {9, 0x00a0}, + {8, 0x0000}, + {8, 0x0080}, + {8, 0x0040}, + {9, 0x00e0}, + {7, 0x0104}, + {8, 0x0058}, + {8, 0x0018}, + {9, 0x0090}, + {7, 0x0114}, + {8, 0x0078}, + {8, 0x0038}, + {9, 0x00d0}, + {7, 0x010c}, + {8, 0x0068}, + {8, 0x0028}, + {9, 0x00b0}, + {8, 0x0008}, + {8, 0x0088}, + {8, 0x0048}, + {9, 0x00f0}, + {7, 0x0102}, + {8, 0x0054}, + {8, 0x0014}, + {8, 0x011c}, + {7, 0x0112}, + {8, 0x0074}, + {8, 0x0034}, + {9, 0x00c8}, + {7, 0x010a}, + {8, 0x0064}, + {8, 0x0024}, + {9, 0x00a8}, + {8, 0x0004}, + {8, 0x0084}, + {8, 0x0044}, + {9, 0x00e8}, + {7, 0x0106}, + {8, 0x005c}, + {8, 0x001c}, + {9, 0x0098}, + {7, 0x0116}, + {8, 0x007c}, + {8, 0x003c}, + {9, 0x00d8}, + {7, 0x010e}, + {8, 0x006c}, + {8, 0x002c}, + {9, 0x00b8}, + {8, 0x000c}, + {8, 0x008c}, + {8, 0x004c}, + {9, 0x00f8}, + {7, 0x0101}, + {8, 0x0052}, + {8, 0x0012}, + {8, 0x011a}, + {7, 0x0111}, + {8, 0x0072}, + {8, 0x0032}, + {9, 0x00c4}, + {7, 0x0109}, + {8, 0x0062}, + {8, 0x0022}, + {9, 0x00a4}, + {8, 0x0002}, + {8, 0x0082}, + {8, 0x0042}, + {9, 0x00e4}, + {7, 0x0105}, + {8, 0x005a}, + {8, 0x001a}, + {9, 0x0094}, + {7, 0x0115}, + {8, 0x007a}, + {8, 0x003a}, + {9, 0x00d4}, + {7, 0x010d}, + {8, 0x006a}, + {8, 0x002a}, + {9, 0x00b4}, + {8, 0x000a}, + {8, 0x008a}, + {8, 0x004a}, + {9, 0x00f4}, + {7, 0x0103}, + {8, 0x0056}, + {8, 0x0016}, + {8, 0x011e}, + {7, 0x0113}, + {8, 0x0076}, + {8, 0x0036}, + {9, 0x00cc}, + {7, 0x010b}, + {8, 0x0066}, + {8, 0x0026}, + {9, 0x00ac}, + {8, 0x0006}, + {8, 0x0086}, + {8, 0x0046}, + {9, 0x00ec}, + {7, 0x0107}, + {8, 0x005e}, + {8, 0x001e}, + {9, 0x009c}, + {7, 0x0117}, + {8, 0x007e}, + {8, 0x003e}, + {9, 0x00dc}, + {7, 0x010f}, + {8, 0x006e}, + {8, 0x002e}, + {9, 0x00bc}, + {8, 0x000e}, + {8, 0x008e}, + {8, 0x004e}, + {9, 0x00fc}, + {7, 0x0100}, + {8, 0x0051}, + {8, 0x0011}, + {8, 0x0119}, + {7, 0x0110}, + {8, 0x0071}, + {8, 0x0031}, + {9, 0x00c2}, + {7, 0x0108}, + {8, 0x0061}, + {8, 0x0021}, + {9, 0x00a2}, + {8, 0x0001}, + {8, 0x0081}, + {8, 0x0041}, + {9, 0x00e2}, + {7, 0x0104}, + {8, 0x0059}, + {8, 0x0019}, + {9, 0x0092}, + {7, 0x0114}, + {8, 0x0079}, + {8, 0x0039}, + {9, 0x00d2}, + {7, 0x010c}, + {8, 0x0069}, + {8, 0x0029}, + {9, 0x00b2}, + {8, 0x0009}, + {8, 0x0089}, + {8, 0x0049}, + {9, 0x00f2}, + {7, 0x0102}, + {8, 0x0055}, + {8, 0x0015}, + {8, 0x011d}, + {7, 0x0112}, + {8, 0x0075}, + {8, 0x0035}, + {9, 0x00ca}, + {7, 0x010a}, + {8, 0x0065}, + {8, 0x0025}, + {9, 0x00aa}, + {8, 0x0005}, + {8, 0x0085}, + {8, 0x0045}, + {9, 0x00ea}, + {7, 0x0106}, + {8, 0x005d}, + {8, 0x001d}, + {9, 0x009a}, + {7, 0x0116}, + {8, 0x007d}, + {8, 0x003d}, + {9, 0x00da}, + {7, 0x010e}, + {8, 0x006d}, + {8, 0x002d}, + {9, 0x00ba}, + {8, 0x000d}, + {8, 0x008d}, + {8, 0x004d}, + {9, 0x00fa}, + {7, 0x0101}, + {8, 0x0053}, + {8, 0x0013}, + {8, 0x011b}, + {7, 0x0111}, + {8, 0x0073}, + {8, 0x0033}, + {9, 0x00c6}, + {7, 0x0109}, + {8, 0x0063}, + {8, 0x0023}, + {9, 0x00a6}, + {8, 0x0003}, + {8, 0x0083}, + {8, 0x0043}, + {9, 0x00e6}, + {7, 0x0105}, + {8, 0x005b}, + {8, 0x001b}, + {9, 0x0096}, + {7, 0x0115}, + {8, 0x007b}, + {8, 0x003b}, + {9, 0x00d6}, + {7, 0x010d}, + {8, 0x006b}, + {8, 0x002b}, + {9, 0x00b6}, + {8, 0x000b}, + {8, 0x008b}, + {8, 0x004b}, + {9, 0x00f6}, + {7, 0x0103}, + {8, 0x0057}, + {8, 0x0017}, + {8, 0x011f}, + {7, 0x0113}, + {8, 0x0077}, + {8, 0x0037}, + {9, 0x00ce}, + {7, 0x010b}, + {8, 0x0067}, + {8, 0x0027}, + {9, 0x00ae}, + {8, 0x0007}, + {8, 0x0087}, + {8, 0x0047}, + {9, 0x00ee}, + {7, 0x0107}, + {8, 0x005f}, + {8, 0x001f}, + {9, 0x009e}, + {7, 0x0117}, + {8, 0x007f}, + {8, 0x003f}, + {9, 0x00de}, + {7, 0x010f}, + {8, 0x006f}, + {8, 0x002f}, + {9, 0x00be}, + {8, 0x000f}, + {8, 0x008f}, + {8, 0x004f}, + {9, 0x00fe}, + {7, 0x0100}, + {8, 0x0050}, + {8, 0x0010}, + {8, 0x0118}, + {7, 0x0110}, + {8, 0x0070}, + {8, 0x0030}, + {9, 0x00c1}, + {7, 0x0108}, + {8, 0x0060}, + {8, 0x0020}, + {9, 0x00a1}, + {8, 0x0000}, + {8, 0x0080}, + {8, 0x0040}, + {9, 0x00e1}, + {7, 0x0104}, + {8, 0x0058}, + {8, 0x0018}, + {9, 0x0091}, + {7, 0x0114}, + {8, 0x0078}, + {8, 0x0038}, + {9, 0x00d1}, + {7, 0x010c}, + {8, 0x0068}, + {8, 0x0028}, + {9, 0x00b1}, + {8, 0x0008}, + {8, 0x0088}, + {8, 0x0048}, + {9, 0x00f1}, + {7, 0x0102}, + {8, 0x0054}, + {8, 0x0014}, + {8, 0x011c}, + {7, 0x0112}, + {8, 0x0074}, + {8, 0x0034}, + {9, 0x00c9}, + {7, 0x010a}, + {8, 0x0064}, + {8, 0x0024}, + {9, 0x00a9}, + {8, 0x0004}, + {8, 0x0084}, + {8, 0x0044}, + {9, 0x00e9}, + {7, 0x0106}, + {8, 0x005c}, + {8, 0x001c}, + {9, 0x0099}, + {7, 0x0116}, + {8, 0x007c}, + {8, 0x003c}, + {9, 0x00d9}, + {7, 0x010e}, + {8, 0x006c}, + {8, 0x002c}, + {9, 0x00b9}, + {8, 0x000c}, + {8, 0x008c}, + {8, 0x004c}, + {9, 0x00f9}, + {7, 0x0101}, + {8, 0x0052}, + {8, 0x0012}, + {8, 0x011a}, + {7, 0x0111}, + {8, 0x0072}, + {8, 0x0032}, + {9, 0x00c5}, + {7, 0x0109}, + {8, 0x0062}, + {8, 0x0022}, + {9, 0x00a5}, + {8, 0x0002}, + {8, 0x0082}, + {8, 0x0042}, + {9, 0x00e5}, + {7, 0x0105}, + {8, 0x005a}, + {8, 0x001a}, + {9, 0x0095}, + {7, 0x0115}, + {8, 0x007a}, + {8, 0x003a}, + {9, 0x00d5}, + {7, 0x010d}, + {8, 0x006a}, + {8, 0x002a}, + {9, 0x00b5}, + {8, 0x000a}, + {8, 0x008a}, + {8, 0x004a}, + {9, 0x00f5}, + {7, 0x0103}, + {8, 0x0056}, + {8, 0x0016}, + {8, 0x011e}, + {7, 0x0113}, + {8, 0x0076}, + {8, 0x0036}, + {9, 0x00cd}, + {7, 0x010b}, + {8, 0x0066}, + {8, 0x0026}, + {9, 0x00ad}, + {8, 0x0006}, + {8, 0x0086}, + {8, 0x0046}, + {9, 0x00ed}, + {7, 0x0107}, + {8, 0x005e}, + {8, 0x001e}, + {9, 0x009d}, + {7, 0x0117}, + {8, 0x007e}, + {8, 0x003e}, + {9, 0x00dd}, + {7, 0x010f}, + {8, 0x006e}, + {8, 0x002e}, + {9, 0x00bd}, + {8, 0x000e}, + {8, 0x008e}, + {8, 0x004e}, + {9, 0x00fd}, + {7, 0x0100}, + {8, 0x0051}, + {8, 0x0011}, + {8, 0x0119}, + {7, 0x0110}, + {8, 0x0071}, + {8, 0x0031}, + {9, 0x00c3}, + {7, 0x0108}, + {8, 0x0061}, + {8, 0x0021}, + {9, 0x00a3}, + {8, 0x0001}, + {8, 0x0081}, + {8, 0x0041}, + {9, 0x00e3}, + {7, 0x0104}, + {8, 0x0059}, + {8, 0x0019}, + {9, 0x0093}, + {7, 0x0114}, + {8, 0x0079}, + {8, 0x0039}, + {9, 0x00d3}, + {7, 0x010c}, + {8, 0x0069}, + {8, 0x0029}, + {9, 0x00b3}, + {8, 0x0009}, + {8, 0x0089}, + {8, 0x0049}, + {9, 0x00f3}, + {7, 0x0102}, + {8, 0x0055}, + {8, 0x0015}, + {8, 0x011d}, + {7, 0x0112}, + {8, 0x0075}, + {8, 0x0035}, + {9, 0x00cb}, + {7, 0x010a}, + {8, 0x0065}, + {8, 0x0025}, + {9, 0x00ab}, + {8, 0x0005}, + {8, 0x0085}, + {8, 0x0045}, + {9, 0x00eb}, + {7, 0x0106}, + {8, 0x005d}, + {8, 0x001d}, + {9, 0x009b}, + {7, 0x0116}, + {8, 0x007d}, + {8, 0x003d}, + {9, 0x00db}, + {7, 0x010e}, + {8, 0x006d}, + {8, 0x002d}, + {9, 0x00bb}, + {8, 0x000d}, + {8, 0x008d}, + {8, 0x004d}, + {9, 0x00fb}, + {7, 0x0101}, + {8, 0x0053}, + {8, 0x0013}, + {8, 0x011b}, + {7, 0x0111}, + {8, 0x0073}, + {8, 0x0033}, + {9, 0x00c7}, + {7, 0x0109}, + {8, 0x0063}, + {8, 0x0023}, + {9, 0x00a7}, + {8, 0x0003}, + {8, 0x0083}, + {8, 0x0043}, + {9, 0x00e7}, + {7, 0x0105}, + {8, 0x005b}, + {8, 0x001b}, + {9, 0x0097}, + {7, 0x0115}, + {8, 0x007b}, + {8, 0x003b}, + {9, 0x00d7}, + {7, 0x010d}, + {8, 0x006b}, + {8, 0x002b}, + {9, 0x00b7}, + {8, 0x000b}, + {8, 0x008b}, + {8, 0x004b}, + {9, 0x00f7}, + {7, 0x0103}, + {8, 0x0057}, + {8, 0x0017}, + {8, 0x011f}, + {7, 0x0113}, + {8, 0x0077}, + {8, 0x0037}, + {9, 0x00cf}, + {7, 0x010b}, + {8, 0x0067}, + {8, 0x0027}, + {9, 0x00af}, + {8, 0x0007}, + {8, 0x0087}, + {8, 0x0047}, + {9, 0x00ef}, + {7, 0x0107}, + {8, 0x005f}, + {8, 0x001f}, + {9, 0x009f}, + {7, 0x0117}, + {8, 0x007f}, + {8, 0x003f}, + {9, 0x00df}, + {7, 0x010f}, + {8, 0x006f}, + {8, 0x002f}, + {9, 0x00bf}, + {8, 0x000f}, + {8, 0x008f}, + {8, 0x004f}, + {9, 0x00ff} +}; + +FlateHuffmanTab FlateStream::fixedLitCodeTab = { + flateFixedLitCodeTabCodes, 9 +}; + +static FlateCode flateFixedDistCodeTabCodes[32] = { + {5, 0x0000}, + {5, 0x0010}, + {5, 0x0008}, + {5, 0x0018}, + {5, 0x0004}, + {5, 0x0014}, + {5, 0x000c}, + {5, 0x001c}, + {5, 0x0002}, + {5, 0x0012}, + {5, 0x000a}, + {5, 0x001a}, + {5, 0x0006}, + {5, 0x0016}, + {5, 0x000e}, + {0, 0x0000}, + {5, 0x0001}, + {5, 0x0011}, + {5, 0x0009}, + {5, 0x0019}, + {5, 0x0005}, + {5, 0x0015}, + {5, 0x000d}, + {5, 0x001d}, + {5, 0x0003}, + {5, 0x0013}, + {5, 0x000b}, + {5, 0x001b}, + {5, 0x0007}, + {5, 0x0017}, + {5, 0x000f}, + {0, 0x0000} +}; + +FlateHuffmanTab FlateStream::fixedDistCodeTab = { + flateFixedDistCodeTabCodes, 5 +}; + +FlateStream::FlateStream(Stream *strA, int predictor, int columns, + int colors, int bits): + FilterStream(strA) { + if (predictor != 1) { + pred = new StreamPredictor(this, predictor, columns, colors, bits); + if (!pred->isOk()) { + delete pred; + pred = NULL; + } + } else { + pred = NULL; + } + litCodeTab.codes = NULL; + distCodeTab.codes = NULL; + memset(buf, 0, flateWindow); + checkForDecompressionBombs = gTrue; +} + +FlateStream::~FlateStream() { + if (litCodeTab.codes != fixedLitCodeTab.codes) { + gfree(litCodeTab.codes); + } + if (distCodeTab.codes != fixedDistCodeTab.codes) { + gfree(distCodeTab.codes); + } + if (pred) { + delete pred; + } + delete str; +} + +Stream *FlateStream::copy() { + if (pred) { + return new FlateStream(str->copy(), pred->getPredictor(), + pred->getWidth(), pred->getNComps(), + pred->getNBits()); + } else { + return new FlateStream(str->copy(), 1, 0, 0, 0); + } +} + +void FlateStream::disableDecompressionBombChecking() { + checkForDecompressionBombs = gFalse; + FilterStream::disableDecompressionBombChecking(); +} + +void FlateStream::reset() { + int cmf, flg; + + index = 0; + remain = 0; + codeBuf = 0; + codeSize = 0; + compressedBlock = gFalse; + endOfBlock = gTrue; + eof = gTrue; + + str->reset(); + if (pred) { + pred->reset(); + } + + // read header + //~ need to look at window size? + endOfBlock = eof = gTrue; + cmf = str->getChar(); + flg = str->getChar(); + totalIn = 2; + totalOut = 0; + if (cmf == EOF || flg == EOF) + return; + if ((cmf & 0x0f) != 0x08) { + error(errSyntaxError, getPos(), + "Unknown compression method in flate stream"); + return; + } + if ((((cmf << 8) + flg) % 31) != 0) { + error(errSyntaxError, getPos(), "Bad FCHECK in flate stream"); + return; + } + if (flg & 0x20) { + error(errSyntaxError, getPos(), "FDICT bit set in flate stream"); + return; + } + + eof = gFalse; +} + +int FlateStream::getChar() { + int c; + + if (pred) { + return pred->getChar(); + } + while (remain == 0) { + if (endOfBlock && eof) + return EOF; + readSome(); + } + c = buf[index]; + index = (index + 1) & flateMask; + --remain; + return c; +} + +int FlateStream::lookChar() { + int c; + + if (pred) { + return pred->lookChar(); + } + while (remain == 0) { + if (endOfBlock && eof) + return EOF; + readSome(); + } + c = buf[index]; + return c; +} + +int FlateStream::getRawChar() { + int c; + + while (remain == 0) { + if (endOfBlock && eof) + return EOF; + readSome(); + } + c = buf[index]; + index = (index + 1) & flateMask; + --remain; + return c; +} + +int FlateStream::getBlock(char *blk, int size) { + int n, k; + + if (pred) { + return pred->getBlock(blk, size); + } + + n = 0; + while (n < size) { + if (remain == 0) { + if (endOfBlock && eof) { + break; + } + readSome(); + } + k = remain; + if (size - n < k) { + k = size - n; + } + if (flateWindow - index < k) { + k = flateWindow - index; + } + memcpy(blk + n, buf + index, k); + n += k; + index = (index + k) & flateMask; + remain -= k; + } + return n; +} + +GString *FlateStream::getPSFilter(int psLevel, const char *indent, + GBool okToReadStream) { + GString *s; + + if (psLevel < 3 || pred) { + return NULL; + } + if (!(s = str->getPSFilter(psLevel, indent, okToReadStream))) { + return NULL; + } + s->append(indent)->append("<< >> /FlateDecode filter\n"); + return s; +} + +GBool FlateStream::isBinary(GBool last) { + return str->isBinary(gTrue); +} + +void FlateStream::readSome() { + int code1, code2; + int len, dist; + int src, dest, n1, n2, n3, i, j, k; + int c; + + if (endOfBlock) { + if (!startBlock()) + return; + } + + if (compressedBlock) { + if ((code1 = getHuffmanCodeWord(&litCodeTab)) == EOF) + goto err; + if (code1 < 256) { + buf[index] = (Guchar)code1; + remain = 1; + } else if (code1 == 256) { + endOfBlock = gTrue; + remain = 0; + } else { + code1 -= 257; + code2 = lengthDecode[code1].bits; + if (code2 > 0 && (code2 = getCodeWord(code2)) == EOF) + goto err; + len = lengthDecode[code1].first + code2; + if ((code1 = getHuffmanCodeWord(&distCodeTab)) == EOF) + goto err; + code2 = distDecode[code1].bits; + if (code2 > 0 && (code2 = getCodeWord(code2)) == EOF) + goto err; + dist = distDecode[code1].first + code2; + dest = index; + src = (index - dist) & flateMask; + // the following is an optimized version of: + // for (k = 0; k < len; ++k) { + // buf[dest] = buf[src]; + // dest = (dest + 1) & flateMask; + // src = (src + 1) & flateMask; + // } + if (dest + len <= flateWindow) { + if (src + len <= flateWindow) { + for (k = 0; k < len; ++k) { + buf[dest + k] = buf[src + k]; + } + } else { + n1 = flateWindow - src; + n2 = len - n1; + for (k = 0; k < n1; ++k) { + buf[dest + k] = buf[src + k]; + } + dest = dest + n1; + src = 0; + for (k = 0; k < n2; ++k) { + buf[dest + k] = buf[src + k]; + } + } + } else { + if (src + len <= flateWindow) { + n1 = flateWindow - dest; + n2 = len - n1; + for (k = 0; k < n1; ++k) { + buf[dest + k] = buf[src + k]; + } + dest = 0; + src = src + n1; + for (k = 0; k < n2; ++k) { + buf[dest + k] = buf[src + k]; + } + } else if (src < dest) { + n1 = flateWindow - dest; + n2 = dest - src; + n3 = len - n1 - n2; + for (k = 0; k < n1; ++k) { + buf[dest + k] = buf[src + k]; + } + dest = 0; + src = src + n1; + for (k = 0; k < n2; ++k) { + buf[dest + k] = buf[src + k]; + } + dest = n2; + src = 0; + for (k = 0; k < n3; ++k) { + buf[dest + k] = buf[src + k]; + } + } else { + n1 = flateWindow - src; + n2 = src - dest; + n3 = len - n1 - n2; + for (k = 0; k < n1; ++k) { + buf[dest + k] = buf[src + k]; + } + dest = dest + n1; + src = 0; + for (k = 0; k < n2; ++k) { + buf[dest + k] = buf[src + k]; + } + dest = 0; + src = n2; + for (k = 0; k < n3; ++k) { + buf[dest + k] = buf[src + k]; + } + } + } + remain = len; + } + + } else { + len = (blockLen < flateWindow) ? blockLen : flateWindow; + for (i = 0, j = index; i < len; ++i, j = (j + 1) & flateMask) { + if ((c = str->getChar()) == EOF) { + endOfBlock = eof = gTrue; + break; + } + buf[j] = (Guchar)c; + } + remain = i; + blockLen -= len; + if (blockLen == 0) + endOfBlock = gTrue; + totalIn += remain; + } + totalOut += remain; + + // check for a 'decompression bomb' + if (checkForDecompressionBombs && + totalOut > decompressionBombSizeThreshold && + totalIn < totalOut / decompressionBombRatioThreshold) { + error(errSyntaxError, getPos(), "Decompression bomb in flate stream"); + endOfBlock = eof = gTrue; + remain = 0; + } + + return; + +err: + error(errSyntaxError, getPos(), "Unexpected end of file in flate stream"); + endOfBlock = eof = gTrue; + remain = 0; +} + +GBool FlateStream::startBlock() { + int blockHdr; + int c; + int check; + + // free the code tables from the previous block + if (litCodeTab.codes != fixedLitCodeTab.codes) { + gfree(litCodeTab.codes); + } + litCodeTab.codes = NULL; + if (distCodeTab.codes != fixedDistCodeTab.codes) { + gfree(distCodeTab.codes); + } + distCodeTab.codes = NULL; + + // read block header + blockHdr = getCodeWord(3); + if (blockHdr & 1) + eof = gTrue; + blockHdr >>= 1; + + // uncompressed block + if (blockHdr == 0) { + compressedBlock = gFalse; + if ((c = str->getChar()) == EOF) + goto err; + blockLen = c & 0xff; + if ((c = str->getChar()) == EOF) + goto err; + blockLen |= (c & 0xff) << 8; + if ((c = str->getChar()) == EOF) + goto err; + check = c & 0xff; + if ((c = str->getChar()) == EOF) + goto err; + check |= (c & 0xff) << 8; + if (check != (~blockLen & 0xffff)) + goto err; + codeBuf = 0; + codeSize = 0; + totalIn += 4; + + // compressed block with fixed codes + } else if (blockHdr == 1) { + compressedBlock = gTrue; + loadFixedCodes(); + + // compressed block with dynamic codes + } else if (blockHdr == 2) { + compressedBlock = gTrue; + if (!readDynamicCodes()) { + goto err; + } + + // unknown block type + } else { + goto err; + } + + endOfBlock = gFalse; + return gTrue; + +err: + error(errSyntaxError, getPos(), "Bad block header in flate stream"); + endOfBlock = eof = gTrue; + return gFalse; +} + +void FlateStream::loadFixedCodes() { + litCodeTab.codes = fixedLitCodeTab.codes; + litCodeTab.maxLen = fixedLitCodeTab.maxLen; + distCodeTab.codes = fixedDistCodeTab.codes; + distCodeTab.maxLen = fixedDistCodeTab.maxLen; +} + +GBool FlateStream::readDynamicCodes() { + int numCodeLenCodes; + int numLitCodes; + int numDistCodes; + int codeLenCodeLengths[flateMaxCodeLenCodes]; + FlateHuffmanTab codeLenCodeTab; + int len, repeat, code; + int i; + + codeLenCodeTab.codes = NULL; + + // read lengths + if ((numLitCodes = getCodeWord(5)) == EOF) { + goto err; + } + numLitCodes += 257; + if ((numDistCodes = getCodeWord(5)) == EOF) { + goto err; + } + numDistCodes += 1; + if ((numCodeLenCodes = getCodeWord(4)) == EOF) { + goto err; + } + numCodeLenCodes += 4; + if (numLitCodes > flateMaxLitCodes || + numDistCodes > flateMaxDistCodes || + numCodeLenCodes > flateMaxCodeLenCodes) { + goto err; + } + + // build the code length code table + for (i = 0; i < flateMaxCodeLenCodes; ++i) { + codeLenCodeLengths[i] = 0; + } + for (i = 0; i < numCodeLenCodes; ++i) { + if ((codeLenCodeLengths[codeLenCodeMap[i]] = getCodeWord(3)) == -1) { + goto err; + } + } + compHuffmanCodes(codeLenCodeLengths, flateMaxCodeLenCodes, &codeLenCodeTab); + + // build the literal and distance code tables + len = 0; + repeat = 0; + i = 0; + while (i < numLitCodes + numDistCodes) { + if ((code = getHuffmanCodeWord(&codeLenCodeTab)) == EOF) { + goto err; + } + if (code == 16) { + if ((repeat = getCodeWord(2)) == EOF) { + goto err; + } + repeat += 3; + if (i + repeat > numLitCodes + numDistCodes) { + goto err; + } + for (; repeat > 0; --repeat) { + codeLengths[i++] = len; + } + } else if (code == 17) { + if ((repeat = getCodeWord(3)) == EOF) { + goto err; + } + repeat += 3; + if (i + repeat > numLitCodes + numDistCodes) { + goto err; + } + len = 0; + for (; repeat > 0; --repeat) { + codeLengths[i++] = 0; + } + } else if (code == 18) { + if ((repeat = getCodeWord(7)) == EOF) { + goto err; + } + repeat += 11; + if (i + repeat > numLitCodes + numDistCodes) { + goto err; + } + len = 0; + for (; repeat > 0; --repeat) { + codeLengths[i++] = 0; + } + } else { + codeLengths[i++] = len = code; + } + } + compHuffmanCodes(codeLengths, numLitCodes, &litCodeTab); + compHuffmanCodes(codeLengths + numLitCodes, numDistCodes, &distCodeTab); + + gfree(codeLenCodeTab.codes); + return gTrue; + +err: + error(errSyntaxError, getPos(), "Bad dynamic code table in flate stream"); + gfree(codeLenCodeTab.codes); + return gFalse; +} + +// Convert an array of lengths, in value order, into a +// Huffman code lookup table. +void FlateStream::compHuffmanCodes(int *lengths, int n, FlateHuffmanTab *tab) { + int tabSize, len, code, code2, skip, val, i, t; + + // find max code length + tab->maxLen = 0; + for (val = 0; val < n; ++val) { + if (lengths[val] > tab->maxLen) { + tab->maxLen = lengths[val]; + } + } + + // allocate the table + tabSize = 1 << tab->maxLen; + tab->codes = (FlateCode *)gmallocn(tabSize, sizeof(FlateCode)); + + // clear the table + for (i = 0; i < tabSize; ++i) { + tab->codes[i].len = 0; + tab->codes[i].val = 0; + } + + // build the table + for (len = 1, code = 0, skip = 2; + len <= tab->maxLen; + ++len, code <<= 1, skip <<= 1) { + for (val = 0; val < n; ++val) { + if (lengths[val] == len) { + + // bit-reverse the code + code2 = 0; + t = code; + for (i = 0; i < len; ++i) { + code2 = (code2 << 1) | (t & 1); + t >>= 1; + } + + // fill in the table entries + for (i = code2; i < tabSize; i += skip) { + tab->codes[i].len = (Gushort)len; + tab->codes[i].val = (Gushort)val; + } + + ++code; + } + } + } +} + +int FlateStream::getHuffmanCodeWord(FlateHuffmanTab *tab) { + FlateCode *code; + int c; + + while (codeSize < tab->maxLen) { + if ((c = str->getChar()) == EOF) { + break; + } + codeBuf |= (c & 0xff) << codeSize; + codeSize += 8; + ++totalIn; + } + code = &tab->codes[codeBuf & ((1 << tab->maxLen) - 1)]; + if (codeSize == 0 || codeSize < code->len || code->len == 0) { + return EOF; + } + codeBuf >>= code->len; + codeSize -= code->len; + return (int)code->val; +} + +int FlateStream::getCodeWord(int bits) { + int c; + + while (codeSize < bits) { + if ((c = str->getChar()) == EOF) + return EOF; + codeBuf |= (c & 0xff) << codeSize; + codeSize += 8; + ++totalIn; + } + c = codeBuf & ((1 << bits) - 1); + codeBuf >>= bits; + codeSize -= bits; + return c; +} + +//------------------------------------------------------------------------ +// EOFStream +//------------------------------------------------------------------------ + +EOFStream::EOFStream(Stream *strA): + FilterStream(strA) { +} + +EOFStream::~EOFStream() { + delete str; +} + +Stream *EOFStream::copy() { + return new EOFStream(str->copy()); +} + +//------------------------------------------------------------------------ +// BufStream +//------------------------------------------------------------------------ + +BufStream::BufStream(Stream *strA, int bufSizeA): FilterStream(strA) { + bufSize = bufSizeA; + buf = (int *)gmallocn(bufSize, sizeof(int)); +} + +BufStream::~BufStream() { + gfree(buf); + delete str; +} + +Stream *BufStream::copy() { + return new BufStream(str->copy(), bufSize); +} + +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 +//------------------------------------------------------------------------ + +FixedLengthEncoder::FixedLengthEncoder(Stream *strA, int lengthA): + FilterStream(strA) { + length = lengthA; + count = 0; +} + +FixedLengthEncoder::~FixedLengthEncoder() { + if (str->isEncoder()) + delete str; +} + +Stream *FixedLengthEncoder::copy() { + error(errInternal, -1, "Called copy() on FixedLengthEncoder"); + return NULL; +} + +void FixedLengthEncoder::reset() { + str->reset(); + count = 0; +} + +int FixedLengthEncoder::getChar() { + if (length >= 0 && count >= length) + return EOF; + ++count; + return str->getChar(); +} + +int FixedLengthEncoder::lookChar() { + if (length >= 0 && count >= length) + return EOF; + return str->getChar(); +} + +GBool FixedLengthEncoder::isBinary(GBool last) { + return str->isBinary(gTrue); +} + +//------------------------------------------------------------------------ +// ASCIIHexEncoder +//------------------------------------------------------------------------ + +ASCIIHexEncoder::ASCIIHexEncoder(Stream *strA): + FilterStream(strA) { + bufPtr = bufEnd = buf; + lineLen = 0; + eof = gFalse; +} + +ASCIIHexEncoder::~ASCIIHexEncoder() { + if (str->isEncoder()) { + delete str; + } +} + +Stream *ASCIIHexEncoder::copy() { + error(errInternal, -1, "Called copy() on ASCIIHexEncoder"); + return NULL; +} + +void ASCIIHexEncoder::reset() { + str->reset(); + bufPtr = bufEnd = buf; + lineLen = 0; + eof = gFalse; +} + +GBool ASCIIHexEncoder::fillBuf() { + static const char *hex = "0123456789abcdef"; + int c; + + if (eof) { + return gFalse; + } + bufPtr = bufEnd = buf; + if ((c = str->getChar()) == EOF) { + *bufEnd++ = '>'; + eof = gTrue; + } else { + if (lineLen >= 64) { + *bufEnd++ = '\n'; + lineLen = 0; + } + *bufEnd++ = hex[(c >> 4) & 0x0f]; + *bufEnd++ = hex[c & 0x0f]; + lineLen += 2; + } + return gTrue; +} + +//------------------------------------------------------------------------ +// ASCII85Encoder +//------------------------------------------------------------------------ + +ASCII85Encoder::ASCII85Encoder(Stream *strA): + FilterStream(strA) { + bufPtr = bufEnd = buf; + lineLen = 0; + eof = gFalse; +} + +ASCII85Encoder::~ASCII85Encoder() { + if (str->isEncoder()) + delete str; +} + +Stream *ASCII85Encoder::copy() { + error(errInternal, -1, "Called copy() on ASCII85Encoder"); + return NULL; +} + +void ASCII85Encoder::reset() { + str->reset(); + bufPtr = bufEnd = buf; + lineLen = 0; + eof = gFalse; +} + +GBool ASCII85Encoder::fillBuf() { + Guint t; + char buf1[5]; + int c0, c1, c2, c3; + int n, i; + + if (eof) { + return gFalse; + } + c0 = str->getChar(); + c1 = str->getChar(); + c2 = str->getChar(); + c3 = str->getChar(); + bufPtr = bufEnd = buf; + if (c3 == EOF) { + if (c0 == EOF) { + n = 0; + t = 0; + } else { + if (c1 == EOF) { + n = 1; + t = c0 << 24; + } else if (c2 == EOF) { + n = 2; + t = (c0 << 24) | (c1 << 16); + } else { + n = 3; + t = (c0 << 24) | (c1 << 16) | (c2 << 8); + } + for (i = 4; i >= 0; --i) { + buf1[i] = (char)(t % 85 + 0x21); + t /= 85; + } + for (i = 0; i <= n; ++i) { + *bufEnd++ = buf1[i]; + if (++lineLen == 65) { + *bufEnd++ = '\n'; + lineLen = 0; + } + } + } + *bufEnd++ = '~'; + *bufEnd++ = '>'; + eof = gTrue; + } else { + t = (c0 << 24) | (c1 << 16) | (c2 << 8) | c3; + if (t == 0) { + *bufEnd++ = 'z'; + if (++lineLen == 65) { + *bufEnd++ = '\n'; + lineLen = 0; + } + } else { + for (i = 4; i >= 0; --i) { + buf1[i] = (char)(t % 85 + 0x21); + t /= 85; + } + for (i = 0; i <= 4; ++i) { + *bufEnd++ = buf1[i]; + if (++lineLen == 65) { + *bufEnd++ = '\n'; + lineLen = 0; + } + } + } + } + return gTrue; +} + +//------------------------------------------------------------------------ +// RunLengthEncoder +//------------------------------------------------------------------------ + +RunLengthEncoder::RunLengthEncoder(Stream *strA): + FilterStream(strA) { + bufPtr = bufEnd = nextEnd = buf; + eof = gFalse; +} + +RunLengthEncoder::~RunLengthEncoder() { + if (str->isEncoder()) + delete str; +} + +Stream *RunLengthEncoder::copy() { + error(errInternal, -1, "Called copy() on RunLengthEncoder"); + return NULL; +} + +void RunLengthEncoder::reset() { + str->reset(); + bufPtr = bufEnd = nextEnd = buf; + eof = gFalse; +} + +// +// When fillBuf finishes, buf[] looks like this: +// +-----+--------------+-----------------+-- +// + tag | ... data ... | next 0, 1, or 2 | +// +-----+--------------+-----------------+-- +// ^ ^ ^ +// bufPtr bufEnd nextEnd +// +GBool RunLengthEncoder::fillBuf() { + int c, c1, c2; + int n; + + // already hit EOF? + if (eof) + return gFalse; + + // grab two bytes + if (nextEnd < bufEnd + 1) { + if ((c1 = str->getChar()) == EOF) { + eof = gTrue; + return gFalse; + } + } else { + c1 = bufEnd[0] & 0xff; + } + if (nextEnd < bufEnd + 2) { + if ((c2 = str->getChar()) == EOF) { + eof = gTrue; + buf[0] = 0; + buf[1] = (char)c1; + bufPtr = buf; + bufEnd = &buf[2]; + return gTrue; + } + } else { + c2 = bufEnd[1] & 0xff; + } + + // check for repeat + c = 0; // make gcc happy + if (c1 == c2) { + n = 2; + while (n < 128 && (c = str->getChar()) == c1) + ++n; + buf[0] = (char)(257 - n); + buf[1] = (char)c1; + bufEnd = &buf[2]; + if (c == EOF) { + eof = gTrue; + } else if (n < 128) { + buf[2] = (char)c; + nextEnd = &buf[3]; + } else { + nextEnd = bufEnd; + } + + // get up to 128 chars + } else { + buf[1] = (char)c1; + buf[2] = (char)c2; + n = 2; + while (n < 128) { + if ((c = str->getChar()) == EOF) { + eof = gTrue; + break; + } + ++n; + buf[n] = (char)c; + if (buf[n] == buf[n-1]) + break; + } + if (buf[n] == buf[n-1]) { + buf[0] = (char)(n-2-1); + bufEnd = &buf[n-1]; + nextEnd = &buf[n+1]; + } else { + buf[0] = (char)(n-1); + bufEnd = nextEnd = &buf[n+1]; + } + } + bufPtr = buf; + return gTrue; +} + +//------------------------------------------------------------------------ +// LZWEncoder +//------------------------------------------------------------------------ + +LZWEncoder::LZWEncoder(Stream *strA): + FilterStream(strA) +{ + inBufStart = 0; + inBufLen = 0; + outBufLen = 0; +} + +LZWEncoder::~LZWEncoder() { + if (str->isEncoder()) { + delete str; + } +} + +Stream *LZWEncoder::copy() { + error(errInternal, -1, "Called copy() on LZWEncoder"); + return NULL; +} + +void LZWEncoder::reset() { + int i; + + str->reset(); + + // initialize code table + for (i = 0; i < 256; ++i) { + table[i].byte = i; + table[i].next = NULL; + table[i].children = NULL; + } + nextSeq = 258; + codeLen = 9; + + // initialize input buffer + inBufLen = str->getBlock((char *)inBuf, sizeof(inBuf)); + inBufStart = 0; + + // initialize output buffer with a clear-table code + outBuf = 256; + outBufLen = 9; + needEOD = gFalse; +} + +int LZWEncoder::getChar() { + int ret; + + if (inBufLen == 0 && !needEOD && outBufLen == 0) { + return EOF; + } + if (outBufLen < 8 && (inBufLen > 0 || needEOD)) { + fillBuf(); + } + if (outBufLen >= 8) { + ret = (outBuf >> (outBufLen - 8)) & 0xff; + outBufLen -= 8; + } else { + ret = (outBuf << (8 - outBufLen)) & 0xff; + outBufLen = 0; + } + return ret; +} + +int LZWEncoder::lookChar() { + if (inBufLen == 0 && !needEOD && outBufLen == 0) { + return EOF; + } + if (outBufLen < 8 && (inBufLen > 0 || needEOD)) { + fillBuf(); + } + if (outBufLen >= 8) { + return (outBuf >> (outBufLen - 8)) & 0xff; + } else { + return (outBuf << (8 - outBufLen)) & 0xff; + } +} + +// On input, outBufLen < 8. +// This function generates, at most, 2 12-bit codes +// --> outBufLen < 8 + 12 + 12 = 32 +void LZWEncoder::fillBuf() { + LZWEncoderNode *p0, *p1; + int seqLen, code, i; + + if (needEOD) { + outBuf = (outBuf << codeLen) | 257; + outBufLen += codeLen; + needEOD = gFalse; + return; + } + + // find longest matching sequence (if any) + p0 = table + inBuf[inBufStart]; + seqLen = 1; + while (inBufLen > seqLen) { + for (p1 = p0->children; p1; p1 = p1->next) { + if (p1->byte == inBuf[inBufStart + seqLen]) { + break; + } + } + if (!p1) { + break; + } + p0 = p1; + ++seqLen; + } + code = (int)(p0 - table); + + // generate an output code + outBuf = (outBuf << codeLen) | code; + outBufLen += codeLen; + + // update the table + table[nextSeq].byte = seqLen < inBufLen ? inBuf[inBufStart + seqLen] : 0; + table[nextSeq].children = NULL; + if (table[code].children) { + table[nextSeq].next = table[code].children; + } else { + table[nextSeq].next = NULL; + } + table[code].children = table + nextSeq; + ++nextSeq; + + // update the input buffer + inBufStart += seqLen; + inBufLen -= seqLen; + if (inBufStart >= 4096 && inBufStart + inBufLen == sizeof(inBuf)) { + memcpy(inBuf, inBuf + inBufStart, inBufLen); + inBufStart = 0; + inBufLen += str->getBlock((char *)inBuf + inBufLen, + (int)sizeof(inBuf) - inBufLen); + } + + // increment codeLen; generate clear-table code + if (nextSeq == (1 << codeLen)) { + ++codeLen; + if (codeLen == 13) { + outBuf = (outBuf << 12) | 256; + outBufLen += 12; + for (i = 0; i < 256; ++i) { + table[i].next = NULL; + table[i].children = NULL; + } + nextSeq = 258; + codeLen = 9; + } + } + + // generate EOD next time + if (inBufLen == 0) { + needEOD = gTrue; + } +} diff --git a/xpdf/Stream.h b/xpdf/Stream.h new file mode 100644 index 0000000..9d084c9 --- /dev/null +++ b/xpdf/Stream.h @@ -0,0 +1,1071 @@ +//======================================================================== +// +// Stream.h +// +// Copyright 1996-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef STREAM_H +#define STREAM_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include +#if HAVE_JPEGLIB +#include +#include +#endif +#include "gtypes.h" +#include "gfile.h" +#include "Object.h" + +class BaseStream; +class SharedFile; + +//------------------------------------------------------------------------ + +enum StreamKind { + strFile, + strASCIIHex, + strASCII85, + strLZW, + strRunLength, + strCCITTFax, + strDCT, + strFlate, + strJBIG2, + strJPX, + strWeird // internal-use stream types +}; + +enum StreamColorSpaceMode { + streamCSNone, + streamCSDeviceGray, + streamCSDeviceRGB, + streamCSDeviceCMYK +}; + +//------------------------------------------------------------------------ + +// This is in Stream.h instead of Decrypt.h to avoid really annoying +// include file dependency loops. +enum CryptAlgorithm { + cryptRC4, + cryptAES, + cryptAES256 +}; + +//------------------------------------------------------------------------ +// Stream (base class) +//------------------------------------------------------------------------ + +class Stream { +public: + + // Constructor. + Stream(); + + // Destructor. + virtual ~Stream(); + + virtual Stream *copy() = 0; + + // Get kind of stream. + virtual StreamKind getKind() = 0; + + virtual GBool isEmbedStream() { return gFalse; } + + // Disable checking for 'decompression bombs', i.e., cases where the + // encryption ratio looks suspiciously high. This should be called + // for things like images which (a) can have very high compression + // ratios in certain cases, and (b) have fixed data sizes controlled + // by the reader. + virtual void disableDecompressionBombChecking() {} + + // Reset stream to beginning. + virtual void reset() = 0; + + // Close down the stream. + virtual void close(); + + // Get next char from stream. + virtual int getChar() = 0; + + // Peek at next char in stream. + virtual int lookChar() = 0; + + // Get next char from stream without using the predictor. + // This is only used by StreamPredictor. + virtual int getRawChar(); + + // Get exactly bytes from stream. Returns the number of + // bytes read -- the returned count will be less than at EOF. + virtual int getBlock(char *blk, int size); + + // Get next line from stream. + virtual char *getLine(char *buf, int size); + + // Discard the next bytes from stream. Returns the number of + // bytes discarded, which will be less than only if EOF is + // reached. + virtual Guint discardChars(Guint n); + + // Get current position in file. + virtual GFileOffset getPos() = 0; + + // Go to a position in the stream. If is negative, the + // position is from the end of the file; otherwise the position is + // from the start of the file. + virtual void setPos(GFileOffset pos, int dir = 0) = 0; + + // Get PostScript command for the filter(s). + virtual GString *getPSFilter(int psLevel, const char *indent, + GBool okToReadStream); + + // Does this stream type potentially contain non-printable chars? + virtual GBool isBinary(GBool last = gTrue) = 0; + + // Get the BaseStream of this stream. + virtual BaseStream *getBaseStream() = 0; + + // Get the stream after the last decoder (this may be a BaseStream + // or a DecryptStream). + virtual Stream *getUndecodedStream() = 0; + + // Get the dictionary associated with this stream. + virtual Dict *getDict() = 0; + + // Is this an encoding filter? + virtual GBool isEncoder() { return gFalse; } + + // Get image parameters which are defined by the stream contents. + virtual void getImageParams(int *bitsPerComponent, + StreamColorSpaceMode *csMode) {} + + // Return the next stream in the "stack". + virtual Stream *getNextStream() { return NULL; } + + // Add filters to this stream according to the parameters in . + // Returns the new stream. + Stream *addFilters(Object *dict, int recursion = 0); + +private: + + Stream *makeFilter(char *name, Stream *str, Object *params, int recursion); +}; + +//------------------------------------------------------------------------ +// BaseStream +// +// This is the base class for all streams that read directly from a file. +//------------------------------------------------------------------------ + +class BaseStream: public Stream { +public: + + BaseStream(Object *dictA); + virtual ~BaseStream(); + virtual Stream *makeSubStream(GFileOffset start, GBool limited, + GFileOffset length, Object *dict) = 0; + virtual void setPos(GFileOffset pos, int dir = 0) = 0; + virtual GBool isBinary(GBool last = gTrue) { return last; } + virtual BaseStream *getBaseStream() { return this; } + virtual Stream *getUndecodedStream() { return this; } + virtual Dict *getDict() { return dict.getDict(); } + virtual GString *getFileName() { return NULL; } + + // Get/set position of first byte of stream within the file. + virtual GFileOffset getStart() = 0; + virtual void moveStart(int delta) = 0; + +protected: + + Object dict; +}; + +//------------------------------------------------------------------------ +// FilterStream +// +// This is the base class for all streams that filter another stream. +//------------------------------------------------------------------------ + +class FilterStream: public Stream { +public: + + FilterStream(Stream *strA); + virtual ~FilterStream(); + virtual void disableDecompressionBombChecking() + { str->disableDecompressionBombChecking(); } + virtual void close(); + virtual GFileOffset getPos() { return str->getPos(); } + virtual void setPos(GFileOffset pos, int dir = 0); + virtual BaseStream *getBaseStream() { return str->getBaseStream(); } + virtual Stream *getUndecodedStream() { return str->getUndecodedStream(); } + virtual Dict *getDict() { return str->getDict(); } + virtual Stream *getNextStream() { return str; } + +protected: + + Stream *str; +}; + +//------------------------------------------------------------------------ +// ImageStream +//------------------------------------------------------------------------ + +class ImageStream { +public: + + // Create an image stream object for an image with the specified + // parameters. Note that these are the actual image parameters, + // which may be different from the predictor parameters. + ImageStream(Stream *strA, int widthA, int nCompsA, int nBitsA); + + ~ImageStream(); + + // Reset the stream. + void reset(); + + // Close down the stream. + void close(); + + // Gets the next pixel from the stream. should be able to hold + // at least nComps elements. Returns false at end of file. + GBool getPixel(Guchar *pix); + + // Returns a pointer to the next line of pixels. Returns NULL at + // end of file. + Guchar *getLine(); + + // Skip an entire line from the image. + void skipLine(); + +private: + + Stream *str; // base stream + int width; // pixels per line + 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 +}; + + +//------------------------------------------------------------------------ +// StreamPredictor +//------------------------------------------------------------------------ + +class StreamPredictor { +public: + + // Create a predictor object. Note that the parameters are for the + // predictor, and may not match the actual image parameters. + StreamPredictor(Stream *strA, int predictorA, + int widthA, int nCompsA, int nBitsA); + + ~StreamPredictor(); + + GBool isOk() { return ok; } + + void reset(); + + int lookChar(); + int getChar(); + int getBlock(char *blk, int size); + + int getPredictor() { return predictor; } + int getWidth() { return width; } + int getNComps() { return nComps; } + int getNBits() { return nBits; } + +private: + + GBool getNextLine(); + + Stream *str; // base stream + int predictor; // predictor + int width; // pixels per line + int nComps; // components per pixel + int nBits; // bits per component + int nVals; // components per line + int pixBytes; // bytes per pixel + int rowBytes; // bytes per line + Guchar *predLine; // line buffer + int predIdx; // current index in predLine + GBool ok; +}; + +//------------------------------------------------------------------------ +// FileStream +//------------------------------------------------------------------------ + +#define fileStreamBufSize 256 + +class FileStream: public BaseStream { +public: + + FileStream(FILE *fA, GFileOffset startA, GBool limitedA, + GFileOffset lengthA, Object *dictA); + virtual ~FileStream(); + virtual Stream *copy(); + virtual Stream *makeSubStream(GFileOffset startA, GBool limitedA, + GFileOffset lengthA, Object *dictA); + virtual StreamKind getKind() { return strFile; } + virtual void reset(); + virtual int getChar() + { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); } + virtual int lookChar() + { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); } + virtual int getBlock(char *blk, int size); + virtual GFileOffset getPos() { return bufPos + (int)(bufPtr - buf); } + virtual void setPos(GFileOffset pos, int dir = 0); + virtual GFileOffset getStart() { return start; } + virtual void moveStart(int delta); + +private: + + FileStream(SharedFile *fA, GFileOffset startA, GBool limitedA, + GFileOffset lengthA, Object *dictA); + GBool fillBuf(); + + SharedFile *f; + GFileOffset start; + GBool limited; + GFileOffset length; + char buf[fileStreamBufSize]; + char *bufPtr; + char *bufEnd; + GFileOffset bufPos; +}; + +//------------------------------------------------------------------------ +// MemStream +//------------------------------------------------------------------------ + +class MemStream: public BaseStream { +public: + + MemStream(char *bufA, Guint startA, Guint lengthA, Object *dictA); + virtual ~MemStream(); + virtual Stream *copy(); + virtual Stream *makeSubStream(GFileOffset start, GBool limited, + GFileOffset lengthA, Object *dictA); + virtual StreamKind getKind() { return strWeird; } + virtual void reset(); + virtual void close(); + virtual int getChar() + { return (bufPtr < bufEnd) ? (*bufPtr++ & 0xff) : EOF; } + virtual int lookChar() + { return (bufPtr < bufEnd) ? (*bufPtr & 0xff) : EOF; } + virtual int getBlock(char *blk, int size); + virtual GFileOffset getPos() { return (GFileOffset)(bufPtr - buf); } + virtual void setPos(GFileOffset pos, int dir = 0); + virtual GFileOffset getStart() { return start; } + virtual void moveStart(int delta); + +private: + + char *buf; + Guint start; + Guint length; + char *bufEnd; + char *bufPtr; + GBool needFree; +}; + +//------------------------------------------------------------------------ +// EmbedStream +// +// This is a special stream type used for embedded streams (inline +// images). It reads directly from the base stream -- after the +// EmbedStream is deleted, reads from the base stream will proceed where +// the BaseStream left off. Note that this is very different behavior +// that creating a new FileStream (using makeSubStream). +//------------------------------------------------------------------------ + +class EmbedStream: public BaseStream { +public: + + EmbedStream(Stream *strA, Object *dictA, GBool limitedA, GFileOffset lengthA); + virtual ~EmbedStream(); + virtual Stream *copy(); + virtual Stream *makeSubStream(GFileOffset start, GBool limitedA, + GFileOffset lengthA, Object *dictA); + virtual StreamKind getKind() { return str->getKind(); } + virtual GBool isEmbedStream() { return gTrue; } + virtual void reset() {} + virtual int getChar(); + virtual int lookChar(); + virtual int getBlock(char *blk, int size); + virtual GFileOffset getPos() { return str->getPos(); } + virtual void setPos(GFileOffset pos, int dir = 0); + virtual GFileOffset getStart(); + virtual void moveStart(int delta); + +private: + + Stream *str; + GBool limited; + GFileOffset length; +}; + +//------------------------------------------------------------------------ +// ASCIIHexStream +//------------------------------------------------------------------------ + +class ASCIIHexStream: public FilterStream { +public: + + ASCIIHexStream(Stream *strA); + virtual ~ASCIIHexStream(); + virtual Stream *copy(); + virtual StreamKind getKind() { return strASCIIHex; } + virtual void reset(); + virtual int getChar() + { int c = lookChar(); buf = EOF; return c; } + virtual int lookChar(); + virtual GString *getPSFilter(int psLevel, const char *indent, + GBool okToReadStream); + virtual GBool isBinary(GBool last = gTrue); + +private: + + int buf; + GBool eof; +}; + +//------------------------------------------------------------------------ +// ASCII85Stream +//------------------------------------------------------------------------ + +class ASCII85Stream: public FilterStream { +public: + + ASCII85Stream(Stream *strA); + virtual ~ASCII85Stream(); + virtual Stream *copy(); + virtual StreamKind getKind() { return strASCII85; } + virtual void reset(); + virtual int getChar() + { int ch = lookChar(); ++index; return ch; } + virtual int lookChar(); + virtual GString *getPSFilter(int psLevel, const char *indent, + GBool okToReadStream); + virtual GBool isBinary(GBool last = gTrue); + +private: + + int c[5]; + int b[4]; + int index, n; + GBool eof; +}; + +//------------------------------------------------------------------------ +// LZWStream +//------------------------------------------------------------------------ + +class LZWStream: public FilterStream { +public: + + LZWStream(Stream *strA, int predictor, int columns, int colors, + int bits, int earlyA); + virtual ~LZWStream(); + virtual Stream *copy(); + virtual StreamKind getKind() { return strLZW; } + virtual void disableDecompressionBombChecking(); + virtual void reset(); + virtual int getChar(); + virtual int lookChar(); + virtual int getRawChar(); + virtual int getBlock(char *blk, int size); + virtual GString *getPSFilter(int psLevel, const char *indent, + GBool okToReadStream); + virtual GBool isBinary(GBool last = gTrue); + +private: + + StreamPredictor *pred; // predictor + int early; // early parameter + GBool eof; // true if at eof + int inputBuf; // input buffer + int inputBits; // number of bits in input buffer + struct { // decoding table + int length; + int head; + Guchar tail; + } table[4097]; + int nextCode; // next code to be used + int nextBits; // number of bits in next code word + int prevCode; // previous code used in stream + int newChar; // next char to be added to table + Guchar seqBuf[4097]; // buffer for current sequence + int seqLength; // length of current sequence + int seqIndex; // index into current sequence + GBool first; // first code after a table clear + GBool checkForDecompressionBombs; + unsigned long long totalIn; // total number of encoded bytes read so far + unsigned long long totalOut; // total number of bytes decoded so far + + GBool processNextCode(); + void clearTable(); + int getCode(); +}; + +//------------------------------------------------------------------------ +// RunLengthStream +//------------------------------------------------------------------------ + +class RunLengthStream: public FilterStream { +public: + + RunLengthStream(Stream *strA); + virtual ~RunLengthStream(); + virtual Stream *copy(); + virtual StreamKind getKind() { return strRunLength; } + virtual void reset(); + virtual int getChar() + { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); } + virtual int lookChar() + { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); } + virtual int getBlock(char *blk, int size); + virtual GString *getPSFilter(int psLevel, const char *indent, + GBool okToReadStream); + virtual GBool isBinary(GBool last = gTrue); + +private: + + char buf[128]; // buffer + char *bufPtr; // next char to read + char *bufEnd; // end of buffer + GBool eof; + + GBool fillBuf(); +}; + +//------------------------------------------------------------------------ +// CCITTFaxStream +//------------------------------------------------------------------------ + +struct CCITTCodeTable; + +class CCITTFaxStream: public FilterStream { +public: + + CCITTFaxStream(Stream *strA, int encodingA, GBool endOfLineA, + GBool byteAlignA, int columnsA, int rowsA, + GBool endOfBlockA, GBool blackA); + virtual ~CCITTFaxStream(); + virtual Stream *copy(); + virtual StreamKind getKind() { return strCCITTFax; } + virtual void reset(); + virtual int getChar(); + virtual int lookChar(); + virtual int getBlock(char *blk, int size); + virtual GString *getPSFilter(int psLevel, const char *indent, + GBool okToReadStream); + virtual GBool isBinary(GBool last = gTrue); + +private: + + int encoding; // 'K' parameter + GBool endOfLine; // 'EndOfLine' parameter + GBool byteAlign; // 'EncodedByteAlign' parameter + int columns; // 'Columns' parameter + int rows; // 'Rows' parameter + GBool endOfBlock; // 'EndOfBlock' parameter + GBool black; // 'BlackIs1' parameter + int blackXOR; + GBool eof; // true if at eof + GBool nextLine2D; // true if next line uses 2D encoding + int row; // current row + Guint inputBuf; // input buffer + int inputBits; // number of bits in input buffer + int *codingLine; // coding line changing elements + int *refLine; // reference line changing elements + int nextCol; // next column to read + int a0i; // index into codingLine + GBool err; // error on current line + int nErrors; // number of errors so far in this stream + + void addPixels(int a1, int blackPixels); + void addPixelsNeg(int a1, int blackPixels); + GBool readRow(); + short getTwoDimCode(); + short getWhiteCode(); + short getBlackCode(); + short lookBits(int n); + void eatBits(int n) { if ((inputBits -= n) < 0) inputBits = 0; } +}; + +//------------------------------------------------------------------------ +// DCTStream +//------------------------------------------------------------------------ + +#if HAVE_JPEGLIB + +class DCTStream; + +#define dctStreamBufSize 4096 + +struct DCTSourceMgr { + jpeg_source_mgr src; + DCTStream *str; + char buf[dctStreamBufSize]; +}; + +struct DCTErrorMgr { + struct jpeg_error_mgr err; + jmp_buf setjmpBuf; +}; + +#else // HAVE_JPEGLIB + +// DCT component info +struct DCTCompInfo { + int id; // component ID + int hSample, vSample; // horiz/vert sampling resolutions + int quantTable; // quantization table number + int prevDC; // DC coefficient accumulator +}; + +struct DCTScanInfo { + GBool comp[4]; // comp[i] is set if component i is + // included in this scan + int numComps; // number of components in the scan + int dcHuffTable[4]; // DC Huffman table numbers + int acHuffTable[4]; // AC Huffman table numbers + int firstCoeff, lastCoeff; // first and last DCT coefficient + int ah, al; // successive approximation parameters +}; + +// DCT Huffman decoding table +struct DCTHuffTable { + Guchar firstSym[17]; // first symbol for this bit length + Gushort firstCode[17]; // first code for this bit length + Gushort numCodes[17]; // number of codes of this bit length + Guchar sym[256]; // symbols +}; + +#endif // HAVE_JPEGLIB + +class DCTStream: public FilterStream { +public: + + DCTStream(Stream *strA, int colorXformA); + virtual ~DCTStream(); + virtual Stream *copy(); + virtual StreamKind getKind() { return strDCT; } + virtual void reset(); + virtual void close(); + virtual int getChar(); + virtual int lookChar(); + virtual int getBlock(char *blk, int size); + virtual GString *getPSFilter(int psLevel, const char *indent, + GBool okToReadStream); + virtual GBool isBinary(GBool last = gTrue); + Stream *getRawStream() { return str; } + +private: + + GBool checkSequentialInterleaved(); + +#if HAVE_JPEGLIB + + int colorXform; // color transform: -1 = unspecified + // 0 = none + // 1 = YUV/YUVK -> RGB/CMYK + jpeg_decompress_struct decomp; + DCTErrorMgr errorMgr; + DCTSourceMgr sourceMgr; + GBool error; + char *lineBuf; + int lineBufHeight; + char *lineBufRows[4]; + char *bufPtr; + char *bufEnd; + GBool inlineImage; + + GBool fillBuf(); + static void errorExit(j_common_ptr d); + static void errorMessage(j_common_ptr d); + static void initSourceCbk(j_decompress_ptr d); + static boolean fillInputBufferCbk(j_decompress_ptr d); + static void skipInputDataCbk(j_decompress_ptr d, long numBytes); + static void termSourceCbk(j_decompress_ptr d); + +#else // HAVE_JPEGLIB + + GBool prepared; // set after prepare() is called + GBool progressive; // set if in progressive mode + GBool interleaved; // set if in interleaved mode + int width, height; // image size + int mcuWidth, mcuHeight; // size of min coding unit, in data units + int bufWidth, bufHeight; // frameBuf size + DCTCompInfo compInfo[4]; // info for each component + DCTScanInfo scanInfo; // info for the current scan + int numComps; // number of components in image + int colorXform; // color transform: -1 = unspecified + // 0 = none + // 1 = YUV/YUVK -> RGB/CMYK + GBool gotJFIFMarker; // set if APP0 JFIF marker was present + GBool gotAdobeMarker; // set if APP14 Adobe marker was present + int restartInterval; // restart interval, in MCUs + Gushort quantTables[4][64]; // quantization tables + int numQuantTables; // number of quantization tables + DCTHuffTable dcHuffTables[4]; // DC Huffman tables + DCTHuffTable acHuffTables[4]; // AC Huffman tables + int numDCHuffTables; // number of DC Huffman tables + int numACHuffTables; // number of AC Huffman tables + Guchar *rowBuf; + Guchar *rowBufPtr; // current position within rowBuf + Guchar *rowBufEnd; // end of valid data in rowBuf + int *frameBuf[4]; // buffer for frame (progressive mode) + int comp, x, y; // current position within image/MCU + int restartCtr; // MCUs left until restart + int restartMarker; // next restart marker + int eobRun; // number of EOBs left in the current run + int inputBuf; // input buffer for variable length codes + int inputBits; // number of valid bits in input buffer + + void prepare(); + void restart(); + GBool readMCURow(); + void readScan(); + GBool readDataUnit(DCTHuffTable *dcHuffTable, + DCTHuffTable *acHuffTable, + int *prevDC, int data[64]); + GBool readProgressiveDataUnit(DCTHuffTable *dcHuffTable, + DCTHuffTable *acHuffTable, + int *prevDC, int data[64]); + void decodeImage(); + void transformDataUnit(Gushort *quantTable, + int dataIn[64], Guchar dataOut[64]); + int readHuffSym(DCTHuffTable *table); + int readAmp(int size); + int readBit(); + GBool readHeader(GBool frame); + GBool readBaselineSOF(); + GBool readProgressiveSOF(); + GBool readScanInfo(); + GBool readQuantTables(); + GBool readHuffmanTables(); + GBool readRestartInterval(); + GBool readJFIFMarker(); + GBool readAdobeMarker(); + GBool readTrailer(); + int readMarker(); + int read16(); + +#endif // HAVE_JPEGLIB +}; + +//------------------------------------------------------------------------ +// FlateStream +//------------------------------------------------------------------------ + +#define flateWindow 32768 // buffer size +#define flateMask (flateWindow-1) +#define flateMaxHuffman 15 // max Huffman code length +#define flateMaxCodeLenCodes 19 // max # code length codes +#define flateMaxLitCodes 288 // max # literal codes +#define flateMaxDistCodes 30 // max # distance codes + +// Huffman code table entry +struct FlateCode { + Gushort len; // code length, in bits + Gushort val; // value represented by this code +}; + +struct FlateHuffmanTab { + FlateCode *codes; + int maxLen; +}; + +// Decoding info for length and distance code words +struct FlateDecode { + int bits; // # extra bits + int first; // first length/distance +}; + +class FlateStream: public FilterStream { +public: + + FlateStream(Stream *strA, int predictor, int columns, + int colors, int bits); + virtual ~FlateStream(); + virtual Stream *copy(); + virtual StreamKind getKind() { return strFlate; } + virtual void disableDecompressionBombChecking(); + virtual void reset(); + virtual int getChar(); + virtual int lookChar(); + virtual int getRawChar(); + virtual int getBlock(char *blk, int size); + virtual GString *getPSFilter(int psLevel, const char *indent, + GBool okToReadStream); + virtual GBool isBinary(GBool last = gTrue); + +private: + + StreamPredictor *pred; // predictor + Guchar buf[flateWindow]; // output data buffer + int index; // current index into output buffer + int remain; // number valid bytes in output buffer + int codeBuf; // input buffer + int codeSize; // number of bits in input buffer + int // literal and distance code lengths + codeLengths[flateMaxLitCodes + flateMaxDistCodes]; + FlateHuffmanTab litCodeTab; // literal code table + FlateHuffmanTab distCodeTab; // distance code table + GBool compressedBlock; // set if reading a compressed block + int blockLen; // remaining length of uncompressed block + GBool endOfBlock; // set when end of block is reached + GBool eof; // set when end of stream is reached + GBool checkForDecompressionBombs; + unsigned long long totalIn; // total number of encoded bytes read so far + unsigned long long totalOut; // total number of bytes decoded so far + + static int // code length code reordering + codeLenCodeMap[flateMaxCodeLenCodes]; + static FlateDecode // length decoding info + lengthDecode[flateMaxLitCodes-257]; + static FlateDecode // distance decoding info + distDecode[flateMaxDistCodes]; + static FlateHuffmanTab // fixed literal code table + fixedLitCodeTab; + static FlateHuffmanTab // fixed distance code table + fixedDistCodeTab; + + void readSome(); + GBool startBlock(); + void loadFixedCodes(); + GBool readDynamicCodes(); + void compHuffmanCodes(int *lengths, int n, FlateHuffmanTab *tab); + int getHuffmanCodeWord(FlateHuffmanTab *tab); + int getCodeWord(int bits); +}; + +//------------------------------------------------------------------------ +// EOFStream +//------------------------------------------------------------------------ + +class EOFStream: public FilterStream { +public: + + EOFStream(Stream *strA); + virtual ~EOFStream(); + virtual Stream *copy(); + virtual StreamKind getKind() { return strWeird; } + virtual void reset() {} + virtual int getChar() { return EOF; } + virtual int lookChar() { return EOF; } + virtual int getBlock(char *blk, int size) { return 0; } + virtual GString *getPSFilter(int psLevel, const char *indent, + GBool okToReadStream) + { return NULL; } + virtual GBool isBinary(GBool last = gTrue) { return gFalse; } +}; + +//------------------------------------------------------------------------ +// BufStream +//------------------------------------------------------------------------ + +class BufStream: public FilterStream { +public: + + BufStream(Stream *strA, int bufSizeA); + virtual ~BufStream(); + virtual Stream *copy(); + virtual StreamKind getKind() { return strWeird; } + virtual void reset(); + virtual int getChar(); + virtual int lookChar(); + virtual GString *getPSFilter(int psLevel, const char *indent, + GBool okToReadStream) + { return NULL; } + virtual GBool isBinary(GBool last = gTrue); + + int lookChar(int idx); + +private: + + int *buf; + int bufSize; +}; + +//------------------------------------------------------------------------ +// FixedLengthEncoder +//------------------------------------------------------------------------ + +class FixedLengthEncoder: public FilterStream { +public: + + FixedLengthEncoder(Stream *strA, int lengthA); + ~FixedLengthEncoder(); + virtual Stream *copy(); + virtual StreamKind getKind() { return strWeird; } + virtual void reset(); + virtual int getChar(); + virtual int lookChar(); + virtual GString *getPSFilter(int psLevel, const char *indent, + GBool okToReadStream) + { return NULL; } + virtual GBool isBinary(GBool last = gTrue); + virtual GBool isEncoder() { return gTrue; } + +private: + + int length; + int count; +}; + +//------------------------------------------------------------------------ +// ASCIIHexEncoder +//------------------------------------------------------------------------ + +class ASCIIHexEncoder: public FilterStream { +public: + + ASCIIHexEncoder(Stream *strA); + virtual ~ASCIIHexEncoder(); + virtual Stream *copy(); + virtual StreamKind getKind() { return strWeird; } + virtual void reset(); + virtual int getChar() + { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); } + virtual int lookChar() + { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); } + virtual GString *getPSFilter(int psLevel, const char *indent, + GBool okToReadStream) + { return NULL; } + virtual GBool isBinary(GBool last = gTrue) { return gFalse; } + virtual GBool isEncoder() { return gTrue; } + +private: + + char buf[4]; + char *bufPtr; + char *bufEnd; + int lineLen; + GBool eof; + + GBool fillBuf(); +}; + +//------------------------------------------------------------------------ +// ASCII85Encoder +//------------------------------------------------------------------------ + +class ASCII85Encoder: public FilterStream { +public: + + ASCII85Encoder(Stream *strA); + virtual ~ASCII85Encoder(); + virtual Stream *copy(); + virtual StreamKind getKind() { return strWeird; } + virtual void reset(); + virtual int getChar() + { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); } + virtual int lookChar() + { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); } + virtual GString *getPSFilter(int psLevel, const char *indent, + GBool okToReadStream) + { return NULL; } + virtual GBool isBinary(GBool last = gTrue) { return gFalse; } + virtual GBool isEncoder() { return gTrue; } + +private: + + char buf[8]; + char *bufPtr; + char *bufEnd; + int lineLen; + GBool eof; + + GBool fillBuf(); +}; + +//------------------------------------------------------------------------ +// RunLengthEncoder +//------------------------------------------------------------------------ + +class RunLengthEncoder: public FilterStream { +public: + + RunLengthEncoder(Stream *strA); + virtual ~RunLengthEncoder(); + virtual Stream *copy(); + virtual StreamKind getKind() { return strWeird; } + virtual void reset(); + virtual int getChar() + { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); } + virtual int lookChar() + { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); } + virtual GString *getPSFilter(int psLevel, const char *indent, + GBool okToReadStream) + { return NULL; } + virtual GBool isBinary(GBool last = gTrue) { return gTrue; } + virtual GBool isEncoder() { return gTrue; } + +private: + + char buf[131]; + char *bufPtr; + char *bufEnd; + char *nextEnd; + GBool eof; + + GBool fillBuf(); +}; + +//------------------------------------------------------------------------ +// LZWEncoder +//------------------------------------------------------------------------ + +struct LZWEncoderNode { + int byte; + LZWEncoderNode *next; // next sibling + LZWEncoderNode *children; // first child +}; + +class LZWEncoder: public FilterStream { +public: + + LZWEncoder(Stream *strA); + virtual ~LZWEncoder(); + virtual Stream *copy(); + virtual StreamKind getKind() { return strWeird; } + virtual void reset(); + virtual int getChar(); + virtual int lookChar(); + virtual GString *getPSFilter(int psLevel, const char *indent, + GBool okToReadStream) + { return NULL; } + virtual GBool isBinary(GBool last = gTrue) { return gTrue; } + virtual GBool isEncoder() { return gTrue; } + +private: + + LZWEncoderNode table[4096]; + int nextSeq; + int codeLen; + Guchar inBuf[8192]; + int inBufStart; + int inBufLen; + int outBuf; + int outBufLen; + GBool needEOD; + + void fillBuf(); +}; + +#endif diff --git a/xpdf/TextOutputDev.cc b/xpdf/TextOutputDev.cc new file mode 100644 index 0000000..e2da940 --- /dev/null +++ b/xpdf/TextOutputDev.cc @@ -0,0 +1,6835 @@ +//======================================================================== +// +// TextOutputDev.cc +// +// Copyright 1997-2014 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include +#include +#include +#include +#include +#ifdef _WIN32 +#include // for O_BINARY +#include // for setmode +#endif +#include "gmem.h" +#include "gmempp.h" +#include "GString.h" +#include "GList.h" +#include "gfile.h" +#include "config.h" +#include "Error.h" +#include "GlobalParams.h" +#include "UnicodeMap.h" +#include "UnicodeRemapping.h" +#include "UnicodeTypeTable.h" +#include "GfxState.h" +#include "Link.h" +#include "TextOutputDev.h" + +//------------------------------------------------------------------------ +// parameters +//------------------------------------------------------------------------ + +// Size of bins used for horizontal and vertical profiles is +// splitPrecisionMul * minFontSize. +#define splitPrecisionMul 0.05 + +// Minimum allowed split precision. +#define minSplitPrecision 0.01 + +// yMin and yMax (or xMin and xMax for rot=1,3) are adjusted by this +// fraction of the text height, to allow for slightly overlapping +// lines (or large ascent/descent values). +#define ascentAdjustFactor 0 +#define descentAdjustFactor 0.35 + +// Gaps larger than max{gap} - splitGapSlack * avgFontSize are +// considered to be equivalent. +#define splitGapSlack 0.2 + +// Gap area (width * height) must be larger than this to allow a +// vertical split (or horizontal split if rot=1,3). +#define minGapArea 3 +#define minTableGapArea 1.5 + +// A large character has a font size larger than +// largeCharThreshold * avgFontSize. +#define largeCharThreshold 1.5 + +// A block will be split vertically only if the resulting chunk widths +// are greater than minChunkWidth * avgFontSize. However, Blocks of +// height less than maxSingleLineHeight * avgFontSize are not subject +// to this minimum chunk width criterion. +#define minChunkWidth 2 +#define maxSingleLineHeight 1.5 + +// Minimum vertical gap is minGapSize * minFontSize. +// (horizontal gap for rot=1,3) +#define minGapSize 0.2 + +// Maximum vertical gap for a "small" split is maxWordGapSize * +// avgFontSize. +#define maxWordGapSize 2.5 +#define tableModeMaxWordGapSize 1.1 + +// Adjacent lines can overlap by at most lineOverlapThreshold * +// lineHeight. +#define lineOverlapThreshold 0.33 + +// Subscripts (superscripts) must overlap the next (previous) line by +// minSubSuperscriptVertOverlap * fontSize. +#define minSubSuperscriptVertOverlap 0.25 + +// Subscripts (superscripts) may horizontally overlap adjacent +// characters by up to maxSubSuperscriptHorizOverlap * fontSize. +#define maxSubSuperscriptHorizOverlap 0.05 + +// Max difference in primary,secondary coordinates (as a fraction of +// the font size) allowed for duplicated text (fake boldface, drop +// shadows) which is to be discarded. +#define dupMaxPriDelta 0.1 +#define dupMaxSecDelta 0.2 + +// Inter-character spacing that varies by less than this multiple of +// font size is assumed to be equivalent. +#define uniformSpacing 0.07 +#define tableModeUniformSpacing 0.14 + +// Typical word spacing, as a fraction of font size. This will be +// added to the minimum inter-character spacing, to account for wide +// character spacing. +#define wordSpacing 0.1 +#define tableModeWordSpacing 0.2 + +// Minimum paragraph indent from left margin, as a fraction of font +// size. +#define minParagraphIndent 0.5 + +// If the space between two lines is greater than +// paragraphSpacingThreshold * avgLineSpacing, start a new paragraph. +#define paragraphSpacingThreshold 1.25 + +// If font size changes by at least this much (measured in points) +// between lines, start a new paragraph. +#define paragraphFontSizeDelta 1 + +// Spaces at the start of a line in physical layout mode are this wide +// (as a multiple of font size). +#define physLayoutSpaceWidth 0.33 + +// In simple layout mode, lines are broken at gaps larger than this +// value multiplied by font size. +#define simpleLayoutGapThreshold 0.7 + +// Minimum overlap in simple2 mode. +#define simple2MinOverlap 0.2 + +// Table cells (TextColumns) are allowed to overlap by this much +// in table layout mode (as a fraction of cell width or height). +#define tableCellOverlapSlack 0.05 + +// Primary axis delta which will cause a line break in raw mode +// (as a fraction of font size). +#define rawModeLineDelta 0.5 + +// Secondary axis delta which will cause a word break in raw mode +// (as a fraction of font size). +#define rawModeWordSpacing 0.15 + +// Secondary axis overlap which will cause a line break in raw mode +// (as a fraction of font size). +#define rawModeCharOverlap 0.2 + +// Max spacing (as a multiple of font size) allowed between the end of +// a line and a clipped character to be included in that line. +#define clippedTextMaxWordSpace 0.5 + +// Max width of underlines (in points). +#define maxUnderlineWidth 3 + +// Max horizontal distance between edge of word and start of underline +// (as a fraction of font size). +#define underlineSlack 0.2 + +// Max vertical distance between baseline of word and start of +// underline (as a fraction of font size). +#define underlineBaselineSlack 0.2 + +// Max distance between edge of text and edge of link border (as a +// fraction of font size). +#define hyperlinkSlack 0.2 + +// Text is considered diagonal if abs(tan(angle)) > diagonalThreshold. +// (Or 1/tan(angle) for 90/270 degrees.) +#define diagonalThreshold 0.1 + +// This value is used as the ascent when computing selection +// rectangles, in order to work around flakey ascent values in fonts. +#define selectionAscent 0.8 + +// Grid size used to bin sort characters for overlap detection. +#define overlapGridWidth 20 +#define overlapGridHeight 20 + +// Minimum character bbox overlap (horizontal and vertical) as a +// fraction of character bbox width/height for a character to be +// treated as overlapping. +#define minCharOverlap 0.3 + +#define maxUnicodeLen 16 + +//------------------------------------------------------------------------ + +static inline double dmin(double x, double y) { + return x < y ? x : y; +} + +static inline double dmax(double x, double y) { + return x > y ? x : y; +} + +//------------------------------------------------------------------------ +// TextChar +//------------------------------------------------------------------------ + +class TextChar { +public: + + TextChar(Unicode cA, int charPosA, int charLenA, + double xMinA, double yMinA, double xMaxA, double yMaxA, + int rotA, GBool rotatedA, GBool clippedA, GBool invisibleA, + TextFontInfo *fontA, double fontSizeA, + double colorRA, double colorGA, double colorBA); + + static int cmpX(const void *p1, const void *p2); + static int cmpY(const void *p1, const void *p2); + static int cmpCharPos(const void *p1, const void *p2); + + Unicode c; + int charPos; + int charLen; + double xMin, yMin, xMax, yMax; + TextFontInfo *font; + double fontSize; + double colorR, + colorG, + colorB; + + // group the byte-size fields to minimize object size + Guchar rot; + char rotated; + char clipped; + char invisible; + char spaceAfter; + char overlap; +}; + +TextChar::TextChar(Unicode cA, int charPosA, int charLenA, + double xMinA, double yMinA, double xMaxA, double yMaxA, + int rotA, GBool rotatedA, GBool clippedA, GBool invisibleA, + TextFontInfo *fontA, double fontSizeA, + double colorRA, double colorGA, double colorBA) { + double t; + + c = cA; + charPos = charPosA; + charLen = charLenA; + xMin = xMinA; + yMin = yMinA; + xMax = xMaxA; + yMax = yMaxA; + // this can happen with vertical writing mode, or with odd values + // for the char/word spacing parameters + if (xMin > xMax) { + t = xMin; xMin = xMax; xMax = t; + } + if (yMin > yMax) { + t = yMin; yMin = yMax; yMax = t; + } + // TextPage::findGaps uses integer coordinates, so clip the char + // bbox to fit in a 32-bit int (this is generally only a problem in + // damaged PDF files) + if (xMin < -1e8) { + xMin = -1e8; + } + if (xMax > 1e8) { + xMax = 1e8; + } + if (yMin < -1e8) { + yMin = -1e8; + } + if (yMax > 1e8) { + yMax = 1e8; + } + // zero-width characters will cause problems in the splitting code + if (rotA & 1) { + if (yMax - yMin < 1e-6) { + yMax = yMin + 1e-6; + } + } else { + if (xMax - xMin < 1e-6) { + xMax = xMin + 1e-6; + } + } + rot = (Guchar)rotA; + rotated = (char)rotatedA; + clipped = (char)clippedA; + invisible = (char)invisibleA; + spaceAfter = (char)gFalse; + font = fontA; + fontSize = fontSizeA; + colorR = colorRA; + colorG = colorGA; + colorB = colorBA; + overlap = gFalse; +} + +int TextChar::cmpX(const void *p1, const void *p2) { + const TextChar *ch1 = *(const TextChar **)p1; + const TextChar *ch2 = *(const TextChar **)p2; + + if (ch1->xMin < ch2->xMin) { + return -1; + } else if (ch1->xMin > ch2->xMin) { + return 1; + } else { + return ch1->charPos - ch2->charPos; + } +} + +int TextChar::cmpY(const void *p1, const void *p2) { + const TextChar *ch1 = *(const TextChar **)p1; + const TextChar *ch2 = *(const TextChar **)p2; + + if (ch1->yMin < ch2->yMin) { + return -1; + } else if (ch1->yMin > ch2->yMin) { + return 1; + } else { + return ch1->charPos - ch2->charPos; + } +} + +int TextChar::cmpCharPos(const void *p1, const void *p2) { + const TextChar *ch1 = *(const TextChar **)p1; + const TextChar *ch2 = *(const TextChar **)p2; + return ch1->charPos - ch2->charPos; +} + +//------------------------------------------------------------------------ +// TextBlock +//------------------------------------------------------------------------ + +enum TextBlockType { + blkVertSplit, + blkHorizSplit, + blkLeaf +}; + +enum TextBlockTag { + blkTagMulticolumn, + blkTagColumn, + blkTagSuperLine, + blkTagLine +}; + +class TextBlock { +public: + + TextBlock(TextBlockType typeA, int rotA); + ~TextBlock(); + void addChild(TextBlock *child); + void addChild(TextChar *child, GBool updateBox); + void prependChild(TextChar *child); + void updateBounds(int childIdx); + + TextBlockType type; + TextBlockTag tag; + int rot; + double xMin, yMin, xMax, yMax; + GBool smallSplit; // true for blkVertSplit/blkHorizSplit + // where the gap size is small + GList *children; // for blkLeaf, children are TextWord; + // for others, children are TextBlock +}; + +TextBlock::TextBlock(TextBlockType typeA, int rotA) { + type = typeA; + tag = blkTagMulticolumn; + rot = rotA; + xMin = yMin = xMax = yMax = 0; + smallSplit = gFalse; + children = new GList(); +} + +TextBlock::~TextBlock() { + if (type == blkLeaf) { + delete children; + } else { + deleteGList(children, TextBlock); + } +} + +void TextBlock::addChild(TextBlock *child) { + if (children->getLength() == 0) { + xMin = child->xMin; + yMin = child->yMin; + xMax = child->xMax; + yMax = child->yMax; + } else { + if (child->xMin < xMin) { + xMin = child->xMin; + } + if (child->yMin < yMin) { + yMin = child->yMin; + } + if (child->xMax > xMax) { + xMax = child->xMax; + } + if (child->yMax > yMax) { + yMax = child->yMax; + } + } + children->append(child); +} + +void TextBlock::addChild(TextChar *child, GBool updateBox) { + if (updateBox) { + if (children->getLength() == 0) { + xMin = child->xMin; + yMin = child->yMin; + xMax = child->xMax; + yMax = child->yMax; + } else { + if (child->xMin < xMin) { + xMin = child->xMin; + } + if (child->yMin < yMin) { + yMin = child->yMin; + } + if (child->xMax > xMax) { + xMax = child->xMax; + } + if (child->yMax > yMax) { + yMax = child->yMax; + } + } + } + children->append(child); +} + +void TextBlock::prependChild(TextChar *child) { + if (children->getLength() == 0) { + xMin = child->xMin; + yMin = child->yMin; + xMax = child->xMax; + yMax = child->yMax; + } else { + if (child->xMin < xMin) { + xMin = child->xMin; + } + if (child->yMin < yMin) { + yMin = child->yMin; + } + if (child->xMax > xMax) { + xMax = child->xMax; + } + if (child->yMax > yMax) { + yMax = child->yMax; + } + } + children->insert(0, child); +} + +void TextBlock::updateBounds(int childIdx) { + TextBlock *child; + + child = (TextBlock *)children->get(childIdx); + if (child->xMin < xMin) { + xMin = child->xMin; + } + if (child->yMin < yMin) { + yMin = child->yMin; + } + if (child->xMax > xMax) { + xMax = child->xMax; + } + if (child->yMax > yMax) { + yMax = child->yMax; + } +} + +//------------------------------------------------------------------------ +// TextCharLine +//------------------------------------------------------------------------ + +class TextCharLine { +public: + + TextCharLine(int rotA); + ~TextCharLine(); + void add(TextChar *ch); + + GList *chars; + double yMin, yMax; + int rot; + TextCharLine *next, *prev; +}; + +TextCharLine::TextCharLine(int rotA) { + chars = new GList(); + yMin = yMax = 0; + rot = rotA; + next = prev = NULL; +} + +TextCharLine::~TextCharLine() { + delete chars; +} + +void TextCharLine::add(TextChar *ch) { + chars->append(ch); + yMin = ch->yMin; + yMax = ch->yMax; +} + +//------------------------------------------------------------------------ +// TextGaps +//------------------------------------------------------------------------ + +struct TextGap { + double x; // center of gap: x for vertical gaps, + // y for horizontal gaps + double w; // width/height of gap +}; + +class TextGaps { +public: + + TextGaps(); + ~TextGaps(); + void addGap(double x, double w); + int getLength() { return length; } + double getX(int idx) { return gaps[idx].x; } + double getW(int idx) { return gaps[idx].w; } + +private: + + int length; + int size; + TextGap *gaps; +}; + +TextGaps::TextGaps() { + length = 0; + size = 16; + gaps = (TextGap *)gmallocn(size, sizeof(TextGap)); +} + +TextGaps::~TextGaps() { + gfree(gaps); +} + +void TextGaps::addGap(double x, double w) { + if (length == size) { + size *= 2; + gaps = (TextGap *)greallocn(gaps, size, sizeof(TextGap)); + } + gaps[length].x = x; + gaps[length].w = w; + ++length; +} + +//------------------------------------------------------------------------ +// SplitLine +//------------------------------------------------------------------------ + +class SplitLine { +public: + + SplitLine(int firstCharIdxA, int lastCharIdxA, + double yMinA, double yMaxA); + ~SplitLine(); + + int firstCharIdx, lastCharIdx; + double yMin, yMax; // xMin, xMax if rot = {1,3} + GList *chars; // [TextChar] +}; + +SplitLine::SplitLine(int firstCharIdxA, int lastCharIdxA, + double yMinA, double yMaxA) { + firstCharIdx = firstCharIdxA; + lastCharIdx = lastCharIdxA; + yMin = yMinA; + yMax = yMaxA; + chars = NULL; +} + +SplitLine::~SplitLine() { + delete chars; +} + +//------------------------------------------------------------------------ +// TextSuperLine +//------------------------------------------------------------------------ + +class TextSuperLine { +public: + + TextSuperLine(GList *linesA); + ~TextSuperLine(); + + GList *lines; // [TextLine] + double yMin, yMax; + double fontSize; +}; + +TextSuperLine::TextSuperLine(GList *linesA) { + TextLine *line; + int i; + + lines = linesA; + yMin = yMax = 0; + fontSize = ((TextLine *)lines->get(0))->fontSize; + for (i = 0; i < lines->getLength(); ++i) { + line = (TextLine *)lines->get(i); + if (i == 0 || line->yMin < yMin) { + yMin = line->yMin; + } + if (i == 0 || line->yMax > yMax) { + yMax = line->yMax; + } + } +} + +TextSuperLine::~TextSuperLine() { + deleteGList(lines, TextLine); +} + +//------------------------------------------------------------------------ +// TextUnderline +//------------------------------------------------------------------------ + +class TextUnderline { +public: + + TextUnderline(double x0A, double y0A, double x1A, double y1A) + { x0 = x0A; y0 = y0A; x1 = x1A; y1 = y1A; horiz = y0 == y1; } + ~TextUnderline() {} + + double x0, y0, x1, y1; + GBool horiz; +}; + +//------------------------------------------------------------------------ +// TextLink +//------------------------------------------------------------------------ + +class TextLink { +public: + + TextLink(double xMinA, double yMinA, double xMaxA, double yMaxA, + GString *uriA) + { xMin = xMinA; yMin = yMinA; xMax = xMaxA; yMax = yMaxA; uri = uriA; } + ~TextLink(); + + double xMin, yMin, xMax, yMax; + GString *uri; +}; + +TextLink::~TextLink() { + if (uri) { + delete uri; + } +} + +//------------------------------------------------------------------------ +// TextOutputControl +//------------------------------------------------------------------------ + +TextOutputControl::TextOutputControl() { + mode = textOutReadingOrder; + fixedPitch = 0; + fixedLineSpacing = 0; + html = gFalse; + clipText = gFalse; + discardDiagonalText = gFalse; + discardRotatedText = gFalse; + discardInvisibleText = gFalse; + discardClippedText = gFalse; + splitRotatedWords = gFalse; + overlapHandling = textOutIgnoreOverlaps; + separateLargeChars = gTrue; + insertBOM = gFalse; + marginLeft = 0; + marginRight = 0; + marginTop = 0; + marginBottom = 0; +} + + +//------------------------------------------------------------------------ +// TextFontInfo +//------------------------------------------------------------------------ + +TextFontInfo::TextFontInfo(GfxState *state) { + GfxFont *gfxFont; + + gfxFont = state->getFont(); + if (gfxFont) { + fontID = *gfxFont->getID(); + ascent = gfxFont->getAscent(); + descent = gfxFont->getDescent(); + // "odd" ascent/descent values cause trouble more often than not + // (in theory these could be legitimate values for oddly designed + // fonts -- but they are more often due to buggy PDF generators) + // (values that are too small are a different issue -- those seem + // to be more commonly legitimate) + if (ascent > 1) { + ascent = 0.75; + } + if (descent < -0.5) { + descent = -0.25; + } + } else { + fontID.num = -1; + fontID.gen = -1; + ascent = 0.75; + descent = -0.25; + } + fontName = (gfxFont && gfxFont->getName()) ? gfxFont->getName()->copy() + : (GString *)NULL; + flags = gfxFont ? gfxFont->getFlags() : 0; + mWidth = 0; + if (gfxFont && !gfxFont->isCIDFont()) { + char *name; + int code; + for (code = 0; code < 256; ++code) { + if ((name = ((Gfx8BitFont *)gfxFont)->getCharName(code)) && + name[0] == 'm' && name[1] == '\0') { + mWidth = ((Gfx8BitFont *)gfxFont)->getWidth((Guchar)code); + break; + } + } + } +} + +TextFontInfo::TextFontInfo() { + fontID.num = -1; + fontID.gen = -1; + fontName = NULL; + flags = 0; + mWidth = 0; + ascent = 0; + descent = 0; +} + +TextFontInfo::~TextFontInfo() { + if (fontName) { + delete fontName; + } +} + +GBool TextFontInfo::matches(GfxState *state) { + Ref id; + + if (state->getFont()) { + id = *state->getFont()->getID(); + } else { + id.num = -1; + id.gen = -1; + } + return id.num == fontID.num && id.gen == fontID.gen; +} + +//------------------------------------------------------------------------ +// TextWord +//------------------------------------------------------------------------ + +// Build a TextWord object, using chars[start .. start+len-1]. +// (If rot >= 2, the chars list is in reverse order.) +TextWord::TextWord(GList *chars, int start, int lenA, + int rotA, GBool rotatedA, int dirA, GBool spaceAfterA) { + TextChar *ch; + int i; + + rot = (char)rotA; + rotated = (char)rotatedA; + len = lenA; + text = (Unicode *)gmallocn(len, sizeof(Unicode)); + edge = (double *)gmallocn(len + 1, sizeof(double)); + charPos = (int *)gmallocn(len + 1, sizeof(int)); + if (rot & 1) { + ch = (TextChar *)chars->get(start); + xMin = ch->xMin; + xMax = ch->xMax; + yMin = ch->yMin; + ch = (TextChar *)chars->get(start + len - 1); + yMax = ch->yMax; + } else { + ch = (TextChar *)chars->get(start); + xMin = ch->xMin; + yMin = ch->yMin; + yMax = ch->yMax; + ch = (TextChar *)chars->get(start + len - 1); + xMax = ch->xMax; + } + for (i = 0; i < len; ++i) { + ch = (TextChar *)chars->get(rot >= 2 ? start + len - 1 - i : start + i); + text[i] = ch->c; + charPos[i] = ch->charPos; + if (i == len - 1) { + charPos[len] = ch->charPos + ch->charLen; + } + switch (rot) { + case 0: + default: + edge[i] = ch->xMin; + if (i == len - 1) { + edge[len] = ch->xMax; + } + break; + case 1: + edge[i] = ch->yMin; + if (i == len - 1) { + edge[len] = ch->yMax; + } + break; + case 2: + edge[i] = ch->xMax; + if (i == len - 1) { + edge[len] = ch->xMin; + } + break; + case 3: + edge[i] = ch->yMax; + if (i == len - 1) { + edge[len] = ch->yMin; + } + break; + } + } + ch = (TextChar *)chars->get(start); + font = ch->font; + fontSize = ch->fontSize; + dir = (char)dirA; + spaceAfter = (char)spaceAfterA; + underlined = gFalse; + link = NULL; + colorR = ch->colorR; + colorG = ch->colorG; + colorB = ch->colorB; + invisible = ch->invisible; +} + +TextWord::TextWord(TextWord *word) { + *this = *word; + text = (Unicode *)gmallocn(len, sizeof(Unicode)); + memcpy(text, word->text, len * sizeof(Unicode)); + edge = (double *)gmallocn(len + 1, sizeof(double)); + memcpy(edge, word->edge, (len + 1) * sizeof(double)); + charPos = (int *)gmallocn(len + 1, sizeof(int)); + memcpy(charPos, word->charPos, (len + 1) * sizeof(int)); +} + +TextWord::~TextWord() { + gfree(text); + gfree(edge); + gfree(charPos); +} + +int TextWord::cmpYX(const void *p1, const void *p2) { + const TextWord *word1 = *(const TextWord **)p1; + const TextWord *word2 = *(const TextWord **)p2; + double cmp; + + if ((cmp = word1->yMin - word2->yMin) == 0) { + cmp = word1->xMin - word2->xMin; + } + return cmp < 0 ? -1 : cmp > 0 ? 1 : 0; +} + +int TextWord::cmpCharPos(const void *p1, const void *p2) { + const TextWord *word1 = *(const TextWord **)p1; + const TextWord *word2 = *(const TextWord **)p2; + + return word1->charPos[0] - word2->charPos[0]; +} + +GString *TextWord::getText() { + GString *s; + UnicodeMap *uMap; + char buf[8]; + int n, i; + + s = new GString(); + if (!(uMap = globalParams->getTextEncoding())) { + return s; + } + for (i = 0; i < len; ++i) { + n = uMap->mapUnicode(text[i], buf, sizeof(buf)); + s->append(buf, n); + } + uMap->decRefCnt(); + return s; +} + +void TextWord::getCharBBox(int charIdx, double *xMinA, double *yMinA, + double *xMaxA, double *yMaxA) { + if (charIdx < 0 || charIdx >= len) { + return; + } + switch (rot) { + case 0: + *xMinA = edge[charIdx]; + *xMaxA = edge[charIdx + 1]; + *yMinA = yMin; + *yMaxA = yMax; + break; + case 1: + *xMinA = xMin; + *xMaxA = xMax; + *yMinA = edge[charIdx]; + *yMaxA = edge[charIdx + 1]; + break; + case 2: + *xMinA = edge[charIdx + 1]; + *xMaxA = edge[charIdx]; + *yMinA = yMin; + *yMaxA = yMax; + break; + case 3: + *xMinA = xMin; + *xMaxA = xMax; + *yMinA = edge[charIdx + 1]; + *yMaxA = edge[charIdx]; + break; + } +} + +double TextWord::getBaseline() { + switch (rot) { + case 0: + default: + return yMax + fontSize * font->descent; + case 1: + return xMin - fontSize * font->descent; + case 2: + return yMin - fontSize * font->descent; + case 3: + return xMax + fontSize * font->descent; + } +} + +GString *TextWord::getLinkURI() { + return link ? link->uri : (GString *)NULL; +} + +//------------------------------------------------------------------------ +// TextLine +//------------------------------------------------------------------------ + +TextLine::TextLine(GList *wordsA, double xMinA, double yMinA, + double xMaxA, double yMaxA, double fontSizeA) { + TextWord *word; + int i, j, k; + + words = wordsA; + rot = 0; + xMin = xMinA; + yMin = yMinA; + xMax = xMaxA; + yMax = yMaxA; + fontSize = fontSizeA; + px = 0; + pw = 0; + + // build the text + len = 0; + for (i = 0; i < words->getLength(); ++i) { + word = (TextWord *)words->get(i); + len += word->len; + if (word->spaceAfter) { + ++len; + } + } + text = (Unicode *)gmallocn(len, sizeof(Unicode)); + edge = (double *)gmallocn(len + 1, sizeof(double)); + j = 0; + for (i = 0; i < words->getLength(); ++i) { + word = (TextWord *)words->get(i); + if (i == 0) { + rot = word->rot; + } + for (k = 0; k < word->len; ++k) { + text[j] = word->text[k]; + edge[j] = word->edge[k]; + ++j; + } + edge[j] = word->edge[word->len]; + if (word->spaceAfter) { + text[j] = (Unicode)0x0020; + ++j; + edge[j] = edge[j - 1]; + } + } + //~ need to check for other Unicode chars used as hyphens + hyphenated = text[len - 1] == (Unicode)'-'; +} + +TextLine::~TextLine() { + deleteGList(words, TextWord); + gfree(text); + gfree(edge); +} + +double TextLine::getBaseline() { + TextWord *word0; + + word0 = (TextWord *)words->get(0); + switch (rot) { + case 0: + default: + return yMax + fontSize * word0->font->descent; + case 1: + return xMin - fontSize * word0->font->descent; + case 2: + return yMin - fontSize * word0->font->descent; + case 3: + return xMax + fontSize * word0->font->descent; + } +} + +int TextLine::cmpX(const void *p1, const void *p2) { + const TextLine *line1 = *(const TextLine **)p1; + const TextLine *line2 = *(const TextLine **)p2; + + if (line1->xMin < line2->xMin) { + return -1; + } else if (line1->xMin > line2->xMin) { + return 1; + } else { + return 0; + } +} + +//------------------------------------------------------------------------ +// TextParagraph +//------------------------------------------------------------------------ + +TextParagraph::TextParagraph(GList *linesA, GBool dropCapA) { + TextLine *line; + int i; + + lines = linesA; + dropCap = dropCapA; + xMin = yMin = xMax = yMax = 0; + for (i = 0; i < lines->getLength(); ++i) { + line = (TextLine *)lines->get(i); + if (i == 0 || line->xMin < xMin) { + xMin = line->xMin; + } + if (i == 0 || line->yMin < yMin) { + yMin = line->yMin; + } + if (i == 0 || line->xMax > xMax) { + xMax = line->xMax; + } + if (i == 0 || line->yMax > yMax) { + yMax = line->yMax; + } + } +} + +TextParagraph::~TextParagraph() { + deleteGList(lines, TextLine); +} + +//------------------------------------------------------------------------ +// TextColumn +//------------------------------------------------------------------------ + +TextColumn::TextColumn(GList *paragraphsA, double xMinA, double yMinA, + double xMaxA, double yMaxA) { + paragraphs = paragraphsA; + xMin = xMinA; + yMin = yMinA; + xMax = xMaxA; + yMax = yMaxA; + px = py = 0; + pw = ph = 0; +} + +TextColumn::~TextColumn() { + deleteGList(paragraphs, TextParagraph); +} + +int TextColumn::getRotation() { + TextParagraph *par; + TextLine *line; + + par = (TextParagraph *)paragraphs->get(0); + line = (TextLine *)par->getLines()->get(0); + return line->getRotation(); +} + +int TextColumn::cmpX(const void *p1, const void *p2) { + const TextColumn *col1 = *(const TextColumn **)p1; + const TextColumn *col2 = *(const TextColumn **)p2; + + if (col1->xMin < col2->xMin) { + return -1; + } else if (col1->xMin > col2->xMin) { + return 1; + } else { + return 0; + } +} + +int TextColumn::cmpY(const void *p1, const void *p2) { + const TextColumn *col1 = *(const TextColumn **)p1; + const TextColumn *col2 = *(const TextColumn **)p2; + + if (col1->yMin < col2->yMin) { + return -1; + } else if (col1->yMin > col2->yMin) { + return 1; + } else { + return 0; + } +} + +int TextColumn::cmpPX(const void *p1, const void *p2) { + const TextColumn *col1 = *(const TextColumn **)p1; + const TextColumn *col2 = *(const TextColumn **)p2; + + if (col1->px < col2->px) { + return -1; + } else if (col1->px > col2->px) { + return 1; + } else { + return 0; + } +} + +//------------------------------------------------------------------------ +// TextWordList +//------------------------------------------------------------------------ + +TextWordList::TextWordList(GList *wordsA, GBool primaryLRA) { + words = wordsA; + primaryLR = primaryLRA; +} + +TextWordList::~TextWordList() { + deleteGList(words, TextWord); +} + +int TextWordList::getLength() { + return words->getLength(); +} + +TextWord *TextWordList::get(int idx) { + if (idx < 0 || idx >= words->getLength()) { + return NULL; + } + return (TextWord *)words->get(idx); +} + +//------------------------------------------------------------------------ +// TextPosition +//------------------------------------------------------------------------ + +int TextPosition::operator==(TextPosition pos) { + return colIdx == pos.colIdx && + parIdx == pos.parIdx && + lineIdx == pos.lineIdx && + charIdx == pos.charIdx; +} + +int TextPosition::operator!=(TextPosition pos) { + return colIdx != pos.colIdx || + parIdx != pos.parIdx || + lineIdx != pos.lineIdx || + charIdx != pos.charIdx; +} + +int TextPosition::operator<(TextPosition pos) { + return colIdx < pos.colIdx || + (colIdx == pos.colIdx && + (parIdx < pos.parIdx || + (parIdx == pos.parIdx && + (lineIdx < pos.lineIdx || + (lineIdx == pos.lineIdx && + charIdx < pos.charIdx))))); +} + +int TextPosition::operator>(TextPosition pos) { + return colIdx > pos.colIdx || + (colIdx == pos.colIdx && + (parIdx > pos.parIdx || + (parIdx == pos.parIdx && + (lineIdx > pos.lineIdx || + (lineIdx == pos.lineIdx && + charIdx > pos.charIdx))))); +} + +//------------------------------------------------------------------------ +// TextPage +//------------------------------------------------------------------------ + +TextPage::TextPage(TextOutputControl *controlA) { + control = *controlA; + remapping = globalParams->getUnicodeRemapping(); + uBufSize = 16; + uBuf = (Unicode *)gmallocn(uBufSize, sizeof(Unicode)); + pageWidth = pageHeight = 0; + charPos = 0; + curFont = NULL; + curFontSize = 0; + curRot = 0; + diagonal = gFalse; + rotated = gFalse; + nTinyChars = 0; + actualText = NULL; + actualTextLen = 0; + actualTextX0 = 0; + actualTextY0 = 0; + actualTextX1 = 0; + actualTextY1 = 0; + actualTextNBytes = 0; + + chars = new GList(); + fonts = new GList(); + + underlines = new GList(); + links = new GList(); + + findCols = NULL; + lastFindXMin = lastFindYMin = 0; + haveLastFind = gFalse; + + problematic = gFalse; +} + +TextPage::~TextPage() { + clear(); + deleteGList(chars, TextChar); + deleteGList(fonts, TextFontInfo); + deleteGList(underlines, TextUnderline); + deleteGList(links, TextLink); + if (findCols) { + deleteGList(findCols, TextColumn); + } + gfree(uBuf); +} + +void TextPage::startPage(GfxState *state) { + clear(); + if (state) { + pageWidth = state->getPageWidth(); + pageHeight = state->getPageHeight(); + } else { + pageWidth = pageHeight = 0; + } +} + +void TextPage::clear() { + pageWidth = pageHeight = 0; + charPos = 0; + curFont = NULL; + curFontSize = 0; + curRot = 0; + diagonal = gFalse; + rotated = gFalse; + nTinyChars = 0; + gfree(actualText); + actualText = NULL; + actualTextLen = 0; + actualTextNBytes = 0; + deleteGList(chars, TextChar); + chars = new GList(); + deleteGList(fonts, TextFontInfo); + fonts = new GList(); + deleteGList(underlines, TextUnderline); + underlines = new GList(); + deleteGList(links, TextLink); + links = new GList(); + + if (findCols) { + deleteGList(findCols, TextColumn); + findCols = NULL; + } + lastFindXMin = lastFindYMin = 0; + haveLastFind = gFalse; + + problematic = gFalse; +} + +void TextPage::updateFont(GfxState *state) { + GfxFont *gfxFont; + double *fm; + char *name; + int code, mCode, letterCode, anyCode; + double w; + double m[4], m2[4]; + int i; + + // get the font info object + curFont = NULL; + for (i = 0; i < fonts->getLength(); ++i) { + curFont = (TextFontInfo *)fonts->get(i); + if (curFont->matches(state)) { + break; + } + curFont = NULL; + } + if (!curFont) { + curFont = new TextFontInfo(state); + fonts->append(curFont); + if (state->getFont() && state->getFont()->problematicForUnicode()) { + problematic = gTrue; + } + } + + // adjust the font size + gfxFont = state->getFont(); + curFontSize = state->getTransformedFontSize(); + if (gfxFont && gfxFont->getType() == fontType3) { + // This is a hack which makes it possible to deal with some Type 3 + // fonts. The problem is that it's impossible to know what the + // base coordinate system used in the font is without actually + // rendering the font. This code tries to guess by looking at the + // width of the character 'm' (which breaks if the font is a + // subset that doesn't contain 'm'). + mCode = letterCode = anyCode = -1; + for (code = 0; code < 256; ++code) { + name = ((Gfx8BitFont *)gfxFont)->getCharName(code); + if (name && name[0] == 'm' && name[1] == '\0') { + mCode = code; + } + if (letterCode < 0 && + name && + ((name[0] >= 'A' && name[0] <= 'Z') || + (name[0] >= 'a' && name[0] <= 'z')) && + name[1] == '\0') { + letterCode = code; + } + if (anyCode < 0 && name && + ((Gfx8BitFont *)gfxFont)->getWidth((Guchar)code) > 0) { + anyCode = code; + } + } + if (mCode >= 0 && + (w = ((Gfx8BitFont *)gfxFont)->getWidth((Guchar)mCode)) > 0) { + // 0.6 is a generic average 'm' width -- yes, this is a hack + curFontSize *= w / 0.6; + } else if (letterCode >= 0 && + (w = ((Gfx8BitFont *)gfxFont)->getWidth((Guchar)letterCode)) + > 0) { + // even more of a hack: 0.5 is a generic letter width + curFontSize *= w / 0.5; + } else if (anyCode >= 0 && + (w = ((Gfx8BitFont *)gfxFont)->getWidth((Guchar)anyCode)) > 0) { + // better than nothing: 0.5 is a generic character width + curFontSize *= w / 0.5; + } + fm = gfxFont->getFontMatrix(); + if (fm[0] != 0) { + curFontSize *= fabs(fm[3] / fm[0]); + } + } + + // compute the rotation + state->getFontTransMat(&m[0], &m[1], &m[2], &m[3]); + if (gfxFont && gfxFont->getType() == fontType3) { + fm = gfxFont->getFontMatrix(); + m2[0] = fm[0] * m[0] + fm[1] * m[2]; + m2[1] = fm[0] * m[1] + fm[1] * m[3]; + m2[2] = fm[2] * m[0] + fm[3] * m[2]; + m2[3] = fm[2] * m[1] + fm[3] * m[3]; + m[0] = m2[0]; + m[1] = m2[1]; + m[2] = m2[2]; + m[3] = m2[3]; + } + if (curFontSize == 0) { + // special case - if the font size is zero, just assume plain + // horizontal text + curRot = 0; + diagonal = gFalse; + } else if (fabs(m[0]) >= fabs(m[1])) { + if (m[0] > 0) { + curRot = 0; + } else { + curRot = 2; + } + diagonal = fabs(m[1]) > diagonalThreshold * fabs(m[0]); + } else { + if (m[1] > 0) { + curRot = 1; + } else { + curRot = 3; + } + diagonal = fabs(m[0]) > diagonalThreshold * fabs(m[1]); + } + // this matches the 'horiz' test in SplashOutputDev::drawChar() + rotated = !(m[0] > 0 && fabs(m[1]) < 0.001 && + fabs(m[2]) < 0.001 && m[3] < 0); +} + +void TextPage::addChar(GfxState *state, double x, double y, + double dx, double dy, + CharCode c, int nBytes, Unicode *u, int uLen) { + double x1, y1, x2, y2, w1, h1, dx2, dy2, ascent, descent, sp; + double xMin, yMin, xMax, yMax, xMid, yMid; + double clipXMin, clipYMin, clipXMax, clipYMax; + GfxRGB rgb; + double alpha; + GBool clipped, rtl; + int uBufLen, i, j; + + // if we're in an ActualText span, save the position info (the + // ActualText chars will be added by TextPage::endActualText()). + if (actualText) { + if (!actualTextNBytes) { + actualTextX0 = x; + actualTextY0 = y; + } + actualTextX1 = x + dx; + actualTextY1 = y + dy; + actualTextNBytes += nBytes; + return; + } + + // throw away diagonal/rotated chars + if ((control.discardDiagonalText && diagonal) || + (control.discardRotatedText && rotated)) { + charPos += nBytes; + return; + } + + // subtract char and word spacing from the dx,dy values + sp = state->getCharSpace(); + if (c == (CharCode)0x20) { + sp += state->getWordSpace(); + } + state->textTransformDelta(sp * state->getHorizScaling(), 0, &dx2, &dy2); + dx -= dx2; + dy -= dy2; + state->transformDelta(dx, dy, &w1, &h1); + + // throw away chars that aren't inside the page bounds + // (and also do a sanity check on the character size) + state->transform(x, y, &x1, &y1); + if (x1 + w1 < control.marginLeft || + x1 > pageWidth - control.marginRight || + y1 + h1 < control.marginTop || + y1 > pageHeight - control.marginBottom || + w1 > pageWidth || + h1 > pageHeight) { + charPos += nBytes; + return; + } + + // check the tiny chars limit + if (!globalParams->getTextKeepTinyChars() && + fabs(w1) < 3 && fabs(h1) < 3) { + if (++nTinyChars > 50000) { + charPos += nBytes; + return; + } + } + + // skip various whitespace characters + // (ActualText spans can result in multiple space chars) + for (i = 0; i < uLen; ++i) { + if (u[i] != (Unicode)0x20 && + u[i] != (Unicode)0x09 && + u[i] != (Unicode)0x0a && + u[i] != (Unicode)0x0d && + u[i] != (Unicode)0xa0) { + break; + } + } + if (i == uLen && uLen >= 1) { + charPos += nBytes; + if (chars->getLength() > 0) { + ((TextChar *)chars->get(chars->getLength() - 1))->spaceAfter = + (char)gTrue; + } + return; + } + + // remap Unicode + uBufLen = 0; + for (i = 0; i < uLen; ++i) { + if (uBufSize - uBufLen < 8 && uBufSize < 20000) { + uBufSize *= 2; + uBuf = (Unicode *)greallocn(uBuf, uBufSize, sizeof(Unicode)); + } + uBufLen += remapping->map(u[i], uBuf + uBufLen, uBufSize - uBufLen); + } + + // add the characters + if (uBufLen > 0) { + + // handle right-to-left ligatures: if there are multiple Unicode + // characters, and they're all right-to-left, insert them in + // right-to-left order + if (uBufLen > 1) { + rtl = gTrue; + for (i = 0; i < uBufLen; ++i) { + if (!unicodeTypeR(uBuf[i])) { + rtl = gFalse; + break; + } + } + } else { + rtl = gFalse; + } + + // compute the bounding box + w1 /= uBufLen; + h1 /= uBufLen; + ascent = curFont->ascent * curFontSize; + descent = curFont->descent * curFontSize; + for (i = 0; i < uBufLen; ++i) { + x2 = x1 + i * w1; + y2 = y1 + i * h1; + switch (curRot) { + case 0: + default: + xMin = x2; + xMax = x2 + w1; + yMin = y2 - ascent; + yMax = y2 - descent; + break; + case 1: + xMin = x2 + descent; + xMax = x2 + ascent; + yMin = y2; + yMax = y2 + h1; + break; + case 2: + xMin = x2 + w1; + xMax = x2; + yMin = y2 + descent; + yMax = y2 + ascent; + break; + case 3: + xMin = x2 - ascent; + xMax = x2 - descent; + yMin = y2 + h1; + yMax = y2; + break; + } + + // check for clipping + clipped = gFalse; + if (control.clipText || control.discardClippedText) { + state->getClipBBox(&clipXMin, &clipYMin, &clipXMax, &clipYMax); + xMid = 0.5 * (xMin + xMax); + yMid = 0.5 * (yMin + yMax); + if (xMid < clipXMin || xMid > clipXMax || + yMid < clipYMin || yMid > clipYMax) { + clipped = gTrue; + } + } + + if ((state->getRender() & 3) == 1) { + state->getStrokeRGB(&rgb); + alpha = state->getStrokeOpacity(); + } else { + state->getFillRGB(&rgb); + alpha = state->getFillOpacity(); + } + if (rtl) { + j = uBufLen - 1 - i; + } else { + j = i; + } + chars->append(new TextChar(uBuf[j], charPos, nBytes, + xMin, yMin, xMax, yMax, + curRot, rotated, clipped, + state->getRender() == 3 || alpha < 0.001, + curFont, curFontSize, + colToDbl(rgb.r), colToDbl(rgb.g), + colToDbl(rgb.b))); + } + } + + charPos += nBytes; +} + +void TextPage::addSpecialChar(double xMin, double yMin, + double xMax, double yMax, + int rot, TextFontInfo *font, double fontSize, + Unicode u) { + chars->append(new TextChar(u, 0, 0, xMin, yMin, xMax, yMax, rot, + gFalse, gFalse, gFalse, font, fontSize, 0, 0, 0)); +} + +//~ this is inefficient -- consider using some sort of tree +//~ structure to store the chars (?) +void TextPage::removeChars(double xMin, double yMin, + double xMax, double yMax, + double xOverlapThresh, double yOverlapThresh) { + int i = 0; + while (i < chars->getLength()) { + TextChar *ch = (TextChar *)chars->get(i); + double xOverlap = (ch->xMax < xMax ? ch->xMax : xMax) + - (ch->xMin > xMin ? ch->xMin : xMin); + double yOverlap = (ch->yMax < yMax ? ch->yMax : yMax) + - (ch->yMin > yMin ? ch->yMin : yMin); + if (xOverlap > xOverlapThresh * (ch->xMax - ch->xMin) && + yOverlap > yOverlapThresh * (ch->yMax - ch->yMin)) { + chars->del(i); + delete ch; + } else { + ++i; + } + } +} + +void TextPage::incCharCount(int nChars) { + charPos += nChars; +} + +void TextPage::beginActualText(GfxState *state, Unicode *u, int uLen) { + if (actualText) { + gfree(actualText); + } + actualText = (Unicode *)gmallocn(uLen, sizeof(Unicode)); + memcpy(actualText, u, uLen * sizeof(Unicode)); + actualTextLen = uLen; + actualTextNBytes = 0; +} + +void TextPage::endActualText(GfxState *state) { + Unicode *u; + + u = actualText; + actualText = NULL; // so we can call TextPage::addChar() + if (actualTextNBytes) { + // now that we have the position info for all of the text inside + // the marked content span, we feed the "ActualText" back through + // addChar() + addChar(state, actualTextX0, actualTextY0, + actualTextX1 - actualTextX0, actualTextY1 - actualTextY0, + 0, actualTextNBytes, u, actualTextLen); + } + gfree(u); + actualText = NULL; + actualTextLen = 0; + actualTextNBytes = gFalse; +} + +void TextPage::addUnderline(double x0, double y0, double x1, double y1) { + underlines->append(new TextUnderline(x0, y0, x1, y1)); +} + +void TextPage::addLink(double xMin, double yMin, double xMax, double yMax, + Link *link) { + GString *uri; + + if (link && link->getAction() && link->getAction()->getKind() == actionURI) { + uri = ((LinkURI *)link->getAction())->getURI()->copy(); + links->append(new TextLink(xMin, yMin, xMax, yMax, uri)); + } +} + +//------------------------------------------------------------------------ +// TextPage: output +//------------------------------------------------------------------------ + +void TextPage::write(void *outputStream, TextOutputFunc outputFunc) { + UnicodeMap *uMap; + char space[8], eol[16], eop[8]; + int spaceLen, eolLen, eopLen; + GBool pageBreaks; + + // get the output encoding + if (!(uMap = globalParams->getTextEncoding())) { + return; + } + spaceLen = uMap->mapUnicode(0x20, space, sizeof(space)); + eolLen = 0; // make gcc happy + switch (globalParams->getTextEOL()) { + case eolUnix: + eolLen = uMap->mapUnicode(0x0a, eol, sizeof(eol)); + break; + case eolDOS: + eolLen = uMap->mapUnicode(0x0d, eol, sizeof(eol)); + eolLen += uMap->mapUnicode(0x0a, eol + eolLen, (int)sizeof(eol) - eolLen); + break; + case eolMac: + eolLen = uMap->mapUnicode(0x0d, eol, sizeof(eol)); + break; + } + eopLen = uMap->mapUnicode(0x0c, eop, sizeof(eop)); + pageBreaks = globalParams->getTextPageBreaks(); + + switch (control.mode) { + case textOutReadingOrder: + writeReadingOrder(outputStream, outputFunc, uMap, space, spaceLen, + eol, eolLen); + break; + case textOutPhysLayout: + case textOutTableLayout: + writePhysLayout(outputStream, outputFunc, uMap, space, spaceLen, + eol, eolLen); + break; + case textOutSimpleLayout: + writeSimpleLayout(outputStream, outputFunc, uMap, space, spaceLen, + eol, eolLen); + break; + case textOutSimple2Layout: + writeSimple2Layout(outputStream, outputFunc, uMap, space, spaceLen, + eol, eolLen); + break; + case textOutLinePrinter: + writeLinePrinter(outputStream, outputFunc, uMap, space, spaceLen, + eol, eolLen); + break; + case textOutRawOrder: + writeRaw(outputStream, outputFunc, uMap, space, spaceLen, + eol, eolLen); + break; + } + + // end of page + if (pageBreaks) { + (*outputFunc)(outputStream, eop, eopLen); + } + + uMap->decRefCnt(); +} + +void TextPage::writeReadingOrder(void *outputStream, + TextOutputFunc outputFunc, + UnicodeMap *uMap, + char *space, int spaceLen, + char *eol, int eolLen) { + TextBlock *tree; + TextColumn *col; + TextParagraph *par; + TextLine *line; + GList *overlappingChars; + GList *columns; + GBool primaryLR; + GString *s; + int colIdx, parIdx, lineIdx, rot, n; + +#if 0 //~debug + dumpChars(chars); +#endif + if (control.overlapHandling != textOutIgnoreOverlaps) { + overlappingChars = separateOverlappingText(chars); + } else { + overlappingChars = NULL; + } + rot = rotateChars(chars); + primaryLR = checkPrimaryLR(chars); + tree = splitChars(chars); +#if 0 //~debug + dumpTree(tree); +#endif + if (!tree) { + // no text + unrotateChars(chars, rot); + return; + } + columns = buildColumns(tree, primaryLR); + delete tree; + unrotateChars(chars, rot); + if (control.html) { + rotateUnderlinesAndLinks(rot); + generateUnderlinesAndLinks(columns); + } + if (overlappingChars) { + if (overlappingChars->getLength() > 0) { + columns->append(buildOverlappingTextColumn(overlappingChars)); + } + deleteGList(overlappingChars, TextChar); + } +#if 0 //~debug + dumpColumns(columns); +#endif + + for (colIdx = 0; colIdx < columns->getLength(); ++colIdx) { + col = (TextColumn *)columns->get(colIdx); + for (parIdx = 0; parIdx < col->paragraphs->getLength(); ++parIdx) { + par = (TextParagraph *)col->paragraphs->get(parIdx); + for (lineIdx = 0; lineIdx < par->lines->getLength(); ++lineIdx) { + line = (TextLine *)par->lines->get(lineIdx); + n = line->len; + if (line->hyphenated && lineIdx + 1 < par->lines->getLength()) { + --n; + } + s = new GString(); + encodeFragment(line->text, n, uMap, primaryLR, s); + if (lineIdx + 1 < par->lines->getLength() && !line->hyphenated) { + s->append(space, spaceLen); + } + (*outputFunc)(outputStream, s->getCString(), s->getLength()); + delete s; + } + (*outputFunc)(outputStream, eol, eolLen); + } + (*outputFunc)(outputStream, eol, eolLen); + } + + deleteGList(columns, TextColumn); +} + +GList *TextPage::makeColumns() { + TextBlock *tree; + GList *overlappingChars; + GList *columns; + GBool primaryLR; + int rot; + + if (control.mode == textOutSimple2Layout) { + primaryLR = checkPrimaryLR(chars); + rotateCharsToZero(chars); + columns = buildSimple2Columns(chars); + unrotateCharsFromZero(chars); + unrotateColumnsFromZero(columns); + } else { + if (control.overlapHandling != textOutIgnoreOverlaps) { + overlappingChars = separateOverlappingText(chars); + } else { + overlappingChars = NULL; + } + rot = rotateChars(chars); + primaryLR = checkPrimaryLR(chars); + if ((tree = splitChars(chars))) { + columns = buildColumns(tree, primaryLR); + delete tree; + } else { + // no text + columns = new GList(); + } + unrotateChars(chars, rot); + unrotateColumns(columns, rot); + if (control.html) { + generateUnderlinesAndLinks(columns); + } + if (overlappingChars) { + if (overlappingChars->getLength() > 0) { + columns->append(buildOverlappingTextColumn(overlappingChars)); + } + deleteGList(overlappingChars, TextChar); + } + } + return columns; +} + +// This handles both physical layout and table layout modes. +void TextPage::writePhysLayout(void *outputStream, + TextOutputFunc outputFunc, + UnicodeMap *uMap, + char *space, int spaceLen, + char *eol, int eolLen) { + TextBlock *tree; + GString **out; + int *outLen; + TextColumn *col; + TextParagraph *par; + TextLine *line; + GList *overlappingChars; + GList *columns; + GBool primaryLR; + int ph, colIdx, parIdx, lineIdx, rot, y, i; + +#if 0 //~debug + dumpChars(chars); +#endif +#if 0 //~debug + dumpUnderlines(); +#endif + if (control.overlapHandling != textOutIgnoreOverlaps) { + overlappingChars = separateOverlappingText(chars); + } else { + overlappingChars = NULL; + } + rot = rotateChars(chars); + primaryLR = checkPrimaryLR(chars); + tree = splitChars(chars); +#if 0 //~debug + dumpTree(tree); +#endif + if (!tree) { + // no text + unrotateChars(chars, rot); + return; + } + //~ this doesn't correctly handle the right-to-left case + columns = buildColumns(tree, gTrue); + delete tree; + unrotateChars(chars, rot); + if (control.html) { + rotateUnderlinesAndLinks(rot); + generateUnderlinesAndLinks(columns); + } + ph = assignPhysLayoutPositions(columns); +#if 0 //~debug + dumpColumns(columns); +#endif + + out = (GString **)gmallocn(ph, sizeof(GString *)); + outLen = (int *)gmallocn(ph, sizeof(int)); + for (i = 0; i < ph; ++i) { + out[i] = NULL; + outLen[i] = 0; + } + + columns->sort(&TextColumn::cmpPX); + for (colIdx = 0; colIdx < columns->getLength(); ++colIdx) { + col = (TextColumn *)columns->get(colIdx); + y = col->py; + for (parIdx = 0; + parIdx < col->paragraphs->getLength() && y < ph; + ++parIdx) { + par = (TextParagraph *)col->paragraphs->get(parIdx); + for (lineIdx = 0; + lineIdx < par->lines->getLength() && y < ph; + ++lineIdx) { + line = (TextLine *)par->lines->get(lineIdx); + if (!out[y]) { + out[y] = new GString(); + } + while (outLen[y] < col->px + line->px) { + out[y]->append(space, spaceLen); + ++outLen[y]; + } + encodeFragment(line->text, line->len, uMap, primaryLR, out[y]); + outLen[y] += line->pw; + ++y; + } + if (parIdx + 1 < col->paragraphs->getLength()) { + ++y; + } + } + } + + for (i = 0; i < ph; ++i) { + if (out[i]) { + (*outputFunc)(outputStream, out[i]->getCString(), out[i]->getLength()); + delete out[i]; + } + (*outputFunc)(outputStream, eol, eolLen); + } + + gfree(out); + gfree(outLen); + + deleteGList(columns, TextColumn); + + if (overlappingChars) { + if (overlappingChars->getLength() > 0) { + TextColumn *col = buildOverlappingTextColumn(overlappingChars); + (*outputFunc)(outputStream, eol, eolLen); + for (parIdx = 0; parIdx < col->paragraphs->getLength(); ++parIdx) { + par = (TextParagraph *)col->paragraphs->get(parIdx); + for (lineIdx = 0; lineIdx < par->lines->getLength(); ++lineIdx) { + line = (TextLine *)par->lines->get(lineIdx); + GString *s = new GString(); + encodeFragment(line->text, line->len, uMap, primaryLR, s); + s->append(eol, eolLen); + (*outputFunc)(outputStream, s->getCString(), s->getLength()); + delete s; + } + if (parIdx < col->paragraphs->getLength() - 1) { + (*outputFunc)(outputStream, eol, eolLen); + } + } + delete col; + } + deleteGList(overlappingChars, TextChar); + } +} + +void TextPage::writeSimpleLayout(void *outputStream, + TextOutputFunc outputFunc, + UnicodeMap *uMap, + char *space, int spaceLen, + char *eol, int eolLen) { + TextBlock *tree; + TextSuperLine *superLine0, *superLine1; + TextLine *line; + GList *superLines; + GString *out; + GBool primaryLR; + int rot, x, i, j; + +#if 0 //~debug + dumpChars(chars); +#endif + rot = rotateChars(chars); + primaryLR = checkPrimaryLR(chars); + tree = splitChars(chars); +#if 0 //~debug + dumpTree(tree); +#endif + if (!tree) { + // no text + unrotateChars(chars, rot); + return; + } + superLines = new GList(); + buildSuperLines(tree, superLines); + delete tree; + unrotateChars(chars, rot); + assignSimpleLayoutPositions(superLines, uMap); + + for (i = 0; i < superLines->getLength(); ++i) { + superLine0 = (TextSuperLine *)superLines->get(i); + out = new GString(); + x = 0; + for (j = 0; j < superLine0->lines->getLength(); ++j) { + line = (TextLine *)superLine0->lines->get(j); + while (x < line->px) { + out->append(space, spaceLen); + ++x; + } + encodeFragment(line->text, line->len, uMap, primaryLR, out); + x += line->pw; + } + (*outputFunc)(outputStream, out->getCString(), out->getLength()); + delete out; + (*outputFunc)(outputStream, eol, eolLen); + if (i + 1 < superLines->getLength()) { + superLine1 = (TextSuperLine *)superLines->get(i + 1); + if (superLine1->yMin - superLine0->yMax > 1.0 * superLine0->fontSize) { + (*outputFunc)(outputStream, eol, eolLen); + } + } + } + + deleteGList(superLines, TextSuperLine); +} + +void TextPage::writeSimple2Layout(void *outputStream, + TextOutputFunc outputFunc, + UnicodeMap *uMap, + char *space, int spaceLen, + char *eol, int eolLen) { + GList *columns; + TextColumn *col; + TextParagraph *par; + TextLine *line; + GString *out; + GBool primaryLR; + int colIdx, parIdx, lineIdx; + + primaryLR = checkPrimaryLR(chars); + rotateCharsToZero(chars); +#if 0 //~debug + dumpChars(chars); +#endif + columns = buildSimple2Columns(chars); + unrotateCharsFromZero(chars); + unrotateColumnsFromZero(columns); + + for (colIdx = 0; colIdx < columns->getLength(); ++colIdx) { + col = (TextColumn *)columns->get(colIdx); + for (parIdx = 0; parIdx < col->paragraphs->getLength(); ++parIdx) { + par = (TextParagraph *)col->paragraphs->get(parIdx); + for (lineIdx = 0; lineIdx < par->lines->getLength(); ++lineIdx) { + line = (TextLine *)par->lines->get(lineIdx); + out = new GString(); + encodeFragment(line->text, line->len, uMap, primaryLR, out); + (*outputFunc)(outputStream, out->getCString(), out->getLength()); + delete out; + (*outputFunc)(outputStream, eol, eolLen); + } + } + } + + deleteGList(columns, TextColumn); +} + +void TextPage::writeLinePrinter(void *outputStream, + TextOutputFunc outputFunc, + UnicodeMap *uMap, + char *space, int spaceLen, + char *eol, int eolLen) { + TextChar *ch, *ch2; + GList *line; + GString *s; + char buf[8]; + double pitch, lineSpacing, delta; + double yMin0, yShift, xMin0, xShift; + double y, x; + int rot, n, i, j, k; + + rot = rotateChars(chars); + chars->sort(&TextChar::cmpX); + // don't call removeDuplicates here, because it expects to be + // working on a secondary list that doesn't own the TextChar objects + chars->sort(&TextChar::cmpY); + + // get character pitch + if (control.fixedPitch > 0) { + pitch = control.fixedPitch; + } else { + // compute (approximate) character pitch + pitch = pageWidth; + for (i = 0; i < chars->getLength(); ++i) { + ch = (TextChar *)chars->get(i); + for (j = i + 1; j < chars->getLength(); ++j) { + ch2 = (TextChar *)chars->get(j); + if (ch2->yMin + ascentAdjustFactor * (ch2->yMax - ch2->yMin) < + ch->yMax - descentAdjustFactor * (ch->yMax - ch->yMin) && + ch->yMin + ascentAdjustFactor * (ch->yMax - ch->yMin) < + ch2->yMax - descentAdjustFactor * (ch2->yMax - ch2->yMin)) { + delta = fabs(ch2->xMin - ch->xMin); + if (delta > 0.01 && delta < pitch) { + pitch = delta; + } + } + } + } + } + + // get line spacing + if (control.fixedLineSpacing > 0) { + lineSpacing = control.fixedLineSpacing; + } else { + // compute (approximate) line spacing + lineSpacing = pageHeight; + i = 0; + while (i < chars->getLength()) { + ch = (TextChar *)chars->get(i); + // look for the first char that does not (substantially) + // vertically overlap this one + delta = 0; + for (++i; delta == 0 && i < chars->getLength(); ++i) { + ch2 = (TextChar *)chars->get(i); + if (ch2->yMin + ascentAdjustFactor * (ch2->yMax - ch2->yMin) > + ch->yMax - descentAdjustFactor * (ch->yMax - ch->yMin)) { + delta = ch2->yMin - ch->yMin; + } + } + if (delta > 0 && delta < lineSpacing) { + lineSpacing = delta; + } + } + } + + // shift the grid to avoid problems with floating point accuracy -- + // for fixed line spacing, this avoids problems with + // dropping/inserting blank lines + if (chars->getLength()) { + yMin0 = ((TextChar *)chars->get(0))->yMin; + yShift = yMin0 - (int)(yMin0 / lineSpacing + 0.5) * lineSpacing + - 0.5 * lineSpacing; + } else { + yShift = 0; + } + + // for each line... + i = 0; + j = chars->getLength() - 1; + for (y = yShift; y < pageHeight; y += lineSpacing) { + + // get the characters in this line + line = new GList; + while (i < chars->getLength() && + ((TextChar *)chars->get(i))->yMin < y + lineSpacing) { + line->append(chars->get(i++)); + } + line->sort(&TextChar::cmpX); + + // shift the grid to avoid problems with floating point accuracy + // -- for fixed char spacing, this avoids problems with + // dropping/inserting spaces + if (line->getLength()) { + xMin0 = ((TextChar *)line->get(0))->xMin; + xShift = xMin0 - (int)(xMin0 / pitch + 0.5) * pitch - 0.5 * pitch; + } else { + xShift = 0; + } + + // write the line + s = new GString(); + x = xShift; + k = 0; + while (k < line->getLength()) { + ch = (TextChar *)line->get(k); + if (ch->xMin < x + pitch) { + n = uMap->mapUnicode(ch->c, buf, sizeof(buf)); + s->append(buf, n); + ++k; + } else { + s->append(space, spaceLen); + n = spaceLen; + } + x += (uMap->isUnicode() ? 1 : n) * pitch; + } + s->append(eol, eolLen); + (*outputFunc)(outputStream, s->getCString(), s->getLength()); + delete s; + delete line; + } + + unrotateChars(chars, rot); +} + +void TextPage::writeRaw(void *outputStream, + TextOutputFunc outputFunc, + UnicodeMap *uMap, + char *space, int spaceLen, + char *eol, int eolLen) { + TextChar *ch, *ch2; + GString *s; + char buf[8]; + int n, i; + + s = new GString(); + + for (i = 0; i < chars->getLength(); ++i) { + + // process one char + ch = (TextChar *)chars->get(i); + n = uMap->mapUnicode(ch->c, buf, sizeof(buf)); + s->append(buf, n); + + // check for space or eol + if (i+1 < chars->getLength()) { + ch2 = (TextChar *)chars->get(i+1); + if (ch2->rot != ch->rot) { + s->append(eol, eolLen); + } else { + switch (ch->rot) { + case 0: + default: + if (fabs(ch2->yMin - ch->yMin) > rawModeLineDelta * ch->fontSize || + ch2->xMin - ch->xMax < -rawModeCharOverlap * ch->fontSize) { + s->append(eol, eolLen); + } else if (ch->spaceAfter || + ch2->xMin - ch->xMax > + rawModeWordSpacing * ch->fontSize) { + s->append(space, spaceLen); + } + break; + case 1: + if (fabs(ch->xMax - ch2->xMax) > rawModeLineDelta * ch->fontSize || + ch2->yMin - ch->yMax < -rawModeCharOverlap * ch->fontSize) { + s->append(eol, eolLen); + } else if (ch->spaceAfter || + ch2->yMin - ch->yMax > + rawModeWordSpacing * ch->fontSize) { + s->append(space, spaceLen); + } + break; + case 2: + if (fabs(ch->yMax - ch2->yMax) > rawModeLineDelta * ch->fontSize || + ch->xMin - ch2->xMax < -rawModeCharOverlap * ch->fontSize) { + s->append(eol, eolLen); + } else if (ch->spaceAfter || + ch->xMin - ch2->xMax > + rawModeWordSpacing * ch->fontSize) { + s->append(space, spaceLen); + } + break; + case 3: + if (fabs(ch2->xMin - ch->xMin) > rawModeLineDelta * ch->fontSize || + ch->yMin - ch2->yMax < -rawModeCharOverlap * ch->fontSize) { + s->append(eol, eolLen); + } else if (ch->spaceAfter || + ch->yMin - ch2->yMax > + rawModeWordSpacing * ch->fontSize) { + s->append(space, spaceLen); + } + break; + } + } + } else { + s->append(eol, eolLen); + } + + if (s->getLength() > 1000) { + (*outputFunc)(outputStream, s->getCString(), s->getLength()); + s->clear(); + } + } + + if (s->getLength() > 0) { + (*outputFunc)(outputStream, s->getCString(), s->getLength()); + } + delete s; +} + +void TextPage::encodeFragment(Unicode *text, int len, UnicodeMap *uMap, + GBool primaryLR, GString *s) { + char lre[8], rle[8], popdf[8], buf[8]; + GBool open; + Unicode opposite; + int lreLen, rleLen, popdfLen, n; + int i, j, k; + + if (uMap->isUnicode()) { + + lreLen = uMap->mapUnicode(0x202a, lre, sizeof(lre)); + rleLen = uMap->mapUnicode(0x202b, rle, sizeof(rle)); + popdfLen = uMap->mapUnicode(0x202c, popdf, sizeof(popdf)); + + if (primaryLR) { + + i = 0; + while (i < len) { + // output a left-to-right section + for (j = i; + j < len && !unicodeEffectiveTypeR(text[j], + j > 0 ? text[j-1] : 0, + j < len-1 ? text[j+1] : 0); + ++j) ; + for (k = i; k < j; ++k) { + n = uMap->mapUnicode(text[k], buf, sizeof(buf)); + s->append(buf, n); + } + i = j; + // output a right-to-left section + for (j = i; + j < len && !unicodeEffectiveTypeLOrNum(text[j], + j > 0 ? text[j-1] : 0, + j < len-1 ? text[j+1] : 0); + ++j) ; + if (j > i) { + s->append(rle, rleLen); + for (k = j - 1; k >= i; --k) { + if (unicodeBracketInfo(text[k], &open, &opposite)) { + n = uMap->mapUnicode(opposite, buf, sizeof(buf)); + } else { + n = uMap->mapUnicode(text[k], buf, sizeof(buf)); + } + s->append(buf, n); + } + s->append(popdf, popdfLen); + i = j; + } + } + + } else { // !primaryLR + + s->append(rle, rleLen); + i = len - 1; + while (i >= 0) { + // output a right-to-left section + for (j = i; + j >= 0 && !unicodeEffectiveTypeLOrNum(text[j], + j > 0 ? text[j-1] : 0, + j < len-1 ? text[j+1] : 0); + --j) ; + for (k = i; k > j; --k) { + if (unicodeBracketInfo(text[k], &open, &opposite)) { + n = uMap->mapUnicode(opposite, buf, sizeof(buf)); + } else { + n = uMap->mapUnicode(text[k], buf, sizeof(buf)); + } + s->append(buf, n); + } + i = j; + // output a left-to-right section + for (j = i; + j >= 0 && !unicodeEffectiveTypeR(text[j], + j > 0 ? text[j-1] : 0, + j < len-1 ? text[j+1] : 0); + --j) ; + if (j < i) { + s->append(lre, lreLen); + for (k = j + 1; k <= i; ++k) { + n = uMap->mapUnicode(text[k], buf, sizeof(buf)); + s->append(buf, n); + } + s->append(popdf, popdfLen); + i = j; + } + } + s->append(popdf, popdfLen); + } + + } else { + for (i = 0; i < len; ++i) { + n = uMap->mapUnicode(text[i], buf, sizeof(buf)); + s->append(buf, n); + } + } +} + +// Returns true if [u] is LTR, in the context of [left]-[u]-[right]. +// NB: returns false if [u] is neutral. +GBool TextPage::unicodeEffectiveTypeLOrNum(Unicode u, Unicode left, + Unicode right) { + GBool open; + Unicode opposite; + if (unicodeBracketInfo(u, &open, &opposite)) { + // bracket takes the direction of the first char inside the bracket + if (open) { + return unicodeTypeL(right) || unicodeTypeNum(right); + } else { + return unicodeTypeL(left) || unicodeTypeNum(left); + } + } else if (unicodeTypeNumSep(u)) { + // numeric separator is numeric if either side is a digit; neutral + // otherwise + return unicodeTypeDigit(left) || unicodeTypeDigit(right); + } else { + return unicodeTypeL(u) || unicodeTypeDigit(u); + } +} + +// Returns true if [u] is RTL, in the context of [left]-[u]-[right]. +// NB: returns false if [u] is neutral. +GBool TextPage::unicodeEffectiveTypeR(Unicode u, Unicode left, Unicode right) { + GBool open; + Unicode opposite; + if (unicodeBracketInfo(u, &open, &opposite)) { + // bracket takes the direction of the first char inside the bracket + if (open) { + return unicodeTypeR(right); + } else { + return unicodeTypeR(left); + } + } else { + return unicodeTypeR(u); + } +} + +//------------------------------------------------------------------------ +// TextPage: layout analysis +//------------------------------------------------------------------------ + +// Determine primary (most common) rotation value. Rotate all chars +// to that primary rotation. +int TextPage::rotateChars(GList *charsA) { + TextChar *ch; + int nChars[4]; + double xMin, yMin, xMax, yMax, t; + int rot, i; + + // determine primary rotation + nChars[0] = nChars[1] = nChars[2] = nChars[3] = 0; + for (i = 0; i < charsA->getLength(); ++i) { + ch = (TextChar *)charsA->get(i); + ++nChars[ch->rot]; + } + rot = 0; + for (i = 1; i < 4; ++i) { + if (nChars[i] > nChars[rot]) { + rot = i; + } + } + + // rotate + switch (rot) { + case 0: + default: + break; + case 1: + for (i = 0; i < charsA->getLength(); ++i) { + ch = (TextChar *)charsA->get(i); + xMin = ch->yMin; + xMax = ch->yMax; + yMin = pageWidth - ch->xMax; + yMax = pageWidth - ch->xMin; + ch->xMin = xMin; + ch->xMax = xMax; + ch->yMin = yMin; + ch->yMax = yMax; + ch->rot = (ch->rot + 3) & 3; + } + t = pageWidth; + pageWidth = pageHeight; + pageHeight = t; + break; + case 2: + for (i = 0; i < charsA->getLength(); ++i) { + ch = (TextChar *)charsA->get(i); + xMin = pageWidth - ch->xMax; + xMax = pageWidth - ch->xMin; + yMin = pageHeight - ch->yMax; + yMax = pageHeight - ch->yMin; + ch->xMin = xMin; + ch->xMax = xMax; + ch->yMin = yMin; + ch->yMax = yMax; + ch->rot = (ch->rot + 2) & 3; + } + break; + case 3: + for (i = 0; i < charsA->getLength(); ++i) { + ch = (TextChar *)charsA->get(i); + xMin = pageHeight - ch->yMax; + xMax = pageHeight - ch->yMin; + yMin = ch->xMin; + yMax = ch->xMax; + ch->xMin = xMin; + ch->xMax = xMax; + ch->yMin = yMin; + ch->yMax = yMax; + ch->rot = (ch->rot + 1) & 3; + } + t = pageWidth; + pageWidth = pageHeight; + pageHeight = t; + break; + } + + return rot; +} + +// Rotate all chars to zero rotation. This leaves the TextChar.rot +// fields unchanged. +void TextPage::rotateCharsToZero(GList *charsA) { + TextChar *ch; + double xMin, yMin, xMax, yMax; + int i; + + for (i = 0; i < charsA->getLength(); ++i) { + ch = (TextChar *)charsA->get(i); + switch (ch->rot) { + case 0: + default: + break; + case 1: + xMin = ch->yMin; + xMax = ch->yMax; + yMin = pageWidth - ch->xMax; + yMax = pageWidth - ch->xMin; + ch->xMin = xMin; + ch->xMax = xMax; + ch->yMin = yMin; + ch->yMax = yMax; + break; + case 2: + xMin = pageWidth - ch->xMax; + xMax = pageWidth - ch->xMin; + yMin = pageHeight - ch->yMax; + yMax = pageHeight - ch->yMin; + ch->xMin = xMin; + ch->xMax = xMax; + ch->yMin = yMin; + ch->yMax = yMax; + break; + case 3: + xMin = pageHeight - ch->yMax; + xMax = pageHeight - ch->yMin; + yMin = ch->xMin; + yMax = ch->xMax; + ch->xMin = xMin; + ch->xMax = xMax; + ch->yMin = yMin; + ch->yMax = yMax; + break; + } + } +} + +// Rotate the TextUnderlines and TextLinks to match the transform +// performed by rotateChars(). +void TextPage::rotateUnderlinesAndLinks(int rot) { + TextUnderline *underline; + TextLink *link; + double xMin, yMin, xMax, yMax; + int i; + + switch (rot) { + case 0: + default: + break; + case 1: + for (i = 0; i < underlines->getLength(); ++i) { + underline = (TextUnderline *)underlines->get(i); + xMin = underline->y0; + xMax = underline->y1; + yMin = pageWidth - underline->x1; + yMax = pageWidth - underline->x0; + underline->x0 = xMin; + underline->x1 = xMax; + underline->y0 = yMin; + underline->y1 = yMax; + underline->horiz = !underline->horiz; + } + for (i = 0; i < links->getLength(); ++i) { + link = (TextLink *)links->get(i); + xMin = link->yMin; + xMax = link->yMax; + yMin = pageWidth - link->xMax; + yMax = pageWidth - link->xMin; + link->xMin = xMin; + link->xMax = xMax; + link->yMin = yMin; + link->yMax = yMax; + } + break; + case 2: + for (i = 0; i < underlines->getLength(); ++i) { + underline = (TextUnderline *)underlines->get(i); + xMin = pageWidth - underline->x1; + xMax = pageWidth - underline->x0; + yMin = pageHeight - underline->y1; + yMax = pageHeight - underline->y0; + underline->x0 = xMin; + underline->x1 = xMax; + underline->y0 = yMin; + underline->y1 = yMax; + } + for (i = 0; i < links->getLength(); ++i) { + link = (TextLink *)links->get(i); + xMin = pageWidth - link->xMax; + xMax = pageWidth - link->xMin; + yMin = pageHeight - link->yMax; + yMax = pageHeight - link->yMin; + link->xMin = xMin; + link->xMax = xMax; + link->yMin = yMin; + link->yMax = yMax; + } + break; + case 3: + for (i = 0; i < underlines->getLength(); ++i) { + underline = (TextUnderline *)underlines->get(i); + xMin = pageHeight - underline->y1; + xMax = pageHeight - underline->y0; + yMin = underline->x0; + yMax = underline->x1; + underline->x0 = xMin; + underline->x1 = xMax; + underline->y0 = yMin; + underline->y1 = yMax; + underline->horiz = !underline->horiz; + } + for (i = 0; i < links->getLength(); ++i) { + link = (TextLink *)links->get(i); + xMin = pageHeight - link->yMax; + xMax = pageHeight - link->yMin; + yMin = link->xMin; + yMax = link->xMax; + link->xMin = xMin; + link->xMax = xMax; + link->yMin = yMin; + link->yMax = yMax; + } + break; + } +} + +// Undo the coordinate transform performed by rotateChars(). +void TextPage::unrotateChars(GList *charsA, int rot) { + TextChar *ch; + double xMin, yMin, xMax, yMax, t; + int i; + + switch (rot) { + case 0: + default: + // no transform + break; + case 1: + t = pageWidth; + pageWidth = pageHeight; + pageHeight = t; + for (i = 0; i < charsA->getLength(); ++i) { + ch = (TextChar *)charsA->get(i); + xMin = pageWidth - ch->yMax; + xMax = pageWidth - ch->yMin; + yMin = ch->xMin; + yMax = ch->xMax; + ch->xMin = xMin; + ch->xMax = xMax; + ch->yMin = yMin; + ch->yMax = yMax; + ch->rot = (ch->rot + 1) & 3; + } + break; + case 2: + for (i = 0; i < charsA->getLength(); ++i) { + ch = (TextChar *)charsA->get(i); + xMin = pageWidth - ch->xMax; + xMax = pageWidth - ch->xMin; + yMin = pageHeight - ch->yMax; + yMax = pageHeight - ch->yMin; + ch->xMin = xMin; + ch->xMax = xMax; + ch->yMin = yMin; + ch->yMax = yMax; + ch->rot = (ch->rot + 2) & 3; + } + break; + case 3: + t = pageWidth; + pageWidth = pageHeight; + pageHeight = t; + for (i = 0; i < charsA->getLength(); ++i) { + ch = (TextChar *)charsA->get(i); + xMin = ch->yMin; + xMax = ch->yMax; + yMin = pageHeight - ch->xMax; + yMax = pageHeight - ch->xMin; + ch->xMin = xMin; + ch->xMax = xMax; + ch->yMin = yMin; + ch->yMax = yMax; + ch->rot = (ch->rot + 3) & 3; + } + break; + } +} + +// Undo the coordinate transform performed by rotateCharsToZero(). +void TextPage::unrotateCharsFromZero(GList *charsA) { + TextChar *ch; + double xMin, yMin, xMax, yMax; + int i; + + for (i = 0; i < charsA->getLength(); ++i) { + ch = (TextChar *)charsA->get(i); + switch (ch->rot) { + case 0: + default: + break; + case 1: + xMin = pageWidth - ch->yMax; + xMax = pageWidth - ch->yMin; + yMin = ch->xMin; + yMax = ch->xMax; + ch->xMin = xMin; + ch->xMax = xMax; + ch->yMin = yMin; + ch->yMax = yMax; + break; + case 2: + xMin = pageWidth - ch->xMax; + xMax = pageWidth - ch->xMin; + yMin = pageHeight - ch->yMax; + yMax = pageHeight - ch->yMin; + ch->xMin = xMin; + ch->xMax = xMax; + ch->yMin = yMin; + ch->yMax = yMax; + break; + case 3: + xMin = ch->yMin; + xMax = ch->yMax; + yMin = pageHeight - ch->xMax; + yMax = pageHeight - ch->xMin; + ch->xMin = xMin; + ch->xMax = xMax; + ch->yMin = yMin; + ch->yMax = yMax; + break; + } + } +} + +// Undo the coordinate transform performed by rotateCharsToZero(). +void TextPage::unrotateColumnsFromZero(GList *columns) { + TextColumn *col; + TextParagraph *par; + TextLine *line; + TextWord *word; + double xMin, yMin, xMax, yMax; + int colIdx, parIdx, lineIdx, wordIdx, i; + + for (colIdx = 0; colIdx < columns->getLength(); ++colIdx) { + col = (TextColumn *)columns->get(colIdx); + switch (col->getRotation()) { + case 0: + default: + break; + case 1: + xMin = pageWidth - col->yMax; + xMax = pageWidth - col->yMin; + yMin = col->xMin; + yMax = col->xMax; + col->xMin = xMin; + col->xMax = xMax; + col->yMin = yMin; + col->yMax = yMax; + for (parIdx = 0; + parIdx < col->paragraphs->getLength(); + ++parIdx) { + par = (TextParagraph *)col->paragraphs->get(parIdx); + xMin = pageWidth - par->yMax; + xMax = pageWidth - par->yMin; + yMin = par->xMin; + yMax = par->xMax; + par->xMin = xMin; + par->xMax = xMax; + par->yMin = yMin; + par->yMax = yMax; + for (lineIdx = 0; + lineIdx < par->lines->getLength(); + ++lineIdx) { + line = (TextLine *)par->lines->get(lineIdx); + xMin = pageWidth - line->yMax; + xMax = pageWidth - line->yMin; + yMin = line->xMin; + yMax = line->xMax; + line->xMin = xMin; + line->xMax = xMax; + line->yMin = yMin; + line->yMax = yMax; + for (wordIdx = 0; wordIdx < line->words->getLength(); ++wordIdx) { + word = (TextWord *)line->words->get(wordIdx); + xMin = pageWidth - word->yMax; + xMax = pageWidth - word->yMin; + yMin = word->xMin; + yMax = word->xMax; + word->xMin = xMin; + word->xMax = xMax; + word->yMin = yMin; + word->yMax = yMax; + } + } + } + break; + case 2: + xMin = pageWidth - col->xMax; + xMax = pageWidth - col->xMin; + yMin = pageHeight - col->yMax; + yMax = pageHeight - col->yMin; + col->xMin = xMin; + col->xMax = xMax; + col->yMin = yMin; + col->yMax = yMax; + for (parIdx = 0; + parIdx < col->paragraphs->getLength(); + ++parIdx) { + par = (TextParagraph *)col->paragraphs->get(parIdx); + xMin = pageWidth - par->xMax; + xMax = pageWidth - par->xMin; + yMin = pageHeight - par->yMax; + yMax = pageHeight - par->yMin; + par->xMin = xMin; + par->xMax = xMax; + par->yMin = yMin; + par->yMax = yMax; + for (lineIdx = 0; + lineIdx < par->lines->getLength(); + ++lineIdx) { + line = (TextLine *)par->lines->get(lineIdx); + xMin = pageWidth - line->xMax; + xMax = pageWidth - line->xMin; + yMin = pageHeight - line->yMax; + yMax = pageHeight - line->yMin; + line->xMin = xMin; + line->xMax = xMax; + line->yMin = yMin; + line->yMax = yMax; + for (i = 0; i <= line->len; ++i) { + line->edge[i] = pageWidth - line->edge[i]; + } + for (wordIdx = 0; wordIdx < line->words->getLength(); ++wordIdx) { + word = (TextWord *)line->words->get(wordIdx); + xMin = pageWidth - word->xMax; + xMax = pageWidth - word->xMin; + yMin = pageHeight - word->yMax; + yMax = pageHeight - word->yMin; + word->xMin = xMin; + word->xMax = xMax; + word->yMin = yMin; + word->yMax = yMax; + for (i = 0; i <= word->len; ++i) { + word->edge[i] = pageWidth - word->edge[i]; + } + } + } + } + break; + case 3: + xMin = col->yMin; + xMax = col->yMax; + yMin = pageHeight - col->xMax; + yMax = pageHeight - col->xMin; + col->xMin = xMin; + col->xMax = xMax; + col->yMin = yMin; + col->yMax = yMax; + for (parIdx = 0; + parIdx < col->paragraphs->getLength(); + ++parIdx) { + par = (TextParagraph *)col->paragraphs->get(parIdx); + xMin = par->yMin; + xMax = par->yMax; + yMin = pageHeight - par->xMax; + yMax = pageHeight - par->xMin; + par->xMin = xMin; + par->xMax = xMax; + par->yMin = yMin; + par->yMax = yMax; + for (lineIdx = 0; + lineIdx < par->lines->getLength(); + ++lineIdx) { + line = (TextLine *)par->lines->get(lineIdx); + xMin = line->yMin; + xMax = line->yMax; + yMin = pageHeight - line->xMax; + yMax = pageHeight - line->xMin; + line->xMin = xMin; + line->xMax = xMax; + line->yMin = yMin; + line->yMax = yMax; + for (i = 0; i <= line->len; ++i) { + line->edge[i] = pageHeight - line->edge[i]; + } + for (wordIdx = 0; wordIdx < line->words->getLength(); ++wordIdx) { + word = (TextWord *)line->words->get(wordIdx); + xMin = word->yMin; + xMax = word->yMax; + yMin = pageHeight - word->xMax; + yMax = pageHeight - word->xMin; + word->xMin = xMin; + word->xMax = xMax; + word->yMin = yMin; + word->yMax = yMax; + for (i = 0; i <= word->len; ++i) { + word->edge[i] = pageHeight - word->edge[i]; + } + } + } + } + break; + } + } +} + +// Undo the coordinate transform performed by rotateChars(). +void TextPage::unrotateColumns(GList *columns, int rot) { + TextColumn *col; + TextParagraph *par; + TextLine *line; + TextWord *word; + double xMin, yMin, xMax, yMax; + int colIdx, parIdx, lineIdx, wordIdx, i; + + switch (rot) { + case 0: + default: + // no transform + break; + case 1: + // NB: this is called after unrotateChars(), which will have + // swapped pageWidth and pageHeight already. + for (colIdx = 0; colIdx < columns->getLength(); ++colIdx) { + col = (TextColumn *)columns->get(colIdx); + xMin = pageWidth - col->yMax; + xMax = pageWidth - col->yMin; + yMin = col->xMin; + yMax = col->xMax; + col->xMin = xMin; + col->xMax = xMax; + col->yMin = yMin; + col->yMax = yMax; + for (parIdx = 0; + parIdx < col->paragraphs->getLength(); + ++parIdx) { + par = (TextParagraph *)col->paragraphs->get(parIdx); + xMin = pageWidth - par->yMax; + xMax = pageWidth - par->yMin; + yMin = par->xMin; + yMax = par->xMax; + par->xMin = xMin; + par->xMax = xMax; + par->yMin = yMin; + par->yMax = yMax; + for (lineIdx = 0; + lineIdx < par->lines->getLength(); + ++lineIdx) { + line = (TextLine *)par->lines->get(lineIdx); + xMin = pageWidth - line->yMax; + xMax = pageWidth - line->yMin; + yMin = line->xMin; + yMax = line->xMax; + line->xMin = xMin; + line->xMax = xMax; + line->yMin = yMin; + line->yMax = yMax; + line->rot = (line->rot + 1) & 3; + if (!(line->rot & 1)) { + for (i = 0; i <= line->len; ++i) { + line->edge[i] = pageWidth - line->edge[i]; + } + } + for (wordIdx = 0; wordIdx < line->words->getLength(); ++wordIdx) { + word = (TextWord *)line->words->get(wordIdx); + xMin = pageWidth - word->yMax; + xMax = pageWidth - word->yMin; + yMin = word->xMin; + yMax = word->xMax; + word->xMin = xMin; + word->xMax = xMax; + word->yMin = yMin; + word->yMax = yMax; + word->rot = (word->rot + 1) & 3; + if (!(word->rot & 1)) { + for (i = 0; i <= word->len; ++i) { + word->edge[i] = pageWidth - word->edge[i]; + } + } + } + } + } + } + break; + case 2: + for (colIdx = 0; colIdx < columns->getLength(); ++colIdx) { + col = (TextColumn *)columns->get(colIdx); + xMin = pageWidth - col->xMax; + xMax = pageWidth - col->xMin; + yMin = pageHeight - col->yMax; + yMax = pageHeight - col->yMin; + col->xMin = xMin; + col->xMax = xMax; + col->yMin = yMin; + col->yMax = yMax; + for (parIdx = 0; + parIdx < col->paragraphs->getLength(); + ++parIdx) { + par = (TextParagraph *)col->paragraphs->get(parIdx); + xMin = pageWidth - par->xMax; + xMax = pageWidth - par->xMin; + yMin = pageHeight - par->yMax; + yMax = pageHeight - par->yMin; + par->xMin = xMin; + par->xMax = xMax; + par->yMin = yMin; + par->yMax = yMax; + for (lineIdx = 0; + lineIdx < par->lines->getLength(); + ++lineIdx) { + line = (TextLine *)par->lines->get(lineIdx); + xMin = pageWidth - line->xMax; + xMax = pageWidth - line->xMin; + yMin = pageHeight - line->yMax; + yMax = pageHeight - line->yMin; + line->xMin = xMin; + line->xMax = xMax; + line->yMin = yMin; + line->yMax = yMax; + line->rot = (line->rot + 2) & 3; + if (line->rot & 1) { + for (i = 0; i <= line->len; ++i) { + line->edge[i] = pageHeight - line->edge[i]; + } + } else { + for (i = 0; i <= line->len; ++i) { + line->edge[i] = pageWidth - line->edge[i]; + } + } + for (wordIdx = 0; wordIdx < line->words->getLength(); ++wordIdx) { + word = (TextWord *)line->words->get(wordIdx); + xMin = pageWidth - word->xMax; + xMax = pageWidth - word->xMin; + yMin = pageHeight - word->yMax; + yMax = pageHeight - word->yMin; + word->xMin = xMin; + word->xMax = xMax; + word->yMin = yMin; + word->yMax = yMax; + word->rot = (word->rot + 2) & 3; + if (word->rot & 1) { + for (i = 0; i <= word->len; ++i) { + word->edge[i] = pageHeight - word->edge[i]; + } + } else { + for (i = 0; i <= word->len; ++i) { + word->edge[i] = pageWidth - word->edge[i]; + } + } + } + } + } + } + break; + case 3: + // NB: this is called after unrotateChars(), which will have + // swapped pageWidth and pageHeight already. + for (colIdx = 0; colIdx < columns->getLength(); ++colIdx) { + col = (TextColumn *)columns->get(colIdx); + xMin = col->yMin; + xMax = col->yMax; + yMin = pageHeight - col->xMax; + yMax = pageHeight - col->xMin; + col->xMin = xMin; + col->xMax = xMax; + col->yMin = yMin; + col->yMax = yMax; + for (parIdx = 0; + parIdx < col->paragraphs->getLength(); + ++parIdx) { + par = (TextParagraph *)col->paragraphs->get(parIdx); + xMin = par->yMin; + xMax = par->yMax; + yMin = pageHeight - par->xMax; + yMax = pageHeight - par->xMin; + par->xMin = xMin; + par->xMax = xMax; + par->yMin = yMin; + par->yMax = yMax; + for (lineIdx = 0; + lineIdx < par->lines->getLength(); + ++lineIdx) { + line = (TextLine *)par->lines->get(lineIdx); + xMin = line->yMin; + xMax = line->yMax; + yMin = pageHeight - line->xMax; + yMax = pageHeight - line->xMin; + line->xMin = xMin; + line->xMax = xMax; + line->yMin = yMin; + line->yMax = yMax; + line->rot = (line->rot + 3) & 3; + if (line->rot & 1) { + for (i = 0; i <= line->len; ++i) { + line->edge[i] = pageHeight - line->edge[i]; + } + } + for (wordIdx = 0; wordIdx < line->words->getLength(); ++wordIdx) { + word = (TextWord *)line->words->get(wordIdx); + xMin = word->yMin; + xMax = word->yMax; + yMin = pageHeight - word->xMax; + yMax = pageHeight - word->xMin; + word->xMin = xMin; + word->xMax = xMax; + word->yMin = yMin; + word->yMax = yMax; + word->rot = (word->rot + 3) & 3; + if (word->rot & 1) { + for (i = 0; i <= word->len; ++i) { + word->edge[i] = pageHeight - word->edge[i]; + } + } + } + } + } + } + break; + } +} + +void TextPage::unrotateWords(GList *words, int rot) { + TextWord *word; + double xMin, yMin, xMax, yMax; + int i, j; + + switch (rot) { + case 0: + default: + // no transform + break; + case 1: + for (i = 0; i < words->getLength(); ++i) { + word = (TextWord *)words->get(i); + xMin = pageWidth - word->yMax; + xMax = pageWidth - word->yMin; + yMin = word->xMin; + yMax = word->xMax; + word->xMin = xMin; + word->xMax = xMax; + word->yMin = yMin; + word->yMax = yMax; + word->rot = (word->rot + 1) & 3; + if (!(word->rot & 1)) { + for (j = 0; j <= word->len; ++j) { + word->edge[j] = pageWidth - word->edge[j]; + } + } + } + break; + case 2: + for (i = 0; i < words->getLength(); ++i) { + word = (TextWord *)words->get(i); + xMin = pageWidth - word->xMax; + xMax = pageWidth - word->xMin; + yMin = pageHeight - word->yMax; + yMax = pageHeight - word->yMin; + word->xMin = xMin; + word->xMax = xMax; + word->yMin = yMin; + word->yMax = yMax; + word->rot = (word->rot + 2) & 3; + if (word->rot & 1) { + for (j = 0; j <= word->len; ++j) { + word->edge[j] = pageHeight - word->edge[j]; + } + } else { + for (j = 0; j <= word->len; ++j) { + word->edge[j] = pageWidth - word->edge[j]; + } + } + } + break; + case 3: + for (i = 0; i < words->getLength(); ++i) { + word = (TextWord *)words->get(i); + xMin = word->yMin; + xMax = word->yMax; + yMin = pageHeight - word->xMax; + yMax = pageHeight - word->xMin; + word->xMin = xMin; + word->xMax = xMax; + word->yMin = yMin; + word->yMax = yMax; + word->rot = (word->rot + 3) & 3; + if (word->rot & 1) { + for (j = 0; j <= word->len; ++j) { + word->edge[j] = pageHeight - word->edge[j]; + } + } + } + break; + } +} + +// Determine the primary text direction (LR vs RL). Returns true for +// LR, false for RL. +GBool TextPage::checkPrimaryLR(GList *charsA) { + TextChar *ch; + int i, lrCount; + + lrCount = 0; + for (i = 0; i < charsA->getLength(); ++i) { + ch = (TextChar *)charsA->get(i); + if (unicodeTypeL(ch->c)) { + ++lrCount; + } else if (unicodeTypeR(ch->c)) { + --lrCount; + } + } + return lrCount >= 0; +} + +// Remove duplicate characters. The list of chars has been sorted -- +// by x for rot=0,2; by y for rot=1,3. +void TextPage::removeDuplicates(GList *charsA, int rot) { + TextChar *ch, *ch2; + double xDelta, yDelta; + int i, j; + + if (rot & 1) { + i = 0; + while (i < charsA->getLength()) { + ch = (TextChar *)charsA->get(i); + xDelta = dupMaxSecDelta * ch->fontSize; + yDelta = dupMaxPriDelta * ch->fontSize; + j = i + 1; + while (j < charsA->getLength()) { + ch2 = (TextChar *)charsA->get(j); + if (ch2->yMin - ch->yMin >= yDelta) { + break; + } + if (ch2->c == ch->c && + fabs(ch2->xMin - ch->xMin) < xDelta && + fabs(ch2->xMax - ch->xMax) < xDelta && + fabs(ch2->yMax - ch->yMax) < yDelta) { + if (ch->invisible && !ch2->invisible) { + charsA->del(i); + --i; + break; + } + if (ch2->spaceAfter) { + ch->spaceAfter = (char)gTrue; + } + charsA->del(j); + } else { + ++j; + } + } + ++i; + } + } else { + i = 0; + while (i < charsA->getLength()) { + ch = (TextChar *)charsA->get(i); + xDelta = dupMaxPriDelta * ch->fontSize; + yDelta = dupMaxSecDelta * ch->fontSize; + j = i + 1; + while (j < charsA->getLength()) { + ch2 = (TextChar *)charsA->get(j); + if (ch2->xMin - ch->xMin >= xDelta) { + break; + } + if (ch2->c == ch->c && + fabs(ch2->xMax - ch->xMax) < xDelta && + fabs(ch2->yMin - ch->yMin) < yDelta && + fabs(ch2->yMax - ch->yMax) < yDelta) { + if (ch->invisible && !ch2->invisible) { + charsA->del(i); + --i; + break; + } + if (ch2->spaceAfter) { + ch->spaceAfter = (char)gTrue; + } + charsA->del(j); + } else { + ++j; + } + } + ++i; + } + } +} + +struct TextCharNode { + TextCharNode(TextChar *chA, TextCharNode *nextA): ch(chA), next(nextA) {} + TextChar *ch; + TextCharNode *next; +}; + +// Separate out any overlapping text. If handling is +// textOutAppendOverlaps, return a list of the overlapping chars; else +// delete them and return NULL. +GList *TextPage::separateOverlappingText(GList *charsA) { + // bin-sort the TextChars + TextCharNode *grid[overlapGridHeight][overlapGridWidth]; + for (int y = 0; y < overlapGridHeight; ++y) { + for (int x = 0; x < overlapGridWidth; ++x) { + grid[y][x] = NULL; + } + } + for (int i = 0; i < charsA->getLength(); ++i) { + TextChar *ch = (TextChar *)charsA->get(i); + int y0 = (int)floor(overlapGridHeight * ch->yMin / pageHeight); + int y1 = (int)ceil(overlapGridHeight * ch->yMax / pageHeight); + int x0 = (int)floor(overlapGridWidth * ch->xMin / pageWidth); + int x1 = (int)ceil(overlapGridWidth * ch->yMin / pageWidth); + if (y0 < 0) { + y0 = 0; + } + if (y1 >= overlapGridHeight) { + y1 = overlapGridHeight - 1; + } + if (x0 < 0) { + x0 = 0; + } + if (x1 >= overlapGridWidth) { + x1 = overlapGridWidth - 1; + } + for (int y = y0; y <= y1; ++y) { + for (int x = x0; x <= x1; ++x) { + grid[y][x] = new TextCharNode(ch, grid[y][x]); + } + } + } + + // look for overlaps in each cell + GBool foundOverlaps = gFalse; + for (int y = 0; y < overlapGridHeight; ++y) { + for (int x = 0; x < overlapGridWidth; ++x) { + for (TextCharNode *p0 = grid[y][x]; p0; p0 = p0->next) { + for (TextCharNode *p1 = p0->next; p1; p1 = p1->next) { + if (p0->ch->colorR != p1->ch->colorR || + p0->ch->colorG != p1->ch->colorG || + p0->ch->colorB != p1->ch->colorB) { + double ovx = (dmin(p0->ch->xMax, p1->ch->xMax) + - dmax(p0->ch->xMin, p1->ch->xMin)) + / dmin(p0->ch->xMax - p0->ch->xMin, + p1->ch->xMax - p1->ch->xMin); + double ovy = (dmin(p0->ch->yMax, p1->ch->yMax) + - dmax(p0->ch->yMin, p1->ch->yMin)) + / dmin(p0->ch->yMax - p0->ch->yMin, + p1->ch->yMax - p1->ch->yMin); + if (ovx > minCharOverlap && ovy > minCharOverlap) { + // assume the lighter colored text is extraneous + if (p0->ch->colorR + p0->ch->colorG + p0->ch->colorB + < p1->ch->colorR + p1->ch->colorG + p1->ch->colorB) { + p1->ch->overlap = gTrue; + } else { + p0->ch->overlap = gTrue; + } + foundOverlaps = gTrue; + } + } + } + } + } + } + + // find overlapped strings + GList *overlapChars = NULL; + if (control.overlapHandling == textOutAppendOverlaps) { + overlapChars = new GList(); + } + if (foundOverlaps) { + charsA->sort(&TextChar::cmpCharPos); + int i = 0; + while (i < charsA->getLength()) { + TextChar *ch0 = (TextChar *)charsA->get(i); + if (ch0->overlap) { + int j0, j1; + for (j0 = i - 1; j0 >= 0; --j0) { + TextChar *ch1 = (TextChar *)charsA->get(j0); + if (ch1->colorR != ch0->colorR || + ch1->colorG != ch0->colorG || + ch1->colorB != ch0->colorB || + ch1->rot != ch0->rot) { + break; + } + } + ++j0; + for (j1 = i + 1; j1 < charsA->getLength(); ++j1) { + TextChar *ch1 = (TextChar *)charsA->get(j1); + if (ch1->colorR != ch0->colorR || + ch1->colorG != ch0->colorG || + ch1->colorB != ch0->colorB || + ch1->rot != ch0->rot) { + break; + } + } + --j1; + for (int j = j0; j <= j1; ++j) { + if (overlapChars) { + overlapChars->append(charsA->get(j0)); + } else { + delete (TextChar *)charsA->get(j0); + } + charsA->del(j0); + } + i = j0; + } else { + ++i; + } + } + } + + // free memory + for (int y = 0; y < overlapGridHeight; ++y) { + for (int x = 0; x < overlapGridWidth; ++x) { + TextCharNode *p0 = grid[y][x]; + while (p0) { + TextCharNode *p1 = p0->next; + delete p0; + p0 = p1; + } + } + } + + return overlapChars; +} + +// Construct a TextColumn from the list of separated overlapping +// chars. +TextColumn *TextPage::buildOverlappingTextColumn(GList *overlappingChars) { + GList *pars = new GList(); + GList *lines = new GList(); + GList *words = new GList(); + int wordStart = 0; + double lineXMin = 0, lineYMin = 0, lineXMax = 0, lineYMax = 0; + double colXMin = 0, colYMin = 0, colXMax = 0, colYMax = 0; + for (int i = 0; i < overlappingChars->getLength(); ++i) { + TextChar *ch = (TextChar *)overlappingChars->get(i); + TextChar *chNext = NULL; + if (i + 1 < overlappingChars->getLength()) { + chNext = (TextChar *)overlappingChars->get(i + 1); + } + double sp = 0; + double dy = 0; + if (chNext) { + switch (ch->rot) { + case 0: + default: + sp = chNext->xMin - ch->xMax; + dy = chNext->yMin - ch->yMin; + break; + case 1: + sp = chNext->yMin - ch->yMax; + dy = chNext->xMax - ch->xMax; + break; + case 2: + sp = ch->xMin - chNext->xMax; + dy = ch->yMax - chNext->yMax; + break; + case 3: + sp = ch->yMin - chNext->yMax; + dy = ch->xMin - chNext->xMin; + break; + } + } + // the +1 here allows for a space character after ch + GBool parBreak = !chNext || + chNext->rot != ch->rot || + chNext->charPos > ch->charPos + ch->charLen + 1; + GBool lineBreak = parBreak || + sp < -rawModeCharOverlap * ch->fontSize || + fabs(dy) > rawModeLineDelta * ch->fontSize; + GBool wordBreak = lineBreak || + ch->spaceAfter || + sp > rawModeWordSpacing * ch->fontSize; + if (!wordBreak) { + continue; + } + TextWord *word = new TextWord(overlappingChars, wordStart, + i - wordStart + 1, ch->rot, ch->rotated, + getCharDirection(ch), !lineBreak); + words->append(word); + if (words->getLength() == 0) { + lineXMin = word->xMin; + lineYMin = word->yMin; + lineXMax = word->xMax; + lineYMax = word->yMax; + } else { + lineXMin = dmin(lineXMin, word->xMin); + lineYMin = dmin(lineYMin, word->yMin); + lineXMax = dmax(lineXMax, word->xMax); + lineYMax = dmax(lineYMax, word->yMax); + } + wordStart = i + 1; + if (!lineBreak) { + continue; + } + lines->append(new TextLine(words, lineXMin, lineYMin, lineXMax, lineYMax, + ((TextWord *)words->get(0))->fontSize)); + words = new GList(); + if (!parBreak) { + continue; + } + TextParagraph *par = new TextParagraph(lines, gFalse); + pars->append(par); + if (pars->getLength() == 0) { + colXMin = par->xMin; + colYMin = par->yMin; + colXMax = par->xMax; + colYMax = par->yMax; + } else { + colXMin = dmin(colXMin, par->xMin); + colYMin = dmin(colYMin, par->yMin); + colXMax = dmax(colXMax, par->xMax); + colYMax = dmax(colYMax, par->yMax); + } + lines = new GList(); + } + delete words; + delete lines; + return new TextColumn(pars, colXMin, colYMin, colXMax, colYMax); +} + +// Split the characters into trees of TextBlocks, one tree for each +// rotation. Merge into a single tree (with the primary rotation). +TextBlock *TextPage::splitChars(GList *charsA) { + TextBlock *tree[4]; + TextBlock *blk; + GList *chars2, *clippedChars; + TextChar *ch; + int rot, i; + + // split: build a tree of TextBlocks for each rotation + clippedChars = new GList(); + for (rot = 0; rot < 4; ++rot) { + chars2 = new GList(); + for (i = 0; i < charsA->getLength(); ++i) { + ch = (TextChar *)charsA->get(i); + if (ch->rot == rot && + !(control.discardInvisibleText && ch->invisible) && + !(control.discardClippedText && ch->clipped)) { + chars2->append(ch); + } + } + tree[rot] = NULL; + if (chars2->getLength() > 0) { + chars2->sort((rot & 1) ? &TextChar::cmpY : &TextChar::cmpX); + removeDuplicates(chars2, rot); + if (control.clipText) { + i = 0; + while (i < chars2->getLength()) { + ch = (TextChar *)chars2->get(i); + if (ch->clipped) { + ch = (TextChar *)chars2->del(i); + clippedChars->append(ch); + } else { + ++i; + } + } + } + if (chars2->getLength() > 0) { + tree[rot] = split(chars2, rot, gFalse); + } + } + delete chars2; + } + + // if the page contains no (unclipped) text, just leave an empty + // column list + if (!tree[0]) { + // normally tree[0] is empty only if there is no text at all, but + // if the caller didn't do rotation, the rotated trees may be + // non-empty, so we need to free them + for (rot = 1; rot < 4; ++rot) { + if (tree[rot]) { + delete tree[rot]; + } + } + delete clippedChars; + return NULL; + } + + // if the main tree is not a multicolumn node, insert one so that + // rotated text has somewhere to go + if (tree[0]->tag != blkTagMulticolumn) { + blk = new TextBlock(blkHorizSplit, 0); + blk->addChild(tree[0]); + blk->tag = blkTagMulticolumn; + tree[0] = blk; + } + + // merge non-primary-rotation text into the primary-rotation tree + for (rot = 1; rot < 4; ++rot) { + if (tree[rot]) { + insertIntoTree(tree[rot], tree[0]); + tree[rot] = NULL; + } + } + + if (clippedChars->getLength()) { + insertClippedChars(clippedChars, tree[0]); + } + delete clippedChars; + +#if 0 //~debug + dumpTree(tree[0]); +#endif + + return tree[0]; +} + +// Generate a tree of TextBlocks, marked as columns, lines, and words. +TextBlock *TextPage::split(GList *charsA, int rot, GBool vertOnly) { + TextBlock *blk; + GList *chars2, *chars3; + GList *splitLines; + TextGaps *horizGaps, *vertGaps; + TextChar *ch; + double xMin, yMin, xMax, yMax, avgFontSize, minFontSize; + double horizGapSize, vertGapSize, minHorizChunkWidth, minVertChunkWidth; + double gap, gapThreshold, smallSplitThreshold, blockHeight, minChunk; + double largeCharSize; + double x0, x1, y0, y1; + int nHorizGaps, nVertGaps, nLargeChars; + int i; + GBool singleLine; + GBool doHorizSplit, doVertSplit, doLineSplit, doLargeCharSplit, smallSplit; + + //----- find all horizontal and vertical gaps + + horizGaps = new TextGaps(); + vertGaps = new TextGaps(); + splitLines = new GList(); + findGaps(charsA, rot, &xMin, &yMin, &xMax, &yMax, &avgFontSize, &minFontSize, + splitLines, horizGaps, vertGaps); + + //----- find the largest horizontal and vertical gaps + + horizGapSize = 0; + for (i = 0; i < horizGaps->getLength(); ++i) { + gap = horizGaps->getW(i); + if (gap > horizGapSize) { + horizGapSize = gap; + } + } + vertGapSize = 0; + for (i = 0; i < vertGaps->getLength(); ++i) { + gap = vertGaps->getW(i); + if (gap > vertGapSize) { + vertGapSize = gap; + } + } + + //----- count horiz/vert gaps equivalent to largest gaps + + minHorizChunkWidth = yMax - yMin; + nHorizGaps = 0; + if (horizGaps->getLength() > 0) { + y0 = yMin; + for (i = 0; i < horizGaps->getLength(); ++i) { + gap = horizGaps->getW(i); + if (gap > horizGapSize - splitGapSlack * avgFontSize) { + ++nHorizGaps; + y1 = horizGaps->getX(i) - 0.5 * gap; + if (y1 - y0 < minHorizChunkWidth) { + minHorizChunkWidth = y1 - y0; + } + y0 = y1 + gap; + } + } + y1 = yMax; + if (y1 - y0 < minHorizChunkWidth) { + minHorizChunkWidth = y1 - y0; + } + } + minVertChunkWidth = xMax - xMin; + nVertGaps = 0; + if (vertGaps->getLength() > 0) { + x0 = xMin; + for (i = 0; i < vertGaps->getLength(); ++i) { + gap = vertGaps->getW(i); + if (gap > vertGapSize - splitGapSlack * avgFontSize) { + ++nVertGaps; + x1 = vertGaps->getX(i) - 0.5 * gap; + if (x1 - x0 < minVertChunkWidth) { + minVertChunkWidth = x1 - x0; + } + x0 = x1 + gap; + } + } + x1 = xMax; + if (x1 - x0 < minVertChunkWidth) { + minVertChunkWidth = x1 - x0; + } + } + + //----- compute splitting parameters + + // compute block height; check for single line + blockHeight = (rot & 1) ? xMax - xMin : yMax - yMin; + singleLine = blockHeight < maxSingleLineHeight * avgFontSize && + splitLines->getLength() == 1; + + // compute the minimum allowed vertical gap size + // (this is a horizontal gap threshold for rot=1,3 + if (control.mode == textOutTableLayout) { + if (rot & 1) { + gapThreshold = (minTableGapArea * avgFontSize * avgFontSize) + / (xMax - xMin); + } else { + gapThreshold = (minTableGapArea * avgFontSize * avgFontSize) + / (yMax - yMin); + } + if (minGapSize * avgFontSize > gapThreshold) { + gapThreshold = minGapSize * avgFontSize; + } + smallSplitThreshold = tableModeMaxWordGapSize * avgFontSize; + } else { + if (rot & 1) { + gapThreshold = (minGapArea * avgFontSize * avgFontSize) / (xMax - xMin); + if (vertGapSize > gapThreshold) { + gapThreshold = vertGapSize; + } + } else { + gapThreshold = (minGapArea * avgFontSize * avgFontSize) / (yMax - yMin); + if (horizGapSize > gapThreshold) { + gapThreshold = horizGapSize; + } + } + if (minGapSize * avgFontSize > gapThreshold) { + gapThreshold = minGapSize * avgFontSize; + } + smallSplitThreshold = maxWordGapSize * avgFontSize; + } + + if (control.mode == textOutTableLayout || + singleLine) { + minChunk = 0; + } else { + minChunk = minChunkWidth * avgFontSize; + } + + // look for large chars + // -- this kludge (multiply by 256, convert to int, divide by 256.0) + // prevents floating point stability issues on x86 with gcc, where + // largeCharSize could otherwise have slightly different values + // here and where it's used below to do the large char partition + // (because it gets truncated from 80 to 64 bits when spilled) + nLargeChars = 0; + largeCharSize = 0; + if (control.separateLargeChars) { + largeCharSize = (int)(largeCharThreshold * avgFontSize * 256) / 256.0; + for (i = 0; i < charsA->getLength(); ++i) { + ch = (TextChar *)charsA->get(i); + if (ch->fontSize > largeCharSize) { + ++nLargeChars; + } + } + } + + // figure out which type of split to do + doHorizSplit = doVertSplit = doLineSplit = doLargeCharSplit = gFalse; + smallSplit = gFalse; + if (rot & 1) { + if (vertOnly) { + if (nHorizGaps > 0 && horizGapSize > minGapSize * minFontSize) { + doHorizSplit = gTrue; + smallSplit = horizGapSize < smallSplitThreshold; + } + } else if (control.mode == textOutSimpleLayout) { + if (nVertGaps > 0) { + doVertSplit = gTrue; + } else if (nHorizGaps > 0 && horizGapSize > minGapSize * minFontSize) { + doHorizSplit = gTrue; + smallSplit = horizGapSize < smallSplitThreshold; + } else if (!vertOnly && splitLines->getLength() > 1) { + doLineSplit = gTrue; + } + } else if (nHorizGaps > 0 && + ((horizGapSize > minGapSize * minFontSize && + nVertGaps == 0 && + splitLines->getLength() <= 1) || + (horizGapSize > gapThreshold && + minHorizChunkWidth > minChunk))) { + doHorizSplit = gTrue; + smallSplit = horizGapSize < smallSplitThreshold; + } else if (nVertGaps > 0) { + doVertSplit = gTrue; + } else if (nLargeChars > 0) { + doLargeCharSplit = gTrue; + } else if (splitLines->getLength() > 1) { + doLineSplit = gTrue; + } + } else { + if (vertOnly) { + if (nVertGaps > 0 && + vertGapSize > minGapSize * minFontSize) { + doVertSplit = gTrue; + smallSplit = vertGapSize < smallSplitThreshold; + } + } else if (control.mode == textOutSimpleLayout) { + if (nHorizGaps > 0) { + doHorizSplit = gTrue; + } else if (nVertGaps > 0 && vertGapSize > minGapSize * minFontSize) { + doVertSplit = gTrue; + smallSplit = vertGapSize < smallSplitThreshold; + } else if (splitLines->getLength() > 1) { + doLineSplit = gTrue; + } + } else if (nVertGaps > 0 && + ((vertGapSize > minGapSize * minFontSize && + nHorizGaps == 0 && + splitLines->getLength() <= 1) || + (vertGapSize > gapThreshold && + minVertChunkWidth > minChunk))) { + doVertSplit = gTrue; + smallSplit = vertGapSize < smallSplitThreshold; + } else if (nHorizGaps > 0) { + doHorizSplit = gTrue; + } else if (nLargeChars > 0) { + doLargeCharSplit = gTrue; + } else if (splitLines->getLength() > 1) { + doLineSplit = gTrue; + } + } + + //----- split the block + + //~ this could use "other content" (vector graphics, rotated text) -- + //~ presence of other content in a gap means we should definitely split + + // split vertically + if (doVertSplit) { +#if 0 //~debug + printf("vert split xMin=%g yMin=%g xMax=%g yMax=%g small=%d\n", + xMin, pageHeight - yMax, xMax, pageHeight - yMin, smallSplit); + for (i = 0; i < vertGaps->getLength(); ++i) { + if (vertGaps->getW(i) > vertGapSize - splitGapSlack * avgFontSize) { + printf(" x=%g\n", vertGaps->getX(i)); + } + } +#endif + blk = new TextBlock(blkVertSplit, rot); + blk->smallSplit = smallSplit; + x0 = xMin - 1; + for (i = 0; i < vertGaps->getLength(); ++i) { + if (vertGaps->getW(i) > vertGapSize - splitGapSlack * avgFontSize) { + x1 = vertGaps->getX(i); + chars2 = getChars(charsA, x0, yMin - 1, x1, yMax + 1); + blk->addChild(split(chars2, rot, vertOnly)); + delete chars2; + x0 = x1; + } + } + chars2 = getChars(charsA, x0, yMin - 1, xMax + 1, yMax + 1); + blk->addChild(split(chars2, rot, vertOnly)); + delete chars2; + + // split horizontally + } else if (doHorizSplit) { +#if 0 //~debug + printf("horiz split xMin=%g yMin=%g xMax=%g yMax=%g small=%d\n", + xMin, pageHeight - yMax, xMax, pageHeight - yMin, smallSplit); + for (i = 0; i < horizGaps->getLength(); ++i) { + if (horizGaps->getW(i) > horizGapSize - splitGapSlack * avgFontSize) { + printf(" y=%g\n", pageHeight - horizGaps->getX(i)); + } + } +#endif + blk = new TextBlock(blkHorizSplit, rot); + blk->smallSplit = smallSplit; + y0 = yMin - 1; + for (i = 0; i < horizGaps->getLength(); ++i) { + if (horizGaps->getW(i) > horizGapSize - splitGapSlack * avgFontSize) { + y1 = horizGaps->getX(i); + chars2 = getChars(charsA, xMin - 1, y0, xMax + 1, y1); + blk->addChild(split(chars2, rot, gFalse)); + delete chars2; + y0 = y1; + } + } + chars2 = getChars(charsA, xMin - 1, y0, xMax + 1, yMax + 1); + blk->addChild(split(chars2, rot, gFalse)); + delete chars2; + + // split into larger and smaller chars + } else if (doLargeCharSplit) { +#if 0 //~debug + printf("large char split xMin=%g yMin=%g xMax=%g yMax=%g\n", + xMin, pageHeight - yMax, xMax, pageHeight - yMin); +#endif + chars2 = new GList(); + chars3 = new GList(); + for (i = 0; i < charsA->getLength(); ++i) { + ch = (TextChar *)charsA->get(i); + if (ch->fontSize > largeCharSize) { + chars2->append(ch); + } else { + chars3->append(ch); + } + } + blk = split(chars3, rot, gFalse); + chars2->sort((rot & 1) ? &TextChar::cmpY : &TextChar::cmpX); + insertLargeChars(chars2, blk); + delete chars2; + delete chars3; + + // split into lines -- this handles the case where lines overlap slightly + } else if (doLineSplit) { + mergeSplitLines(charsA, rot, splitLines); +#if 0 //~debug + printf("line split xMin=%g yMin=%g xMax=%g yMax=%g\n", + xMin, pageHeight - yMax, xMax, pageHeight - yMin); + for (i = 0; i < splitLines->getLength(); ++i) { + SplitLine *splitLine = (SplitLine *)splitLines->get(i); + printf(" yMin=%g yMax=%g\n", + pageHeight - splitLine->yMax, pageHeight - splitLine->yMin); + } +#endif + if (splitLines->getLength() == 1) { + // if merging sub/superscripts resulted in a single line, then + // it's a leaf + blk = new TextBlock(blkLeaf, rot); + SplitLine *splitLine = (SplitLine *)splitLines->get(0); + for (i = 0; i < splitLine->chars->getLength(); ++i) { + blk->addChild((TextChar *)splitLine->chars->get(i), gTrue); + } + } else { + blk = new TextBlock((rot & 1) ? blkVertSplit : blkHorizSplit, rot); + blk->smallSplit = gFalse; + for (i = 0; i < splitLines->getLength(); ++i) { + SplitLine *splitLine = (SplitLine *)splitLines->get(i); + blk->addChild(split(splitLine->chars, rot, singleLine)); + } + } + + // create a leaf node + } else { +#if 0 //~debug + printf("leaf xMin=%g yMin=%g xMax=%g yMax=%g\n", + xMin, pageHeight - yMax, xMax, pageHeight - yMin); + printf(" "); + for (i = 0; i < charsA->getLength(); ++i) { + printf("%c", ((TextChar *)charsA->get(i))->c); + } + printf("\n"); +#endif + blk = new TextBlock(blkLeaf, rot); + charsA->sort((rot & 1) ? &TextChar::cmpY : &TextChar::cmpX); + for (i = 0; i < charsA->getLength(); ++i) { + blk->addChild((TextChar *)charsA->get(i), gTrue); + } + } + + deleteGList(splitLines, SplitLine); + delete horizGaps; + delete vertGaps; + + tagBlock(blk); + + return blk; +} + +// Return the subset of chars inside a rectangle. +GList *TextPage::getChars(GList *charsA, double xMin, double yMin, + double xMax, double yMax) { + GList *ret; + TextChar *ch; + double x, y; + int i; + + ret = new GList(); + for (i = 0; i < charsA->getLength(); ++i) { + ch = (TextChar *)charsA->get(i); + // compute the center of the adjusted bbox, and check to see if + // that's inside the specified rectangle + x = 0.5 * (ch->xMin + ch->xMax); + y = 0.5 * (ch->yMin + ch->yMax + + (ascentAdjustFactor - descentAdjustFactor) * + (ch->yMax - ch->yMin)); + if (x > xMin && x < xMax && y > yMin && y < yMax) { + ret->append(ch); + } + } + return ret; +} + +void TextPage::findGaps(GList *charsA, int rot, + double *xMinOut, double *yMinOut, + double *xMaxOut, double *yMaxOut, + double *avgFontSizeOut, double *minFontSizeOut, + GList *splitLines, + TextGaps *horizGaps, TextGaps *vertGaps) { + //----- compute bbox, min font size, and average font size + + double xMin = 0, yMin = 0, xMax = 0, yMax = 0; + double avgFontSize = 0, minFontSize = 0; + for (int i = 0; i < charsA->getLength(); ++i) { + TextChar *ch = (TextChar *)charsA->get(i); + if (i == 0 || ch->xMin < xMin) { + xMin = ch->xMin; + } + if (i == 0 || ch->yMin < yMin) { + yMin = ch->yMin; + } + if (i == 0 || ch->xMax > xMax) { + xMax = ch->xMax; + } + if (i == 0 || ch->yMax > yMax) { + yMax = ch->yMax; + } + avgFontSize += ch->fontSize; + if (i == 0 || ch->fontSize < minFontSize) { + minFontSize = ch->fontSize; + } + } + avgFontSize /= charsA->getLength(); + *xMinOut = xMin; + *yMinOut = yMin; + *xMaxOut = xMax; + *yMaxOut = yMax; + *avgFontSizeOut = avgFontSize; + *minFontSizeOut = minFontSize; + + //----- find vertical gaps + + if (rot & 1) { + charsA->sort(&TextChar::cmpY); + double yyMax = 0; + for (int i = 0; i < charsA->getLength(); ++i) { + TextChar *ch = (TextChar *)charsA->get(i); + if (i == 0) { + yyMax = ch->yMax; + } else if (ch->yMin <= yyMax) { + if (ch->yMax > yyMax) { + yyMax = ch->yMax; + } + } else { + horizGaps->addGap(0.5 * (ch->yMin + yyMax), ch->yMin - yyMax); + yyMax = ch->yMax; + } + } + } else { + charsA->sort(&TextChar::cmpX); + double xxMax = 0; + for (int i = 0; i < charsA->getLength(); ++i) { + TextChar *ch = (TextChar *)charsA->get(i); + if (i == 0) { + xxMax = ch->xMax; + } else if (ch->xMin <= xxMax) { + if (ch->xMax > xxMax) { + xxMax = ch->xMax; + } + } else { + vertGaps->addGap(0.5 * (ch->xMin + xxMax), ch->xMin - xxMax); + xxMax = ch->xMax; + } + } + } + + //----- partition into lines and find horizontal gaps + + if (rot & 1) { + charsA->sort(&TextChar::cmpX); + SplitLine *splitLine = NULL; + double xxMin = 0, xxMax = 0; + for (int i = 0; i < charsA->getLength(); ++i) { + TextChar *ch = (TextChar *)charsA->get(i); + if (i == 0 || + ch->xMin > xxMax - lineOverlapThreshold * (xxMax - xxMin)) { + if (i > 0 && ch->xMin > xxMax) { + vertGaps->addGap(0.5 * (ch->xMin + xxMax), ch->xMin - xxMax); + } + xxMin = ch->xMin; + xxMax = ch->xMax; + splitLine = new SplitLine(i, i, xxMin, xxMax); + splitLines->append(splitLine); + } else { + splitLine->lastCharIdx = i; + if (ch->xMax > xxMax) { + xxMax = ch->xMax; + splitLine->yMax = xxMax; + } + } + } + } else { + charsA->sort(&TextChar::cmpY); + SplitLine *splitLine = NULL; + double yyMin = 0, yyMax = 0; + for (int i = 0; i < charsA->getLength(); ++i) { + TextChar *ch = (TextChar *)charsA->get(i); + if (i == 0 || + ch->yMin > yyMax - lineOverlapThreshold * (yyMax - yyMin)) { + if (i > 0 && ch->yMin > yyMax) { + horizGaps->addGap(0.5 * (ch->yMin + yyMax), ch->yMin - yyMax); + } + yyMin = ch->yMin; + yyMax = ch->yMax; + splitLine = new SplitLine(i, i, yyMin, yyMax); + splitLines->append(splitLine); + } else { + splitLine->lastCharIdx = i; + if (ch->yMax > yyMax) { + yyMax = ch->yMax; + splitLine->yMax = yyMax; + } + } + } + } +} + +void TextPage::mergeSplitLines(GList *charsA, int rot, GList *splitLines) { + if (rot & 1) { + + // build the list of chars in each line, sort by y + for (int i = 0; i < splitLines->getLength(); ++i) { + SplitLine *splitLine = (SplitLine *)splitLines->get(i); + splitLine->chars = new GList(); + for (int j = splitLine->firstCharIdx; j <= splitLine->lastCharIdx; ++j) { + splitLine->chars->append(charsA->get(j)); + } + splitLine->chars->sort(&TextChar::cmpY); + } + + // look for sub/superscripts accidentally split into separate lines + for (int i = 0; i < splitLines->getLength(); ++i) { + SplitLine *splitLine = (SplitLine *)splitLines->get(i); + SplitLine *prevLine = NULL; + SplitLine *nextLine = NULL; + + // check for overlapping lines + GBool maybeSub = gFalse; + if (i > 0) { + prevLine = (SplitLine *)splitLines->get(i-1); + double minOverlap = minSubSuperscriptVertOverlap + * (prevLine->yMax - prevLine->yMin); + maybeSub = prevLine->yMax - splitLine->yMin > minOverlap; + } + GBool maybeSuper = gFalse; + if (i < splitLines->getLength() - 1) { + nextLine = (SplitLine *)splitLines->get(i+1); + double minOverlap = minSubSuperscriptVertOverlap + * (nextLine->yMax - nextLine->yMin); + maybeSuper = splitLine->yMax - nextLine->yMin > minOverlap; + } + if (!maybeSub && !maybeSuper) { + continue; + } + + // check whether each char in the line is a subscript or + // superscript: look at the two chars above-left and above-right + // the subscript (or below-left and below-right the superscript) + // and check that they are either to the left and right of the + // subscript (superscript), or above the subscript (below the + // superscript) to account for cases with both a subscript and + // superscript + int idxAbove = 0; + int idxBelow = 0; + GBool allSubSuper = gTrue; + for (int idx = 0; idx < splitLine->chars->getLength(); ++idx) { + TextChar *ch = (TextChar *)splitLine->chars->get(idx); + double maxOverlap = maxSubSuperscriptHorizOverlap + * (ch->xMax - ch->xMin); + GBool isSub = gFalse; + if (maybeSub) { + while (idxAbove < prevLine->chars->getLength() && + ((TextChar *)prevLine->chars->get(idxAbove))->yMin < ch->yMin) { + ++idxAbove; + } + isSub = ch->xMin < prevLine->yMax && + (idxAbove == 0 || + ch->yMin > ((TextChar *)prevLine->chars->get(idxAbove - 1))->yMax - maxOverlap || + ch->xMin > ((TextChar *)prevLine->chars->get(idxAbove - 1))->xMax) && + (idxAbove == prevLine->chars->getLength() || + ch->yMax < ((TextChar *)prevLine->chars->get(idxAbove))->yMin + maxOverlap || + ch->xMin > ((TextChar *)prevLine->chars->get(idxAbove))->xMax); + } + GBool isSuper = gFalse; + if (maybeSuper) { + while (idxBelow < nextLine->chars->getLength() && + ((TextChar *)nextLine->chars->get(idxBelow))->yMin < ch->yMin) { + ++idxBelow; + } + isSuper = ch->xMax > nextLine->yMin && + (idxBelow == 0 || + ch->yMin > ((TextChar *)nextLine->chars->get(idxBelow - 1))->yMax - maxOverlap || + ch->xMax < ((TextChar *)nextLine->chars->get(idxBelow - 1))->xMin) && + (idxBelow == nextLine->chars->getLength() || + ch->yMax < ((TextChar *)nextLine->chars->get(idxBelow))->yMin + maxOverlap || + ch->xMax < ((TextChar *)nextLine->chars->get(idxBelow))->xMin); + } + if (!isSub && !isSuper) { + allSubSuper = gFalse; + break; + } + } + + // merge sub/superscripts into correct lines + if (allSubSuper) { + for (int idx = 0; idx < splitLine->chars->getLength(); ++idx) { + TextChar *ch = (TextChar *)splitLine->chars->get(idx); + if (maybeSub && ch->xMin < prevLine->yMax) { + prevLine->chars->append(ch); + if (ch->xMin < prevLine->yMin) { + prevLine->yMin = ch->xMin; + } + if (ch->xMax > prevLine->yMax) { + prevLine->yMax = ch->xMax; + } + } else { + nextLine->chars->append(ch); + if (ch->xMin < nextLine->yMin) { + nextLine->yMin = ch->xMin; + } + if (ch->xMax > nextLine->yMax) { + nextLine->yMax = ch->xMax; + } + } + } + if (maybeSub) { + prevLine->chars->sort(&TextChar::cmpY); + } + if (maybeSuper) { + nextLine->chars->sort(&TextChar::cmpY); + } + delete splitLine; + splitLines->del(i); + } + } + + } else { + + // build the list of chars in each line, sort by x + for (int i = 0; i < splitLines->getLength(); ++i) { + SplitLine *splitLine = (SplitLine *)splitLines->get(i); + splitLine->chars = new GList(); + for (int j = splitLine->firstCharIdx; j <= splitLine->lastCharIdx; ++j) { + splitLine->chars->append(charsA->get(j)); + } + splitLine->chars->sort(&TextChar::cmpX); + } + + // look for sub/superscripts accidentally split into separate lines + for (int i = 0; i < splitLines->getLength(); ++i) { + SplitLine *splitLine = (SplitLine *)splitLines->get(i); + SplitLine *prevLine = NULL; + SplitLine *nextLine = NULL; + + // check for overlapping lines + GBool maybeSub = gFalse; + if (i > 0) { + prevLine = (SplitLine *)splitLines->get(i-1); + double minOverlap = minSubSuperscriptVertOverlap + * (prevLine->yMax - prevLine->yMin); + maybeSub = prevLine->yMax - splitLine->yMin > minOverlap; + } + GBool maybeSuper = gFalse; + if (i < splitLines->getLength() - 1) { + nextLine = (SplitLine *)splitLines->get(i+1); + double minOverlap = minSubSuperscriptVertOverlap + * (nextLine->yMax - nextLine->yMin); + maybeSuper = splitLine->yMax - nextLine->yMin > minOverlap; + } + if (!maybeSub && !maybeSuper) { + continue; + } + + // check whether each char in the line is a subscript or + // superscript: look at the two chars above-left and above-right + // the subscript (or below-left and below-right the superscript) + // and check that they are either to the left and right of the + // subscript (superscript), or above the subscript (below the + // superscript) to account for cases with both a subscript and + // superscript + int idxAbove = 0; + int idxBelow = 0; + GBool allSubSuper = gTrue; + for (int idx = 0; idx < splitLine->chars->getLength(); ++idx) { + TextChar *ch = (TextChar *)splitLine->chars->get(idx); + double maxOverlap = maxSubSuperscriptHorizOverlap + * (ch->yMax - ch->yMin); + GBool isSub = gFalse; + if (maybeSub) { + while (idxAbove < prevLine->chars->getLength() && + ((TextChar *)prevLine->chars->get(idxAbove))->xMin < ch->xMin) { + ++idxAbove; + } + isSub = ch->yMin < prevLine->yMax && + (idxAbove == 0 || + ch->xMin > ((TextChar *)prevLine->chars->get(idxAbove - 1))->xMax - maxOverlap || + ch->yMin > ((TextChar *)prevLine->chars->get(idxAbove - 1))->yMax) && + (idxAbove == prevLine->chars->getLength() || + ch->xMax < ((TextChar *)prevLine->chars->get(idxAbove))->xMin + maxOverlap || + ch->yMin > ((TextChar *)prevLine->chars->get(idxAbove))->yMax); + } + GBool isSuper = gFalse; + if (maybeSuper) { + while (idxBelow < nextLine->chars->getLength() && + ((TextChar *)nextLine->chars->get(idxBelow))->xMin < ch->xMin) { + ++idxBelow; + } + isSuper = ch->yMax > nextLine->yMin && + (idxBelow == 0 || + ch->xMin > ((TextChar *)nextLine->chars->get(idxBelow - 1))->xMax - maxOverlap || + ch->yMax < ((TextChar *)nextLine->chars->get(idxBelow - 1))->yMin) && + (idxBelow == nextLine->chars->getLength() || + ch->xMax < ((TextChar *)nextLine->chars->get(idxBelow))->xMin + maxOverlap || + ch->yMax < ((TextChar *)nextLine->chars->get(idxBelow))->yMin); + } + if (!isSub && !isSuper) { + allSubSuper = gFalse; + break; + } + } + + // merge sub/superscripts into correct lines + if (allSubSuper) { + for (int idx = 0; idx < splitLine->chars->getLength(); ++idx) { + TextChar *ch = (TextChar *)splitLine->chars->get(idx); + if (maybeSub && ch->yMin < prevLine->yMax) { + prevLine->chars->append(ch); + if (ch->yMin < prevLine->yMin) { + prevLine->yMin = ch->yMin; + } + if (ch->yMax > prevLine->yMax) { + prevLine->yMax = ch->yMax; + } + } else { + nextLine->chars->append(ch); + if (ch->yMin < nextLine->yMin) { + nextLine->yMin = ch->yMin; + } + if (ch->yMax > nextLine->yMax) { + nextLine->yMax = ch->yMax; + } + } + } + if (maybeSub) { + prevLine->chars->sort(&TextChar::cmpX); + } + if (maybeSuper) { + nextLine->chars->sort(&TextChar::cmpX); + } + delete splitLine; + splitLines->del(i); + } + } + + } +} + +// Decide whether this block is a line, column, or multiple columns: +// - all leaf nodes are lines +// - horiz split nodes whose children are lines or columns are columns +// - other horiz split nodes are multiple columns +// - vert split nodes, with small gaps, whose children are lines are lines +// - other vert split nodes are multiple columns +// (for rot=1,3: the horiz and vert splits are swapped) +// In table layout mode: +// - all leaf nodes are lines +// - vert split nodes, with small gaps, whose children are lines are lines +// - everything else is multiple columns +// In simple layout mode: +// - all leaf nodes are lines +// - vert split nodes with small gaps are lines +// - vert split nodes with large gaps are super-lines +// - horiz split nodes are columns +void TextPage::tagBlock(TextBlock *blk) { + TextBlock *child; + int i; + + if (control.mode == textOutTableLayout) { + if (blk->type == blkLeaf) { + blk->tag = blkTagLine; + } else if (blk->type == ((blk->rot & 1) ? blkHorizSplit : blkVertSplit) && + blk->smallSplit) { + blk->tag = blkTagLine; + for (i = 0; i < blk->children->getLength(); ++i) { + child = (TextBlock *)blk->children->get(i); + if (child->tag != blkTagLine) { + blk->tag = blkTagMulticolumn; + break; + } + } + } else { + blk->tag = blkTagMulticolumn; + } + return; + } + + if (control.mode == textOutSimpleLayout) { + if (blk->type == blkLeaf) { + blk->tag = blkTagLine; + } else if (blk->type == ((blk->rot & 1) ? blkHorizSplit : blkVertSplit)) { + blk->tag = blk->smallSplit ? blkTagLine : blkTagSuperLine; + } else { + blk->tag = blkTagColumn; + } + return; + } + + if (blk->type == blkLeaf) { + blk->tag = blkTagLine; + + } else { + if (blk->type == ((blk->rot & 1) ? blkVertSplit : blkHorizSplit)) { + blk->tag = blkTagColumn; + for (i = 0; i < blk->children->getLength(); ++i) { + child = (TextBlock *)blk->children->get(i); + if (child->tag != blkTagColumn && child->tag != blkTagLine) { + blk->tag = blkTagMulticolumn; + break; + } + } + } else { + if (blk->smallSplit) { + blk->tag = blkTagLine; + for (i = 0; i < blk->children->getLength(); ++i) { + child = (TextBlock *)blk->children->get(i); + if (child->tag != blkTagLine) { + blk->tag = blkTagMulticolumn; + break; + } + } + } else { + blk->tag = blkTagMulticolumn; + } + } + } +} + +// Insert a list of large characters into a tree. +void TextPage::insertLargeChars(GList *largeChars, TextBlock *blk) { + TextChar *ch, *ch2; + GBool singleLine; + double minOverlap; + int i; + + //~ this currently works only for characters in the primary rotation + + // check to see if the large chars are a single line + singleLine = gTrue; + for (i = 1; i < largeChars->getLength(); ++i) { + ch = (TextChar *)largeChars->get(i-1); + ch2 = (TextChar *)largeChars->get(i); + minOverlap = 0.5 * (ch->fontSize < ch2->fontSize ? ch->fontSize + : ch2->fontSize); + if (ch->yMax - ch2->yMin < minOverlap || + ch2->yMax - ch->yMin < minOverlap) { + singleLine = gFalse; + break; + } + } + + if (singleLine) { + // if the large chars are a single line, prepend them to the first + // leaf node in blk + insertLargeCharsInFirstLeaf(largeChars, blk); + } else { + // if the large chars are not a single line, prepend each one to + // the appropriate leaf node -- this handles cases like bullets + // drawn in a large font, on the left edge of a column + for (i = largeChars->getLength() - 1; i >= 0; --i) { + ch = (TextChar *)largeChars->get(i); + insertLargeCharInLeaf(ch, blk); + } + } +} + +// Find the first leaf (in depth-first order) in blk, and prepend a +// list of large chars. +void TextPage::insertLargeCharsInFirstLeaf(GList *largeChars, TextBlock *blk) { + TextChar *ch; + int i; + + if (blk->type == blkLeaf) { + for (i = largeChars->getLength() - 1; i >= 0; --i) { + ch = (TextChar *)largeChars->get(i); + blk->prependChild(ch); + } + } else { + insertLargeCharsInFirstLeaf(largeChars, (TextBlock *)blk->children->get(0)); + blk->updateBounds(0); + } +} + +// Find the leaf in where large char belongs, and prepend +// it. +void TextPage::insertLargeCharInLeaf(TextChar *ch, TextBlock *blk) { + TextBlock *child; + double y; + int i; + + //~ this currently works only for characters in the primary rotation + + //~ this currently just looks down the left edge of blk + //~ -- it could be extended to do more + + // estimate the baseline of ch + y = ch->yMin + 0.75 * (ch->yMax - ch->yMin); + + if (blk->type == blkLeaf) { + blk->prependChild(ch); + } else if (blk->type == blkHorizSplit) { + for (i = 0; i < blk->children->getLength(); ++i) { + child = (TextBlock *)blk->children->get(i); + if (y < child->yMax || i == blk->children->getLength() - 1) { + insertLargeCharInLeaf(ch, child); + blk->updateBounds(i); + break; + } + } + } else { + insertLargeCharInLeaf(ch, (TextBlock *)blk->children->get(0)); + blk->updateBounds(0); + } +} + +// Merge blk (rot != 0) into primaryTree (rot == 0). +void TextPage::insertIntoTree(TextBlock *blk, TextBlock *primaryTree) { + TextBlock *child; + + // we insert a whole column at a time - so call insertIntoTree + // recursively until we get to a column (or line) + + if (blk->tag == blkTagMulticolumn) { + while (blk->children->getLength()) { + child = (TextBlock *)blk->children->del(0); + insertIntoTree(child, primaryTree); + } + delete blk; + } else { + insertColumnIntoTree(blk, primaryTree); + } +} + +// Insert a column (as an atomic subtree) into tree. +// Requirement: tree is not a leaf node. +void TextPage::insertColumnIntoTree(TextBlock *column, TextBlock *tree) { + TextBlock *child; + int i; + + for (i = 0; i < tree->children->getLength(); ++i) { + child = (TextBlock *)tree->children->get(i); + if (child->tag == blkTagMulticolumn && + column->xMin >= child->xMin && + column->yMin >= child->yMin && + column->xMax <= child->xMax && + column->yMax <= child->yMax) { + insertColumnIntoTree(column, child); + tree->tag = blkTagMulticolumn; + return; + } + } + + if (tree->type == blkVertSplit) { + if (tree->rot == 1 || tree->rot == 2) { + for (i = 0; i < tree->children->getLength(); ++i) { + child = (TextBlock *)tree->children->get(i); + if (column->xMax > 0.5 * (child->xMin + child->xMax)) { + break; + } + } + } else { + for (i = 0; i < tree->children->getLength(); ++i) { + child = (TextBlock *)tree->children->get(i); + if (column->xMin < 0.5 * (child->xMin + child->xMax)) { + break; + } + } + } + } else if (tree->type == blkHorizSplit) { + if (tree->rot >= 2) { + for (i = 0; i < tree->children->getLength(); ++i) { + child = (TextBlock *)tree->children->get(i); + if (column->yMax > 0.5 * (child->yMin + child->yMax)) { + break; + } + } + } else { + for (i = 0; i < tree->children->getLength(); ++i) { + child = (TextBlock *)tree->children->get(i); + if (column->yMin < 0.5 * (child->yMin + child->yMax)) { + break; + } + } + } + } else { + // this should never happen + return; + } + tree->children->insert(i, column); + tree->tag = blkTagMulticolumn; +} + +// Insert clipped characters back into the TextBlock tree. +void TextPage::insertClippedChars(GList *clippedChars, TextBlock *tree) { + TextChar *ch, *ch2; + TextBlock *leaf; + double y; + int i; + + //~ this currently works only for characters in the primary rotation + + clippedChars->sort(TextChar::cmpX); + while (clippedChars->getLength()) { + ch = (TextChar *)clippedChars->del(0); + if (ch->rot != 0) { + continue; + } + if (!(leaf = findClippedCharLeaf(ch, tree))) { + continue; + } + leaf->addChild(ch, gFalse); + i = 0; + while (i < clippedChars->getLength()) { + ch2 = (TextChar *)clippedChars->get(i); + if (ch2->xMin > ch->xMax + clippedTextMaxWordSpace * ch->fontSize) { + break; + } + y = 0.5 * (ch2->yMin + ch2->yMax); + if (y > leaf->yMin && y < leaf->yMax) { + ch2 = (TextChar *)clippedChars->del(i); + leaf->addChild(ch2, gFalse); + ch = ch2; + } else { + ++i; + } + } + } +} + +// Find the leaf in to which clipped char can be appended. +// Returns NULL if there is no appropriate append point. +TextBlock *TextPage::findClippedCharLeaf(TextChar *ch, TextBlock *tree) { + TextBlock *ret, *child; + double y; + int i; + + //~ this currently works only for characters in the primary rotation + + y = 0.5 * (ch->yMin + ch->yMax); + if (tree->type == blkLeaf) { + if (tree->rot == 0) { + if (y > tree->yMin && y < tree->yMax && + ch->xMin <= tree->xMax + clippedTextMaxWordSpace * ch->fontSize) { + return tree; + } + } + } else { + for (i = 0; i < tree->children->getLength(); ++i) { + child = (TextBlock *)tree->children->get(i); + if ((ret = findClippedCharLeaf(ch, child))) { + return ret; + } + } + } + return NULL; +} + +// Convert the tree of TextBlocks into a list of TextColumns. +GList *TextPage::buildColumns(TextBlock *tree, GBool primaryLR) { + GList *columns; + + columns = new GList(); + buildColumns2(tree, columns, primaryLR); + return columns; +} + +void TextPage::buildColumns2(TextBlock *blk, GList *columns, GBool primaryLR) { + TextColumn *col; + int i; + + switch (blk->tag) { + case blkTagSuperLine: // should never happen + case blkTagLine: + case blkTagColumn: + col = buildColumn(blk); + columns->append(col); + break; + case blkTagMulticolumn: +#if 0 //~tmp + if (!primaryLR && blk->type == blkVertSplit) { + for (i = blk->children->getLength() - 1; i >= 0; --i) { + buildColumns2((TextBlock *)blk->children->get(i), columns, primaryLR); + } + } else { +#endif + for (i = 0; i < blk->children->getLength(); ++i) { + buildColumns2((TextBlock *)blk->children->get(i), columns, primaryLR); + } +#if 0 //~tmp + } +#endif + break; + } +} + +TextColumn *TextPage::buildColumn(TextBlock *blk) { + GList *lines, *parLines; + GList *paragraphs; + TextLine *line0, *line1; + GBool dropCap; + double spaceThresh, indent0, indent1, fontSize0, fontSize1; + int i; + + lines = new GList(); + buildLines(blk, lines, gFalse); + + spaceThresh = paragraphSpacingThreshold * getAverageLineSpacing(lines); + + //~ could look for bulleted lists here: look for the case where + //~ all out-dented lines start with the same char + + //~ this doesn't handle right-to-left scripts (need to look for indents + //~ on the right instead of left, etc.) + + // build the paragraphs + paragraphs = new GList(); + i = 0; + while (i < lines->getLength()) { + + // get the first line of the paragraph + parLines = new GList(); + dropCap = gFalse; + line0 = (TextLine *)lines->get(i); + parLines->append(line0); + ++i; + + if (i < lines->getLength()) { + line1 = (TextLine *)lines->get(i); + indent0 = getLineIndent(line0, blk); + indent1 = getLineIndent(line1, blk); + fontSize0 = line0->fontSize; + fontSize1 = line1->fontSize; + + // inverted indent + if (indent1 - indent0 > minParagraphIndent * fontSize0 && + fabs(fontSize0 - fontSize1) <= paragraphFontSizeDelta && + getLineSpacing(line0, line1) <= spaceThresh) { + parLines->append(line1); + indent0 = indent1; + for (++i; i < lines->getLength(); ++i) { + line1 = (TextLine *)lines->get(i); + indent1 = getLineIndent(line1, blk); + fontSize1 = line1->fontSize; + if (indent0 - indent1 > minParagraphIndent * fontSize0) { + break; + } + if (fabs(fontSize0 - fontSize1) > paragraphFontSizeDelta) { + break; + } + if (getLineSpacing((TextLine *)lines->get(i - 1), line1) + > spaceThresh) { + break; + } + parLines->append(line1); + } + + // drop cap + } else if (fontSize0 > largeCharThreshold * fontSize1 && + indent1 - indent0 > minParagraphIndent * fontSize1 && + getLineSpacing(line0, line1) < 0) { + dropCap = gTrue; + parLines->append(line1); + fontSize0 = fontSize1; + for (++i; i < lines->getLength(); ++i) { + line1 = (TextLine *)lines->get(i); + indent1 = getLineIndent(line1, blk); + if (indent1 - indent0 <= minParagraphIndent * fontSize0) { + break; + } + if (getLineSpacing((TextLine *)lines->get(i - 1), line1) + > spaceThresh) { + break; + } + parLines->append(line1); + } + for (; i < lines->getLength(); ++i) { + line1 = (TextLine *)lines->get(i); + indent1 = getLineIndent(line1, blk); + fontSize1 = line1->fontSize; + if (indent1 - indent0 > minParagraphIndent * fontSize0) { + break; + } + if (fabs(fontSize0 - fontSize1) > paragraphFontSizeDelta) { + break; + } + if (getLineSpacing((TextLine *)lines->get(i - 1), line1) + > spaceThresh) { + break; + } + parLines->append(line1); + } + + // regular indent or no indent + } else if (fabs(fontSize0 - fontSize1) <= paragraphFontSizeDelta && + getLineSpacing(line0, line1) <= spaceThresh) { + parLines->append(line1); + indent0 = indent1; + for (++i; i < lines->getLength(); ++i) { + line1 = (TextLine *)lines->get(i); + indent1 = getLineIndent(line1, blk); + fontSize1 = line1->fontSize; + if (indent1 - indent0 > minParagraphIndent * fontSize0) { + break; + } + if (fabs(fontSize0 - fontSize1) > paragraphFontSizeDelta) { + break; + } + if (getLineSpacing((TextLine *)lines->get(i - 1), line1) + > spaceThresh) { + break; + } + parLines->append(line1); + } + } + } + + paragraphs->append(new TextParagraph(parLines, dropCap)); + } + + delete lines; + + return new TextColumn(paragraphs, blk->xMin, blk->yMin, + blk->xMax, blk->yMax); +} + +double TextPage::getLineIndent(TextLine *line, TextBlock *blk) { + double indent; + + switch (line->rot) { + case 0: + default: indent = line->xMin - blk->xMin; break; + case 1: indent = line->yMin - blk->yMin; break; + case 2: indent = blk->xMax - line->xMax; break; + case 3: indent = blk->yMax - line->yMax; break; + } + return indent; +} + +// Compute average line spacing in column. +double TextPage::getAverageLineSpacing(GList *lines) { + double avg, sp; + int n, i; + + avg = 0; + n = 0; + for (i = 1; i < lines->getLength(); ++i) { + sp = getLineSpacing((TextLine *)lines->get(i - 1), + (TextLine *)lines->get(i)); + if (sp > 0) { + avg += sp; + ++n; + } + } + if (n > 0) { + avg /= n; + } + return avg; +} + +// Compute the space between two lines. +double TextPage::getLineSpacing(TextLine *line0, TextLine *line1) { + double sp; + + switch (line0->rot) { + case 0: + default: sp = line1->yMin - line0->yMax; break; + case 1: sp = line0->xMin - line1->xMax; break; + case 2: sp = line0->yMin - line1->yMin; break; + case 3: sp = line1->xMin - line1->xMax; break; + } + return sp; +} + +void TextPage::buildLines(TextBlock *blk, GList *lines, + GBool splitSuperLines) { + TextLine *line; + int i; + + if (blk->tag == blkTagLine || + (blk->tag == blkTagSuperLine && !splitSuperLines)) { + line = buildLine(blk); + if (blk->rot == 1 || blk->rot == 2) { + lines->insert(0, line); + } else { + lines->append(line); + } + } else { + for (i = 0; i < blk->children->getLength(); ++i) { + buildLines((TextBlock *)blk->children->get(i), lines, splitSuperLines); + } + } +} + +GList *TextPage::buildSimple2Columns(GList *charsA) { + GList *columns, *paragraphs, *lines; + TextParagraph *paragraph; + int rot; + + charsA->sort(&TextChar::cmpX); + columns = new GList(); + for (rot = 0; rot < 4; ++rot) { + lines = buildSimple2Lines(charsA, rot); + if (lines->getLength() == 0) { + delete lines; + continue; + } + paragraph = new TextParagraph(lines, gFalse); + paragraphs = new GList(); + paragraphs->append(paragraph); + columns->append(new TextColumn(paragraphs, + paragraph->xMin, paragraph->yMin, + paragraph->xMax, paragraph->yMax)); + } + return columns; +} + +GList *TextPage::buildSimple2Lines(GList *charsA, int rot) { + GList *openCharLines, *lines; + TextCharLine *firstCharLine, *lastCharLine, *charLine, *p; + TextChar *ch; + TextLine *line; + double bestOverlap, overlap, xMin, yMin, xMax, yMax; + int bestLine, i, j, k, m; + + firstCharLine = lastCharLine = NULL; + openCharLines = new GList(); + for (i = 0; i < charsA->getLength(); ++i) { + ch = (TextChar *)charsA->get(i); + if (ch->rot != rot) { + continue; + } + + // find the first open line with line.yMax > ch.yMin + j = -1; + k = openCharLines->getLength(); + while (j < k - 1) { + // invariants: openLines[j].yMax <= ch.yMin (or j = -1) + // openLines[k].yMax > ch.yMin (or k = nOpenLines) + // j < k - 1 + m = j + (k - j) / 2; + charLine = (TextCharLine *)openCharLines->get(m); + if (charLine->yMax <= ch->yMin) { + j = m; + } else { + k = m; + } + } + + // check overlap for all overlapping lines + // i.e., all lines with line.yMin < ch.yMax and line.yMax > ch.yMin + bestLine = -1; + bestOverlap = 0; + for (; k < openCharLines->getLength(); ++k) { + charLine = (TextCharLine *)openCharLines->get(k); + if (charLine->yMin >= ch->yMax) { + break; + } + overlap = ((ch->yMax < charLine->yMax ? ch->yMax : charLine->yMax) + - (ch->yMin > charLine->yMin ? ch->yMin : charLine->yMin)) + / (ch->yMax - ch->yMin); + if (overlap > bestOverlap) { + bestLine = k; + bestOverlap = overlap; + } + } + + // found an overlapping line + if (bestLine >= 0 && bestOverlap > simple2MinOverlap) { + k = bestLine; + charLine = (TextCharLine *)openCharLines->get(k); + + // else insert a new line immediately before line k + } else { + charLine = new TextCharLine(ch->rot); + if (k < openCharLines->getLength()) { + p = (TextCharLine *)openCharLines->get(k); + if (p->prev) { + p->prev->next = charLine; + charLine->prev = p->prev; + } else { + firstCharLine = charLine; + } + p->prev = charLine; + charLine->next = p; + } else { + if (lastCharLine) { + lastCharLine->next = charLine; + charLine->prev = lastCharLine; + } else { + firstCharLine = charLine; + } + lastCharLine = charLine; + } + openCharLines->insert(k, charLine); + } + + // add the char to the line + charLine->add(ch); + charLine->yMin = ch->yMin; + charLine->yMax = ch->yMax; + + // update open lines before k + j = k - 1; + while (j >= 0) { + charLine = (TextCharLine *)openCharLines->get(j); + if (charLine->yMax <= ch->yMin) { + break; + } + charLine->yMax = ch->yMin; + if (charLine->yMin < charLine->yMax) { + break; + } + openCharLines->del(j); + --j; + } + + // update open lines after k + j = k + 1; + while (j < openCharLines->getLength()) { + charLine = (TextCharLine *)openCharLines->get(j); + if (charLine->yMin >= ch->yMax) { + break; + } + charLine->yMin = ch->yMax; + if (charLine->yMin < charLine->yMax) { + break; + } + openCharLines->del(j); + } + } + + // build TextLine objects + lines = new GList(); + for (charLine = firstCharLine; charLine; charLine = p) { + xMin = yMin = xMax = yMax = 0; + for (j = 0; j < charLine->chars->getLength(); ++j) { + ch = (TextChar *)charLine->chars->get(j); + if (j == 0) { + xMin = ch->xMin; + yMin = ch->yMin; + xMax = ch->xMax; + yMax = ch->yMax; + } else { + if (ch->xMin < xMin) { + xMin = ch->xMin; + } + if (ch->yMin < yMin) { + yMin = ch->yMin; + } + if (ch->xMax < xMax) { + xMax = ch->xMax; + } + if (ch->yMax < yMax) { + yMax = ch->yMax; + } + } + } + // the chars have been rotated to 0, without changing the + // TextChar.rot values, so we need to tell buildLine to use rot=0, + // and then set the word and line rotation correctly afterward + line = buildLine(charLine->chars, 0, xMin, yMin, xMax, yMax); + line->rot = charLine->rot; + for (i = 0; i < line->words->getLength(); ++i) { + ((TextWord *)line->words->get(i))->rot = (char)charLine->rot; + } + lines->append(line); + p = charLine->next; + delete charLine; + } + + delete openCharLines; + + return lines; +} + +TextLine *TextPage::buildLine(TextBlock *blk) { + GList *charsA; + + charsA = new GList(); + getLineChars(blk, charsA); + TextLine *line = buildLine(charsA, blk->rot, + blk->xMin, blk->yMin, blk->xMax, blk->yMax); + delete charsA; + return line; +} + +TextLine *TextPage::buildLine(GList *charsA, int rot, + double xMin, double yMin, + double xMax, double yMax) { + GList *words; + TextChar *ch, *ch2; + TextWord *word; + double wordSp, lineFontSize, sp; + int dir, dir2; + GBool rotated, spaceAfter, spaceBefore; + int i, j; + + wordSp = computeWordSpacingThreshold(charsA, rot); + + words = new GList(); + lineFontSize = 0; + spaceBefore = gFalse; + i = 0; + while (i < charsA->getLength()) { + sp = wordSp - 1; + spaceAfter = gFalse; + dir = getCharDirection( + (TextChar *)charsA->get(i), + (i > 0 && !spaceAfter) ? (TextChar *)charsA->get(i-1) + : (TextChar *)NULL, + (i < charsA->getLength() - 1) ? (TextChar *)charsA->get(i+1) + : (TextChar *)NULL); + rotated = ((TextChar *)charsA->get(i))->rotated; + for (j = i+1; j < charsA->getLength(); ++j) { + ch = (TextChar *)charsA->get(j-1); + ch2 = (TextChar *)charsA->get(j); + sp = (rot & 1) ? (ch2->yMin - ch->yMax) : (ch2->xMin - ch->xMax); + if (sp > wordSp) { + spaceAfter = gTrue; + break; + } + // look for significant overlaps, which can happen with clipped + // characters (among other things) + if (sp < -ch->fontSize) { + spaceAfter = gTrue; + break; + } + dir2 = getCharDirection( + ch2, ch, + (j < charsA->getLength() - 1) ? (TextChar *)charsA->get(j+1) + : (TextChar *)NULL); + if (ch->font != ch2->font || + fabs(ch->fontSize - ch2->fontSize) > 0.01 || + (control.splitRotatedWords && ch2->rotated != rotated) || + (dir && dir2 && dir2 != dir) || + (control.mode == textOutRawOrder && + ch2->charPos != ch->charPos + ch->charLen)) { + break; + } + if (!dir && dir2) { + dir = dir2; + } + sp = wordSp - 1; + } + word = new TextWord(charsA, i, j - i, rot, rotated, dir, + (rot >= 2) ? spaceBefore : spaceAfter); + spaceBefore = spaceAfter; + i = j; + if (rot >= 2) { + words->insert(0, word); + } else { + words->append(word); + } + if (i == 0 || word->fontSize > lineFontSize) { + lineFontSize = word->fontSize; + } + } + + return new TextLine(words, xMin, yMin, xMax, yMax, lineFontSize); +} + +void TextPage::getLineChars(TextBlock *blk, GList *charsA) { + int i; + + if (blk->type == blkLeaf) { + charsA->append(blk->children); + } else { + for (i = 0; i < blk->children->getLength(); ++i) { + getLineChars((TextBlock *)blk->children->get(i), charsA); + } + } +} + +// Compute the inter-word spacing threshold for a line of chars. +// Spaces greater than this threshold will be considered inter-word +// spaces. +double TextPage::computeWordSpacingThreshold(GList *charsA, int rot) { + TextChar *ch, *ch2; + double uniformSp, wordSp; + double avgFontSize; + double minAdjGap, maxAdjGap, minSpGap, maxSpGap, minGap, maxGap, gap, gap2; + int i; + + if (control.mode == textOutTableLayout) { + uniformSp = tableModeUniformSpacing; + wordSp = tableModeWordSpacing; + } else { + uniformSp = uniformSpacing; + wordSp = wordSpacing; + } + + avgFontSize = 0; + minGap = maxGap = 0; + minAdjGap = minSpGap = 1; + maxAdjGap = maxSpGap = 0; + for (i = 0; i < charsA->getLength(); ++i) { + ch = (TextChar *)charsA->get(i); + avgFontSize += ch->fontSize; + if (i < charsA->getLength() - 1) { + ch2 = (TextChar *)charsA->get(i+1); + gap = (rot & 1) ? (ch2->yMin - ch->yMax) : (ch2->xMin - ch->xMax); + if (ch->spaceAfter) { + if (minSpGap > maxSpGap) { + minSpGap = maxSpGap = gap; + } else if (gap < minSpGap) { + minSpGap = gap; + } else if (gap > maxSpGap) { + maxSpGap = gap; + } + } else { + if (minAdjGap > maxAdjGap) { + minAdjGap = maxAdjGap = gap; + } else if (gap < minAdjGap) { + minAdjGap = gap; + } else if (gap > maxAdjGap) { + maxAdjGap = gap; + } + } + if (i == 0 || gap < minGap) { + minGap = gap; + } + if (gap > maxGap) { + maxGap = gap; + } + } + } + avgFontSize /= charsA->getLength(); + if (minGap < 0) { + minGap = 0; + } + + // if spacing is nearly uniform (minGap is close to maxGap), there + // are three cases: + // (1) if the SpGap and AdjGap values are both available and + // sensible, use them + // (2) if only the SpGap values are available, meaning that every + // character in the line had a space after it, split after every + // character + // (3) otherwise assume it's a single word (technically it could be + // either "ABC" or "A B C", but it's essentially impossible to + // tell) + if (maxGap - minGap < uniformSp * avgFontSize) { + if (minSpGap <= maxSpGap) { + if (minAdjGap <= maxAdjGap && + minSpGap - maxAdjGap > 0.01) { + return 0.5 * (maxAdjGap + minSpGap); + } else if (minAdjGap > maxAdjGap && + maxSpGap - minSpGap < uniformSp * avgFontSize) { + return minSpGap - 1; + } + } + return maxGap + 1; + + // if there is some variation in spacing, but it's small, assume + // there are some inter-word spaces + } else if (maxGap - minGap < wordSp * avgFontSize) { + return 0.5 * (minGap + maxGap); + + // if there is a large variation in spacing, use the SpGap/AdjGap + // values if they look reasonable, otherwise, assume a reasonable + // threshold for inter-word spacing (we can't use something like + // 0.5*(minGap+maxGap) here because there can be outliers at the + // high end) + } else { + if (minAdjGap <= maxAdjGap && + minSpGap <= maxSpGap && + minSpGap - maxAdjGap > uniformSp * avgFontSize) { + gap = wordSp * avgFontSize; + gap2 = 0.5 * (minSpGap - minGap); + return minGap + (gap < gap2 ? gap : gap2); + } else { + return minGap + wordSp * avgFontSize; + } + } +} + +// Check the character's direction: returns 1 for L or Num; -1 for R; 0 +// for others. +int TextPage::getCharDirection(TextChar *ch) { + if (unicodeTypeL(ch->c) || unicodeTypeNum(ch->c)) { + return 1; + } + if (unicodeTypeR(ch->c)) { + return -1; + } + return 0; +} + +// Check the character's direction, in the context of the left and +// right neighboring characters (either of which may be NULL). +// Returns 1 for L or Num; -1 for R; 0 for others. +int TextPage::getCharDirection(TextChar *ch, TextChar *left, TextChar *right) { + GBool open; + Unicode opposite; + if (unicodeBracketInfo(ch->c, &open, &opposite)) { + // bracket takes the direction of the first char inside the bracket + Unicode first = 0; + if (open && right) { + first = right->c; + } else if (!open && left) { + first = left->c; + } + if (unicodeTypeL(first) || unicodeTypeNum(first)) { + return 1; + } + if (unicodeTypeR(first)) { + return -1; + } + return 0; + } else if (unicodeTypeNumSep(ch->c)) { + // numeric separator is numeric if either side is a digit; neutral + // otherwise + if ((left && unicodeTypeDigit(left->c)) || + (right && unicodeTypeDigit(right->c))) { + return 1; + } + return 0; + } else { + if (unicodeTypeL(ch->c) || unicodeTypeDigit(ch->c)) { + return 1; + } + if (unicodeTypeR(ch->c)) { + return -1; + } + return 0; + } +} + +int TextPage::assignPhysLayoutPositions(GList *columns) { + assignLinePhysPositions(columns); + return assignColumnPhysPositions(columns); +} + +// Assign a physical x coordinate for each TextLine (relative to the +// containing TextColumn). This also computes TextColumn width and +// height. +void TextPage::assignLinePhysPositions(GList *columns) { + TextColumn *col; + TextParagraph *par; + TextLine *line; + UnicodeMap *uMap; + int colIdx, parIdx, lineIdx; + + if (!(uMap = globalParams->getTextEncoding())) { + return; + } + + for (colIdx = 0; colIdx < columns->getLength(); ++colIdx) { + col = (TextColumn *)columns->get(colIdx); + col->pw = col->ph = 0; + for (parIdx = 0; parIdx < col->paragraphs->getLength(); ++parIdx) { + par = (TextParagraph *)col->paragraphs->get(parIdx); + for (lineIdx = 0; lineIdx < par->lines->getLength(); ++lineIdx) { + line = (TextLine *)par->lines->get(lineIdx); + computeLinePhysWidth(line, uMap); + if (control.fixedPitch > 0) { + line->px = (int)((line->xMin - col->xMin) / control.fixedPitch); + } else if (fabs(line->fontSize) < 0.001) { + line->px = 0; + } else { + line->px = (int)((line->xMin - col->xMin) / + (physLayoutSpaceWidth * line->fontSize)); + } + if (line->px + line->pw > col->pw) { + col->pw = line->px + line->pw; + } + } + col->ph += par->lines->getLength(); + } + col->ph += col->paragraphs->getLength() - 1; + } + + uMap->decRefCnt(); +} + +void TextPage::computeLinePhysWidth(TextLine *line, UnicodeMap *uMap) { + char buf[8]; + int n, i; + + if (uMap->isUnicode()) { + line->pw = line->len; + } else { + line->pw = 0; + for (i = 0; i < line->len; ++i) { + n = uMap->mapUnicode(line->text[i], buf, sizeof(buf)); + line->pw += n; + } + } +} + +// Assign physical x and y coordinates for each TextColumn. Returns +// the text height (max physical y + 1). +int TextPage::assignColumnPhysPositions(GList *columns) { + TextColumn *col, *col2; + double slack, xOverlap, yOverlap; + int ph, i, j; + + if (control.mode == textOutTableLayout) { + slack = tableCellOverlapSlack; + } else { + slack = 0; + } + + // assign x positions + columns->sort(&TextColumn::cmpX); + for (i = 0; i < columns->getLength(); ++i) { + col = (TextColumn *)columns->get(i); + if (control.fixedPitch) { + col->px = (int)(col->xMin / control.fixedPitch); + } else { + col->px = 0; + for (j = 0; j < i; ++j) { + col2 = (TextColumn *)columns->get(j); + xOverlap = col2->xMax - col->xMin; + if (xOverlap < slack * (col2->xMax - col2->xMin)) { + if (col2->px + col2->pw + 2 > col->px) { + col->px = col2->px + col2->pw + 2; + } + } else { + yOverlap = (col->yMax < col2->yMax ? col->yMax : col2->yMax) - + (col->yMin > col2->yMin ? col->yMin : col2->yMin); + if (yOverlap > 0 && xOverlap < yOverlap) { + if (col2->px + col2->pw > col->px) { + col->px = col2->px + col2->pw; + } + } else { + if (col2->px > col->px) { + col->px = col2->px; + } + } + } + } + } + } + + // assign y positions + ph = 0; + columns->sort(&TextColumn::cmpY); + for (i = 0; i < columns->getLength(); ++i) { + col = (TextColumn *)columns->get(i); + col->py = 0; + for (j = 0; j < i; ++j) { + col2 = (TextColumn *)columns->get(j); + yOverlap = col2->yMax - col->yMin; + if (yOverlap < slack * (col2->yMax - col2->yMin)) { + if (col2->py + col2->ph + 1 > col->py) { + col->py = col2->py + col2->ph + 1; + } + } else { + xOverlap = (col->xMax < col2->xMax ? col->xMax : col2->xMax) - + (col->xMin > col2->xMin ? col->xMin : col2->xMin); + if (xOverlap > 0 && yOverlap < xOverlap) { + if (col2->py + col2->ph > col->py) { + col->py = col2->py + col2->ph; + } + } else { + if (col2->py > col->py) { + col->py = col2->py; + } + } + } + } + if (col->py + col->ph > ph) { + ph = col->py + col->ph; + } + } + + return ph; +} + +void TextPage::buildSuperLines(TextBlock *blk, GList *superLines) { + GList *lines; + int i; + + if (blk->tag == blkTagLine || blk->tag == blkTagSuperLine) { + lines = new GList(); + buildLines(blk, lines, gTrue); + superLines->append(new TextSuperLine(lines)); + } else { + for (i = 0; i < blk->children->getLength(); ++i) { + buildSuperLines((TextBlock *)blk->children->get(i), superLines); + } + } +} + +void TextPage::assignSimpleLayoutPositions(GList *superLines, + UnicodeMap *uMap) { + GList *lines; + TextLine *line0, *line1; + double xMin, xMax; + int px, px2, sp, i, j; + + // build a list of lines and sort by x + lines = new GList(); + for (i = 0; i < superLines->getLength(); ++i) { + lines->append(((TextSuperLine *)superLines->get(i))->lines); + } + lines->sort(&TextLine::cmpX); + + // assign positions + xMin = ((TextLine *)lines->get(0))->xMin; + for (i = 0; i < lines->getLength(); ++i) { + line0 = (TextLine *)lines->get(i); + computeLinePhysWidth(line0, uMap); + px = 0; + xMax = xMin; + for (j = 0; j < i; ++j) { + line1 = (TextLine *)lines->get(j); + if (line0->xMin > line1->xMax) { + if (line1->xMax > xMax) { + xMax = line1->xMax; + } + px2 = line1->px + line1->pw; + if (px2 > px) { + px = px2; + } + } + } + sp = (int)((line0->xMin - xMax) / (0.5 * line0->fontSize) + 0.5); + if (sp < 1 && xMax > xMin) { + sp = 1; + } + line0->px = px + sp; + } + + delete lines; +} + +void TextPage::generateUnderlinesAndLinks(GList *columns) { + TextColumn *col; + TextParagraph *par; + TextLine *line; + TextWord *word; + TextUnderline *underline; + TextLink *link; + double base, uSlack, ubSlack, hSlack; + int colIdx, parIdx, lineIdx, wordIdx, i; + + for (colIdx = 0; colIdx < columns->getLength(); ++colIdx) { + col = (TextColumn *)columns->get(colIdx); + for (parIdx = 0; parIdx < col->paragraphs->getLength(); ++parIdx) { + par = (TextParagraph *)col->paragraphs->get(parIdx); + for (lineIdx = 0; lineIdx < par->lines->getLength(); ++lineIdx) { + line = (TextLine *)par->lines->get(lineIdx); + for (wordIdx = 0; wordIdx < line->words->getLength(); ++wordIdx) { + word = (TextWord *)line->words->get(wordIdx); + base = word->getBaseline(); + uSlack = underlineSlack * word->fontSize; + ubSlack = underlineBaselineSlack * word->fontSize; + hSlack = hyperlinkSlack * word->fontSize; + + //----- handle underlining + for (i = 0; i < underlines->getLength(); ++i) { + underline = (TextUnderline *)underlines->get(i); + if (underline->horiz) { + if (word->rot == 0 || word->rot == 2) { + if (fabs(underline->y0 - base) < ubSlack && + underline->x0 < word->xMin + uSlack && + word->xMax - uSlack < underline->x1) { + word->underlined = gTrue; + } + } + } else { + if (word->rot == 1 || word->rot == 3) { + if (fabs(underline->x0 - base) < ubSlack && + underline->y0 < word->yMin + uSlack && + word->yMax - uSlack < underline->y1) { + word->underlined = gTrue; + } + } + } + } + + //----- handle links + for (i = 0; i < links->getLength(); ++i) { + link = (TextLink *)links->get(i); + if (link->xMin < word->xMin + hSlack && + word->xMax - hSlack < link->xMax && + link->yMin < word->yMin + hSlack && + word->yMax - hSlack < link->yMax) { + word->link = link; + } + } + } + } + } + } +} + +//------------------------------------------------------------------------ +// TextPage: access +//------------------------------------------------------------------------ + +GBool TextPage::findText(Unicode *s, int len, + GBool startAtTop, GBool stopAtBottom, + GBool startAtLast, GBool stopAtLast, + GBool caseSensitive, GBool backward, + GBool wholeWord, + double *xMin, double *yMin, + double *xMax, double *yMax) { + TextColumn *column; + TextParagraph *par; + TextLine *line; + Unicode *s2, *txt; + Unicode *p; + double xStart, yStart, xStop, yStop; + double xMin0, yMin0, xMax0, yMax0; + double xMin1, yMin1, xMax1, yMax1; + GBool found; + int txtSize, m, colIdx, parIdx, lineIdx, i, j, k; + + //~ need to handle right-to-left text + //~ - pass primaryLR to buildColumns + + buildFindCols(); + + // convert the search string to lowercase + if (!caseSensitive) { + s2 = (Unicode *)gmallocn(len, sizeof(Unicode)); + for (i = 0; i < len; ++i) { + s2[i] = unicodeToLower(s[i]); + } + } else { + s2 = s; + } + + txt = NULL; + txtSize = 0; + + xStart = yStart = xStop = yStop = 0; + if (startAtLast && haveLastFind) { + xStart = lastFindXMin; + yStart = lastFindYMin; + } else if (!startAtTop) { + xStart = *xMin; + yStart = *yMin; + } + if (stopAtLast && haveLastFind) { + xStop = lastFindXMin; + yStop = lastFindYMin; + } else if (!stopAtBottom) { + xStop = *xMax; + yStop = *yMax; + } + + found = gFalse; + xMin0 = xMax0 = yMin0 = yMax0 = 0; // make gcc happy + xMin1 = xMax1 = yMin1 = yMax1 = 0; // make gcc happy + + for (colIdx = backward ? findCols->getLength() - 1 : 0; + backward ? colIdx >= 0 : colIdx < findCols->getLength(); + colIdx += backward ? -1 : 1) { + column = (TextColumn *)findCols->get(colIdx); + + // check: is the column above the top limit? + if (!startAtTop && (backward ? column->yMin > yStart + : column->yMax < yStart)) { + continue; + } + + // check: is the column below the bottom limit? + if (!stopAtBottom && (backward ? column->yMax < yStop + : column->yMin > yStop)) { + continue; + } + + for (parIdx = backward ? column->paragraphs->getLength() - 1 : 0; + backward ? parIdx >= 0 : parIdx < column->paragraphs->getLength(); + parIdx += backward ? -1 : 1) { + par = (TextParagraph *)column->paragraphs->get(parIdx); + + // check: is the paragraph above the top limit? + if (!startAtTop && (backward ? par->yMin > yStart + : par->yMax < yStart)) { + continue; + } + + // check: is the paragraph below the bottom limit? + if (!stopAtBottom && (backward ? par->yMax < yStop + : par->yMin > yStop)) { + continue; + } + + for (lineIdx = backward ? par->lines->getLength() - 1 : 0; + backward ? lineIdx >= 0 : lineIdx < par->lines->getLength(); + lineIdx += backward ? -1 : 1) { + line = (TextLine *)par->lines->get(lineIdx); + + // check: is the line above the top limit? + if (!startAtTop && (backward ? line->yMin > yStart + : line->yMax < yStart)) { + continue; + } + + // check: is the line below the bottom limit? + if (!stopAtBottom && (backward ? line->yMax < yStop + : line->yMin > yStop)) { + continue; + } + + // convert the line to lowercase + m = line->len; + if (!caseSensitive) { + if (m > txtSize) { + txt = (Unicode *)greallocn(txt, m, sizeof(Unicode)); + txtSize = m; + } + for (k = 0; k < m; ++k) { + txt[k] = unicodeToLower(line->text[k]); + } + } else { + txt = line->text; + } + + // search each position in this line + j = backward ? m - len : 0; + p = txt + j; + while (backward ? j >= 0 : j <= m - len) { + if (!wholeWord || + ((j == 0 || !unicodeTypeWord(txt[j - 1])) && + (j + len == m || !unicodeTypeWord(txt[j + len])))) { + + // compare the strings + for (k = 0; k < len; ++k) { + if (p[k] != s2[k]) { + break; + } + } + + // found it + if (k == len) { + switch (line->rot) { + case 0: + xMin1 = line->edge[j]; + xMax1 = line->edge[j + len]; + yMin1 = line->yMin; + yMax1 = line->yMax; + break; + case 1: + xMin1 = line->xMin; + xMax1 = line->xMax; + yMin1 = line->edge[j]; + yMax1 = line->edge[j + len]; + break; + case 2: + xMin1 = line->edge[j + len]; + xMax1 = line->edge[j]; + yMin1 = line->yMin; + yMax1 = line->yMax; + break; + case 3: + xMin1 = line->xMin; + xMax1 = line->xMax; + yMin1 = line->edge[j + len]; + yMax1 = line->edge[j]; + break; + } + if (backward) { + if ((startAtTop || + yMin1 < yStart || (yMin1 == yStart && xMin1 < xStart)) && + (stopAtBottom || + yMin1 > yStop || (yMin1 == yStop && xMin1 > xStop))) { + if (!found || + yMin1 > yMin0 || (yMin1 == yMin0 && xMin1 > xMin0)) { + xMin0 = xMin1; + xMax0 = xMax1; + yMin0 = yMin1; + yMax0 = yMax1; + found = gTrue; + } + } + } else { + if ((startAtTop || + yMin1 > yStart || (yMin1 == yStart && xMin1 > xStart)) && + (stopAtBottom || + yMin1 < yStop || (yMin1 == yStop && xMin1 < xStop))) { + if (!found || + yMin1 < yMin0 || (yMin1 == yMin0 && xMin1 < xMin0)) { + xMin0 = xMin1; + xMax0 = xMax1; + yMin0 = yMin1; + yMax0 = yMax1; + found = gTrue; + } + } + } + } + } + if (backward) { + --j; + --p; + } else { + ++j; + ++p; + } + } + } + } + } + + if (!caseSensitive) { + gfree(s2); + gfree(txt); + } + + if (found) { + *xMin = xMin0; + *xMax = xMax0; + *yMin = yMin0; + *yMax = yMax0; + lastFindXMin = xMin0; + lastFindYMin = yMin0; + haveLastFind = gTrue; + return gTrue; + } + + return gFalse; +} + +GString *TextPage::getText(double xMin, double yMin, + double xMax, double yMax, GBool forceEOL) { + UnicodeMap *uMap; + char space[8], eol[16]; + int spaceLen, eolLen; + GList *chars2; + GString **out; + int *outLen; + TextColumn *col; + TextParagraph *par; + TextLine *line; + TextChar *ch; + GBool primaryLR; + TextBlock *tree; + GList *columns; + GString *ret; + double xx, yy; + int rot, colIdx, parIdx, lineIdx, ph, y, i; + + // get the output encoding + if (!(uMap = globalParams->getTextEncoding())) { + return NULL; + } + spaceLen = uMap->mapUnicode(0x20, space, sizeof(space)); + eolLen = 0; // make gcc happy + switch (globalParams->getTextEOL()) { + case eolUnix: + eolLen = uMap->mapUnicode(0x0a, eol, sizeof(eol)); + break; + case eolDOS: + eolLen = uMap->mapUnicode(0x0d, eol, sizeof(eol)); + eolLen += uMap->mapUnicode(0x0a, eol + eolLen, (int)sizeof(eol) - eolLen); + break; + case eolMac: + eolLen = uMap->mapUnicode(0x0d, eol, sizeof(eol)); + break; + } + + // get all chars in the rectangle + // (i.e., all chars whose center lies inside the rectangle) + chars2 = new GList(); + for (i = 0; i < chars->getLength(); ++i) { + ch = (TextChar *)chars->get(i); + xx = 0.5 * (ch->xMin + ch->xMax); + yy = 0.5 * (ch->yMin + ch->yMax); + if (xx > xMin && xx < xMax && yy > yMin && yy < yMax) { + chars2->append(ch); + } + } +#if 0 //~debug + dumpChars(chars2); +#endif + + rot = rotateChars(chars2); + primaryLR = checkPrimaryLR(chars2); + tree = splitChars(chars2); + if (!tree) { + unrotateChars(chars2, rot); + delete chars2; + return new GString(); + } +#if 0 //~debug + dumpTree(tree); +#endif + columns = buildColumns(tree, primaryLR); + delete tree; + ph = assignPhysLayoutPositions(columns); +#if 0 //~debug + dumpColumns(columns); +#endif + unrotateChars(chars2, rot); + delete chars2; + + out = (GString **)gmallocn(ph, sizeof(GString *)); + outLen = (int *)gmallocn(ph, sizeof(int)); + for (i = 0; i < ph; ++i) { + out[i] = NULL; + outLen[i] = 0; + } + + columns->sort(&TextColumn::cmpPX); + for (colIdx = 0; colIdx < columns->getLength(); ++colIdx) { + col = (TextColumn *)columns->get(colIdx); + y = col->py; + for (parIdx = 0; + parIdx < col->paragraphs->getLength() && y < ph; + ++parIdx) { + par = (TextParagraph *)col->paragraphs->get(parIdx); + for (lineIdx = 0; + lineIdx < par->lines->getLength() && y < ph; + ++lineIdx) { + line = (TextLine *)par->lines->get(lineIdx); + if (!out[y]) { + out[y] = new GString(); + } + while (outLen[y] < col->px + line->px) { + out[y]->append(space, spaceLen); + ++outLen[y]; + } + encodeFragment(line->text, line->len, uMap, primaryLR, out[y]); + outLen[y] += line->pw; + ++y; + } + if (parIdx + 1 < col->paragraphs->getLength()) { + ++y; + } + } + } + + ret = new GString(); + for (i = 0; i < ph; ++i) { + if (out[i]) { + ret->append(out[i]); + delete out[i]; + } + if (ph > 1 || forceEOL) { + ret->append(eol, eolLen); + } + } + + gfree(out); + gfree(outLen); + deleteGList(columns, TextColumn); + uMap->decRefCnt(); + + return ret; +} + +GBool TextPage::findCharRange(int pos, int length, + double *xMin, double *yMin, + double *xMax, double *yMax) { + TextChar *ch; + double xMin2, yMin2, xMax2, yMax2; + GBool first; + int i; + + //~ this doesn't correctly handle ranges split across multiple lines + //~ (the highlighted region is the bounding box of all the parts of + //~ the range) + + xMin2 = yMin2 = xMax2 = yMax2 = 0; + first = gTrue; + for (i = 0; i < chars->getLength(); ++i) { + ch = (TextChar *)chars->get(i); + if (ch->charPos >= pos && ch->charPos < pos + length) { + if (first || ch->xMin < xMin2) { + xMin2 = ch->xMin; + } + if (first || ch->yMin < yMin2) { + yMin2 = ch->yMin; + } + if (first || ch->xMax > xMax2) { + xMax2 = ch->xMax; + } + if (first || ch->yMax > yMax2) { + yMax2 = ch->yMax; + } + first = gFalse; + } + } + if (first) { + return gFalse; + } + *xMin = xMin2; + *yMin = yMin2; + *xMax = xMax2; + *yMax = yMax2; + return gTrue; +} + +GBool TextPage::checkPointInside(double x, double y) { + TextColumn *col; + int colIdx; + + buildFindCols(); + + //~ this doesn't handle RtL, vertical, or rotated text + //~ this doesn't handle drop caps + + for (colIdx = 0; colIdx < findCols->getLength(); ++colIdx) { + col = (TextColumn *)findCols->get(colIdx); + if (col->getRotation() != 0) { + continue; + } + if (x >= col->getXMin() && x <= col->getXMax() && + y >= col->getYMin() && y <= col->getYMax()) { + return gTrue; + } + } + return gFalse; +} + +GBool TextPage::findPointInside(double x, double y, TextPosition *pos) { + TextColumn *col; + int colIdx; + + buildFindCols(); + + //~ this doesn't handle RtL, vertical, or rotated text + //~ this doesn't handle drop caps + + for (colIdx = 0; colIdx < findCols->getLength(); ++colIdx) { + col = (TextColumn *)findCols->get(colIdx); + if (col->getRotation() != 0) { + continue; + } + if (x >= col->getXMin() && x <= col->getXMax() && + y >= col->getYMin() && y <= col->getYMax()) { + pos->colIdx = colIdx; + findPointInColumn(col, x, y, pos); + return gTrue; + } + } + return gFalse; +} + +GBool TextPage::findPointNear(double x, double y, TextPosition *pos) { + TextColumn *col; + double nearestDist, dx, dy; + int nearestColIdx, colIdx; + + buildFindCols(); + + //~ this doesn't handle RtL, vertical, or rotated text + //~ this doesn't handle drop caps + + nearestColIdx = -1; + nearestDist = 0; + for (colIdx = 0; colIdx < findCols->getLength(); ++colIdx) { + col = (TextColumn *)findCols->get(colIdx); + if (col->getRotation() != 0) { + continue; + } + if (x < col->getXMin()) { + dx = col->getXMin() - x; + } else if (x > col->getXMax()) { + dx = x - col->getXMax(); + } else { + dx = 0; + } + if (y < col->getYMin()) { + dy = col->getYMin() - y; + } else if (y > col->getYMax()) { + dy = y - col->getYMax(); + } else { + dy = 0; + } + if (nearestColIdx < 0 || dx + dy < nearestDist) { + nearestColIdx = colIdx; + nearestDist = dx + dy; + } + } + if (nearestColIdx < 0) { + return gFalse; + } + pos->colIdx = nearestColIdx; + col = (TextColumn *)findCols->get(nearestColIdx); + findPointInColumn(col, x, y, pos); + return gTrue; +} + +GBool TextPage::findWordPoints(double x, double y, + TextPosition *startPos, TextPosition *endPos) { + TextPosition pos; + TextColumn *col; + TextParagraph *par; + TextLine *line; + int startCharIdx, endCharIdx; + + if (!findPointInside(x, y, &pos)) { + return gFalse; + } + col = (TextColumn *)findCols->get(pos.colIdx); + par = (TextParagraph *)col->getParagraphs()->get(pos.parIdx); + line = (TextLine *)par->getLines()->get(pos.lineIdx); + + for (startCharIdx = pos.charIdx; + startCharIdx > 0 && line->text[startCharIdx - 1] != 0x20; + --startCharIdx) ; + *startPos = pos; + startPos->charIdx = startCharIdx; + + for (endCharIdx = pos.charIdx; + endCharIdx < line->len && line->text[endCharIdx] != 0x20; + ++endCharIdx) ; + *endPos = pos; + endPos->charIdx = endCharIdx; + + return gTrue; +} + +GBool TextPage::findLinePoints(double x, double y, + TextPosition *startPos, TextPosition *endPos) { + TextPosition pos; + TextColumn *col; + TextParagraph *par; + TextLine *line; + + if (!findPointInside(x, y, &pos)) { + return gFalse; + } + col = (TextColumn *)findCols->get(pos.colIdx); + par = (TextParagraph *)col->getParagraphs()->get(pos.parIdx); + line = (TextLine *)par->getLines()->get(pos.lineIdx); + + *startPos = pos; + startPos->charIdx = 0; + + *endPos = pos; + endPos->charIdx = line->len; + + return gTrue; +} + +// Find the position in [col] corresponding to [x],[y]. The column, +// [col], was found by findPointInside() or findPointNear(). +void TextPage::findPointInColumn(TextColumn *col, double x, double y, + TextPosition *pos) { + TextParagraph *par; + TextLine *line; + GList *pars, *lines; + int parIdx, lineIdx, charIdx; + + //~ this doesn't handle RtL, vertical, or rotated text + //~ this doesn't handle drop caps + + pars = col->getParagraphs(); + //~ could use a binary search here + for (parIdx = 0; parIdx < pars->getLength() - 1; ++parIdx) { + par = (TextParagraph *)pars->get(parIdx); + if (y <= par->getYMax()) { + break; + } + } + par = (TextParagraph *)pars->get(parIdx); + + lines = par->getLines(); + //~ could use a binary search here + for (lineIdx = 0; lineIdx < lines->getLength() - 1; ++lineIdx) { + line = (TextLine *)lines->get(lineIdx); + if (y <= line->getYMax()) { + break; + } + } + line = (TextLine *)lines->get(lineIdx); + + //~ could use a binary search here + for (charIdx = 0; charIdx < line->getLength(); ++charIdx) { + if (x <= 0.5 * (line->getEdge(charIdx) + line->getEdge(charIdx + 1))) { + break; + } + } + + pos->parIdx = parIdx; + pos->lineIdx = lineIdx; + pos->charIdx = charIdx; +} + +void TextPage::convertPosToPointUpper(TextPosition *pos, + double *x, double *y) { + TextColumn *col; + TextParagraph *par; + TextLine *line; + + buildFindCols(); + col = (TextColumn *)findCols->get(pos->colIdx); + par = (TextParagraph *)col->getParagraphs()->get(pos->parIdx); + line = (TextLine *)par->getLines()->get(pos->lineIdx); + *x = line->getEdge(pos->charIdx); + *y = line->getBaseline() - selectionAscent * line->fontSize; +} + +void TextPage::convertPosToPointLower(TextPosition *pos, + double *x, double *y) { + TextColumn *col; + TextParagraph *par; + TextLine *line; + + buildFindCols(); + col = (TextColumn *)findCols->get(pos->colIdx); + par = (TextParagraph *)col->getParagraphs()->get(pos->parIdx); + line = (TextLine *)par->getLines()->get(pos->lineIdx); + *x = line->getEdge(pos->charIdx); + *y = line->getYMax(); +} + +void TextPage::convertPosToPointLeftEdge(TextPosition *pos, + double *x, double *y) { + TextColumn *col; + TextParagraph *par; + TextLine *line; + + buildFindCols(); + col = (TextColumn *)findCols->get(pos->colIdx); + par = (TextParagraph *)col->getParagraphs()->get(pos->parIdx); + line = (TextLine *)par->getLines()->get(pos->lineIdx); + *x = col->getXMin(); + *y = line->getBaseline() - selectionAscent * line->fontSize; +} + +void TextPage::convertPosToPointRightEdge(TextPosition *pos, + double *x, double *y) { + TextColumn *col; + TextParagraph *par; + TextLine *line; + + buildFindCols(); + col = (TextColumn *)findCols->get(pos->colIdx); + par = (TextParagraph *)col->getParagraphs()->get(pos->parIdx); + line = (TextLine *)par->getLines()->get(pos->lineIdx); + *x = col->getXMax(); + *y = line->getYMax(); +} + +void TextPage::getColumnUpperRight(int colIdx, double *x, double *y) { + TextColumn *col; + TextParagraph *par0; + TextLine *line0; + + buildFindCols(); + col = (TextColumn *)findCols->get(colIdx); + *x = col->getXMax(); + par0 = (TextParagraph *)col->paragraphs->get(0); + line0 = (TextLine *)par0->lines->get(0); + *y = line0->getBaseline() - selectionAscent * line0->fontSize; +} + +void TextPage::getColumnLowerLeft(int colIdx, double *x, double *y) { + TextColumn *col; + + buildFindCols(); + col = (TextColumn *)findCols->get(colIdx); + *x = col->getXMin(); + *y = col->getYMax(); +} + +void TextPage::buildFindCols() { + TextBlock *tree; + int rot; + + if (findCols) { + return; + } + rot = rotateChars(chars); + if ((tree = splitChars(chars))) { + findCols = buildColumns(tree, gFalse); + delete tree; + } else { + // no text + findCols = new GList(); + } + unrotateChars(chars, rot); + unrotateColumns(findCols, rot); +} + +TextWordList *TextPage::makeWordList() { + return makeWordListForChars(chars); +} + +TextWordList *TextPage::makeWordListForRect(double xMin, double yMin, + double xMax, double yMax) { + TextWordList *words; + GList *chars2; + TextChar *ch; + double xx, yy; + int i; + + // get all chars in the rectangle + // (i.e., all chars whose center lies inside the rectangle) + chars2 = new GList(); + for (i = 0; i < chars->getLength(); ++i) { + ch = (TextChar *)chars->get(i); + xx = 0.5 * (ch->xMin + ch->xMax); + yy = 0.5 * (ch->yMin + ch->yMax); + if (xx > xMin && xx < xMax && yy > yMin && yy < yMax) { + chars2->append(ch); + } + } + + words = makeWordListForChars(chars2); + + delete chars2; + + return words; +} + +TextWordList *TextPage::makeWordListForChars(GList *charList) { + TextBlock *tree; + GList *columns; + TextColumn *col; + TextParagraph *par; + TextLine *line; + TextWord *word; + GList *overlappingChars; + GList *words; + GBool primaryLR; + int rot, colIdx, parIdx, lineIdx, wordIdx; + +#if 0 //~debug + dumpChars(charList); +#endif + + if (control.mode == textOutSimple2Layout) { + rot = 0; + primaryLR = checkPrimaryLR(chars); + rotateCharsToZero(chars); + columns = buildSimple2Columns(chars); + unrotateCharsFromZero(chars); + unrotateColumnsFromZero(columns); + + } else { + if (control.overlapHandling != textOutIgnoreOverlaps) { + overlappingChars = separateOverlappingText(chars); + } else { + overlappingChars = NULL; + } + rot = rotateChars(charList); + primaryLR = checkPrimaryLR(charList); + tree = splitChars(charList); +#if 0 //~debug + dumpTree(tree); +#endif + if (!tree) { + // no text + unrotateChars(charList, rot); + return new TextWordList(new GList(), gTrue); + } + columns = buildColumns(tree, primaryLR); +#if 0 //~debug + dumpColumns(columns, gTrue); +#endif + delete tree; + unrotateChars(charList, rot); + if (control.html) { + rotateUnderlinesAndLinks(rot); + generateUnderlinesAndLinks(columns); + } + if (overlappingChars) { + if (overlappingChars->getLength() > 0) { + columns->append(buildOverlappingTextColumn(overlappingChars)); + } + deleteGList(overlappingChars, TextChar); + } + } + + words = new GList(); + for (colIdx = 0; colIdx < columns->getLength(); ++colIdx) { + col = (TextColumn *)columns->get(colIdx); + for (parIdx = 0; parIdx < col->paragraphs->getLength(); ++parIdx) { + par = (TextParagraph *)col->paragraphs->get(parIdx); + for (lineIdx = 0; lineIdx < par->lines->getLength(); ++lineIdx) { + line = (TextLine *)par->lines->get(lineIdx); + for (wordIdx = 0; wordIdx < line->words->getLength(); ++wordIdx) { + word = ((TextWord *)line->words->get(wordIdx))->copy(); + if (wordIdx == line->words->getLength() - 1 && + !line->getHyphenated()) { + word->spaceAfter = gTrue; + } + words->append(word); + } + } + } + } + + switch (control.mode) { + case textOutReadingOrder: + case textOutSimple2Layout: + // already in reading order + break; + case textOutPhysLayout: + case textOutSimpleLayout: + case textOutTableLayout: + case textOutLinePrinter: + words->sort(&TextWord::cmpYX); + break; + case textOutRawOrder: + words->sort(&TextWord::cmpCharPos); + break; + } + + // this has to be done after sorting with cmpYX + unrotateWords(words, rot); + + deleteGList(columns, TextColumn); + + return new TextWordList(words, primaryLR); +} + +GBool TextPage::primaryDirectionIsLR() { + return checkPrimaryLR(chars); +} + +//------------------------------------------------------------------------ +// TextPage: debug +//------------------------------------------------------------------------ + +#if 0 //~debug + +void TextPage::dumpChars(GList *charsA) { + TextChar *ch; + int i; + + for (i = 0; i < charsA->getLength(); ++i) { + ch = (TextChar *)charsA->get(i); + printf("char: U+%04x '%c' xMin=%g yMin=%g xMax=%g yMax=%g fontSize=%g rot=%d charPos=%d charLen=%d spaceAfter=%d\n", + ch->c, ch->c & 0xff, ch->xMin, ch->yMin, ch->xMax, ch->yMax, + ch->fontSize, ch->rot, ch->charPos, ch->charLen, ch->spaceAfter); + } +} + +void TextPage::dumpTree(TextBlock *tree, int indent) { + TextChar *ch; + int i; + + printf("%*sblock: type=%s tag=%s small=%d rot=%d xMin=%g yMin=%g xMax=%g yMax=%g\n", + indent, "", + tree->type == blkLeaf ? "leaf" : + tree->type == blkHorizSplit ? "horiz" : "vert", + tree->tag == blkTagMulticolumn ? "multicolumn" : + tree->tag == blkTagColumn ? "column" : + tree->tag == blkTagSuperLine ? "superline" : "line", + tree->smallSplit, + tree->rot, tree->xMin, tree->yMin, tree->xMax, tree->yMax); + if (tree->type == blkLeaf) { + for (i = 0; i < tree->children->getLength(); ++i) { + ch = (TextChar *)tree->children->get(i); + printf("%*schar: '%c' xMin=%g yMin=%g xMax=%g yMax=%g font=%d.%d\n", + indent + 2, "", ch->c & 0xff, + ch->xMin, ch->yMin, ch->xMax, ch->yMax, + ch->font->fontID.num, ch->font->fontID.gen); + } + } else { + for (i = 0; i < tree->children->getLength(); ++i) { + dumpTree((TextBlock *)tree->children->get(i), indent + 2); + } + } +} + +void TextPage::dumpColumns(GList *columns, GBool dumpWords) { + TextColumn *col; + TextParagraph *par; + TextLine *line; + TextWord *word; + int colIdx, parIdx, lineIdx, wordIdx, i; + + for (colIdx = 0; colIdx < columns->getLength(); ++colIdx) { + col = (TextColumn *)columns->get(colIdx); + printf("column: xMin=%g yMin=%g xMax=%g yMax=%g px=%d py=%d pw=%d ph=%d\n", + col->xMin, col->yMin, col->xMax, col->yMax, + col->px, col->py, col->pw, col->ph); + for (parIdx = 0; parIdx < col->paragraphs->getLength(); ++parIdx) { + par = (TextParagraph *)col->paragraphs->get(parIdx); + printf(" paragraph:\n"); + for (lineIdx = 0; lineIdx < par->lines->getLength(); ++lineIdx) { + line = (TextLine *)par->lines->get(lineIdx); + printf(" line: xMin=%g yMin=%g xMax=%g yMax=%g px=%d pw=%d rot=%d\n", + line->xMin, line->yMin, line->xMax, line->yMax, + line->px, line->pw, line->rot); + if (dumpWords) { + for (wordIdx = 0; wordIdx < line->words->getLength(); ++wordIdx) { + word = (TextWord *)line->words->get(wordIdx); + printf(" word: xMin=%g yMin=%g xMax=%g yMax=%g\n", + word->xMin, word->yMin, word->xMax, word->yMax); + printf(" '"); + for (i = 0; i < word->len; ++i) { + printf("%c", word->text[i] & 0xff); + } + printf("'\n"); + } + } else { + printf(" '"); + for (i = 0; i < line->len; ++i) { + printf("%c", line->text[i] & 0xff); + } + printf("'\n"); + } + } + } + } +} + +void TextPage::dumpUnderlines() { + TextUnderline *u; + int i; + + printf("underlines:\n"); + for (i = 0; i < underlines->getLength(); ++i) { + u = (TextUnderline *)underlines->get(i); + printf(" horiz=%d x0=%g y0=%g x1=%g y1=%g\n", + u->horiz, u->x0, u->y0, u->x1, u->y1); + } +} +#endif //~debug + +//------------------------------------------------------------------------ +// TextOutputDev +//------------------------------------------------------------------------ + +static void outputToFile(void *stream, const char *text, int len) { + fwrite(text, 1, len, (FILE *)stream); +} + +TextOutputDev::TextOutputDev(char *fileName, TextOutputControl *controlA, + GBool append, GBool fileNameIsUTF8) { + text = NULL; + control = *controlA; + ok = gTrue; + + // open file + needClose = gFalse; + if (fileName) { + if (!strcmp(fileName, "-")) { + outputStream = stdout; +#ifdef WIN32 + // keep DOS from munging the end-of-line characters + setmode(fileno(stdout), O_BINARY); +#endif + } else { + if (fileNameIsUTF8) { + outputStream = openFile(fileName, append ? "ab" : "wb"); + } else { + outputStream = fopen(fileName, append ? "ab" : "wb"); + } + if (!outputStream) { + error(errIO, -1, "Couldn't open text file '{0:s}'", fileName); + ok = gFalse; + return; + } + needClose = gTrue; + } + outputFunc = &outputToFile; + } else { + outputFunc = NULL; + outputStream = NULL; + } + + // set up text object + text = new TextPage(&control); + generateBOM(); +} + +TextOutputDev::TextOutputDev(TextOutputFunc func, void *stream, + TextOutputControl *controlA) { + outputFunc = func; + outputStream = stream; + needClose = gFalse; + control = *controlA; + text = new TextPage(&control); + generateBOM(); + ok = gTrue; +} + +TextOutputDev::~TextOutputDev() { + if (needClose) { + fclose((FILE *)outputStream); + } + if (text) { + delete text; + } +} + +void TextOutputDev::generateBOM() { + UnicodeMap *uMap; + char bom[8]; + int bomLen; + + // insert Unicode BOM + if (control.insertBOM && outputStream) { + if (!(uMap = globalParams->getTextEncoding())) { + return; + } + bomLen = uMap->mapUnicode(0xfeff, bom, sizeof(bom)); + uMap->decRefCnt(); + (*outputFunc)(outputStream, bom, bomLen); + } +} + +void TextOutputDev::startPage(int pageNum, GfxState *state) { + text->startPage(state); +} + +void TextOutputDev::endPage() { + if (outputStream) { + text->write(outputStream, outputFunc); + } +} + +void TextOutputDev::restoreState(GfxState *state) { + text->updateFont(state); +} + +void TextOutputDev::updateFont(GfxState *state) { + text->updateFont(state); +} + +void TextOutputDev::beginString(GfxState *state, GString *s) { +} + +void TextOutputDev::endString(GfxState *state) { +} + +void TextOutputDev::drawChar(GfxState *state, double x, double y, + double dx, double dy, + double originX, double originY, + CharCode c, int nBytes, Unicode *u, int uLen) { + text->addChar(state, x, y, dx, dy, c, nBytes, u, uLen); +} + +void TextOutputDev::incCharCount(int nChars) { + text->incCharCount(nChars); +} + +void TextOutputDev::beginActualText(GfxState *state, Unicode *u, int uLen) { + text->beginActualText(state, u, uLen); +} + +void TextOutputDev::endActualText(GfxState *state) { + text->endActualText(state); +} + +void TextOutputDev::stroke(GfxState *state) { + GfxPath *path; + GfxSubpath *subpath; + double x[2], y[2], t; + + if (!control.html) { + return; + } + path = state->getPath(); + if (path->getNumSubpaths() != 1) { + return; + } + subpath = path->getSubpath(0); + if (subpath->getNumPoints() != 2) { + return; + } + state->transform(subpath->getX(0), subpath->getY(0), &x[0], &y[0]); + state->transform(subpath->getX(1), subpath->getY(1), &x[1], &y[1]); + + // look for a vertical or horizontal line + if (x[0] == x[1] || y[0] == y[1]) { + if (x[0] > x[1]) { + t = x[0]; x[0] = x[1]; x[1] = t; + } + if (y[0] > y[1]) { + t = y[0]; y[0] = y[1]; y[1] = t; + } + text->addUnderline(x[0], y[0], x[1], y[1]); + } +} + +void TextOutputDev::fill(GfxState *state) { + GfxPath *path; + GfxSubpath *subpath; + double x[5], y[5]; + double rx0, ry0, rx1, ry1, t; + int i; + + if (!control.html) { + return; + } + path = state->getPath(); + if (path->getNumSubpaths() != 1) { + return; + } + subpath = path->getSubpath(0); + if (subpath->getNumPoints() != 5) { + return; + } + for (i = 0; i < 5; ++i) { + if (subpath->getCurve(i)) { + return; + } + state->transform(subpath->getX(i), subpath->getY(i), &x[i], &y[i]); + } + + // look for a rectangle + if (x[0] == x[1] && y[1] == y[2] && x[2] == x[3] && y[3] == y[4] && + x[0] == x[4] && y[0] == y[4]) { + rx0 = x[0]; + ry0 = y[0]; + rx1 = x[2]; + ry1 = y[1]; + } else if (y[0] == y[1] && x[1] == x[2] && y[2] == y[3] && x[3] == x[4] && + x[0] == x[4] && y[0] == y[4]) { + rx0 = x[0]; + ry0 = y[0]; + rx1 = x[1]; + ry1 = y[2]; + } else { + return; + } + if (rx1 < rx0) { + t = rx0; + rx0 = rx1; + rx1 = t; + } + if (ry1 < ry0) { + t = ry0; + ry0 = ry1; + ry1 = t; + } + + // skinny horizontal rectangle + if (ry1 - ry0 < rx1 - rx0) { + if (ry1 - ry0 < maxUnderlineWidth) { + ry0 = 0.5 * (ry0 + ry1); + text->addUnderline(rx0, ry0, rx1, ry0); + } + + // skinny vertical rectangle + } else { + if (rx1 - rx0 < maxUnderlineWidth) { + rx0 = 0.5 * (rx0 + rx1); + text->addUnderline(rx0, ry0, rx0, ry1); + } + } +} + +void TextOutputDev::eoFill(GfxState *state) { + if (!control.html) { + return; + } + fill(state); +} + +void TextOutputDev::processLink(Link *link) { + double x1, y1, x2, y2; + int xMin, yMin, xMax, yMax, x, y; + + if (!control.html) { + return; + } + link->getRect(&x1, &y1, &x2, &y2); + cvtUserToDev(x1, y1, &x, &y); + xMin = xMax = x; + yMin = yMax = y; + cvtUserToDev(x1, y2, &x, &y); + if (x < xMin) { + xMin = x; + } else if (x > xMax) { + xMax = x; + } + if (y < yMin) { + yMin = y; + } else if (y > yMax) { + yMax = y; + } + cvtUserToDev(x2, y1, &x, &y); + if (x < xMin) { + xMin = x; + } else if (x > xMax) { + xMax = x; + } + if (y < yMin) { + yMin = y; + } else if (y > yMax) { + yMax = y; + } + cvtUserToDev(x2, y2, &x, &y); + if (x < xMin) { + xMin = x; + } else if (x > xMax) { + xMax = x; + } + if (y < yMin) { + yMin = y; + } else if (y > yMax) { + yMax = y; + } + text->addLink(xMin, yMin, xMax, yMax, link); +} + +GBool TextOutputDev::findText(Unicode *s, int len, + GBool startAtTop, GBool stopAtBottom, + GBool startAtLast, GBool stopAtLast, + GBool caseSensitive, GBool backward, + GBool wholeWord, + double *xMin, double *yMin, + double *xMax, double *yMax) { + return text->findText(s, len, startAtTop, stopAtBottom, + startAtLast, stopAtLast, + caseSensitive, backward, wholeWord, + xMin, yMin, xMax, yMax); +} + +GString *TextOutputDev::getText(double xMin, double yMin, + double xMax, double yMax) { + return text->getText(xMin, yMin, xMax, yMax); +} + +GBool TextOutputDev::findCharRange(int pos, int length, + double *xMin, double *yMin, + double *xMax, double *yMax) { + return text->findCharRange(pos, length, xMin, yMin, xMax, yMax); +} + +TextWordList *TextOutputDev::makeWordList() { + return text->makeWordList(); +} + +TextWordList *TextOutputDev::makeWordListForRect(double xMin, double yMin, + double xMax, double yMax) { + return text->makeWordListForRect(xMin, yMin, xMax, yMax); +} + +TextPage *TextOutputDev::takeText() { + TextPage *ret; + + ret = text; + text = new TextPage(&control); + return ret; +} diff --git a/xpdf/TextOutputDev.h b/xpdf/TextOutputDev.h new file mode 100644 index 0000000..302975c --- /dev/null +++ b/xpdf/TextOutputDev.h @@ -0,0 +1,800 @@ +//======================================================================== +// +// TextOutputDev.h +// +// Copyright 1997-2012 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef TEXTOUTPUTDEV_H +#define TEXTOUTPUTDEV_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include +#include "gtypes.h" +#include "GfxFont.h" +#include "OutputDev.h" + +class GList; +class UnicodeMap; +class UnicodeRemapping; + +class TextBlock; +class TextChar; +class TextGaps; +class TextLink; +class TextPage; + +//------------------------------------------------------------------------ + +typedef void (*TextOutputFunc)(void *stream, const char *text, int len); + +//------------------------------------------------------------------------ +// TextOutputControl +//------------------------------------------------------------------------ + +enum TextOutputMode { + textOutReadingOrder, // format into reading order + textOutPhysLayout, // maintain original physical layout + textOutSimpleLayout, // simple one-column physical layout + textOutSimple2Layout, // simple one-column physical layout + textOutTableLayout, // similar to PhysLayout, but optimized + // for tables + textOutLinePrinter, // strict fixed-pitch/height layout + textOutRawOrder // keep text in content stream order +}; + +enum TextOutputOverlapHandling { + textOutIgnoreOverlaps, // no special handling for overlaps + textOutAppendOverlaps, // append overlapping text to main text + textOutDiscardOverlaps // discard overlapping text +}; + +class TextOutputControl { +public: + + TextOutputControl(); + ~TextOutputControl() {} + + TextOutputMode mode; // formatting mode + double fixedPitch; // if this is non-zero, assume fixed-pitch + // characters with this width + // (only relevant for PhysLayout, Table, + // and LinePrinter modes) + double fixedLineSpacing; // fixed line spacing (only relevant for + // LinePrinter mode) + GBool html; // enable extra processing for HTML + GBool clipText; // separate clipped text and add it back + // in after forming columns + GBool discardDiagonalText; // discard all text that's not close to + // 0/90/180/270 degrees + GBool discardRotatedText; // discard all text that's not horizontal + // (0 degrees) + GBool discardInvisibleText; // discard all invisible characters + GBool discardClippedText; // discard all clipped characters + GBool splitRotatedWords; // do not combine horizontal and + // non-horizontal chars in a single + // word + TextOutputOverlapHandling // how to handle overlapping text + overlapHandling; + GBool separateLargeChars; // separate "large" characters from + // "regular" characters + GBool insertBOM; // insert a Unicode BOM at the start of + // the text output + double marginLeft, // characters outside the margins are + marginRight, // discarded + marginTop, + marginBottom; +}; + +//------------------------------------------------------------------------ +// TextFontInfo +//------------------------------------------------------------------------ + +class TextFontInfo { +public: + + // Create a TextFontInfo for the current font in [state]. + TextFontInfo(GfxState *state); + + // Create a dummy TextFontInfo. + TextFontInfo(); + + ~TextFontInfo(); + + GBool matches(GfxState *state); + + // Get the font name (which may be NULL). + GString *getFontName() { return fontName; } + + // Get font descriptor flags. + GBool isFixedWidth() { return flags & fontFixedWidth; } + GBool isSerif() { return flags & fontSerif; } + GBool isSymbolic() { return flags & fontSymbolic; } + GBool isItalic() { return flags & fontItalic; } + GBool isBold() { return flags & fontBold; } + + // Get the width of the 'm' character, if available. + double getMWidth() { return mWidth; } + + Ref getFontID() { return fontID; } + +private: + + Ref fontID; + GString *fontName; + int flags; + double mWidth; + double ascent, descent; + + friend class TextLine; + friend class TextPage; + friend class TextWord; +}; + +//------------------------------------------------------------------------ +// TextWord +//------------------------------------------------------------------------ + +class TextWord { +public: + + TextWord(GList *chars, int start, int lenA, + int rotA, GBool rotatedA, int dirA, GBool spaceAfterA); + ~TextWord(); + TextWord *copy() { return new TextWord(this); } + + // Get the TextFontInfo object associated with this word. + TextFontInfo *getFontInfo() { return font; } + + int getLength() { return len; } + Unicode getChar(int idx) { return text[idx]; } + GString *getText(); + GString *getFontName() { return font->fontName; } + void getColor(double *r, double *g, double *b) + { *r = colorR; *g = colorG; *b = colorB; } + GBool isInvisible() { return invisible; } + void getBBox(double *xMinA, double *yMinA, double *xMaxA, double *yMaxA) + { *xMinA = xMin; *yMinA = yMin; *xMaxA = xMax; *yMaxA = yMax; } + void getCharBBox(int charIdx, double *xMinA, double *yMinA, + double *xMaxA, double *yMaxA); + double getFontSize() { return fontSize; } + int getRotation() { return rot; } + GBool isRotated() { return (GBool)rotated; } + int getCharPos() { return charPos[0]; } + int getCharLen() { return charPos[len] - charPos[0]; } + int getDirection() { return dir; } + GBool getSpaceAfter() { return spaceAfter; } + double getBaseline(); + GBool isUnderlined() { return underlined; } + GString *getLinkURI(); + +private: + + TextWord(TextWord *word); + static int cmpYX(const void *p1, const void *p2); + static int cmpCharPos(const void *p1, const void *p2); + + double xMin, xMax; // bounding box x coordinates + double yMin, yMax; // bounding box y coordinates + Unicode *text; // the text + int *charPos; // character position (within content stream) + // of each char (plus one extra entry for + // the last char) + double *edge; // "near" edge x or y coord of each char + // (plus one extra entry for the last char) + int len; // number of characters + TextFontInfo *font; // font information + double fontSize; // font size + TextLink *link; + double colorR, // word color + colorG, + colorB; + GBool invisible; // set for invisible text (render mode 3) + + // group the byte-size fields to minimize object size + Guchar rot; // rotation, multiple of 90 degrees + // (0, 1, 2, or 3) + char rotated; // set if this word is non-horizontal + char dir; // character direction (+1 = left-to-right; + // -1 = right-to-left; 0 = neither) + char spaceAfter; // set if there is a space between this + // word and the next word on the line + char underlined; + + friend class TextBlock; + friend class TextLine; + friend class TextPage; +}; + +//------------------------------------------------------------------------ +// TextLine +//------------------------------------------------------------------------ + +class TextLine { +public: + + TextLine(GList *wordsA, double xMinA, double yMinA, + double xMaxA, double yMaxA, double fontSizeA); + ~TextLine(); + + double getXMin() { return xMin; } + double getYMin() { return yMin; } + double getXMax() { return xMax; } + double getYMax() { return yMax; } + double getBaseline(); + int getRotation() { return rot; } + GList *getWords() { return words; } + Unicode *getUnicode() { return text; } + int getLength() { return len; } + double getEdge(int idx) { return edge[idx]; } + GBool getHyphenated() { return hyphenated; } + +private: + + static int cmpX(const void *p1, const void *p2); + + GList *words; // [TextWord] + int rot; // rotation, multiple of 90 degrees + // (0, 1, 2, or 3) + double xMin, xMax; // bounding box x coordinates + double yMin, yMax; // bounding box y coordinates + double fontSize; // main (max) font size for this line + Unicode *text; // Unicode text of the line, including + // spaces between words + double *edge; // "near" edge x or y coord of each char + // (plus one extra entry for the last char) + int len; // number of Unicode chars + GBool hyphenated; // set if last char is a hyphen + int px; // x offset (in characters, relative to + // containing column) in physical layout mode + int pw; // line width (in characters) in physical + // layout mode + + friend class TextSuperLine; + friend class TextPage; + friend class TextParagraph; +}; + +//------------------------------------------------------------------------ +// TextParagraph +//------------------------------------------------------------------------ + +class TextParagraph { +public: + + TextParagraph(GList *linesA, GBool dropCapA); + ~TextParagraph(); + + // Get the list of TextLine objects. + GList *getLines() { return lines; } + + GBool hasDropCap() { return dropCap; } + + double getXMin() { return xMin; } + double getYMin() { return yMin; } + double getXMax() { return xMax; } + double getYMax() { return yMax; } + +private: + + GList *lines; // [TextLine] + GBool dropCap; // paragraph starts with a drop capital + double xMin, xMax; // bounding box x coordinates + double yMin, yMax; // bounding box y coordinates + + friend class TextPage; +}; + +//------------------------------------------------------------------------ +// TextColumn +//------------------------------------------------------------------------ + +class TextColumn { +public: + + TextColumn(GList *paragraphsA, double xMinA, double yMinA, + double xMaxA, double yMaxA); + ~TextColumn(); + + // Get the list of TextParagraph objects. + GList *getParagraphs() { return paragraphs; } + + double getXMin() { return xMin; } + double getYMin() { return yMin; } + double getXMax() { return xMax; } + double getYMax() { return yMax; } + + int getRotation(); + +private: + + static int cmpX(const void *p1, const void *p2); + static int cmpY(const void *p1, const void *p2); + static int cmpPX(const void *p1, const void *p2); + + GList *paragraphs; // [TextParagraph] + double xMin, xMax; // bounding box x coordinates + double yMin, yMax; // bounding box y coordinates + int px, py; // x, y position (in characters) in physical + // layout mode + int pw, ph; // column width, height (in characters) in + // physical layout mode + + friend class TextPage; +}; + +//------------------------------------------------------------------------ +// TextWordList +//------------------------------------------------------------------------ + +class TextWordList { +public: + + TextWordList(GList *wordsA, GBool primaryLRA); + + ~TextWordList(); + + // Return the number of words on the list. + int getLength(); + + // Return the th word from the list. + TextWord *get(int idx); + + // Returns true if primary direction is left-to-right, or false if + // right-to-left. + GBool getPrimaryLR() { return primaryLR; } + +private: + + GList *words; // [TextWord] + GBool primaryLR; +}; + +//------------------------------------------------------------------------ +// TextPosition +//------------------------------------------------------------------------ + +// Position within a TextColumn tree. The position is in column +// [colIdx], paragraph [parIdx], line [lineIdx], before character +// [charIdx]. +class TextPosition { +public: + + TextPosition(): colIdx(0), parIdx(0), lineIdx(0), charIdx(0) {} + TextPosition(int colIdxA, int parIdxA, int lineIdxA, int charIdxA): + colIdx(colIdxA), parIdx(parIdxA), lineIdx(lineIdxA), charIdx(charIdxA) {} + + int operator==(TextPosition pos); + int operator!=(TextPosition pos); + int operator<(TextPosition pos); + int operator>(TextPosition pos); + + int colIdx, parIdx, lineIdx, charIdx; +}; + +//------------------------------------------------------------------------ +// TextPage +//------------------------------------------------------------------------ + +class TextPage { +public: + + TextPage(TextOutputControl *controlA); + ~TextPage(); + + // Write contents of page to a stream. + void write(void *outputStream, TextOutputFunc outputFunc); + + // Find a string. If is true, starts looking at the + // top of the page; else if is true, starts looking + // immediately after the last find result; else starts looking at + // ,. If is true, stops looking at the + // bottom of the page; else if is true, stops looking + // just before the last find result; else stops looking at + // ,. + GBool 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); + + // Get the text which is inside the specified rectangle. Multi-line + // text always includes end-of-line markers at the end of each line. + // If is true, an end-of-line marker will be appended to + // single-line text as well. + GString *getText(double xMin, double yMin, + double xMax, double yMax, + GBool forceEOL = gFalse); + + // Find a string by character position and length. If found, sets + // the text bounding rectangle and returns true; otherwise returns + // false. + GBool findCharRange(int pos, int length, + double *xMin, double *yMin, + double *xMax, double *yMax); + + // Returns true if x,y falls inside a column. + GBool checkPointInside(double x, double y); + + // Find a point inside a column. Returns false if x,y fall outside + // all columns. + GBool findPointInside(double x, double y, TextPosition *pos); + + // Find a point in the nearest column. Returns false only if there + // are no columns. + GBool findPointNear(double x, double y, TextPosition *pos); + + // Find the start and end of a word inside a column. Returns false + // if x,y fall outside all columns. + GBool findWordPoints(double x, double y, + TextPosition *startPos, TextPosition *endPos); + + // Find the start and end of a line inside a column. Returns false + // if x,y fall outside all columns. + GBool findLinePoints(double x, double y, + TextPosition *startPos, TextPosition *endPos); + + // Get the upper point of a TextPosition. + void convertPosToPointUpper(TextPosition *pos, double *x, double *y); + + // Get the lower point of a TextPosition. + void convertPosToPointLower(TextPosition *pos, double *x, double *y); + + // Get the upper left corner of the line containing a TextPosition. + void convertPosToPointLeftEdge(TextPosition *pos, double *x, double *y); + + // Get the lower right corner of the line containing a TextPosition. + void convertPosToPointRightEdge(TextPosition *pos, double *x, double *y); + + // Get the upper right corner of a column. + void getColumnUpperRight(int colIdx, double *x, double *y); + + // Get the lower left corner of a column. + void getColumnLowerLeft(int colIdx, double *x, double *y); + + // Create and return a list of TextColumn objects. + GList *makeColumns(); + + // Get the list of all TextFontInfo objects used on this page. + GList *getFonts() { return fonts; } + + // Build a flat word list, in the specified ordering. + TextWordList *makeWordList(); + + // Build a word list containing only words inside the specified + // rectangle. + TextWordList *makeWordListForRect(double xMin, double yMin, + double xMax, double yMax); + + // Returns true if the primary character direction is left-to-right, + // false if it is right-to-left. + GBool primaryDirectionIsLR(); + + // Returns true if any of the fonts used on this page are likely to + // be problematic when converting text to Unicode. + GBool problematicForUnicode() { return problematic; } + + // Add a 'special' character to this TextPage. This is currently + // used by pdftohtml to insert markers for form fields. + void addSpecialChar(double xMin, double yMin, double xMax, double yMax, + int rot, TextFontInfo *font, double fontSize, + Unicode u); + + // Remove characters that fall inside a region. + void removeChars(double xMin, double yMin, double xMax, double yMax, + double xOverlapThresh, double yOverlapThresh); + +private: + + void startPage(GfxState *state); + void clear(); + void updateFont(GfxState *state); + void addChar(GfxState *state, double x, double y, + double dx, double dy, + CharCode c, int nBytes, Unicode *u, int uLen); + void incCharCount(int nChars); + void beginActualText(GfxState *state, Unicode *u, int uLen); + void endActualText(GfxState *state); + void addUnderline(double x0, double y0, double x1, double y1); + void addLink(double xMin, double yMin, double xMax, double yMax, + Link *link); + + // output + void writeReadingOrder(void *outputStream, + TextOutputFunc outputFunc, + UnicodeMap *uMap, + char *space, int spaceLen, + char *eol, int eolLen); + void writePhysLayout(void *outputStream, + TextOutputFunc outputFunc, + UnicodeMap *uMap, + char *space, int spaceLen, + char *eol, int eolLen); + void writeSimpleLayout(void *outputStream, + TextOutputFunc outputFunc, + UnicodeMap *uMap, + char *space, int spaceLen, + char *eol, int eolLen); + void writeSimple2Layout(void *outputStream, + TextOutputFunc outputFunc, + UnicodeMap *uMap, + char *space, int spaceLen, + char *eol, int eolLen); + void writeLinePrinter(void *outputStream, + TextOutputFunc outputFunc, + UnicodeMap *uMap, + char *space, int spaceLen, + char *eol, int eolLen); + void writeRaw(void *outputStream, + TextOutputFunc outputFunc, + UnicodeMap *uMap, + char *space, int spaceLen, + char *eol, int eolLen); + void encodeFragment(Unicode *text, int len, UnicodeMap *uMap, + GBool primaryLR, GString *s); + GBool unicodeEffectiveTypeLOrNum(Unicode u, Unicode left, Unicode right); + GBool unicodeEffectiveTypeR(Unicode u, Unicode left, Unicode right); + + // analysis + int rotateChars(GList *charsA); + void rotateCharsToZero(GList *charsA); + void rotateUnderlinesAndLinks(int rot); + void unrotateChars(GList *charsA, int rot); + void unrotateCharsFromZero(GList *charsA); + void unrotateColumnsFromZero(GList *columns); + void unrotateColumns(GList *columns, int rot); + void unrotateWords(GList *words, int rot); + GBool checkPrimaryLR(GList *charsA); + void removeDuplicates(GList *charsA, int rot); + GList *separateOverlappingText(GList *charsA); + TextColumn *buildOverlappingTextColumn(GList *overlappingChars); + TextBlock *splitChars(GList *charsA); + TextBlock *split(GList *charsA, int rot, GBool vertOnly); + GList *getChars(GList *charsA, double xMin, double yMin, + double xMax, double yMax); + void findGaps(GList *charsA, int rot, + double *xMinOut, double *yMinOut, + double *xMaxOut, double *yMaxOut, + double *avgFontSizeOut, double *minFontSizeOut, + GList *splitLines, + TextGaps *horizGaps, TextGaps *vertGaps); + void mergeSplitLines(GList *charsA, int rot, GList *splitLines); + void tagBlock(TextBlock *blk); + void insertLargeChars(GList *largeChars, TextBlock *blk); + void insertLargeCharsInFirstLeaf(GList *largeChars, TextBlock *blk); + void insertLargeCharInLeaf(TextChar *ch, TextBlock *blk); + void insertIntoTree(TextBlock *subtree, TextBlock *primaryTree); + void insertColumnIntoTree(TextBlock *column, TextBlock *tree); + void insertClippedChars(GList *clippedChars, TextBlock *tree); + TextBlock *findClippedCharLeaf(TextChar *ch, TextBlock *tree); + GList *buildColumns(TextBlock *tree, GBool primaryLR); + void buildColumns2(TextBlock *blk, GList *columns, GBool primaryLR); + TextColumn *buildColumn(TextBlock *tree); + double getLineIndent(TextLine *line, TextBlock *blk); + double getAverageLineSpacing(GList *lines); + double getLineSpacing(TextLine *line0, TextLine *line1); + void buildLines(TextBlock *blk, GList *lines, GBool splitSuperLines); + GList *buildSimple2Columns(GList *charsA); + GList *buildSimple2Lines(GList *charsA, int rot); + TextLine *buildLine(TextBlock *blk); + TextLine *buildLine(GList *charsA, int rot, + double xMin, double yMin, double xMax, double yMax); + void getLineChars(TextBlock *blk, GList *charsA); + double computeWordSpacingThreshold(GList *charsA, int rot); + int getCharDirection(TextChar *ch); + int getCharDirection(TextChar *ch, TextChar *left, TextChar *right); + int assignPhysLayoutPositions(GList *columns); + void assignLinePhysPositions(GList *columns); + void computeLinePhysWidth(TextLine *line, UnicodeMap *uMap); + int assignColumnPhysPositions(GList *columns); + void buildSuperLines(TextBlock *blk, GList *superLines); + void assignSimpleLayoutPositions(GList *superLines, UnicodeMap *uMap); + void generateUnderlinesAndLinks(GList *columns); + void findPointInColumn(TextColumn *col, double x, double y, + TextPosition *pos); + void buildFindCols(); + + // debug +#if 0 //~debug + void dumpChars(GList *charsA); + void dumpTree(TextBlock *tree, int indent = 0); + void dumpColumns(GList *columns, GBool dumpWords = gFalse); + void dumpUnderlines(); +#endif + + // word list + TextWordList *makeWordListForChars(GList *charList); + + TextOutputControl control; // formatting parameters + + UnicodeRemapping *remapping; + Unicode *uBuf; + int uBufSize; + + double pageWidth, pageHeight; // width and height of current page + int charPos; // next character position (within content + // stream) + TextFontInfo *curFont; // current font + double curFontSize; // current font size + int curRot; // current rotation + GBool diagonal; // set if rotation is not close to + // 0/90/180/270 degrees + GBool rotated; // set if text is not horizontal (0 degrees) + int nTinyChars; // number of "tiny" chars seen so far + Unicode *actualText; // current "ActualText" span + int actualTextLen; + double actualTextX0, + actualTextY0, + actualTextX1, + actualTextY1; + int actualTextNBytes; + + GList *chars; // [TextChar] + GList *fonts; // all font info objects used on this + // page [TextFontInfo] + + GList *underlines; // [TextUnderline] + GList *links; // [TextLink] + + GList *findCols; // text used by the findText**/findPoint** + // functions [TextColumn] + double lastFindXMin, // coordinates of the last "find" result + lastFindYMin; + GBool haveLastFind; + + GBool problematic; // true if any of the fonts used on this + // page are marked as problematic for + // Unicode conversion + + friend class TextOutputDev; +}; + +//------------------------------------------------------------------------ +// TextOutputDev +//------------------------------------------------------------------------ + +class TextOutputDev: public OutputDev { +public: + + // Open a text output file. If is NULL, no file is + // written (this is useful, e.g., for searching text). If + // is true, the original physical layout of the text + // is maintained. If is true, the text is kept in + // content stream order. + TextOutputDev(char *fileName, TextOutputControl *controlA, + GBool append, GBool fileNameIsUTF8 = gFalse); + + // Create a TextOutputDev which will write to a generic stream. If + // is true, the original physical layout of the text + // is maintained. If is true, the text is kept in + // content stream order. + TextOutputDev(TextOutputFunc func, void *stream, + TextOutputControl *controlA); + + // Destructor. + virtual ~TextOutputDev(); + + // Check if file was successfully created. + virtual GBool isOk() { return ok; } + + //---- get info about output device + + // 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; } + + // Does this device use drawChar() or drawString()? + virtual GBool useDrawChar() { 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; } + + // 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. + virtual void startPage(int pageNum, GfxState *state); + + // End a page. + virtual void endPage(); + + //----- save/restore graphics state + virtual void restoreState(GfxState *state); + + //----- update text state + virtual void updateFont(GfxState *state); + + //----- text drawing + virtual void beginString(GfxState *state, GString *s); + virtual void endString(GfxState *state); + virtual void drawChar(GfxState *state, double x, double y, + 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); + virtual void fill(GfxState *state); + virtual void eoFill(GfxState *state); + + //----- link borders + virtual void processLink(Link *link); + + //----- special access + + // Find a string. If is true, starts looking at the + // top of the page; else if is true, starts looking + // immediately after the last find result; else starts looking at + // ,. If is true, stops looking at the + // bottom of the page; else if is true, stops looking + // just before the last find result; else stops looking at + // ,. + GBool 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); + + // Get the text which is inside the specified rectangle. + GString *getText(double xMin, double yMin, + double xMax, double yMax); + + // Find a string by character position and length. If found, sets + // the text bounding rectangle and returns true; otherwise returns + // false. + GBool findCharRange(int pos, int length, + double *xMin, double *yMin, + double *xMax, double *yMax); + + // Build a flat word list, in content stream order (if + // this->rawOrder is true), physical layout order (if + // this->physLayout is true and this->rawOrder is false), or reading + // order (if both flags are false). + TextWordList *makeWordList(); + + // Build a word list containing only words inside the specified + // rectangle. + TextWordList *makeWordListForRect(double xMin, double yMin, + double xMax, double yMax); + + // Returns the TextPage object for the last rasterized page, + // transferring ownership to the caller. + TextPage *takeText(); + + // Turn extra processing for HTML conversion on or off. + void enableHTMLExtras(GBool html) { control.html = html; } + +private: + + void generateBOM(); + + TextOutputFunc outputFunc; // output function + void *outputStream; // output stream + GBool needClose; // need to close the output file? + // (only if outputStream is a FILE*) + TextPage *text; // text for the current page + TextOutputControl control; // formatting parameters + GBool ok; // set up ok? +}; + +#endif diff --git a/xpdf/TextString.cc b/xpdf/TextString.cc new file mode 100644 index 0000000..8e54a1d --- /dev/null +++ b/xpdf/TextString.cc @@ -0,0 +1,213 @@ +//======================================================================== +// +// TextString.cc +// +// Copyright 2011-2013 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include "gmem.h" +#include "gmempp.h" +#include "GString.h" +#include "PDFDocEncoding.h" +#include "UTF8.h" +#include "TextString.h" + +//------------------------------------------------------------------------ + +TextString::TextString() { + u = NULL; + len = size = 0; +} + +TextString::TextString(GString *s) { + u = NULL; + len = size = 0; + append(s); +} + +TextString::TextString(TextString *s) { + len = size = s->len; + if (len) { + u = (Unicode *)gmallocn(size, sizeof(Unicode)); + memcpy(u, s->u, len * sizeof(Unicode)); + } else { + u = NULL; + } +} + +TextString::~TextString() { + gfree(u); +} + +TextString *TextString::append(Unicode c) { + expand(1); + u[len] = c; + ++len; + return this; +} + +TextString *TextString::append(GString *s) { + return insert(len, s); +} + +TextString *TextString::insert(int idx, Unicode c) { + if (idx >= 0 && idx <= len) { + expand(1); + if (idx < len) { + memmove(u + idx + 1, u + idx, (len - idx) * sizeof(Unicode)); + } + u[idx] = c; + ++len; + } + return this; +} + +TextString *TextString::insert(int idx, Unicode *u2, int n) { + if (idx >= 0 && idx <= len) { + expand(n); + if (idx < len) { + memmove(u + idx + n, u + idx, (len - idx) * sizeof(Unicode)); + } + memcpy(u + idx, u2, n * sizeof(Unicode)); + len += n; + } + return this; +} + +TextString *TextString::insert(int idx, GString *s) { + Unicode uBuf[100]; + int n, i; + + if (idx >= 0 && idx <= len) { + // look for a UTF-16BE BOM + if ((s->getChar(0) & 0xff) == 0xfe && + (s->getChar(1) & 0xff) == 0xff) { + i = 2; + n = 0; + while (getUTF16BE(s, &i, uBuf + n)) { + ++n; + if (n == sizeof(uBuf) / sizeof(Unicode)) { + insert(idx, uBuf, n); + idx += n; + n = 0; + } + } + if (n > 0) { + insert(idx, uBuf, n); + } + + // look for a UTF-16LE BOM + // (technically, this isn't allowed by the PDF spec, but some + // PDF files use it) + } else if ((s->getChar(0) & 0xff) == 0xff && + (s->getChar(1) & 0xff) == 0xfe) { + i = 2; + n = 0; + while (getUTF16LE(s, &i, uBuf + n)) { + ++n; + if (n == sizeof(uBuf) / sizeof(Unicode)) { + insert(idx, uBuf, n); + idx += n; + n = 0; + } + } + if (n > 0) { + insert(idx, uBuf, n); + } + + // look for a UTF-8 BOM + } else if ((s->getChar(0) & 0xff) == 0xef && + (s->getChar(1) & 0xff) == 0xbb && + (s->getChar(2) & 0xff) == 0xbf) { + i = 3; + n = 0; + while (getUTF8(s, &i, uBuf + n)) { + ++n; + if (n == sizeof(uBuf) / sizeof(Unicode)) { + insert(idx, uBuf, n); + idx += n; + n = 0; + } + } + if (n > 0) { + insert(idx, uBuf, n); + } + + // otherwise, use PDFDocEncoding + } else { + n = s->getLength(); + expand(n); + if (idx < len) { + memmove(u + idx + n, u + idx, (len - idx) * sizeof(Unicode)); + } + for (i = 0; i < n; ++i) { + u[idx + i] = pdfDocEncoding[s->getChar(i) & 0xff]; + } + len += n; + } + } + return this; +} + +void TextString::expand(int delta) { + int newLen; + + newLen = len + delta; + if (delta > INT_MAX - len) { + // trigger an out-of-memory error + size = -1; + } else if (newLen <= size) { + return; + } else if (size > 0 && size <= INT_MAX / 2 && size*2 >= newLen) { + size *= 2; + } else { + size = newLen; + } + u = (Unicode *)greallocn(u, size, sizeof(Unicode)); +} + +GString *TextString::toPDFTextString() { + GString *s; + GBool useUnicode; + int i; + + useUnicode = gFalse; + for (i = 0; i < len; ++i) { + if (u[i] >= 0x80) { + useUnicode = gTrue; + break; + } + } + s = new GString(); + if (useUnicode) { + s->append((char)0xfe); + s->append((char)0xff); + for (i = 0; i < len; ++i) { + s->append((char)(u[i] >> 8)); + s->append((char)u[i]); + } + } else { + for (i = 0; i < len; ++i) { + s->append((char)u[i]); + } + } + return s; +} + +GString *TextString::toUTF8() { + GString *s = new GString(); + for (int i = 0; i < len; ++i) { + char buf[8]; + int n = mapUTF8(u[i], buf, sizeof(buf)); + s->append(buf, n); + } + return s; +} diff --git a/xpdf/TextString.h b/xpdf/TextString.h new file mode 100644 index 0000000..c296d7d --- /dev/null +++ b/xpdf/TextString.h @@ -0,0 +1,71 @@ +//======================================================================== +// +// TextString.h +// +// Copyright 2011-2013 Glyph & Cog, LLC +// +// Represents a PDF "text string", which can either be a UTF-16BE +// string (with a leading byte order marker), or an 8-bit string in +// PDFDocEncoding. +// +//======================================================================== + +#ifndef TEXTSTRING_H +#define TEXTSTRING_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "CharTypes.h" + +class GString; + +//------------------------------------------------------------------------ + +class TextString { +public: + + // Create an empty TextString. + TextString(); + + // Create a TextString from a PDF text string. + TextString(GString *s); + + // Copy a TextString. + TextString(TextString *s); + + ~TextString(); + + // Append a Unicode character or PDF text string to this TextString. + TextString *append(Unicode c); + TextString *append(GString *s); + + // Insert a Unicode character, sequence of Unicode characters, or + // PDF text string in this TextString. + TextString *insert(int idx, Unicode c); + TextString *insert(int idx, Unicode *u2, int n); + TextString *insert(int idx, GString *s); + + // Get the Unicode characters in the TextString. + int getLength() { return len; } + Unicode *getUnicode() { return u; } + + // Create a PDF text string from a TextString. + GString *toPDFTextString(); + + // Convert a TextString to UTF-8. + GString *toUTF8(); + +private: + + void expand(int delta); + + Unicode *u; // NB: not null-terminated + int len; + int size; +}; + +#endif diff --git a/xpdf/TileCache.cc b/xpdf/TileCache.cc new file mode 100644 index 0000000..ff002ed --- /dev/null +++ b/xpdf/TileCache.cc @@ -0,0 +1,562 @@ +//======================================================================== +// +// TileCache.cc +// +// Copyright 2014 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include "gmem.h" +#include "gmempp.h" +#include "GList.h" +#include "GMutex.h" +#ifdef _WIN32 +# include +#else +# include +# include +#endif +#include "Object.h" +#include "PDFDoc.h" +#include "SplashBitmap.h" +#include "SplashOutputDev.h" +#include "DisplayState.h" +#include "GfxState.h" +#include "TileMap.h" +#include "TileCache.h" + +//------------------------------------------------------------------------ +// CachedTileDesc +//------------------------------------------------------------------------ + +enum CachedTileState { + cachedTileUnstarted, // worker thread hasn't started + // rasterization yet + cachedTileStarted, // worker thread is rasterizing the tile + cachedTileFinished, // rasterization is done + cachedTileCanceled // worker thread should stop rasterizing + // and remove this tile from the cache +}; + +class CachedTileDesc: public TileDesc { +public: + + CachedTileDesc(TileDesc *tile): + TileDesc(tile->page, tile->rotate, tile->dpi, + tile->tx, tile->ty, tile->tw, tile->th), + state(cachedTileUnstarted), active(gTrue), + bitmap(NULL), freeBitmap(gFalse) {} + ~CachedTileDesc(); + + CachedTileState state; + GBool active; + SplashBitmap *bitmap; + GBool freeBitmap; +}; + +CachedTileDesc::~CachedTileDesc() { + if (freeBitmap) { + delete bitmap; + } +} + +//------------------------------------------------------------------------ +// OS-dependent threading support code +// +// NB: This wrapper code is not meant to be general purpose. Pthreads +// condition objects are not equivalent to Windows event objects, in +// general. +//------------------------------------------------------------------------ + +//-------------------- Windows -------------------- +#ifdef _WIN32 + +typedef HANDLE GThreadID; +typedef DWORD (WINAPI *GThreadFunc)(void *); +#define GThreadReturn DWORD WINAPI + +static void gCreateThread(GThreadID *thr, GThreadFunc threadFunc, + void *data) { + *thr = CreateThread(NULL, 0, threadFunc, data, 0, NULL); +} + +static void gJoinThread(GThreadID thr) { + WaitForSingleObject(thr, INFINITE); + CloseHandle(thr); +} + +typedef HANDLE GCondition; + +static void gInitCondition(GCondition *c) { + *c = CreateEvent(NULL, TRUE, FALSE, NULL); +} + +static void gDestroyCondition(GCondition *c) { + CloseHandle(*c); +} + +static void gSignalCondition(GCondition *c) { + SetEvent(*c); +} + +static void gClearCondition(GCondition *c) { + ResetEvent(*c); +} + +static void gWaitCondition(GCondition *c, GMutex *m) { + LeaveCriticalSection(m); + WaitForSingleObject(*c, INFINITE); + EnterCriticalSection(m); +} + +//-------------------- pthreads -------------------- +#else + +typedef pthread_t GThreadID; +typedef void *(*GThreadFunc)(void *); +#define GThreadReturn void* + +static void gCreateThread(GThreadID *thr, GThreadFunc threadFunc, + void *data) { + pthread_create(thr, NULL, threadFunc, data); +} + +static void gJoinThread(GThreadID thr) { + pthread_join(thr, NULL); +} + +typedef pthread_cond_t GCondition; + +static void gInitCondition(GCondition *c) { + pthread_cond_init(c, NULL); +} + +static void gDestroyCondition(GCondition *c) { + pthread_cond_destroy(c); +} + +static void gSignalCondition(GCondition *c) { + pthread_cond_broadcast(c); +} + +static void gClearCondition(GCondition *c) { +} + +static void gWaitCondition(GCondition *c, GMutex *m) { + pthread_cond_wait(c, m); +} + +#endif + +//------------------------------------------------------------------------ +// TileCacheThreadPool +//------------------------------------------------------------------------ + +class TileCacheThreadPool { +public: + + TileCacheThreadPool(TileCache *tileCacheA, int nThreadsA); + ~TileCacheThreadPool(); + + // Called by the client when one or more jobs have been added to the + // queue. This must be called with the mutex unlocked. + void jobAdded(); + + // Wait for at least one job to be finished. This must be called + // with the mutex locked. + void waitForFinishedJob(); + + // The client should use the mutex to protect the queue data + // structure. + void lockMutex() { gLockMutex(&mutex); } + void unlockMutex() { gUnlockMutex(&mutex); } + +private: + + static GThreadReturn threadFunc(void *arg); + void worker(); + + TileCache *tileCache; + int nThreads; + GThreadID *threads; + GBool quit; + GMutex mutex; + GCondition cond; // signalled when a job is added to the + // queue and when the quit flag is set + GCondition finishCond; // signalled whenever a worker thread + // finishes rasterizing a tile +}; + +TileCacheThreadPool::TileCacheThreadPool(TileCache *tileCacheA, + int nThreadsA) { + int i; + + tileCache = tileCacheA; + nThreads = nThreadsA; + quit = gFalse; + gInitMutex(&mutex); + gInitCondition(&cond); + gInitCondition(&finishCond); + threads = (GThreadID *)gmallocn(nThreads, sizeof(GThreadID)); + for (i = 0; i < nThreads; ++i) { + gCreateThread(&threads[i], &threadFunc, this); + } +} + +TileCacheThreadPool::~TileCacheThreadPool() { + int i; + + gLockMutex(&mutex); + quit = true; + gSignalCondition(&cond); + gUnlockMutex(&mutex); + for (i = 0; i < nThreads; ++i) { + gJoinThread(threads[i]); + } + gDestroyCondition(&cond); + gDestroyCondition(&finishCond); + gDestroyMutex(&mutex); + gfree(threads); +} + +void TileCacheThreadPool::jobAdded() { + gLockMutex(&mutex); + gSignalCondition(&cond); + gUnlockMutex(&mutex); +} + +GThreadReturn TileCacheThreadPool::threadFunc(void *arg) { + ((TileCacheThreadPool *)arg)->worker(); + return 0; +} + +void TileCacheThreadPool::worker() { + CachedTileDesc *ct; + + while (1) { + gLockMutex(&mutex); + while (!quit && !(ct = tileCache->getUnstartedTile())) { + gWaitCondition(&cond, &mutex); + } + if (quit) { + gUnlockMutex(&mutex); + break; + } + if (!tileCache->hasUnstartedTiles()) { + gClearCondition(&cond); + } + gUnlockMutex(&mutex); + tileCache->rasterizeTile(ct); + gSignalCondition(&finishCond); + } +} + +void TileCacheThreadPool::waitForFinishedJob() { + gWaitCondition(&finishCond, &mutex); +} + +//------------------------------------------------------------------------ +// TileCache +//------------------------------------------------------------------------ + +TileCache::TileCache(DisplayState *stateA) { + state = stateA; + state->setTileCache(this); + cache = new GList(); + threadPool = new TileCacheThreadPool(this, state->getNWorkerThreads()); + tileDoneCbk = NULL; + tileDoneCbkData = NULL; +} + +TileCache::~TileCache() { + flushCache(gFalse); + delete threadPool; + delete cache; +} + +void TileCache::setActiveTileList(GList *tiles) { + TileDesc *tile; + CachedTileDesc *ct; + int tileIdx, cacheIdx; + GBool newTiles; + + threadPool->lockMutex(); + + // remove any unstarted tiles not on the new active list; + // cancel any started tiles not on the new active list; + // mark all other tiles as inactive (active tiles will be marked later) + cacheIdx = 0; + while (cacheIdx < cache->getLength()) { + ct = (CachedTileDesc *)cache->get(cacheIdx); + if (ct->state == cachedTileUnstarted && findTile(ct, tiles) < 0) { + delete (CachedTileDesc *)cache->del(cacheIdx); + } else if (ct->state == cachedTileStarted && findTile(ct, tiles) < 0) { + ct->state = cachedTileCanceled; + ++cacheIdx; + } else { + ct->active = gFalse; + ++cacheIdx; + } + } + + // mark cached tiles as active; add any new tiles to the cache + newTiles = gFalse; + for (tileIdx = 0; tileIdx < tiles->getLength(); ++tileIdx) { + tile = (TileDesc *)tiles->get(tileIdx); + cacheIdx = findTile(tile, cache); + if (cacheIdx >= 0) { + ct = (CachedTileDesc *)cache->del(cacheIdx); + } else { + ct = new CachedTileDesc(tile); + newTiles = gTrue; + } + ct->active = gTrue; + cache->insert(0, ct); + } + + cleanCache(); + + threadPool->unlockMutex(); + + if (newTiles) { + threadPool->jobAdded(); + } +} + +SplashBitmap *TileCache::getTileBitmap(TileDesc *tile, GBool *finished) { + CachedTileDesc *ct; + SplashBitmap *bitmap; + int cacheIdx; + + threadPool->lockMutex(); + cacheIdx = findTile(tile, cache); + if (cacheIdx < 0) { + threadPool->unlockMutex(); + return NULL; + } + ct = (CachedTileDesc *)cache->get(cacheIdx); + if (ct->state != cachedTileCanceled) { + bitmap = ct->bitmap; + } else { + bitmap = NULL; + } + if (finished) { + *finished = ct->state == cachedTileFinished; + } + threadPool->unlockMutex(); + return bitmap; +} + +void TileCache::paperColorChanged() { + flushCache(gFalse); +} + +void TileCache::reverseVideoChanged() { + flushCache(gFalse); +} + +void TileCache::optionalContentChanged() { + flushCache(gFalse); +} + +void TileCache::docChanged() { + flushCache(gTrue); +} + + +void TileCache::forceRedraw() { + flushCache(gFalse); +} + +// Search for on , and return its index if found, or +// -1 if not found. If is part of the cache, or if +// is the cache, the caller must have locked the ThreadPool mutex. +int TileCache::findTile(TileDesc *tile, GList *tileList) { + TileDesc *t; + int i; + + for (i = 0; i < tileList->getLength(); ++i) { + t = (TileDesc *)tileList->get(i); + if (t->matches(tile)) { + return i; + } + } + return -1; +} + +// If there are too many tiles in the cache, remove the least recently +// used tiles. Never removes active tiles. The caller must have +// locked the ThreadPool mutex. +void TileCache::cleanCache() { + CachedTileDesc *ct; + int n, i; + + // count the number of non-canceled tiles + n = 0; + for (i = 0; i < cache->getLength(); ++i) { + ct = (CachedTileDesc *)cache->get(i); + if (ct->state != cachedTileCanceled) { + ++n; + } + } + + // if there are too many non-canceled tiles, remove tiles + i = cache->getLength() - 1; + while (n > state->getTileCacheSize() && i >= 0) { + ct = (CachedTileDesc *)cache->get(i); + if (ct->active) { + break; + } + // any non-active tiles with state == cachedTileUnstarted should + // already have been removed by setActiveTileList() + if (ct->state == cachedTileFinished) { + delete (CachedTileDesc *)cache->del(i); + --n; + --i; + } else { + --i; + } + } +} + +// Remove all cached tiles. For tiles that are being rasterized, sets +// state to canceled. If is true, this function won't return +// until the cache is empty, i.e., until all possible users of the +// PDFDoc are done. +void TileCache::flushCache(GBool wait) { + CachedTileDesc *ct; + int i; + + threadPool->lockMutex(); + i = 0; + while (i < cache->getLength()) { + ct = (CachedTileDesc *)cache->get(i); + switch (ct->state) { + case cachedTileUnstarted: + case cachedTileFinished: + delete (CachedTileDesc *)cache->del(i); + break; + case cachedTileStarted: + ct->state = cachedTileCanceled; + ++i; + break; + case cachedTileCanceled: + default: + ++i; + break; + } + } + if (wait) { + while (cache->getLength() > 0) { + threadPool->waitForFinishedJob(); + } + } + threadPool->unlockMutex(); +} + +// Remove a tile from the cache and delete it. This will be called +// with the TileCacheThreadPool mutex locked. +void TileCache::removeTile(CachedTileDesc *ct) { + int i; + + for (i = 0; i < cache->getLength(); ++i) { + if (cache->get(i) == ct) { + delete (CachedTileDesc *)cache->del(i); + break; + } + } +} + +// Return true if there are one or more unstarted tiles. This will be +// called with the TileCacheThreadPool mutex locked. +GBool TileCache::hasUnstartedTiles() { + CachedTileDesc *ct; + int i; + + for (i = 0; i < cache->getLength(); ++i) { + ct = (CachedTileDesc *)cache->get(i); + if (ct->state == cachedTileUnstarted) { + return gTrue; + } + } + return gFalse; +} + +// Return the next unstarted tile, changing its state to +// cachedTileStarted. If there are no unstarted tiles, return NULL. +// This will be called with the TileCacheThreadPool mutex locked. +CachedTileDesc *TileCache::getUnstartedTile() { + CachedTileDesc *ct; + int i; + + for (i = 0; i < cache->getLength(); ++i) { + ct = (CachedTileDesc *)cache->get(i); + if (ct->state == cachedTileUnstarted) { + ct->state = cachedTileStarted; + return ct; + } + } + return NULL; +} + +struct TileCacheStartPageInfo { + TileCache *tileCache; + CachedTileDesc *ct; + SplashOutputDev *out; +}; + +void TileCache::startPageCbk(void *data) { + TileCacheStartPageInfo *info = (TileCacheStartPageInfo *)data; + + info->tileCache->threadPool->lockMutex(); + info->ct->bitmap = info->out->getBitmap(); + info->ct->freeBitmap = gFalse; + info->tileCache->threadPool->unlockMutex(); +} + +// Rasterize . The state has already been set to +// cachedTileStarted. +void TileCache::rasterizeTile(CachedTileDesc *ct) { + SplashOutputDev *out; + TileCacheStartPageInfo info; + + + out = new SplashOutputDev(state->getColorMode(), 1, state->getReverseVideo(), + state->getPaperColor()); + info.tileCache = this; + info.ct = ct; + info.out = out; + out->setStartPageCallback(&TileCache::startPageCbk, &info); + out->startDoc(state->getDoc()->getXRef()); + state->getDoc()->displayPageSlice(out, ct->page, ct->dpi, ct->dpi, ct->rotate, + gFalse, gTrue, gFalse, + ct->tx, ct->ty, ct->tw, ct->th, + &abortCheckCbk, ct); + if (ct->state == cachedTileCanceled) { + threadPool->lockMutex(); + removeTile(ct); + threadPool->unlockMutex(); + } else { + threadPool->lockMutex(); + ct->bitmap = out->takeBitmap(); + ct->freeBitmap = gTrue; + ct->state = cachedTileFinished; + threadPool->unlockMutex(); + if (tileDoneCbk) { + (*tileDoneCbk)(tileDoneCbkData); + } + } + delete out; +} + + +GBool TileCache::abortCheckCbk(void *data) { + CachedTileDesc *ct = (CachedTileDesc *)data; + return ct->state == cachedTileCanceled; +} diff --git a/xpdf/TileCache.h b/xpdf/TileCache.h new file mode 100644 index 0000000..bea58c4 --- /dev/null +++ b/xpdf/TileCache.h @@ -0,0 +1,78 @@ +//======================================================================== +// +// TileCache.h +// +// Copyright 2014 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef TILECACHE_H +#define TILECACHE_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "gtypes.h" +#include "SplashTypes.h" + +class SplashBitmap; +class SplashOutputDev; +class DisplayState; +class CachedTileDesc; +class TileCacheThreadPool; +class TileDesc; + +//------------------------------------------------------------------------ + +class TileCache { +public: + + TileCache(DisplayState *stateA); + ~TileCache(); + + // Set the list of currently displayed tiles (TileDesc objects). + void setActiveTileList(GList *tiles); + + // Return the bitmap for a tile. The tile must be on the current + // active list. This can return NULL if tile rasterization hasn't + // started yet. If is non-NULL, * will be set + // to true if rasterization of this bitmap is finished, false + // otherwise. + SplashBitmap *getTileBitmap(TileDesc *tile, GBool *finished); + + // Set a callback to be called whenever a tile rasterization is + // finished. NB: this callback will be called from a worker thread. + void setTileDoneCbk(void (*cbk)(void *data), void *data) + { tileDoneCbk = cbk; tileDoneCbkData = data; } + + void paperColorChanged(); + void reverseVideoChanged(); + void optionalContentChanged(); + void docChanged(); + void forceRedraw(); + +private: + + int findTile(TileDesc *tile, GList *tileList); + void cleanCache(); + void flushCache(GBool wait); + void removeTile(CachedTileDesc *ct); + GBool hasUnstartedTiles(); + CachedTileDesc *getUnstartedTile(); + static void startPageCbk(void *data); + void rasterizeTile(CachedTileDesc *tile); + static GBool abortCheckCbk(void *data); + + DisplayState *state; + GList *cache; // [CachedTileDesc] + TileCacheThreadPool *threadPool; + void (*tileDoneCbk)(void *data); + void *tileDoneCbkData; + + friend class TileCacheThreadPool; +}; + +#endif diff --git a/xpdf/TileCompositor.cc b/xpdf/TileCompositor.cc new file mode 100644 index 0000000..70128a4 --- /dev/null +++ b/xpdf/TileCompositor.cc @@ -0,0 +1,452 @@ +//======================================================================== +// +// TileCompositor.cc +// +// Copyright 2014 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include +#include "gmempp.h" +#include "GString.h" +#include "GList.h" +#include "SplashBitmap.h" +#include "GlobalParams.h" +#include "DisplayState.h" +#include "TileMap.h" +#include "TileCache.h" +#include "TileCompositor.h" + +//------------------------------------------------------------------------ + +// 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); +} + +//------------------------------------------------------------------------ + +TileCompositor::TileCompositor(DisplayState *stateA, + TileMap *tileMapA, + TileCache *tileCacheA) { + state = stateA; + state->setTileCompositor(this); + tileMap = tileMapA; + tileCache = tileCacheA; + bitmap = NULL; + bitmapValid = gFalse; +} + +TileCompositor::~TileCompositor() { + delete bitmap; +} + +SplashBitmap *TileCompositor::getBitmap(GBool *finished) { + GList *tiles; + PlacedTileDesc *tile; + SplashBitmap *tileBitmap; + GBool allTilesFinished, tileFinished; + int xSrc, ySrc, xDest, yDest, w, h, i; + + if (bitmapValid) { + *finished = gTrue; + return bitmap; + } + if (!bitmap || + bitmap->getWidth() != state->getWinW() || + bitmap->getHeight() != state->getWinH()) { + if (bitmap) { + delete bitmap; + } + bitmap = new SplashBitmap(state->getWinW(), state->getWinH(), + state->getBitmapRowPad(), state->getColorMode(), + gFalse, gTrue, NULL); + } + clearBitmap(); + + //--- PDF content + allTilesFinished = gTrue; + tiles = tileMap->getTileList(); + tileCache->setActiveTileList(tiles); + for (i = 0; i < tiles->getLength(); ++i) { + tile = (PlacedTileDesc *)tiles->get(i); + if (tile->px >= 0) { + xSrc = 0; + xDest = tile->px; + w = tile->tw; + } else { + xSrc = -tile->px; + xDest = 0; + w = tile->tw + tile->px; + } + if (xDest + w > state->getWinW()) { + w = state->getWinW() - xDest; + } + if (tile->py >= 0) { + ySrc = 0; + yDest = tile->py; + h = tile->th; + } else { + ySrc = -tile->py; + yDest = 0; + h = tile->th + tile->py; + } + if (yDest + h > state->getWinH()) { + h = state->getWinH() - yDest; + } + if (w > 0 && h > 0) { + if ((tileBitmap = tileCache->getTileBitmap(tile, &tileFinished))) { + blit(tileBitmap, xSrc, ySrc, + bitmap, xDest, yDest, w, h, !tileFinished); + } else { + fill(xDest, yDest, w, h, state->getPaperColor()); + } + allTilesFinished &= tileFinished; + } + } + + + //--- selection + if (state->hasSelection()) { + drawSelection(); + } + + if (finished) { + *finished = allTilesFinished; + } + bitmapValid = allTilesFinished; + + return bitmap; +} + +void TileCompositor::drawSelection() { + SelectRect *rect; + int x0, y0, x1, y1, t, i; + + for (i = 0; i < state->getNumSelectRects(); ++i) { + rect = state->getSelectRect(i); + tileMap->cvtUserToWindow(rect->page, rect->x0, rect->y0, &x0, &y0); + tileMap->cvtUserToWindow(rect->page, rect->x1, rect->y1, &x1, &y1); + if (x0 > x1) { + t = x0; x0 = x1; x1 = t; + } + if (y0 > y1) { + t = y0; y0 = y1; y1 = t; + } + if (x0 < 0) { + x0 = 0; + } else if (x0 > state->getWinW()) { + x0 = state->getWinW(); + } + if (y0 < 0) { + y0 = 0; + } else if (y0 > state->getWinH()) { + y0 = state->getWinH(); + } + if (x1 < 0) { + x1 = 0; + } else if (x1 > state->getWinW()) { + x1 = state->getWinW(); + } + if (y1 < 0) { + y1 = 0; + } else if (y1 > state->getWinH()) { + y1 = state->getWinH(); + } + // NB: in any of the non-continuous modes, if selectPage isn't + // displayed, cvtUserToWindow will return 0,0 -- so we need to + // check for x0 < x1 and y0 < y1 here + if (x0 < x1 && y0 < y1) { + applySelection(x0, y0, x1 - x0, y1 - y0, state->getSelectColor()); + } + } +} + + +void TileCompositor::paperColorChanged() { + bitmapValid = gFalse; +} + +void TileCompositor::matteColorChanged() { + bitmapValid = gFalse; +} + +void TileCompositor::selectColorChanged() { + bitmapValid = gFalse; +} + +void TileCompositor::reverseVideoChanged() { + bitmapValid = gFalse; +} + +void TileCompositor::docChanged() { + bitmapValid = gFalse; +} + +void TileCompositor::windowSizeChanged() { + bitmapValid = gFalse; +} + +void TileCompositor::displayModeChanged() { + bitmapValid = gFalse; +} + +void TileCompositor::zoomChanged() { + bitmapValid = gFalse; +} + +void TileCompositor::rotateChanged() { + bitmapValid = gFalse; +} + +void TileCompositor::scrollPositionChanged() { + bitmapValid = gFalse; +} + +void TileCompositor::selectionChanged() { + bitmapValid = gFalse; +} + +void TileCompositor::regionsChanged() { + bitmapValid = gFalse; +} + +void TileCompositor::optionalContentChanged() { + bitmapValid = gFalse; +} + + +void TileCompositor::forceRedraw() { + bitmapValid = gFalse; +} + +// Clear the bitmap to matteColor. This only supports the RGB8 and +// BGR8 color modes. +void TileCompositor::clearBitmap() { + SplashColorPtr data, row, p; + SplashBitmapRowSize rowSize; + int w, h, x, y; + + w = bitmap->getWidth(); + h = bitmap->getHeight(); + rowSize = bitmap->getRowSize(); + data = bitmap->getDataPtr(); + + switch (state->getColorMode()) { + case splashModeRGB8: + if (state->getMatteColor()[0] == state->getMatteColor()[1] && + state->getMatteColor()[1] == state->getMatteColor()[2]) { + if (rowSize < 0) { + memset(data + rowSize * (h - 1), state->getMatteColor()[0], + -rowSize * h); + } else { + memset(data, state->getMatteColor()[0], rowSize * h); + } + } else { + row = data; + for (y = 0; y < h; ++y) { + p = row; + for (x = 0; x < w; ++x) { + *p++ = state->getMatteColor()[0]; + *p++ = state->getMatteColor()[1]; + *p++ = state->getMatteColor()[2]; + } + row += rowSize; + } + } + break; + case splashModeBGR8: + if (state->getMatteColor()[0] == state->getMatteColor()[1] && + state->getMatteColor()[1] == state->getMatteColor()[2]) { + if (rowSize < 0) { + memset(data + rowSize * (h - 1), state->getMatteColor()[0], + -rowSize * h); + } else { + memset(data, state->getMatteColor()[0], rowSize * h); + } + } else { + row = data; + for (y = 0; y < h; ++y) { + p = row; + for (x = 0; x < w; ++x) { + *p++ = state->getMatteColor()[2]; + *p++ = state->getMatteColor()[1]; + *p++ = state->getMatteColor()[0]; + } + row += rowSize; + } + } + break; + default: + break; + } +} + +// Copy [xSrc, ySrc, w, h] from srcBitmap to [xDest, yDest] in +// destBitmap. This only supports the RGB8 and BGR8 color modes. +// If [compositeWithPaper] is true, composites the source bitmap +// with the paper color (used for incremental updates). +void TileCompositor::blit(SplashBitmap *srcBitmap, int xSrc, int ySrc, + SplashBitmap *destBitmap, int xDest, int yDest, + int w, int h, GBool compositeWithPaper) { + SplashColorPtr srcData, destData, srcP, destP; + SplashColorPtr paperColor; + Guchar *alphaData, *alphaP; + Guchar alpha, alpha1; + SplashBitmapRowSize srcRowSize, destRowSize; + size_t alphaRowSize; + int x, y; + + srcData = srcBitmap->getDataPtr(); + srcRowSize = srcBitmap->getRowSize(); + destData = destBitmap->getDataPtr(); + destRowSize = destBitmap->getRowSize(); + + if (compositeWithPaper && (alphaData = srcBitmap->getAlphaPtr())) { + alphaRowSize = srcBitmap->getAlphaRowSize(); + paperColor = state->getPaperColor(); + for (y = 0; y < h; ++y) { + destP = &destData[(yDest + y) * destRowSize + 3 * xDest]; + srcP = &srcData[(ySrc + y) * srcRowSize + 3 * xSrc]; + alphaP = &alphaData[(ySrc + y) * alphaRowSize + xSrc]; + for (x = 0; x < w; ++x) { + alpha = *alphaP++; + //~ this needs to swap paperColor 0/1/2 in BGR8 mode (?) + if (alpha == 255) { + destP[0] = srcP[0]; + destP[1] = srcP[1]; + destP[2] = srcP[2]; + } else if (alpha == 0) { + destP[0] = paperColor[0]; + destP[1] = paperColor[1]; + destP[2] = paperColor[2]; + } else { + alpha1 = (Guchar)(255 - alpha); + destP[0] = div255(alpha1 * paperColor[0] + alpha * srcP[0]); + destP[1] = div255(alpha1 * paperColor[1] + alpha * srcP[1]); + destP[2] = div255(alpha1 * paperColor[2] + alpha * srcP[2]); + } + srcP += 3; + destP += 3; + } + } + } else { + for (y = 0; y < h; ++y) { + destP = &destData[(yDest + y) * destRowSize + 3 * xDest]; + srcP = &srcData[(ySrc + y) * srcRowSize + 3 * xSrc]; + memcpy(destP, srcP, 3 * w); + } + } +} + +// Fill [xDest, yDest, w, h] with color. This only supports the RGB8 +// and BGR8 color modes. +void TileCompositor::fill(int xDest, int yDest, int w, int h, + SplashColorPtr color) { + SplashColorPtr data, p; + Guchar c0, c1, c2; + SplashBitmapRowSize rowSize; + int x, y; + + if (xDest < 0) { + w += xDest; + xDest = 0; + } + if (xDest + w > state->getWinW()) { + w = state->getWinW() - xDest; + } + if (w <= 0) { + return; + } + if (yDest < 0) { + h += yDest; + yDest = 0; + } + if (yDest + h > state->getWinH()) { + h = state->getWinH() - yDest; + } + if (h <= 0) { + return; + } + data = bitmap->getDataPtr(); + rowSize = bitmap->getRowSize(); + if (bitmap->getMode() == splashModeRGB8) { + c0 = color[0]; + c1 = color[1]; + c2 = color[2]; + } else { + c0 = color[2]; + c1 = color[1]; + c2 = color[0]; + } + for (y = 0; y < h; ++y) { + p = &data[(yDest + y) * rowSize + 3 * xDest]; + for (x = 0; x < w; ++x) { + p[0] = c0; + p[1] = c1; + p[2] = c2; + p += 3; + } + } +} + +// Apply a selection of to the specified rectangle. This only +// supports the RGB8 and BGR8 color modes. +void TileCompositor::applySelection(int xDest, int yDest, int w, int h, + SplashColorPtr color) { + SplashColorPtr data, p; + Guchar c0, c1, c2; + SplashBitmapRowSize rowSize; + int x, y; + + if (xDest < 0) { + w += xDest; + xDest = 0; + } + if (xDest + w > state->getWinW()) { + w = state->getWinW() - xDest; + } + if (w <= 0) { + return; + } + if (yDest < 0) { + h += yDest; + yDest = 0; + } + if (yDest + h > state->getWinH()) { + h = state->getWinH() - yDest; + } + if (h <= 0) { + return; + } + data = bitmap->getDataPtr(); + rowSize = bitmap->getRowSize(); + if (bitmap->getMode() == splashModeRGB8) { + c0 = color[0]; + c1 = color[1]; + c2 = color[2]; + } else { + c0 = color[2]; + c1 = color[1]; + c2 = color[0]; + } + for (y = 0; y < h; ++y) { + p = &data[(yDest + y) * rowSize + 3 * xDest]; + for (x = 0; x < w; ++x) { + p[0] = (Guchar)((3 * p[0] + c0) / 4); + p[1] = (Guchar)((3 * p[1] + c1) / 4); + p[2] = (Guchar)((3 * p[2] + c2) / 4); + p += 3; + } + } +} + +//------------------------------------------------------------------------ + diff --git a/xpdf/TileCompositor.h b/xpdf/TileCompositor.h new file mode 100644 index 0000000..aa06c9d --- /dev/null +++ b/xpdf/TileCompositor.h @@ -0,0 +1,77 @@ +//======================================================================== +// +// TileCompositor.h +// +// Copyright 2014 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef TILECOMPOSITOR_H +#define TILECOMPOSITOR_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "SplashTypes.h" + +class GList; +class SplashBitmap; +class DisplayState; +class TileCache; + +//------------------------------------------------------------------------ + +class TileCompositor { +public: + + TileCompositor(DisplayState *stateA, + TileMap *tileMapA, TileCache *tileCacheA); + ~TileCompositor(); + + // Returns the window bitmap. The returned bitmap is owned by the + // TileCompositor object (and may be reused) -- the caller should + // not modify or free it. If is is non-NULL, * + // will be set to true if all of the needed tiles are finished, + // i.e., if the returned bitmap is complete. + SplashBitmap *getBitmap(GBool *finished); + + void paperColorChanged(); + void matteColorChanged(); + void selectColorChanged(); + void reverseVideoChanged(); + void docChanged(); + void windowSizeChanged(); + void displayModeChanged(); + void zoomChanged(); + void rotateChanged(); + void scrollPositionChanged(); + void selectionChanged(); + void regionsChanged(); + void optionalContentChanged(); + void forceRedraw(); + +private: + + void clearBitmap(); + void blit(SplashBitmap *srcBitmap, int xSrc, int ySrc, + SplashBitmap *destBitmap, int xDest, int yDest, + int w, int h, GBool compositeWithPaper); + void fill(int xDest, int yDest, int w, int h, + SplashColorPtr color); + void drawSelection(); + void applySelection(int xDest, int yDest, int w, int h, + SplashColorPtr color); + + DisplayState *state; + TileMap *tileMap; + TileCache *tileCache; + + SplashBitmap *bitmap; + GBool bitmapValid; + +}; + +#endif diff --git a/xpdf/TileMap.cc b/xpdf/TileMap.cc new file mode 100644 index 0000000..d591662 --- /dev/null +++ b/xpdf/TileMap.cc @@ -0,0 +1,1690 @@ +//======================================================================== +// +// TileMap.cc +// +// Copyright 2014 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include "gmem.h" +#include "gmempp.h" +#include "GList.h" +#include "PDFDoc.h" +#include "DisplayState.h" +#include "TileMap.h" + +//------------------------------------------------------------------------ + +// Number of pixels of matte color between pages (above and below each +// other) in continuous mode. +#define continuousPageSpacing 3 + +// Number of pixels of matte color between facing pages (left and +// right of each other) in side-by-side mode. +#define sideBySidePageSpacing 3 + +// Number of pixels of matte color between pages (left and right of +// each other) in horizontal continuous mode. +#define horizContinuousPageSpacing 3 + +//------------------------------------------------------------------------ + +TileMap::TileMap(DisplayState *stateA) { + state = stateA; + state->setTileMap(this); + pageDPI = NULL; + pageW = pageH = NULL; + tileW = tileH = NULL; + pageBoxW = pageBoxH = NULL; + pageX = pageY = NULL; + tiles = NULL; +} + +TileMap::~TileMap() { + clearPageParams(); + clearContinuousModeParams(); + gfree(pageBoxW); + gfree(pageBoxH); + if (tiles) { + deleteGList(tiles, PlacedTileDesc); + } +} + +GList *TileMap::getTileList() { + double pageDPI1, pageDPI2; + int pageW1, pageH1, tileW1, tileH1, pageW2, pageH2, tileW2, tileH2; + int offsetX, offsetY, offsetX2; + int x0, y0, x1, y1, x, y, tx, ty, tw, th, page; + + if (tiles) { + return tiles; + } + + tiles = new GList(); + + if (!state->getDoc() || !state->getDoc()->getNumPages()) { + return tiles; + } + + updatePageParams(); + updateContinuousModeParams(); + + switch (state->getDisplayMode()) { + + case displaySingle: + page = state->getScrollPage(); + pageDPI1 = pageDPI[page - 1]; + pageW1 = pageW[page - 1]; + pageH1 = pageH[page - 1]; + tileW1 = tileW[page - 1]; + tileH1 = tileH[page - 1]; + if (pageW1 < state->getWinW()) { + offsetX = (state->getWinW() - pageW1) / 2; + } else { + offsetX = 0; + } + if (pageH1 < state->getWinH()) { + offsetY = (state->getWinH() - pageH1) / 2; + } else { + offsetY = 0; + } + if ((x0 = state->getScrollX() - offsetX) < 0) { + x0 = 0; + } + if ((y0 = state->getScrollY() - offsetY) < 0) { + y0 = 0; + } + if ((x1 = state->getScrollX() + state->getWinW() - 1 - offsetX) >= pageW1) { + x1 = pageW1 - 1; + } + if ((y1 = state->getScrollY() + state->getWinH() - 1 - offsetY) >= pageH1) { + y1 = pageH1 - 1; + } + for (y = y0 / tileH1; y <= y1 / tileH1; ++y) { + for (x = x0 / tileW1; x <= x1 / tileW1; ++x) { + tx = x * tileW1; + ty = y * tileH1; + tw = tileW1; + if (tx + tw > pageW1) { + tw = pageW1 - tx; + } + th = tileH1; + if (ty + th > pageH1) { + th = pageH1 - ty; + } + tiles->append(new PlacedTileDesc(page, state->getRotate(), pageDPI1, + tx, ty, tw, th, + tx - state->getScrollX() + offsetX, + ty - state->getScrollY() + offsetY)); + } + } + break; + + case displayContinuous: + if (totalH < state->getWinH()) { + offsetY = (state->getWinH() - totalH) / 2; + } else { + offsetY = 0; + } + page = findContinuousPage(state->getScrollY()); + while (page <= state->getDoc()->getNumPages() && + pageY[page - 1] < state->getScrollY() + state->getWinH()) { + pageDPI1 = pageDPI[page - 1]; + pageW1 = pageW[page - 1]; + pageH1 = pageH[page - 1]; + tileW1 = tileW[page - 1]; + tileH1 = tileH[page - 1]; + if (maxW < state->getWinW()) { + offsetX = (state->getWinW() - maxW) / 2; + } else { + offsetX = 0; + } + offsetX += (maxW - pageW1) / 2; + if ((x0 = state->getScrollX() - offsetX) < 0) { + x0 = 0; + } + if ((y0 = state->getScrollY() - pageY[page - 1] - offsetY) < 0) { + y0 = 0; + } + if ((x1 = state->getScrollX() + state->getWinW() - 1 - offsetX) + >= pageW1) { + x1 = pageW1 - 1; + } + if ((y1 = state->getScrollY() - pageY[page - 1] + + state->getWinH() - 1 - offsetY) + >= pageH1) { + y1 = pageH1 - 1; + } + for (y = y0 / tileH1; y <= y1 / tileH1; ++y) { + for (x = x0 / tileW1; x <= x1 / tileW1; ++x) { + tx = x * tileW1; + ty = y * tileH1; + tw = tileW1; + if (tx + tw > pageW1) { + tw = pageW1 - tx; + } + th = tileH1; + if (ty + th > pageH1) { + th = pageH1 - ty; + } + tiles->append(new PlacedTileDesc( + page, state->getRotate(), pageDPI1, + tx, ty, tw, th, + tx - state->getScrollX() + offsetX, + ty - state->getScrollY() + pageY[page - 1] + + offsetY)); + } + } + ++page; + } + break; + + case displaySideBySideSingle: + page = state->getScrollPage(); + pageDPI1 = pageDPI[page - 1]; + pageW1 = pageW[page - 1]; + pageH1 = pageH[page - 1]; + tileW1 = tileW[page - 1]; + tileH1 = tileH[page - 1]; + if (page + 1 <= state->getDoc()->getNumPages()) { + pageDPI2 = pageDPI[page]; + pageW2 = pageW[page]; + pageH2 = pageH[page]; + tileW2 = tileW[page]; + tileH2 = tileH[page]; + } else { + // display a single page as though there were a blank facing + // page of the same size + pageDPI2 = pageDPI1; + pageW2 = pageW1; + pageH2 = pageH1; + tileW2 = tileW1; + tileH2 = tileH1; + } + if (pageW1 + sideBySidePageSpacing + pageW2 < state->getWinW()) { + offsetX = (state->getWinW() - + (pageW1 + sideBySidePageSpacing + pageW2)) / 2; + } else { + offsetX = 0; + } + offsetX2 = offsetX + pageW1 + sideBySidePageSpacing; + if (pageH1 < state->getWinH() && pageH2 < state->getWinH()) { + if (pageH1 > pageH2) { + offsetY = (state->getWinH() - pageH1) / 2; + } else { + offsetY = (state->getWinH() - pageH2) / 2; + } + } else { + offsetY = 0; + } + // left page + if ((x0 = state->getScrollX() - offsetX) < 0) { + x0 = 0; + } + if ((y0 = state->getScrollY() - offsetY) < 0) { + y0 = 0; + } + if ((x1 = state->getScrollX() + state->getWinW() - 1 - offsetX) >= pageW1) { + x1 = pageW1 - 1; + } else if (x1 < 0) { + x1 = -tileW2; + } + if ((y1 = state->getScrollY() + state->getWinH() - 1 - offsetY) >= pageH1) { + y1 = pageH1 - 1; + } else if (y1 < 0) { + y1 = -tileH2; + } + for (y = y0 / tileH1; y <= y1 / tileH1; ++y) { + for (x = x0 / tileW1; x <= x1 / tileW1; ++x) { + tx = x * tileW1; + ty = y * tileH1; + tw = tileW1; + if (tx + tw > pageW1) { + tw = pageW1 - tx; + } + th = tileH1; + if (ty + th > pageH1) { + th = pageH1 - ty; + } + tiles->append(new PlacedTileDesc(page, + state->getRotate(), pageDPI1, + tx, ty, tw, th, + tx - state->getScrollX() + offsetX, + ty - state->getScrollY() + offsetY)); + } + } + // right page + if (page + 1 <= state->getDoc()->getNumPages()) { + if ((x0 = state->getScrollX() - offsetX2) < 0) { + x0 = 0; + } + if ((y0 = state->getScrollY() - offsetY) < 0) { + y0 = 0; + } + if ((x1 = state->getScrollX() + state->getWinW() - 1 - offsetX2) + >= pageW2) { + x1 = pageW2 - 1; + } else if (x1 < 0) { + x1 = -tileW2; + } + if ((y1 = state->getScrollY() + state->getWinH() - 1 - offsetY) + >= pageH2) { + y1 = pageH2 - 1; + } else if (y1 < 0) { + y1 = -tileH2; + } + for (y = y0 / tileH2; y <= y1 / tileH2; ++y) { + for (x = x0 / tileW2; x <= x1 / tileW2; ++x) { + tx = x * tileW2; + ty = y * tileH2; + tw = tileW2; + if (tx + tw > pageW2) { + tw = pageW2 - tx; + } + th = tileH2; + if (ty + th > pageH2) { + th = pageH2 - ty; + } + tiles->append(new PlacedTileDesc(page + 1, + state->getRotate(), pageDPI2, + tx, ty, tw, th, + tx - state->getScrollX() + offsetX2, + ty - state->getScrollY() + offsetY)); + } + } + } + break; + + case displaySideBySideContinuous: + if (totalH < state->getWinH()) { + offsetY = (state->getWinH() - totalH) / 2; + } else { + offsetY = 0; + } + page = findSideBySideContinuousPage(state->getScrollY()); + while (page <= state->getDoc()->getNumPages() && + (pageY[page - 1] < state->getScrollY() + state->getWinH() || + (page + 1 <= state->getDoc()->getNumPages() && + pageY[page] < state->getScrollY() + state->getWinH()))) { + pageDPI1 = pageDPI[page - 1]; + pageW1 = pageW[page - 1]; + pageH1 = pageH[page - 1]; + tileW1 = tileW[page - 1]; + tileH1 = tileH[page - 1]; + if (page + 1 <= state->getDoc()->getNumPages()) { + pageDPI2 = pageDPI[page]; + pageW2 = pageW[page]; + pageH2 = pageH[page]; + tileW2 = tileW[page]; + tileH2 = tileH[page]; + } else { + // display a single page as though there were a blank facing + // page of the same size + pageDPI2 = pageDPI1; + pageW2 = pageW1; + pageH2 = pageH1; + tileW2 = tileW1; + tileH2 = tileH1; + } + if (maxW + sideBySidePageSpacing + maxW2 < state->getWinW()) { + offsetX = (state->getWinW() - + (maxW + sideBySidePageSpacing + maxW2)) / 2; + } else { + offsetX = 0; + } + offsetX += maxW - pageW1; + offsetX2 = offsetX + pageW1 + sideBySidePageSpacing; + // left page + if ((x0 = state->getScrollX() - offsetX) < 0) { + x0 = 0; + } + if ((y0 = state->getScrollY() - pageY[page - 1] - offsetY) < 0) { + y0 = 0; + } + if ((x1 = state->getScrollX() + state->getWinW() - 1 - offsetX) + >= pageW1) { + x1 = pageW1 - 1; + } else if (x1 < 0) { + x1 = -tileW2; + } + if ((y1 = state->getScrollY() - pageY[page - 1] + + state->getWinH() - 1 - offsetY) + >= pageH1) { + y1 = pageH1 - 1; + } else if (y1 < 0) { + y1 = -tileH2; + } + for (y = y0 / tileH1; y <= y1 / tileH1; ++y) { + for (x = x0 / tileW1; x <= x1 / tileW1; ++x) { + tx = x * tileW1; + ty = y * tileH1; + tw = tileW1; + if (tx + tw > pageW1) { + tw = pageW1 - tx; + } + th = tileH1; + if (ty + th > pageH1) { + th = pageH1 - ty; + } + tiles->append(new PlacedTileDesc( + page, state->getRotate(), pageDPI1, + tx, ty, tw, th, + tx - state->getScrollX() + offsetX, + ty - state->getScrollY() + pageY[page - 1] + + offsetY)); + } + } + ++page; + // right page + if (page <= state->getDoc()->getNumPages()) { + if ((x0 = state->getScrollX() - offsetX2) < 0) { + x0 = 0; + } + if ((y0 = state->getScrollY() - pageY[page - 1] - offsetY) < 0) { + y0 = 0; + } + if ((x1 = state->getScrollX() + state->getWinW() - 1 - offsetX2) + >= pageW2) { + x1 = pageW2 - 1; + } else if (x1 < 0) { + x1 = -tileW2; + } + if ((y1 = state->getScrollY() - pageY[page - 1] + + state->getWinH() - 1 - offsetY) + >= pageH2) { + y1 = pageH2 - 1; + } else if (y1 < 0) { + y1 = -tileH2; + } + for (y = y0 / tileH2; y <= y1 / tileH2; ++y) { + for (x = x0 / tileW2; x <= x1 / tileW2; ++x) { + tx = x * tileW2; + ty = y * tileH2; + tw = tileW2; + if (tx + tw > pageW2) { + tw = pageW2 - tx; + } + th = tileH2; + if (ty + th > pageH2) { + th = pageH2 - ty; + } + tiles->append(new PlacedTileDesc( + page, state->getRotate(), pageDPI2, + tx, ty, tw, th, + tx - state->getScrollX() + offsetX2, + ty - state->getScrollY() + pageY[page - 1] + + offsetY)); + } + } + } + ++page; + } + break; + + case displayHorizontalContinuous: + if (totalW < state->getWinW()) { + offsetX = (state->getWinW() - totalW) / 2; + } else { + offsetX = 0; + } + page = findHorizContinuousPage(state->getScrollX()); + while (page <= state->getDoc()->getNumPages() && + pageX[page - 1] < state->getScrollX() + state->getWinW()) { + pageDPI1 = pageDPI[page - 1]; + pageW1 = pageW[page - 1]; + pageH1 = pageH[page - 1]; + tileW1 = tileW[page - 1]; + tileH1 = tileH[page - 1]; + if (maxH < state->getWinH()) { + offsetY = (state->getWinH() - maxH) / 2; + } else { + offsetY = 0; + } + if ((x0 = state->getScrollX() - pageX[page - 1] - offsetX) < 0) { + x0 = 0; + } + if ((y0 = state->getScrollY() - offsetY) < 0) { + y0 = 0; + } + if ((x1 = state->getScrollX() - pageX[page - 1] + + state->getWinW() - 1 - offsetX) + >= pageW1) { + x1 = pageW1 - 1; + } + if ((y1 = state->getScrollY() + state->getWinH() - 1 - offsetY) + >= pageH1) { + y1 = pageH1 - 1; + } + for (y = y0 / tileH1; y <= y1 / tileH1; ++y) { + for (x = x0 / tileW1; x <= x1 / tileW1; ++x) { + tx = x * tileW1; + ty = y * tileH1; + tw = tileW1; + if (tx + tw > pageW1) { + tw = pageW1 - tx; + } + th = tileH1; + if (ty + th > pageH1) { + th = pageH1 - ty; + } + tiles->append(new PlacedTileDesc( + page, state->getRotate(), pageDPI1, + tx, ty, tw, th, + tx - state->getScrollX() + pageX[page - 1] + + offsetX, + ty - state->getScrollY() + offsetY)); + } + } + ++page; + } + break; + } + + return tiles; +} + +void TileMap::getScrollLimits(int *horizMax, int *vertMax) { + int pageW1, pageH1, pageW2, pageH2; + + if (!state->getDoc() || !state->getDoc()->getNumPages()) { + *horizMax = *vertMax = 0; + return; + } + + updatePageParams(); + updateContinuousModeParams(); + + switch (state->getDisplayMode()) { + case displaySingle: + *horizMax = pageW[state->getScrollPage() - 1]; + *vertMax = pageH[state->getScrollPage() - 1]; + break; + case displayContinuous: + *horizMax = maxW; + *vertMax = totalH; + break; + case displaySideBySideSingle: + pageW1 = pageW[state->getScrollPage() - 1]; + pageH1 = pageH[state->getScrollPage() - 1]; + if (state->getScrollPage() + 1 <= state->getDoc()->getNumPages()) { + pageW2 = pageW[state->getScrollPage()]; + pageH2 = pageH[state->getScrollPage()]; + } else { + pageW2 = pageW1; + pageH2 = pageH1; + } + *horizMax = pageW1 + sideBySidePageSpacing + pageW2; + *vertMax = pageH1 > pageH2 ? pageH1 : pageH2; + break; + case displaySideBySideContinuous: + *horizMax = maxW + sideBySidePageSpacing + maxW2; + *vertMax = totalH; + break; + case displayHorizontalContinuous: + *horizMax = totalW; + *vertMax = maxH; + break; + default: // should never happen + *horizMax = *vertMax = 0; + break; + } +} + +GBool TileMap::cvtWindowToUser(int xw, int yw, + int *pg, double *xu, double *yu) { + GBool ok; + int xd, yd; + + if (!state->getDoc() || !state->getDoc()->getNumPages()) { + *pg = 0; + *xu = *yu = 0; + return gFalse; + } + + ok = cvtWindowToDev(xw, yw, pg, &xd, &yd); + cvtDevToUser(*pg, xd, yd, xu, yu); + return ok; +} + +GBool TileMap::cvtWindowToDev(int xw, int yw, + int *pg, int *xd, int *yd) { + int pageW1, pageH1, pageW2, pageH2, offsetX, offsetX2, offsetY; + + if (!state->getDoc() || !state->getDoc()->getNumPages()) { + *pg = 0; + *xd = *yd = 0; + return gFalse; + } + + updatePageParams(); + updateContinuousModeParams(); + + switch (state->getDisplayMode()) { + + case displaySingle: + *pg = state->getScrollPage(); + pageW1 = pageW[*pg - 1]; + pageH1 = pageH[*pg - 1]; + if (pageW1 < state->getWinW()) { + offsetX = (state->getWinW() - pageW1) / 2; + } else { + offsetX = 0; + } + if (pageH1 < state->getWinH()) { + offsetY = (state->getWinH() - pageH1) / 2; + } else { + offsetY = 0; + } + *xd = xw - offsetX + state->getScrollX(); + *yd = yw - offsetY + state->getScrollY(); + return *xd >= 0 && *xd < pageW1 && *yd >= 0 && *yd < pageH1; + + case displayContinuous: + if (totalH < state->getWinH()) { + offsetY = (state->getWinH() - totalH) / 2; + } else { + offsetY = 0; + } + *pg = findContinuousPage(yw - offsetY + state->getScrollY()); + if (*pg < 1 || *pg > state->getDoc()->getNumPages()) { + *pg = 0; + *xd = *yd = 0; + return gFalse; + } + pageW1 = pageW[*pg - 1]; + pageH1 = pageH[*pg - 1]; + if (maxW < state->getWinW()) { + offsetX = (state->getWinW() - maxW) / 2; + } else { + offsetX = 0; + } + offsetX += (maxW - pageW1) / 2; + *xd = xw - offsetX + state->getScrollX(); + *yd = yw - offsetY - pageY[*pg - 1] + state->getScrollY(); + return *xd >= 0 && *xd < pageW1 && *yd >= 0 && *yd < pageH1; + + case displaySideBySideSingle: + pageW1 = pageW[state->getScrollPage() - 1]; + pageH1 = pageH[state->getScrollPage() - 1]; + if (state->getScrollPage() + 1 <= state->getDoc()->getNumPages()) { + pageW2 = pageW[state->getScrollPage()]; + pageH2 = pageH[state->getScrollPage()]; + } else { + // display a single page as though there were a blank facing + // page of the same size + pageW2 = pageW1; + pageH2 = pageH1; + } + if (pageW1 + sideBySidePageSpacing + pageW2 < state->getWinW()) { + offsetX = (state->getWinW() - + (pageW1 + sideBySidePageSpacing + pageW2)) / 2; + } else { + offsetX = 0; + } + offsetX2 = offsetX + pageW1 + sideBySidePageSpacing; + if (pageH1 < state->getWinH() && pageH2 < state->getWinH()) { + if (pageH1 > pageH2) { + offsetY = (state->getWinH() - pageH1) / 2; + } else { + offsetY = (state->getWinH() - pageH2) / 2; + } + } else { + offsetY = 0; + } + if (xw + state->getScrollX() < offsetX2) { + *pg = state->getScrollPage(); + *xd = xw - offsetX + state->getScrollX(); + *yd = yw - offsetY + state->getScrollY(); + return *xd >= 0 && *xd < pageW1 && *yd >= 0 && *yd < pageH1; + } else { + if (state->getScrollPage() + 1 > state->getDoc()->getNumPages()) { + *pg = *xd = *yd = 0; + return gFalse; + } + *pg = state->getScrollPage() + 1; + *xd = xw - offsetX2 + state->getScrollX(); + *yd = yw - offsetY + state->getScrollY(); + return *xd >= 0 && *xd < pageW2 && *yd >= 0 && *yd < pageH2; + } + + case displaySideBySideContinuous: + if (totalH < state->getWinH()) { + offsetY = (state->getWinH() - totalH) / 2; + } else { + offsetY = 0; + } + *pg = findSideBySideContinuousPage(yw - offsetY + state->getScrollY()); + if (*pg < 1 || *pg > state->getDoc()->getNumPages()) { + *pg = 0; + *xd = *yd = 0; + return gFalse; + } + pageW1 = pageW[*pg - 1]; + pageH1 = pageH[*pg - 1]; + if (*pg + 1 <= state->getDoc()->getNumPages()) { + pageW2 = pageW[*pg]; + pageH2 = pageH[*pg]; + } else { + pageW2 = pageH2 = 0; + } + if (maxW + sideBySidePageSpacing + maxW2 < state->getWinW()) { + offsetX = (state->getWinW() - + (maxW + sideBySidePageSpacing + maxW2)) / 2; + } else { + offsetX = 0; + } + offsetX += maxW - pageW1; + offsetX2 = offsetX + pageW1 + sideBySidePageSpacing; + if (xw + state->getScrollX() < offsetX2) { + *xd = xw - offsetX + state->getScrollX(); + *yd = yw - offsetY - pageY[*pg - 1] + state->getScrollY(); + return *xd >= 0 && *xd < pageW1 && *yd >= 0 && *yd < pageH1; + } else { + if (*pg + 1 > state->getDoc()->getNumPages()) { + *pg = *xd = *yd = 0; + return false; + } + ++*pg; + *xd = xw - offsetX2 + state->getScrollX(); + *yd = yw - offsetY - pageY[*pg - 1] + state->getScrollY(); + return *xd >= 0 && *xd < pageW2 && *yd >= 0 && *yd < pageH2; + } + + case displayHorizontalContinuous: + if (totalW < state->getWinW()) { + offsetX = (state->getWinW() - totalW) / 2; + } else { + offsetX = 0; + } + *pg = findHorizContinuousPage(xw - offsetX + state->getScrollX()); + if (*pg < 1 || *pg > state->getDoc()->getNumPages()) { + *pg = 0; + *xd = *yd = 0; + return gFalse; + } + pageW1 = pageW[*pg - 1]; + pageH1 = pageH[*pg - 1]; + if (maxH < state->getWinH()) { + offsetY = (state->getWinH() - maxH) / 2; + } else { + offsetY = 0; + } + *xd = xw - offsetX - pageX[*pg - 1] + state->getScrollX(); + *yd = yw - offsetY + state->getScrollY(); + return *xd >= 0 && *xd < pageW1 && *yd >= 0 && *yd < pageH1; + } + + return gFalse; +} + +GBool TileMap::cvtUserToWindow(int pg, double xu, double yu, + int *xw, int *yw) { + int xd, yd; + + cvtUserToDev(pg, xu, yu, &xd, &yd); + return cvtDevToWindow(pg, xd, yd, xw, yw); +} + +GBool TileMap::cvtDevToWindow(int pg, int xd, int yd, + int *xw, int *yw) { + int leftPg, pageW1, pageH1, pageW2, pageH2, offsetX, offsetX2, offsetY; + + if (!state->getDoc() || + pg < 1 || pg > state->getDoc()->getNumPages()) { + *xw = *yw = 0; + return gFalse; + } + + updatePageParams(); + updateContinuousModeParams(); + + switch (state->getDisplayMode()) { + + case displaySingle: + if (pg != state->getScrollPage()) { + *xw = *yw = 0; + return gFalse; + } + pageW1 = pageW[pg - 1]; + pageH1 = pageH[pg - 1]; + if (pageW1 < state->getWinW()) { + offsetX = (state->getWinW() - pageW1) / 2; + } else { + offsetX = 0; + } + if (pageH1 < state->getWinH()) { + offsetY = (state->getWinH() - pageH1) / 2; + } else { + offsetY = 0; + } + *xw = xd + offsetX - state->getScrollX(); + *yw = yd + offsetY - state->getScrollY(); + break; + + case displayContinuous: + pageW1 = pageW[pg - 1]; + pageH1 = pageH[pg - 1]; + if (maxW < state->getWinW()) { + offsetX = (state->getWinW() - maxW) / 2; + } else { + offsetX = 0; + } + offsetX += (maxW - pageW1) / 2; + if (totalH < state->getWinH()) { + offsetY = (state->getWinH() - totalH) / 2; + } else { + offsetY = 0; + } + *xw = xd + offsetX - state->getScrollX(); + *yw = pageY[pg - 1] + yd + offsetY - state->getScrollY(); + break; + + case displaySideBySideSingle: + leftPg = (state->getScrollPage() - 1) | 1; + if (!(pg == leftPg || + (pg == leftPg + 1 && + leftPg + 1 <= state->getDoc()->getNumPages()))) { + *xw = *yw = 0; + return gFalse; + } + pageW1 = pageW[leftPg - 1]; + pageH1 = pageH[leftPg - 1]; + if (leftPg + 1 <= state->getDoc()->getNumPages()) { + pageW2 = pageW[leftPg]; + pageH2 = pageH[leftPg]; + } else { + // display a single page as though there were a blank facing + // page of the same size + pageW2 = pageW1; + pageH2 = pageH1; + } + if (pageW1 + sideBySidePageSpacing + pageW2 < state->getWinW()) { + offsetX = (state->getWinW() - + (pageW1 + sideBySidePageSpacing + pageW2)) / 2; + } else { + offsetX = 0; + } + offsetX2 = offsetX + pageW1 + sideBySidePageSpacing; + if (pageH1 < state->getWinH() && pageH2 < state->getWinH()) { + if (pageH1 > pageH2) { + offsetY = (state->getWinH() - pageH1) / 2; + } else { + offsetY = (state->getWinH() - pageH2) / 2; + } + } else { + offsetY = 0; + } + if (pg == leftPg) { + *xw = xd + offsetX - state->getScrollX(); + } else { + *xw = xd + offsetX2 - state->getScrollX(); + } + *yw = yd + offsetY - state->getScrollY(); + break; + + case displaySideBySideContinuous: + leftPg = (pg - 1) | 1; + pageW1 = pageW[leftPg - 1]; + pageH1 = pageH[leftPg - 1]; + if (maxW + sideBySidePageSpacing + maxW2 < state->getWinW()) { + offsetX = (state->getWinW() - + (maxW + sideBySidePageSpacing + maxW2)) / 2; + } else { + offsetX = 0; + } + offsetX += maxW - pageW1; + offsetX2 = offsetX + pageW1 + sideBySidePageSpacing; + if (totalH < state->getWinH()) { + offsetY = (state->getWinH() - totalH) / 2; + } else { + offsetY = 0; + } + if (pg == leftPg) { + *xw = xd + offsetX - state->getScrollX(); + } else { + *xw = xd + offsetX2 - state->getScrollX(); + } + *yw = pageY[pg - 1] + yd + offsetY - state->getScrollY(); + break; + + case displayHorizontalContinuous: + if (totalW < state->getWinW()) { + offsetX = (state->getWinW() - totalW) / 2; + } else { + offsetX = 0; + } + if (maxH < state->getWinH()) { + offsetY = (state->getWinH() - maxH) / 2; + } else { + offsetY = 0; + } + *xw = pageX[pg - 1] + xd + offsetX - state->getScrollX(); + *yw = yd + offsetY - state->getScrollY(); + break; + } + + return gTrue; +} + +void TileMap::cvtUserToDev(int pg, double xu, double yu, int *xd, int *yd) { + double m[6]; + + if (!state->getDoc() || + pg < 1 || pg > state->getDoc()->getNumPages()) { + *xd = *yd = 0; + return; + } + + computePageMatrix(pg, m); + *xd = (int)(xu * m[0] + yu * m[2] + m[4] + 0.5); + *yd = (int)(xu * m[1] + yu * m[3] + m[5] + 0.5); +} + +void TileMap::cvtDevToUser(int pg, int xd, int yd, double *xu, double *yu) { + double m[6], im[6]; + + if (!state->getDoc() || + pg < 1 || pg > state->getDoc()->getNumPages()) { + *xu = *yu = 0; + return; + } + + computePageMatrix(pg, m); + invertMatrix(m, im); + *xu = xd * im[0] + yd * im[2] + im[4]; + *yu = xd * im[1] + yd * im[3] + im[5]; +} + +void TileMap::getWindowPageRange(int x, int y, int w, int h, + int *firstPage, int *lastPage) { + GList *tiles; + PlacedTileDesc *tile; + int i; + + if (!state->getDoc() || !state->getDoc()->getNumPages()) { + *firstPage = *lastPage = 0; + return; + } + *firstPage = state->getDoc()->getNumPages(); + *lastPage = 0; + tiles = getTileList(); + for (i = 0; i < tiles->getLength(); ++i) { + tile = (PlacedTileDesc *)tiles->get(i); + if (tile->px < x + w && + tile->px + tile->tw > x && + tile->py < y + h && + tile->py + tile->th > y) { + if (tile->page < *firstPage) { + *firstPage = tile->page; + } + if (tile->page > *lastPage) { + *lastPage = tile->page; + } + } + } +} + +int TileMap::getPageTopY(int page) { + if (!state->getDoc() || !state->getDoc()->getNumPages()) { + return 0; + } + + updateContinuousModeParams(); + + switch (state->getDisplayMode()) { + case displaySingle: + case displaySideBySideSingle: + case displayHorizontalContinuous: + default: + return 0; + case displayContinuous: + case displaySideBySideContinuous: + return pageY[page - 1]; + } +} + +int TileMap::getPageBottomY(int page) { + if (!state->getDoc() || !state->getDoc()->getNumPages()) { + return 0; + } + + updatePageParams(); + updateContinuousModeParams(); + + switch (state->getDisplayMode()) { + case displaySingle: + case displaySideBySideSingle: + case displayHorizontalContinuous: + default: + return pageH[page - 1] - state->getWinH(); + case displayContinuous: + case displaySideBySideContinuous: + return pageY[page - 1] + pageH[page - 1] - state->getWinH(); + } +} + +int TileMap::getPageLeftX(int page) { + int leftPage, rightPage, pageW1, pageW2, offsetX, offsetX2; + + if (!state->getDoc() || !state->getDoc()->getNumPages()) { + return 0; + } + + updatePageParams(); + updateContinuousModeParams(); + + switch (state->getDisplayMode()) { + case displaySingle: + default: + return 0; + case displayContinuous: + return (maxW - pageW[page - 1]) / 2; + case displaySideBySideSingle: + leftPage = ((page - 1) & ~1) + 1; + rightPage = leftPage + 1; + pageW1 = pageW[leftPage - 1]; + if (rightPage <= state->getDoc()->getNumPages()) { + pageW2 = pageW[rightPage - 1]; + } else { + // display a single page as though there were a blank facing + // page of the same size + pageW2 = pageW1; + } + if (pageW1 + sideBySidePageSpacing + pageW2 < state->getWinW()) { + offsetX = (state->getWinW() - + (pageW1 + sideBySidePageSpacing + pageW2)) / 2; + } else { + offsetX = 0; + } + offsetX2 = offsetX + pageW1 + sideBySidePageSpacing; + return (page == leftPage) ? offsetX : offsetX2; + case displaySideBySideContinuous: + leftPage = ((page - 1) & ~1) + 1; + rightPage = leftPage + 1; + pageW1 = pageW[leftPage - 1]; + if (maxW + sideBySidePageSpacing + maxW2 < state->getWinW()) { + offsetX = (state->getWinW() - + (maxW + sideBySidePageSpacing + maxW2)) / 2; + } else { + offsetX = 0; + } + offsetX += maxW - pageW1; + offsetX2 = offsetX + pageW1 + sideBySidePageSpacing; + return (page == leftPage) ? offsetX : offsetX2; + case displayHorizontalContinuous: + return pageX[page - 1]; + } +} + +int TileMap::getPageRightX(int page) { + int leftPage, rightPage, pageW1, pageW2, offsetX, offsetX2; + + if (!state->getDoc() || !state->getDoc()->getNumPages()) { + return 0; + } + + updatePageParams(); + updateContinuousModeParams(); + + switch (state->getDisplayMode()) { + case displaySingle: + default: + return pageW[page - 1] - state->getWinW(); + case displayContinuous: + return (maxW + pageW[page - 1]) / 2 - state->getWinW(); + case displaySideBySideSingle: + leftPage = ((page - 1) & ~1) + 1; + rightPage = leftPage + 1; + pageW1 = pageW[leftPage - 1]; + if (rightPage <= state->getDoc()->getNumPages()) { + pageW2 = pageW[rightPage - 1]; + } else { + // display a single page as though there were a blank facing + // page of the same size + pageW2 = pageW1; + } + if (pageW1 + sideBySidePageSpacing + pageW2 < state->getWinW()) { + offsetX = (state->getWinW() - + (pageW1 + sideBySidePageSpacing + pageW2)) / 2; + } else { + offsetX = 0; + } + offsetX2 = offsetX + pageW1 + sideBySidePageSpacing; + return (page == leftPage) ? offsetX + pageW1 - state->getWinW() + : offsetX2 + pageW2 - state->getWinW(); + case displaySideBySideContinuous: + leftPage = ((page - 1) & ~1) + 1; + rightPage = leftPage + 1; + pageW1 = pageW[leftPage - 1]; + if (rightPage <= state->getDoc()->getNumPages()) { + pageW2 = pageW[rightPage - 1]; + } else { + // display a single page as though there were a blank facing + // page of the same size + pageW2 = pageW1; + } + if (maxW + sideBySidePageSpacing + maxW2 < state->getWinW()) { + offsetX = (state->getWinW() - + (maxW + sideBySidePageSpacing + maxW2)) / 2; + } else { + offsetX = 0; + } + offsetX += maxW - pageW1; + offsetX2 = offsetX + pageW1 + sideBySidePageSpacing; + return (page == leftPage) ? offsetX + pageW1 - state->getWinW() + : offsetX2 + pageW2 - state->getWinW(); + case displayHorizontalContinuous: + return pageX[page - 1] + pageW[page - 1] - state->getWinW(); + } +} + +int TileMap::getFirstPage() { + updateContinuousModeParams(); + switch (state->getDisplayMode()) { + case displaySingle: + default: + return state->getScrollPage(); + case displayContinuous: + return findContinuousPage(state->getScrollY()); + case displaySideBySideSingle: + return state->getScrollPage(); + case displaySideBySideContinuous: + return findSideBySideContinuousPage(state->getScrollY()); + case displayHorizontalContinuous: + return findHorizContinuousPage(state->getScrollX()); + } +} + +int TileMap::getFirstPageTop() { + int page; + + updateContinuousModeParams(); + switch (state->getDisplayMode()) { + case displaySingle: + default: + return state->getScrollPage(); + case displayContinuous: + page = findContinuousPage(state->getScrollY()); + if (page < state->getDoc()->getNumPages() && + pageY[page - 1] < state->getScrollY()) { + return page + 1; + } else { + return page; + } + case displaySideBySideSingle: + return state->getScrollPage(); + case displaySideBySideContinuous: + page = findSideBySideContinuousPage(state->getScrollY()); + if (page < state->getDoc()->getNumPages() && + pageY[page - 1] < state->getScrollY()) { + return page + 1; + } else { + return page; + } + case displayHorizontalContinuous: + page = findHorizContinuousPage(state->getScrollX()); + if (page < state->getDoc()->getNumPages() && + pageX[page - 1] < state->getScrollX()) { + return page + 1; + } else { + return page; + } + } +} + +int TileMap::getMidPage() { + int wx, wy, pg, x, y; + + wx = state->getWinW() / 2; + wy = state->getWinH() / 2; + if (!cvtWindowToDev(wx, wy, &pg, &x, &y)) { + if (state->getDisplayMode() == displayContinuous) { + wy += continuousPageSpacing; + } else if (state->getDisplayMode() == displaySideBySideContinuous) { + wx += sideBySidePageSpacing; + wy += continuousPageSpacing; + } else if (state->getDisplayMode() == displayHorizontalContinuous) { + wx += horizContinuousPageSpacing; + } else { + return state->getScrollPage(); + } + if (!cvtWindowToDev(wx, wy, &pg, &x, &y)) { + return 1; + } + } + return pg; +} + +int TileMap::getLastPage() { + int pg, x, y, n; + + switch (state->getDisplayMode()) { + case displaySingle: + default: + return state->getScrollPage(); + case displayContinuous: + if (!cvtWindowToDev(state->getWinW() / 2, state->getWinH() - 1, + &pg, &x, &y)) { + return state->getDoc()->getNumPages(); + } + return pg; + case displaySideBySideSingle: + pg = state->getScrollPage() + 1; + n = state->getDoc()->getNumPages(); + if (pg > n) { + pg = n; + } + return pg; + case displaySideBySideContinuous: + if (!cvtWindowToDev(state->getWinW() / 2, state->getWinH() - 1, + &pg, &x, &y)) { + return state->getScrollPage(); + } + pg = ((pg - 1) & ~1) + 2; + n = state->getDoc()->getNumPages(); + if (pg > n) { + pg = n; + } + return pg; + case displayHorizontalContinuous: + x = state->getWinW() - 1; + y = state->getWinH() / 2; + if (!cvtWindowToDev(state->getWinW() - 1, state->getWinH() / 2, + &pg, &x, &y)) { + return state->getDoc()->getNumPages(); + } + return pg; + } +} + +double TileMap::getDPI(int page) { + if (page < 1 || page > state->getDoc()->getNumPages()) { + return 0; + } + updatePageParams(); + return pageDPI[page - 1]; +} + +double TileMap::getPageBoxWidth(int page) { + return pageBoxW[page - 1]; +} + +double TileMap::getPageBoxHeight(int page) { + return pageBoxH[page - 1]; +} + +int TileMap::getContinuousPageSpacing() { + return continuousPageSpacing; +} + +int TileMap::getSideBySidePageSpacing() { + return sideBySidePageSpacing; +} + +int TileMap::getHorizContinuousPageSpacing() { + return horizContinuousPageSpacing; +} + +void TileMap::docChanged() { + PDFDoc *doc; + int nPages, pg, rot; + + doc = state->getDoc(); + + if (doc) { + nPages = doc->getNumPages(); + } else { + nPages = 0; + } + pageBoxW = (double *)greallocn(pageBoxW, nPages, sizeof(double)); + pageBoxH = (double *)greallocn(pageBoxH, nPages, sizeof(double)); + for (pg = 1; pg <= nPages; ++pg) { + rot = doc->getPageRotate(pg); + if (rot == 0 || rot == 180) { + pageBoxW[pg - 1] = doc->getPageCropWidth(pg); + pageBoxH[pg - 1] = doc->getPageCropHeight(pg); + } else { + pageBoxW[pg - 1] = doc->getPageCropHeight(pg); + pageBoxH[pg - 1] = doc->getPageCropWidth(pg); + } + } + + clearPageParams(); + clearContinuousModeParams(); + if (tiles) { + deleteGList(tiles, PlacedTileDesc); + tiles = NULL; + } +} + +void TileMap::windowSizeChanged() { + clearPageParams(); + clearContinuousModeParams(); + if (tiles) { + deleteGList(tiles, PlacedTileDesc); + tiles = NULL; + } +} + +void TileMap::displayModeChanged() { + clearPageParams(); + clearContinuousModeParams(); + if (tiles) { + deleteGList(tiles, PlacedTileDesc); + tiles = NULL; + } +} + +void TileMap::zoomChanged() { + clearPageParams(); + clearContinuousModeParams(); + if (tiles) { + deleteGList(tiles, PlacedTileDesc); + tiles = NULL; + } +} + +void TileMap::rotateChanged() { + clearPageParams(); + clearContinuousModeParams(); + if (tiles) { + deleteGList(tiles, PlacedTileDesc); + tiles = NULL; + } +} + +void TileMap::scrollPositionChanged() { + if (tiles) { + deleteGList(tiles, PlacedTileDesc); + tiles = NULL; + } +} + + +void TileMap::forceRedraw() { + clearPageParams(); + clearContinuousModeParams(); + if (tiles) { + deleteGList(tiles, PlacedTileDesc); + tiles = NULL; + } +} + +void TileMap::clearPageParams() { + gfree(pageDPI); + gfree(pageW); + gfree(pageH); + gfree(tileW); + gfree(tileH); + pageDPI = NULL; + pageW = pageH = NULL; + tileW = tileH = NULL; +} + +void TileMap::updatePageParams() { + double rotPageBoxW, rotPageBoxW2, rotPageBoxH, rotPageBoxH2, rotPageBoxHMax; + double hDPI, vDPI, dpi; + int page, otherPage, nxTiles, nyTiles; + + //--- check to see if the continuous mode params have already been updated + if (pageDPI) { + return; + } + + //--- allocate memory + pageDPI = (double *)gmallocn(state->getDoc()->getNumPages(), sizeof(double)); + pageW = (int *)gmallocn(state->getDoc()->getNumPages(), sizeof(int)); + pageH = (int *)gmallocn(state->getDoc()->getNumPages(), sizeof(int)); + tileW = (int *)gmallocn(state->getDoc()->getNumPages(), sizeof(int)); + tileH = (int *)gmallocn(state->getDoc()->getNumPages(), sizeof(int)); + + for (page = 1; page <= state->getDoc()->getNumPages(); ++page) { + + //--- special handling for side-by-side modes + if (state->displayModeIsSideBySide()) { + + // rotate the page boxes + if (page & 1) { + otherPage = page + 1; + if (otherPage >= state->getDoc()->getNumPages()) { + otherPage = page; + } + } else { + otherPage = page - 1; + if (otherPage < 1) { + otherPage = page; + } + } + if (state->getRotate() == 0 || state->getRotate() == 180) { + rotPageBoxW = pageBoxW[page - 1]; + rotPageBoxW2 = pageBoxW[otherPage - 1]; + rotPageBoxH = pageBoxH[page - 1]; + rotPageBoxH2 = pageBoxH[otherPage - 1]; + } else { + rotPageBoxW = pageBoxH[page - 1]; + rotPageBoxW2 = pageBoxH[otherPage - 1]; + rotPageBoxH = pageBoxW[page - 1]; + rotPageBoxH2 = pageBoxW[otherPage - 1]; + } + rotPageBoxHMax = (rotPageBoxH > rotPageBoxH2) ? rotPageBoxH + : rotPageBoxH2; + + // compute resolution + if (state->getZoom() == zoomPage) { + hDPI = ((state->getWinW() - sideBySidePageSpacing) / + (rotPageBoxW + rotPageBoxW2)) * 72.0; + vDPI = (state->getWinH() / rotPageBoxHMax) * 72.0; + dpi = hDPI < vDPI ? hDPI : vDPI; + // allow for some floating point jitter + dpi -= 0.01; + } else if (state->getZoom() == zoomWidth) { + dpi = ((state->getWinW() - sideBySidePageSpacing) / + (rotPageBoxW + rotPageBoxW2)) * 72.0; + // allow for some floating point jitter + dpi -= 0.01; + } else if (state->getZoom() == zoomHeight) { + dpi = (state->getWinH() / rotPageBoxHMax) * 72.0; + // allow for some floating point jitter + dpi -= 0.01; + } else { + dpi = 0.01 * state->getZoom() * 72.0; + } + + //--- all other (non-side-by-side) modes + } else { + + // rotate the page boxes + if (state->getRotate() == 0 || state->getRotate() == 180) { + rotPageBoxW = pageBoxW[page - 1]; + rotPageBoxH = pageBoxH[page - 1]; + } else { + rotPageBoxW = pageBoxH[page - 1]; + rotPageBoxH = pageBoxW[page - 1]; + } + + // compute resolution + if (state->getZoom() == zoomPage) { + hDPI = (state->getWinW() / rotPageBoxW) * 72.0; + vDPI = (state->getWinH() / rotPageBoxH) * 72.0; + dpi = hDPI < vDPI ? hDPI : vDPI; + // allow for some floating point jitter + dpi -= 0.01; + } else if (state->getZoom() == zoomWidth) { + dpi = (state->getWinW() / rotPageBoxW) * 72.0; + // allow for some floating point jitter + dpi -= 0.01; + } else if (state->getZoom() == zoomHeight) { + dpi = (state->getWinH() / rotPageBoxH) * 72.0; + // allow for some floating point jitter + dpi -= 0.01; + } else { + dpi = 0.01 * state->getZoom() * 72.0; + } + + } + pageDPI[page - 1] = dpi; + + // compute bitmap size + pageW[page - 1] = (int)((rotPageBoxW * dpi / 72.0) + 0.5); + if (pageW[page - 1] < 1) { + pageW[page - 1] = 1; + } + pageH[page - 1] = (int)((rotPageBoxH * dpi / 72.0) + 0.5); + if (pageH[page - 1] < 1) { + pageH[page - 1] = 1; + } + + // compute tile size + // (tile width and height are rounded up -- the bottom and right + // tiles may be slightly smaller than the computed size) + if (pageW[page - 1] <= state->getMaxTileWidth()) { + nxTiles = 1; + tileW[page - 1] = pageW[page - 1]; + } else { + nxTiles = (pageW[page - 1] + state->getMaxTileWidth() - 1) + / state->getMaxTileWidth(); + tileW[page - 1] = (pageW[page - 1] + nxTiles - 1) / nxTiles; + } + if (pageH[page - 1] <= state->getMaxTileHeight()) { + nyTiles = 1; + tileH[page - 1] = pageH[page - 1]; + } else { + nyTiles = (pageH[page - 1] + state->getMaxTileHeight() - 1) + / state->getMaxTileHeight(); + tileH[page - 1] = (pageH[page - 1] + nyTiles - 1) / nyTiles; + } + + } +} + +void TileMap::clearContinuousModeParams() { + gfree(pageX); + pageX = pageY = NULL; +} + +void TileMap::updateContinuousModeParams() { + int page, pageW1, pageH1, pageW2, pageH2, x, y; + + // check to see if the continuous mode params have already been updated + if (pageX) { + return; + } + + updatePageParams(); + + switch (state->getDisplayMode()) { + case displayContinuous: + if (!pageX) { + pageX = pageY = (int *)gmallocn(state->getDoc()->getNumPages(), + sizeof(int)); + } + y = 0; + maxW = 0; + for (page = 1; page <= state->getDoc()->getNumPages(); ++page) { + pageY[page - 1] = y; + y += pageH[page - 1] + continuousPageSpacing; + if (page == 1 || pageW[page - 1] > maxW) { + maxW = pageW[page - 1]; + } + } + totalH = y - continuousPageSpacing; + break; + case displaySideBySideContinuous: + if (!pageX) { + pageX = pageY = (int *)gmallocn(state->getDoc()->getNumPages(), + sizeof(int)); + } + y = 0; + maxW = maxW2 = 0; + for (page = 1; page <= state->getDoc()->getNumPages(); page += 2) { + pageW1 = pageW[page - 1]; + pageH1 = pageH[page - 1]; + if (page + 1 <= state->getDoc()->getNumPages()) { + pageW2 = pageW[page]; + pageH2 = pageH[page]; + } else { + pageW2 = pageW1; + pageH2 = pageH1; + } + pageY[page - 1] = y; + if (page == 1 || pageW1 > maxW) { + maxW = pageW1; + } + if (page + 1 <= state->getDoc()->getNumPages()) { + pageY[page] = y; + } + if (pageW2 > maxW2) { + maxW2 = pageW2; + } + y += (pageH1 > pageH2) ? pageH1 : pageH2; + y += continuousPageSpacing; + } + totalH = y - continuousPageSpacing; + break; + case displayHorizontalContinuous: + if (!pageX) { + pageX = pageY = (int *)gmallocn(state->getDoc()->getNumPages(), + sizeof(int)); + } + x = 0; + maxH = 0; + for (page = 1; page <= state->getDoc()->getNumPages(); ++page) { + pageX[page - 1] = x; + x += pageW[page - 1] + horizContinuousPageSpacing; + if (page == 1 || pageH[page - 1] > maxH) { + maxH = pageH[page - 1]; + } + } + totalW = x - horizContinuousPageSpacing; + break; + default: + break; + } +} + +void TileMap::computePageMatrix(int page, double *m) { + PDFRectangle *cropBox; + double px1, py1, px2, py2, k; + int rotate; + + updatePageParams(); + cropBox = state->getDoc()->getCatalog()->getPage(page)->getCropBox(); + px1 = cropBox->x1; + py1 = cropBox->y1; + px2 = cropBox->x2; + py2 = cropBox->y2; + k = pageDPI[page - 1] / 72.0; + rotate = state->getRotate() + + state->getDoc()->getCatalog()->getPage(page)->getRotate(); + if (rotate > 360) { + rotate -= 360; + } + switch (rotate) { + case 0: + default: + m[0] = k; + m[1] = 0; + m[2] = 0; + m[3] = -k; + m[4] = -k * px1; + m[5] = k * py2; + break; + case 90: + m[0] = 0; + m[1] = k; + m[2] = k; + m[3] = 0; + m[4] = -k * py1; + m[5] = -k * px1; + break; + case 180: + m[0] = -k; + m[1] = 0; + m[2] = 0; + m[3] = k; + m[4] = k * px2; + m[5] = -k * py1; + break; + case 270: + m[0] = 0; + m[1] = -k; + m[2] = -k; + m[3] = 0; + m[4] = k * py2; + m[5] = k * px2; + break; + } +} + +void TileMap::invertMatrix(double *m, double *im) { + double det; + + det = 1 / (m[0] * m[3] - m[1] * m[2]); + im[0] = m[3] * det; + im[1] = -m[1] * det; + im[2] = -m[2] * det; + im[3] = m[0] * det; + im[4] = (m[2] * m[5] - m[3] * m[4]) * det; + im[5] = (m[1] * m[4] - m[0] * m[5]) * det; +} + +int TileMap::findContinuousPage(int y) { + int a, b, m; + + if (y < pageY[0]) { + return 0; + } + if (y >= totalH) { + return state->getDoc()->getNumPages() + 1; + } + a = -1; + b = state->getDoc()->getNumPages(); + // invariant: pageY[a] < y < pageY[b] + while (b - a > 1) { + m = (a + b) / 2; + if (y > pageY[m] - continuousPageSpacing) { + a = m; + } else if (y < pageY[m] - continuousPageSpacing) { + b = m; + } else { + return m + 1; + } + } + return a + 1; +} + +int TileMap::findSideBySideContinuousPage(int y) { + int a, b, m; + + if (y < pageY[0]) { + return 0; + } + if (y >= totalH) { + return (state->getDoc()->getNumPages() + 2) & ~1; + } + a = -2; + b = (state->getDoc()->getNumPages() + 1) & ~1; + // invariant: pageY[a] < y < pageY[b] + while (b - a > 2) { + m = ((a + b) / 2) & ~1; + if (y > pageY[m] - continuousPageSpacing) { + a = m; + } else if (y < pageY[m] - continuousPageSpacing) { + b = m; + } else { + return m + 1; + } + } + return a + 1; +} + +int TileMap::findHorizContinuousPage(int x) { + int a, b, m; + + if (x < pageX[0]) { + return 0; + } + if (x >= totalW) { + return state->getDoc()->getNumPages() + 1; + } + a = -1; + b = state->getDoc()->getNumPages(); + // invariant: pageX[a] < x < pageX[b] + while (b - a > 1) { + m = (a + b) / 2; + if (x > pageX[m] - horizContinuousPageSpacing) { + a = m; + } else if (x < pageX[m] - horizContinuousPageSpacing) { + b = m; + } else { + return m + 1; + } + } + return a + 1; +} diff --git a/xpdf/TileMap.h b/xpdf/TileMap.h new file mode 100644 index 0000000..222877c --- /dev/null +++ b/xpdf/TileMap.h @@ -0,0 +1,247 @@ +//======================================================================== +// +// TileMap.h +// +// Copyright 2014 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef TILEMAP_H +#define TILEMAP_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "gtypes.h" + +class GList; +class DisplayState; + +//------------------------------------------------------------------------ + +// Tile descriptor: this is all of the information needed to specify a +// tile. +class TileDesc { +public: + + TileDesc(int pageA, int rotateA, double dpiA, + int txA, int tyA, int twA, int thA): + page(pageA), rotate(rotateA), dpi(dpiA), + tx(txA), ty(tyA), tw(twA), th(thA) {} + + GBool matches(TileDesc *tile) { + return page == tile->page && rotate == tile->rotate && + dpi == tile->dpi && + tx == tile->tx && ty == tile->ty && + tw == tile->tw && th == tile->th; + } + + int page; // page number + int rotate; // rotation + double dpi; // tile resolution + int tx, ty; // origin of tile, relative to top left + // corner of page + int tw, th; // tile size +}; + +//------------------------------------------------------------------------ + +// A TileDesc plus the tile's location in the display. +class PlacedTileDesc: public TileDesc { +public: + + PlacedTileDesc(int pageA, int rotateA, double dpiA, + int txA, int tyA, int twA, int thA, + int pxA, int pyA): + TileDesc(pageA, rotateA, dpiA, txA, tyA, twA, thA), px(pxA), py(pyA) {} + + int px, py; // position, in window coordinates, of + // tile origin +}; + +//------------------------------------------------------------------------ + +// Tile map: this maps window position to tile, and vice versa; and +// computes the list of tiles needed for the current display. +class TileMap { +public: + + TileMap(DisplayState *stateA); + ~TileMap(); + + // Returns a list of PlacedTileDesc objects describing the tiles + // needed for the current display. The returned list is owned by + // the TileMap object (and may be reused) -- the caller should not + // modify or free it. + GList *getTileList(); + + // Return the max values for the horizontal and vertical scrollbars. + // Scroll thumbs should be winW and winH. + void getScrollLimits(int *horizMax, int *vertMax); + + // Coordinate conversion functions. + // - user space: per-page, as defined by PDF file; unit = point + // - device space: (0,0) is upper-left corner of a page; unit = pixel + // - window space: (0,0) is upper-left corner of drawing area; unit = pixel + // Conversions to window space return false if the specified page + // isn't visible (in non-continuous modes). Conversions from window + // space return false if the point isn't on a page. Otherwise, + // these functions do not do bounds-checking or any clipping to + // window or page coordinates. + GBool cvtWindowToUser(int xw, int yw, + int *pg, double *xu, double *yu); + GBool cvtWindowToDev(int xw, int yw, + int *pg, int *xd, int *yd); + GBool cvtUserToWindow(int pg, double xu, double yu, + int *xw, int *yw); + GBool cvtDevToWindow(int pg, int xd, int yd, + int *xw, int *yw); + void cvtUserToDev(int pg, double xu, double yu, int *xd, int *yd); + void cvtDevToUser(int pg, int xd, int yd, double *xu, double *yu); + + // Return the range of pages intersected by a rectangle in window + // coordinates. E.g., these are the pages that will need to be + // redrawn for a redraw event covering that rectangle. + void getWindowPageRange(int x, int y, int w, int h, + int *firstPage, int *lastPage); + + // Return the scrollY setting that would place the top of at + // the top of the window. (In non-continuous modes, this just + // returns zero.) + int getPageTopY(int page); + + // Return the scrollY setting that would place the bottom of + // at the bottom of the window. + int getPageBottomY(int page); + + // Return the scrollX setting that would place the left side of + // at the left side of the window. (In non-continuous modes, + // this just returns zero.) + int getPageLeftX(int page); + + // Return the scrollX setting that would place the right side of + // at the right side of the window. + int getPageRightX(int page); + + // In continuous modes: return the lowest page number visible + // anywhere in the window; in non-continuous modes: return the + // current page. + int getFirstPage(); + + // In continuous modes: return the lowest page number whose top (or + // left) edge is visible in the window (or if no top/left edge is + // visilble, the page after the single visible page); in + // non-continuous modes: return the current page. + int getFirstPageTop(); + + // In continuous modes: return the page number at the center of the + // window; in non-continuous modes: return the current page. + int getMidPage(); + + // In continuous modes: return the highest page number visible + // anywhere in the window; in non-continuous modes: return the + // current page. + int getLastPage(); + + // Get the resolution at which the specified will be rasterized. + double getDPI(int page); + + // Get the width and height of a page, in points. + double getPageBoxWidth(int page); + double getPageBoxHeight(int page); + + // Get the number of pixels (vertically) between adjacent pages in + // continuous / side-by-side continuous mode. + int getContinuousPageSpacing(); + + // Get the number of pixels (horizontally) between facing pages in + // the side-by-side modes. + int getSideBySidePageSpacing(); + + // Get the number of pixels (horizontally) between adjacent pages in + // horizontal continuous mode. + int getHorizContinuousPageSpacing(); + + void docChanged(); + void windowSizeChanged(); + void displayModeChanged(); + void zoomChanged(); + void rotateChanged(); + void scrollPositionChanged(); + void forceRedraw(); + +private: + + // Clear the pageDPI, pageW, pageH, tileW, and tileH arrays. + void clearPageParams(); + + // Update pageDPI, pageW, pageH, tileW, tileH (if needed). + void updatePageParams(); + + // Clear the pageX/pageY array. + void clearContinuousModeParams(); + + // Update pageX, pageY, maxW, maxW2, maxH, totalW, totalH. + void updateContinuousModeParams(); + + // Compute the user-to-device transform matrix for the specified + // page. + void computePageMatrix(int page, double *m); + + // Invert a matrix. + void invertMatrix(double *m, double *im); + + // Return the page number at y. If y falls in a gap between pages, + // return the next page. If y falls after the last page, return + // numPages + 1. + int findContinuousPage(int y); + + // Return the left-side page number at y. If y falls in a gap between + // page pairs, return the next page. If y falls after the last page, + // return numPages + 1 (or numPages + 2 if numPages is odd). + int findSideBySideContinuousPage(int y); + + // Return the page number at x. If x falls in a gap between pages, + // return the next page. If x falls after the last page, return + // numPages + 1. + int findHorizContinuousPage(int x); + + DisplayState *state; + + double *pageBoxW, *pageBoxH; // page sizes, in points + + // Page parameters: + // pageDPI[pg-1] = rasterization resolution + // pageW[pg-1], pageH[pg-1] = size of rasterized page + // tileW[pg-1], tileH[pg-1] = size of tiles + double *pageDPI; + int *pageW, *pageH; + int *tileW, *tileH; + + // In displayContinuous mode: + // pageY[pg-1] = top edge of page + // maxW = max page width + // totalH = total page height (including gaps) + // In displaySideBySideContinuous mode: + // pageY[pg-1] = top edge of page-pair + // pageY[pg] = top edge of page-pair (if pg+1 <= nPages) + // maxW = max left-side page width + // maxW2 = max right-side page width + // totalH = total page-pair height (including gaps) + // In displayHorizontalContinuous mode: + // pageX[pg-1] = left edge of page + // maxH = max page height + // totalW = total page width (including gaps) + // Only one of pageX or pageY is used at a time, so a single array + // is allocated, i.e., pageX = pageY. + int *pageX, *pageY; + int maxW, maxW2, maxH; + int totalW, totalH; + + GList *tiles; +}; + +#endif diff --git a/xpdf/UTF8.cc b/xpdf/UTF8.cc new file mode 100644 index 0000000..9ee0142 --- /dev/null +++ b/xpdf/UTF8.cc @@ -0,0 +1,183 @@ +//======================================================================== +// +// UTF8.cc +// +// Copyright 2001-2017 Glyph & Cog, LLC +// +//======================================================================== + +#include +#include "UTF8.h" + +int mapUTF8(Unicode u, char *buf, int bufSize) { + if (u <= 0x0000007f) { + if (bufSize < 1) { + return 0; + } + buf[0] = (char)u; + return 1; + } else if (u <= 0x000007ff) { + if (bufSize < 2) { + return 0; + } + buf[0] = (char)(0xc0 + (u >> 6)); + buf[1] = (char)(0x80 + (u & 0x3f)); + return 2; + } else if (u <= 0x0000ffff) { + if (bufSize < 3) { + return 0; + } + buf[0] = (char)(0xe0 + (u >> 12)); + buf[1] = (char)(0x80 + ((u >> 6) & 0x3f)); + buf[2] = (char)(0x80 + (u & 0x3f)); + return 3; + } else if (u <= 0x0010ffff) { + if (bufSize < 4) { + return 0; + } + buf[0] = (char)(0xf0 + (u >> 18)); + buf[1] = (char)(0x80 + ((u >> 12) & 0x3f)); + buf[2] = (char)(0x80 + ((u >> 6) & 0x3f)); + buf[3] = (char)(0x80 + (u & 0x3f)); + return 4; + } else { + return 0; + } +} + +int mapUCS2(Unicode u, char *buf, int bufSize) { + if (u <= 0xffff) { + if (bufSize < 2) { + return 0; + } + buf[0] = (char)((u >> 8) & 0xff); + buf[1] = (char)(u & 0xff); + return 2; + } else { + return 0; + } +} + +GBool getUTF8(GString *s, int *i, Unicode *u) { + Guchar c0, c1, c2, c3, c4, c5; + + if (*i >= s->getLength()) { + return gFalse; + } + c0 = (Guchar)s->getChar((*i)++); + if (c0 < 0x80) { + *u = (Unicode)c0; + } else if (c0 < 0xe0) { + if (*i < s->getLength() && + ((c1 = (Guchar)s->getChar(*i)) & 0xc0) == 0x80) { + *i += 1; + *u = (Unicode)(((c0 & 0x1f) << 6) | + (c1 & 0x3f)); + } else { + *u = (Unicode)c0; + } + } else if (c0 < 0xf0) { + if (*i < s->getLength() - 1 && + ((c1 = (Guchar)s->getChar(*i)) & 0xc0) == 0x80 && + ((c2 = (Guchar)s->getChar(*i + 1)) & 0xc0) == 0x80) { + *i += 2; + *u = (Unicode)(((c0 & 0x0f) << 12) | + ((c1 & 0x3f) << 6) | + (c2 & 0x3f)); + } else { + *u = (Unicode)c0; + } + } else if (c0 < 0xf8) { + if (*i < s->getLength() - 2 && + ((c1 = (Guchar)s->getChar(*i)) & 0xc0) == 0x80 && + ((c2 = (Guchar)s->getChar(*i + 1)) & 0xc0) == 0x80 && + ((c3 = (Guchar)s->getChar(*i + 2)) & 0xc0) == 0x80) { + *i += 3; + *u = (Unicode)(((c0 & 0x07) << 18) | + ((c1 & 0x3f) << 12) | + ((c2 & 0x3f) << 6) | + (c3 & 0x3f)); + } else { + *u = (Unicode)c0; + } + } else if (c0 < 0xfc) { + if (*i < s->getLength() - 3 && + ((c1 = (Guchar)s->getChar(*i)) & 0xc0) == 0x80 && + ((c2 = (Guchar)s->getChar(*i + 1)) & 0xc0) == 0x80 && + ((c3 = (Guchar)s->getChar(*i + 2)) & 0xc0) == 0x80 && + ((c4 = (Guchar)s->getChar(*i + 3)) & 0xc0) == 0x80) { + *i += 4; + *u = (Unicode)(((c0 & 0x03) << 24) | + ((c1 & 0x3f) << 18) | + ((c2 & 0x3f) << 12) | + ((c3 & 0x3f) << 6) | + (c4 & 0x3f)); + } else { + *u = (Unicode)c0; + } + } else if (c0 < 0xfe) { + if (*i < s->getLength() - 4 && + ((c1 = (Guchar)s->getChar(*i)) & 0xc0) == 0x80 && + ((c2 = (Guchar)s->getChar(*i + 1)) & 0xc0) == 0x80 && + ((c3 = (Guchar)s->getChar(*i + 2)) & 0xc0) == 0x80 && + ((c4 = (Guchar)s->getChar(*i + 3)) & 0xc0) == 0x80 && + ((c5 = (Guchar)s->getChar(*i + 4)) & 0xc0) == 0x80) { + *i += 5; + *u = (Unicode)(((c0 & 0x01) << 30) | + ((c1 & 0x3f) << 24) | + ((c2 & 0x3f) << 18) | + ((c3 & 0x3f) << 12) | + ((c4 & 0x3f) << 6) | + (c5 & 0x3f)); + } else { + *u = (Unicode)c0; + } + } else { + *u = (Unicode)c0; + } + return gTrue; +} + +GBool getUTF16BE(GString *s, int *i, Unicode *u) { + int w0, w1; + + if (*i >= s->getLength() - 1) { + return gFalse; + } + w0 = ((s->getChar(*i) & 0xff) << 8) | (s->getChar(*i + 1) & 0xff); + *i += 2; + if (w0 < 0xd800 || w0 >= 0xe000) { + *u = (Unicode)w0; + } else { + if (*i < s->getLength() - 1) { + w1 = ((s->getChar(*i) & 0xff) << 8) | (s->getChar(*i + 1) & 0xff); + *i += 2; + *u = 0x10000 + ((w0 - 0xd800) << 10) + (w1 - 0xdc00); + } else { + *u = (Unicode)w0; + } + } + return gTrue; +} + +GBool getUTF16LE(GString *s, int *i, Unicode *u) { + int w0, w1; + + if (*i >= s->getLength() - 1) { + return gFalse; + } + w0 = (s->getChar(*i) & 0xff) | ((s->getChar(*i + 1) & 0xff) << 8); + *i += 2; + if (w0 < 0xd800 || w0 >= 0xe000) { + *u = (Unicode)w0; + } else { + if (*i < s->getLength() - 1) { + w1 = (s->getChar(*i) & 0xff) | ((s->getChar(*i + 1) & 0xff) << 8); + *i += 2; + *u = 0x10000 + ((w0 - 0xd800) << 10) + (w1 - 0xdc00); + } else { + *u = (Unicode)w0; + } + } + return gTrue; +} diff --git a/xpdf/UTF8.h b/xpdf/UTF8.h new file mode 100644 index 0000000..1f29030 --- /dev/null +++ b/xpdf/UTF8.h @@ -0,0 +1,42 @@ +//======================================================================== +// +// UTF8.h +// +// Copyright 2001-2017 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef UTF8_H +#define UTF8_H + +#include + +#include "gtypes.h" +#include "GString.h" +#include "CharTypes.h" + +// Convert [u] to UTF-8 in [buf]. Returns the number of bytes written +// to [buf]. If [u] requires more then [bufSize] bytes in UTF-8, +// writes nothing and returns 0. +extern int mapUTF8(Unicode u, char *buf, int bufSize); + +// Convert [u] to UCS-2BE in [buf]. Returns the number of bytes +// written to [buf]. If [u] requires more then [bufSize] bytes in +// UCS-2, writes nothing and returns 0. +extern int mapUCS2(Unicode u, char *buf, int bufSize); + +// Parse one UTF-8 character from [s], starting at *[i]. Writes the +// character to *[u], updates *[i] to point to the next available byte +// in [s], and returns true. At end of string: writes nothing to *[u] +// or *[i] and returns false. For an invalid UTF-8 character: sets +// *[u] to the next byte, advances *[i] by one (to avoid infinite +// loops), and returns true. +extern GBool getUTF8(GString *s, int *i, Unicode *u); + +// Same as getUTF8, but for UTF-16BE. +extern GBool getUTF16BE(GString *s, int *i, Unicode *u); + +// Same as getUTF8, but for UTF-16LE. +extern GBool getUTF16LE(GString *s, int *i, Unicode *u); + +#endif diff --git a/xpdf/UnicodeMap.cc b/xpdf/UnicodeMap.cc new file mode 100644 index 0000000..833d6fc --- /dev/null +++ b/xpdf/UnicodeMap.cc @@ -0,0 +1,281 @@ +//======================================================================== +// +// UnicodeMap.cc +// +// Copyright 2001-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include +#include "gmem.h" +#include "gmempp.h" +#include "gfile.h" +#include "GString.h" +#include "GList.h" +#include "Error.h" +#include "GlobalParams.h" +#include "UnicodeMap.h" + +//------------------------------------------------------------------------ + +#define maxExtCode 16 + +struct UnicodeMapExt { + Unicode u; // Unicode char + char code[maxExtCode]; + Guint nBytes; +}; + +//------------------------------------------------------------------------ + +UnicodeMap *UnicodeMap::parse(GString *encodingNameA) { + FILE *f; + UnicodeMap *map; + UnicodeMapRange *range; + UnicodeMapExt *eMap; + int size, eMapsSize; + char buf[256]; + int line, nBytes, i, x; + char *tok1, *tok2, *tok3; + + if (!(f = globalParams->getUnicodeMapFile(encodingNameA))) { + error(errSyntaxError, -1, + "Couldn't find unicodeMap file for the '{0:t}' encoding", + encodingNameA); + return NULL; + } + + map = new UnicodeMap(encodingNameA->copy()); + + size = 8; + map->ranges = (UnicodeMapRange *)gmallocn(size, sizeof(UnicodeMapRange)); + eMapsSize = 0; + + line = 1; + while (getLine(buf, sizeof(buf), f)) { + if ((tok1 = strtok(buf, " \t\r\n")) && + (tok2 = strtok(NULL, " \t\r\n"))) { + if (!(tok3 = strtok(NULL, " \t\r\n"))) { + tok3 = tok2; + tok2 = tok1; + } + nBytes = (int)strlen(tok3) / 2; + if (nBytes <= 4) { + if (map->len == size) { + size *= 2; + map->ranges = (UnicodeMapRange *) + greallocn(map->ranges, size, sizeof(UnicodeMapRange)); + } + range = &map->ranges[map->len]; + sscanf(tok1, "%x", &range->start); + sscanf(tok2, "%x", &range->end); + sscanf(tok3, "%x", &range->code); + range->nBytes = nBytes; + ++map->len; + } else if (tok2 == tok1) { + if (map->eMapsLen == eMapsSize) { + eMapsSize += 16; + map->eMaps = (UnicodeMapExt *) + greallocn(map->eMaps, eMapsSize, sizeof(UnicodeMapExt)); + } + eMap = &map->eMaps[map->eMapsLen]; + sscanf(tok1, "%x", &eMap->u); + for (i = 0; i < nBytes; ++i) { + sscanf(tok3 + i*2, "%2x", &x); + eMap->code[i] = (char)x; + } + eMap->nBytes = nBytes; + ++map->eMapsLen; + } else { + error(errSyntaxError, -1, + "Bad line ({0:d}) in unicodeMap file for the '{1:t}' encoding", + line, encodingNameA); + } + } else { + error(errSyntaxError, -1, + "Bad line ({0:d}) in unicodeMap file for the '{1:t}' encoding", + line, encodingNameA); + } + ++line; + } + + fclose(f); + + return map; +} + +UnicodeMap::UnicodeMap(GString *encodingNameA) { + encodingName = encodingNameA; + unicodeOut = gFalse; + kind = unicodeMapUser; + ranges = NULL; + len = 0; + eMaps = NULL; + eMapsLen = 0; + refCnt = 1; +} + +UnicodeMap::UnicodeMap(const char *encodingNameA, GBool unicodeOutA, + UnicodeMapRange *rangesA, int lenA) { + encodingName = new GString(encodingNameA); + unicodeOut = unicodeOutA; + kind = unicodeMapResident; + ranges = rangesA; + len = lenA; + eMaps = NULL; + eMapsLen = 0; + refCnt = 1; +} + +UnicodeMap::UnicodeMap(const char *encodingNameA, GBool unicodeOutA, + UnicodeMapFunc funcA) { + encodingName = new GString(encodingNameA); + unicodeOut = unicodeOutA; + kind = unicodeMapFunc; + func = funcA; + eMaps = NULL; + eMapsLen = 0; + refCnt = 1; +} + +UnicodeMap::~UnicodeMap() { + delete encodingName; + if (kind == unicodeMapUser && ranges) { + gfree(ranges); + } + if (eMaps) { + gfree(eMaps); + } +} + +void UnicodeMap::incRefCnt() { +#if MULTITHREADED + gAtomicIncrement(&refCnt); +#else + ++refCnt; +#endif +} + +void UnicodeMap::decRefCnt() { + GBool done; + +#if MULTITHREADED + done = gAtomicDecrement(&refCnt) == 0; +#else + done = --refCnt == 0; +#endif + if (done) { + delete this; + } +} + +GBool UnicodeMap::match(GString *encodingNameA) { + return !encodingName->cmp(encodingNameA); +} + +int UnicodeMap::mapUnicode(Unicode u, char *buf, int bufSize) { + int a, b, m, n, i, j; + Guint code; + + if (kind == unicodeMapFunc) { + return (*func)(u, buf, bufSize); + } + + a = 0; + b = len; + if (u >= ranges[a].start) { + // invariant: ranges[a].start <= u < ranges[b].start + while (b - a > 1) { + m = (a + b) / 2; + if (u >= ranges[m].start) { + a = m; + } else if (u < ranges[m].start) { + b = m; + } + } + if (u <= ranges[a].end) { + n = ranges[a].nBytes; + if (n > bufSize) { + return 0; + } + code = ranges[a].code + (u - ranges[a].start); + for (i = n - 1; i >= 0; --i) { + buf[i] = (char)(code & 0xff); + code >>= 8; + } + return n; + } + } + + for (i = 0; i < eMapsLen; ++i) { + if (eMaps[i].u == u) { + n = eMaps[i].nBytes; + for (j = 0; j < n; ++j) { + buf[j] = eMaps[i].code[j]; + } + return n; + } + } + + return 0; +} + +//------------------------------------------------------------------------ + +UnicodeMapCache::UnicodeMapCache() { + int i; + + for (i = 0; i < unicodeMapCacheSize; ++i) { + cache[i] = NULL; + } +} + +UnicodeMapCache::~UnicodeMapCache() { + int i; + + for (i = 0; i < unicodeMapCacheSize; ++i) { + if (cache[i]) { + cache[i]->decRefCnt(); + } + } +} + +UnicodeMap *UnicodeMapCache::getUnicodeMap(GString *encodingName) { + UnicodeMap *map; + int i, j; + + if (cache[0] && cache[0]->match(encodingName)) { + cache[0]->incRefCnt(); + return cache[0]; + } + for (i = 1; i < unicodeMapCacheSize; ++i) { + if (cache[i] && cache[i]->match(encodingName)) { + map = cache[i]; + for (j = i; j >= 1; --j) { + cache[j] = cache[j - 1]; + } + cache[0] = map; + map->incRefCnt(); + return map; + } + } + if ((map = UnicodeMap::parse(encodingName))) { + if (cache[unicodeMapCacheSize - 1]) { + cache[unicodeMapCacheSize - 1]->decRefCnt(); + } + for (j = unicodeMapCacheSize - 1; j >= 1; --j) { + cache[j] = cache[j - 1]; + } + cache[0] = map; + map->incRefCnt(); + return map; + } + return NULL; +} diff --git a/xpdf/UnicodeMap.h b/xpdf/UnicodeMap.h new file mode 100644 index 0000000..a15d628 --- /dev/null +++ b/xpdf/UnicodeMap.h @@ -0,0 +1,124 @@ +//======================================================================== +// +// UnicodeMap.h +// +// Mapping from Unicode to an encoding. +// +// Copyright 2001-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef UNICODEMAP_H +#define UNICODEMAP_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "gtypes.h" +#include "CharTypes.h" + +#if MULTITHREADED +#include "GMutex.h" +#endif + +class GString; + +//------------------------------------------------------------------------ + +enum UnicodeMapKind { + unicodeMapUser, // read from a file + unicodeMapResident, // static list of ranges + unicodeMapFunc // function pointer +}; + +typedef int (*UnicodeMapFunc)(Unicode u, char *buf, int bufSize); + +struct UnicodeMapRange { + Unicode start, end; // range of Unicode chars + Guint code, nBytes; // first output code +}; + +struct UnicodeMapExt; + +//------------------------------------------------------------------------ + +class UnicodeMap { +public: + + // Create the UnicodeMap specified by . Sets the + // initial reference count to 1. Returns NULL on failure. + static UnicodeMap *parse(GString *encodingNameA); + + // Create a resident UnicodeMap. + 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(const char *encodingNameA, GBool unicodeOutA, + UnicodeMapFunc funcA); + + ~UnicodeMap(); + + void incRefCnt(); + void decRefCnt(); + + GString *getEncodingName() { return encodingName; } + + GBool isUnicode() { return unicodeOut; } + + // Return true if this UnicodeMap matches the specified + // . + GBool match(GString *encodingNameA); + + // Map Unicode to the target encoding. Fills in with the + // output and returns the number of bytes used. Output will be + // truncated at bytes. No string terminator is written. + // Returns 0 if no mapping is found. + int mapUnicode(Unicode u, char *buf, int bufSize); + +private: + + UnicodeMap(GString *encodingNameA); + + GString *encodingName; + UnicodeMapKind kind; + GBool unicodeOut; + union { + UnicodeMapRange *ranges; // (user, resident) + UnicodeMapFunc func; // (func) + }; + int len; // (user, resident) + UnicodeMapExt *eMaps; // (user) + int eMapsLen; // (user) +#if MULTITHREADED + GAtomicCounter refCnt; +#else + int refCnt; +#endif +}; + +//------------------------------------------------------------------------ + +#define unicodeMapCacheSize 4 + +class UnicodeMapCache { +public: + + UnicodeMapCache(); + ~UnicodeMapCache(); + + // Get the UnicodeMap for . Increments its reference + // count; there will be one reference for the cache plus one for the + // caller of this function. Returns NULL on failure. + UnicodeMap *getUnicodeMap(GString *encodingName); + +private: + + UnicodeMap *cache[unicodeMapCacheSize]; +}; + +#endif diff --git a/xpdf/UnicodeMapTables.h b/xpdf/UnicodeMapTables.h new file mode 100644 index 0000000..d103c2e --- /dev/null +++ b/xpdf/UnicodeMapTables.h @@ -0,0 +1,366 @@ +//======================================================================== +// +// UnicodeMapTables.h +// +// Copyright 2001-2014 Glyph & Cog, LLC +// +//======================================================================== + +static UnicodeMapRange latin1UnicodeMapRanges[] = { + { 0x000a, 0x000a, 0x0a, 1 }, + { 0x000c, 0x000d, 0x0c, 1 }, + { 0x0020, 0x007e, 0x20, 1 }, + { 0x00a0, 0x00a0, 0x20, 1 }, + { 0x00a1, 0x00ff, 0xa1, 1 }, + { 0x010c, 0x010c, 0x43, 1 }, + { 0x010d, 0x010d, 0x63, 1 }, + { 0x0131, 0x0131, 0x69, 1 }, + { 0x0141, 0x0141, 0x4c, 1 }, + { 0x0142, 0x0142, 0x6c, 1 }, + { 0x0152, 0x0152, 0x4f45, 2 }, + { 0x0153, 0x0153, 0x6f65, 2 }, + { 0x0160, 0x0160, 0x53, 1 }, + { 0x0161, 0x0161, 0x73, 1 }, + { 0x0178, 0x0178, 0x59, 1 }, + { 0x017d, 0x017d, 0x5a, 1 }, + { 0x017e, 0x017e, 0x7a, 1 }, + { 0x02c6, 0x02c6, 0x5e, 1 }, + { 0x02da, 0x02da, 0xb0, 1 }, + { 0x02dc, 0x02dc, 0x7e, 1 }, + { 0x2010, 0x2010, 0x2d, 1 }, + { 0x2013, 0x2013, 0x2d, 1 }, + { 0x2014, 0x2014, 0x2d2d, 2 }, + { 0x2018, 0x2018, 0x60, 1 }, + { 0x2019, 0x2019, 0x27, 1 }, + { 0x201a, 0x201a, 0x2c, 1 }, + { 0x201c, 0x201c, 0x22, 1 }, + { 0x201d, 0x201d, 0x22, 1 }, + { 0x201e, 0x201e, 0x2c2c, 2 }, + { 0x2022, 0x2022, 0xb7, 1 }, + { 0x2026, 0x2026, 0x2e2e2e, 3 }, + { 0x2039, 0x2039, 0x3c, 1 }, + { 0x203a, 0x203a, 0x3e, 1 }, + { 0x2044, 0x2044, 0x2f, 1 }, + { 0x2122, 0x2122, 0x544d, 2 }, + { 0x2212, 0x2212, 0x2d, 1 }, + { 0xf6f9, 0xf6f9, 0x4c, 1 }, + { 0xf6fa, 0xf6fa, 0x4f45, 2 }, + { 0xf6fc, 0xf6fc, 0xb0, 1 }, + { 0xf6fd, 0xf6fd, 0x53, 1 }, + { 0xf6fe, 0xf6fe, 0x7e, 1 }, + { 0xf6ff, 0xf6ff, 0x5a, 1 }, + { 0xf721, 0xf721, 0x21, 1 }, + { 0xf724, 0xf724, 0x24, 1 }, + { 0xf726, 0xf726, 0x26, 1 }, + { 0xf730, 0xf739, 0x30, 1 }, + { 0xf73f, 0xf73f, 0x3f, 1 }, + { 0xf761, 0xf77a, 0x41, 1 }, + { 0xf7a1, 0xf7a2, 0xa1, 1 }, + { 0xf7bf, 0xf7bf, 0xbf, 1 }, + { 0xf7e0, 0xf7f6, 0xc0, 1 }, + { 0xf7f8, 0xf7fe, 0xd8, 1 }, + { 0xf7ff, 0xf7ff, 0x59, 1 }, + { 0xfb00, 0xfb00, 0x6666, 2 }, + { 0xfb01, 0xfb01, 0x6669, 2 }, + { 0xfb02, 0xfb02, 0x666c, 2 }, + { 0xfb03, 0xfb03, 0x666669, 3 }, + { 0xfb04, 0xfb04, 0x66666c, 3 }, + { 0xfb05, 0xfb05, 0x7374, 2 }, + { 0xfb06, 0xfb06, 0x7374, 2 } +}; +#define latin1UnicodeMapLen (sizeof(latin1UnicodeMapRanges) / sizeof(UnicodeMapRange)) + +static UnicodeMapRange ascii7UnicodeMapRanges[] = { + { 0x000a, 0x000a, 0x0a, 1 }, + { 0x000c, 0x000d, 0x0c, 1 }, + { 0x0020, 0x005f, 0x20, 1 }, + { 0x0061, 0x007e, 0x61, 1 }, + { 0x00a0, 0x00a0, 0x20, 1 }, + { 0x00a6, 0x00a6, 0x7c, 1 }, + { 0x00a9, 0x00a9, 0x286329, 3 }, + { 0x00ae, 0x00ae, 0x285229, 3 }, + { 0x00b7, 0x00b7, 0x2a, 1 }, + { 0x00bc, 0x00bc, 0x312f34, 3 }, + { 0x00bd, 0x00bd, 0x312f32, 3 }, + { 0x00be, 0x00be, 0x332f34, 3 }, + { 0x00c0, 0x00c0, 0x41, 1 }, + { 0x00c1, 0x00c1, 0x41, 1 }, + { 0x00c2, 0x00c2, 0x41, 1 }, + { 0x00c3, 0x00c3, 0x41, 1 }, + { 0x00c4, 0x00c4, 0x41, 1 }, + { 0x00c5, 0x00c5, 0x41, 1 }, + { 0x00c6, 0x00c6, 0x4145, 2 }, + { 0x00c7, 0x00c7, 0x43, 1 }, + { 0x00c8, 0x00c8, 0x45, 1 }, + { 0x00c9, 0x00c9, 0x45, 1 }, + { 0x00ca, 0x00ca, 0x45, 1 }, + { 0x00cb, 0x00cb, 0x45, 1 }, + { 0x00cc, 0x00cc, 0x49, 1 }, + { 0x00cd, 0x00cd, 0x49, 1 }, + { 0x00ce, 0x00ce, 0x49, 1 }, + { 0x00cf, 0x00cf, 0x49, 1 }, + { 0x00d1, 0x00d2, 0x4e, 1 }, + { 0x00d3, 0x00d3, 0x4f, 1 }, + { 0x00d4, 0x00d4, 0x4f, 1 }, + { 0x00d5, 0x00d5, 0x4f, 1 }, + { 0x00d6, 0x00d6, 0x4f, 1 }, + { 0x00d7, 0x00d7, 0x78, 1 }, + { 0x00d8, 0x00d8, 0x4f, 1 }, + { 0x00d9, 0x00d9, 0x55, 1 }, + { 0x00da, 0x00da, 0x55, 1 }, + { 0x00db, 0x00db, 0x55, 1 }, + { 0x00dc, 0x00dc, 0x55, 1 }, + { 0x00dd, 0x00dd, 0x59, 1 }, + { 0x00e0, 0x00e0, 0x61, 1 }, + { 0x00e1, 0x00e1, 0x61, 1 }, + { 0x00e2, 0x00e2, 0x61, 1 }, + { 0x00e3, 0x00e3, 0x61, 1 }, + { 0x00e4, 0x00e4, 0x61, 1 }, + { 0x00e5, 0x00e5, 0x61, 1 }, + { 0x00e6, 0x00e6, 0x6165, 2 }, + { 0x00e7, 0x00e7, 0x63, 1 }, + { 0x00e8, 0x00e8, 0x65, 1 }, + { 0x00e9, 0x00e9, 0x65, 1 }, + { 0x00ea, 0x00ea, 0x65, 1 }, + { 0x00eb, 0x00eb, 0x65, 1 }, + { 0x00ec, 0x00ec, 0x69, 1 }, + { 0x00ed, 0x00ed, 0x69, 1 }, + { 0x00ee, 0x00ee, 0x69, 1 }, + { 0x00ef, 0x00ef, 0x69, 1 }, + { 0x00f1, 0x00f2, 0x6e, 1 }, + { 0x00f3, 0x00f3, 0x6f, 1 }, + { 0x00f4, 0x00f4, 0x6f, 1 }, + { 0x00f5, 0x00f5, 0x6f, 1 }, + { 0x00f6, 0x00f6, 0x6f, 1 }, + { 0x00f7, 0x00f7, 0x2f, 1 }, + { 0x00f8, 0x00f8, 0x6f, 1 }, + { 0x00f9, 0x00f9, 0x75, 1 }, + { 0x00fa, 0x00fa, 0x75, 1 }, + { 0x00fb, 0x00fb, 0x75, 1 }, + { 0x00fc, 0x00fc, 0x75, 1 }, + { 0x00fd, 0x00fd, 0x79, 1 }, + { 0x00ff, 0x00ff, 0x79, 1 }, + { 0x0131, 0x0131, 0x69, 1 }, + { 0x0141, 0x0141, 0x4c, 1 }, + { 0x0152, 0x0152, 0x4f45, 2 }, + { 0x0153, 0x0153, 0x6f65, 2 }, + { 0x0160, 0x0160, 0x53, 1 }, + { 0x0178, 0x0178, 0x59, 1 }, + { 0x017d, 0x017d, 0x5a, 1 }, + { 0x2013, 0x2013, 0x2d, 1 }, + { 0x2014, 0x2014, 0x2d2d, 2 }, + { 0x2018, 0x2018, 0x60, 1 }, + { 0x2019, 0x2019, 0x27, 1 }, + { 0x201c, 0x201c, 0x22, 1 }, + { 0x201d, 0x201d, 0x22, 1 }, + { 0x2022, 0x2022, 0x2a, 1 }, + { 0x2026, 0x2026, 0x2e2e2e, 3 }, + { 0x2122, 0x2122, 0x544d, 2 }, + { 0x2212, 0x2212, 0x2d, 1 }, + { 0xf6f9, 0xf6f9, 0x4c, 1 }, + { 0xf6fa, 0xf6fa, 0x4f45, 2 }, + { 0xf6fd, 0xf6fd, 0x53, 1 }, + { 0xf6fe, 0xf6fe, 0x7e, 1 }, + { 0xf6ff, 0xf6ff, 0x5a, 1 }, + { 0xf721, 0xf721, 0x21, 1 }, + { 0xf724, 0xf724, 0x24, 1 }, + { 0xf726, 0xf726, 0x26, 1 }, + { 0xf730, 0xf739, 0x30, 1 }, + { 0xf73f, 0xf73f, 0x3f, 1 }, + { 0xf761, 0xf77a, 0x41, 1 }, + { 0xf7e0, 0xf7e0, 0x41, 1 }, + { 0xf7e1, 0xf7e1, 0x41, 1 }, + { 0xf7e2, 0xf7e2, 0x41, 1 }, + { 0xf7e3, 0xf7e3, 0x41, 1 }, + { 0xf7e4, 0xf7e4, 0x41, 1 }, + { 0xf7e5, 0xf7e5, 0x41, 1 }, + { 0xf7e6, 0xf7e6, 0x4145, 2 }, + { 0xf7e7, 0xf7e7, 0x43, 1 }, + { 0xf7e8, 0xf7e8, 0x45, 1 }, + { 0xf7e9, 0xf7e9, 0x45, 1 }, + { 0xf7ea, 0xf7ea, 0x45, 1 }, + { 0xf7eb, 0xf7eb, 0x45, 1 }, + { 0xf7ec, 0xf7ec, 0x49, 1 }, + { 0xf7ed, 0xf7ed, 0x49, 1 }, + { 0xf7ee, 0xf7ee, 0x49, 1 }, + { 0xf7ef, 0xf7ef, 0x49, 1 }, + { 0xf7f1, 0xf7f2, 0x4e, 1 }, + { 0xf7f3, 0xf7f3, 0x4f, 1 }, + { 0xf7f4, 0xf7f4, 0x4f, 1 }, + { 0xf7f5, 0xf7f5, 0x4f, 1 }, + { 0xf7f6, 0xf7f6, 0x4f, 1 }, + { 0xf7f8, 0xf7f8, 0x4f, 1 }, + { 0xf7f9, 0xf7f9, 0x55, 1 }, + { 0xf7fa, 0xf7fa, 0x55, 1 }, + { 0xf7fb, 0xf7fb, 0x55, 1 }, + { 0xf7fc, 0xf7fc, 0x55, 1 }, + { 0xf7fd, 0xf7fd, 0x59, 1 }, + { 0xf7ff, 0xf7ff, 0x59, 1 }, + { 0xfb00, 0xfb00, 0x6666, 2 }, + { 0xfb01, 0xfb01, 0x6669, 2 }, + { 0xfb02, 0xfb02, 0x666c, 2 }, + { 0xfb03, 0xfb03, 0x666669, 3 }, + { 0xfb04, 0xfb04, 0x66666c, 3 }, + { 0xfb05, 0xfb05, 0x7374, 2 }, + { 0xfb06, 0xfb06, 0x7374, 2 } +}; +#define ascii7UnicodeMapLen (sizeof(ascii7UnicodeMapRanges) / sizeof(UnicodeMapRange)) + +static UnicodeMapRange symbolUnicodeMapRanges[] = { + { 0x0020, 0x0021, 0x20, 1 }, + { 0x0023, 0x0023, 0x23, 1 }, + { 0x0025, 0x0026, 0x25, 1 }, + { 0x0028, 0x0029, 0x28, 1 }, + { 0x002b, 0x002c, 0x2b, 1 }, + { 0x002e, 0x003f, 0x2e, 1 }, + { 0x005b, 0x005b, 0x5b, 1 }, + { 0x005d, 0x005d, 0x5d, 1 }, + { 0x005f, 0x005f, 0x5f, 1 }, + { 0x007b, 0x007d, 0x7b, 1 }, + { 0x00ac, 0x00ac, 0xd8, 1 }, + { 0x00b0, 0x00b1, 0xb0, 1 }, + { 0x00b5, 0x00b5, 0x6d, 1 }, + { 0x00d7, 0x00d7, 0xb4, 1 }, + { 0x00f7, 0x00f7, 0xb8, 1 }, + { 0x0192, 0x0192, 0xa6, 1 }, + { 0x0391, 0x0392, 0x41, 1 }, + { 0x0393, 0x0393, 0x47, 1 }, + { 0x0395, 0x0395, 0x45, 1 }, + { 0x0396, 0x0396, 0x5a, 1 }, + { 0x0397, 0x0397, 0x48, 1 }, + { 0x0398, 0x0398, 0x51, 1 }, + { 0x0399, 0x0399, 0x49, 1 }, + { 0x039a, 0x039d, 0x4b, 1 }, + { 0x039e, 0x039e, 0x58, 1 }, + { 0x039f, 0x03a0, 0x4f, 1 }, + { 0x03a1, 0x03a1, 0x52, 1 }, + { 0x03a3, 0x03a5, 0x53, 1 }, + { 0x03a6, 0x03a6, 0x46, 1 }, + { 0x03a7, 0x03a7, 0x43, 1 }, + { 0x03a8, 0x03a8, 0x59, 1 }, + { 0x03b1, 0x03b2, 0x61, 1 }, + { 0x03b3, 0x03b3, 0x67, 1 }, + { 0x03b4, 0x03b5, 0x64, 1 }, + { 0x03b6, 0x03b6, 0x7a, 1 }, + { 0x03b7, 0x03b7, 0x68, 1 }, + { 0x03b8, 0x03b8, 0x71, 1 }, + { 0x03b9, 0x03b9, 0x69, 1 }, + { 0x03ba, 0x03bb, 0x6b, 1 }, + { 0x03bd, 0x03bd, 0x6e, 1 }, + { 0x03be, 0x03be, 0x78, 1 }, + { 0x03bf, 0x03c0, 0x6f, 1 }, + { 0x03c1, 0x03c1, 0x72, 1 }, + { 0x03c2, 0x03c2, 0x56, 1 }, + { 0x03c3, 0x03c5, 0x73, 1 }, + { 0x03c6, 0x03c6, 0x66, 1 }, + { 0x03c7, 0x03c7, 0x63, 1 }, + { 0x03c8, 0x03c8, 0x79, 1 }, + { 0x03c9, 0x03c9, 0x77, 1 }, + { 0x03d1, 0x03d1, 0x4a, 1 }, + { 0x03d2, 0x03d2, 0xa1, 1 }, + { 0x03d5, 0x03d5, 0x6a, 1 }, + { 0x03d6, 0x03d6, 0x76, 1 }, + { 0x2022, 0x2022, 0xb7, 1 }, + { 0x2026, 0x2026, 0xbc, 1 }, + { 0x2032, 0x2032, 0xa2, 1 }, + { 0x2033, 0x2033, 0xb2, 1 }, + { 0x2044, 0x2044, 0xa4, 1 }, + { 0x2111, 0x2111, 0xc1, 1 }, + { 0x2118, 0x2118, 0xc3, 1 }, + { 0x211c, 0x211c, 0xc2, 1 }, + { 0x2126, 0x2126, 0x57, 1 }, + { 0x2135, 0x2135, 0xc0, 1 }, + { 0x2190, 0x2193, 0xac, 1 }, + { 0x2194, 0x2194, 0xab, 1 }, + { 0x21b5, 0x21b5, 0xbf, 1 }, + { 0x21d0, 0x21d3, 0xdc, 1 }, + { 0x21d4, 0x21d4, 0xdb, 1 }, + { 0x2200, 0x2200, 0x22, 1 }, + { 0x2202, 0x2202, 0xb6, 1 }, + { 0x2203, 0x2203, 0x24, 1 }, + { 0x2205, 0x2205, 0xc6, 1 }, + { 0x2206, 0x2206, 0x44, 1 }, + { 0x2207, 0x2207, 0xd1, 1 }, + { 0x2208, 0x2209, 0xce, 1 }, + { 0x220b, 0x220b, 0x27, 1 }, + { 0x220f, 0x220f, 0xd5, 1 }, + { 0x2211, 0x2211, 0xe5, 1 }, + { 0x2212, 0x2212, 0x2d, 1 }, + { 0x2217, 0x2217, 0x2a, 1 }, + { 0x221a, 0x221a, 0xd6, 1 }, + { 0x221d, 0x221d, 0xb5, 1 }, + { 0x221e, 0x221e, 0xa5, 1 }, + { 0x2220, 0x2220, 0xd0, 1 }, + { 0x2227, 0x2228, 0xd9, 1 }, + { 0x2229, 0x222a, 0xc7, 1 }, + { 0x222b, 0x222b, 0xf2, 1 }, + { 0x2234, 0x2234, 0x5c, 1 }, + { 0x223c, 0x223c, 0x7e, 1 }, + { 0x2245, 0x2245, 0x40, 1 }, + { 0x2248, 0x2248, 0xbb, 1 }, + { 0x2260, 0x2261, 0xb9, 1 }, + { 0x2264, 0x2264, 0xa3, 1 }, + { 0x2265, 0x2265, 0xb3, 1 }, + { 0x2282, 0x2282, 0xcc, 1 }, + { 0x2283, 0x2283, 0xc9, 1 }, + { 0x2284, 0x2284, 0xcb, 1 }, + { 0x2286, 0x2286, 0xcd, 1 }, + { 0x2287, 0x2287, 0xca, 1 }, + { 0x2295, 0x2295, 0xc5, 1 }, + { 0x2297, 0x2297, 0xc4, 1 }, + { 0x22a5, 0x22a5, 0x5e, 1 }, + { 0x22c5, 0x22c5, 0xd7, 1 }, + { 0x2320, 0x2320, 0xf3, 1 }, + { 0x2321, 0x2321, 0xf5, 1 }, + { 0x2329, 0x2329, 0xe1, 1 }, + { 0x232a, 0x232a, 0xf1, 1 }, + { 0x25ca, 0x25ca, 0xe0, 1 }, + { 0x2660, 0x2660, 0xaa, 1 }, + { 0x2663, 0x2663, 0xa7, 1 }, + { 0x2665, 0x2665, 0xa9, 1 }, + { 0x2666, 0x2666, 0xa8, 1 }, + { 0xf6d9, 0xf6d9, 0xd3, 1 }, + { 0xf6da, 0xf6da, 0xd2, 1 }, + { 0xf6db, 0xf6db, 0xd4, 1 }, + { 0xf8e5, 0xf8e5, 0x60, 1 }, + { 0xf8e6, 0xf8e7, 0xbd, 1 }, + { 0xf8e8, 0xf8ea, 0xe2, 1 }, + { 0xf8eb, 0xf8f4, 0xe6, 1 }, + { 0xf8f5, 0xf8f5, 0xf4, 1 }, + { 0xf8f6, 0xf8fe, 0xf6, 1 } +}; +#define symbolUnicodeMapLen (sizeof(symbolUnicodeMapRanges) / sizeof(UnicodeMapRange)) + +static UnicodeMapRange zapfDingbatsUnicodeMapRanges[] = { + { 0x0020, 0x0020, 0x20, 1 }, + { 0x2192, 0x2192, 0xd5, 1 }, + { 0x2194, 0x2195, 0xd6, 1 }, + { 0x2460, 0x2469, 0xac, 1 }, + { 0x25a0, 0x25a0, 0x6e, 1 }, + { 0x25b2, 0x25b2, 0x73, 1 }, + { 0x25bc, 0x25bc, 0x74, 1 }, + { 0x25c6, 0x25c6, 0x75, 1 }, + { 0x25cf, 0x25cf, 0x6c, 1 }, + { 0x25d7, 0x25d7, 0x77, 1 }, + { 0x2605, 0x2605, 0x48, 1 }, + { 0x260e, 0x260e, 0x25, 1 }, + { 0x261b, 0x261b, 0x2a, 1 }, + { 0x261e, 0x261e, 0x2b, 1 }, + { 0x2660, 0x2660, 0xab, 1 }, + { 0x2663, 0x2663, 0xa8, 1 }, + { 0x2665, 0x2665, 0xaa, 1 }, + { 0x2666, 0x2666, 0xa9, 1 }, + { 0x2701, 0x2704, 0x21, 1 }, + { 0x2706, 0x2709, 0x26, 1 }, + { 0x270c, 0x2727, 0x2c, 1 }, + { 0x2729, 0x274b, 0x49, 1 }, + { 0x274d, 0x274d, 0x6d, 1 }, + { 0x274f, 0x2752, 0x6f, 1 }, + { 0x2756, 0x2756, 0x76, 1 }, + { 0x2758, 0x275e, 0x78, 1 }, + { 0x2761, 0x2767, 0xa1, 1 }, + { 0x2776, 0x2794, 0xb6, 1 }, + { 0x2798, 0x27af, 0xd8, 1 }, + { 0x27b1, 0x27be, 0xf1, 1 } +}; +#define zapfDingbatsUnicodeMapLen (sizeof(zapfDingbatsUnicodeMapRanges) / sizeof(UnicodeMapRange)) diff --git a/xpdf/UnicodeRemapping.cc b/xpdf/UnicodeRemapping.cc new file mode 100644 index 0000000..72dbc0e --- /dev/null +++ b/xpdf/UnicodeRemapping.cc @@ -0,0 +1,201 @@ +//======================================================================== +// +// UnicodeRemapping.cc +// +// Copyright 2018 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include +#include "gmem.h" +#include "gmempp.h" +#include "gfile.h" +#include "GString.h" +#include "Error.h" +#include "UnicodeRemapping.h" + +//------------------------------------------------------------------------ + +#define maxUnicodeString 8 + +struct UnicodeRemappingString { + Unicode in; + Unicode out[maxUnicodeString]; + int len; +}; + +//------------------------------------------------------------------------ + +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 -byte hex string into *. 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; +} + +//------------------------------------------------------------------------ + +UnicodeRemapping::UnicodeRemapping() { + for (int i = 0; i < 256; ++i) { + page0[i] = (Unicode)i; + } + sMap = NULL; + sMapLen = sMapSize = 0; +} + +UnicodeRemapping::~UnicodeRemapping() { + gfree(sMap); +} + +void UnicodeRemapping::addRemapping(Unicode in, Unicode *out, int len) { + int i, j; + + if (in < 256 && len == 1) { + page0[in] = out[0]; + } else { + if (in < 256) { + page0[in] = 0xffffffff; + } + if (sMapLen == sMapSize) { + sMapSize += 16; + sMap = (UnicodeRemappingString *) + greallocn(sMap, sMapSize, sizeof(UnicodeRemappingString)); + } + i = findSMap(in); + if (i < sMapLen) { + memmove(sMap + i + 1, sMap + i, + (sMapLen - i) * sizeof(UnicodeRemappingString)); + } + sMap[i].in = in; + for (j = 0; j < len && j < maxUnicodeString; ++j) { + sMap[i].out[j] = out[j]; + } + sMap[i].len = j; + ++sMapLen; + } +} + +void UnicodeRemapping::parseFile(GString *fileName) { + FILE *f; + char buf[256]; + Unicode in; + Unicode out[maxUnicodeString]; + char *tok; + int line, n; + + if (!(f = openFile(fileName->getCString(), "r"))) { + error(errSyntaxError, -1, "Couldn't open unicodeRemapping file '{0:t}'", + fileName); + return; + } + + line = 0; + while (getLine(buf, sizeof(buf), f)) { + ++line; + if (!(tok = strtok(buf, " \t\r\n")) || + !parseHex(tok, (int)strlen(tok), &in)) { + error(errSyntaxWarning, -1, + "Bad line ({0:d}) in unicodeRemapping file '{1:t}'", + line, fileName); + continue; + } + n = 0; + while (n < maxUnicodeString) { + if (!(tok = strtok(NULL, " \t\r\n"))) { + break; + } + if (!parseHex(tok, (int)strlen(tok), &out[n])) { + error(errSyntaxWarning, -1, + "Bad line ({0:d}) in unicodeRemapping file '{1:t}'", + line, fileName); + break; + } + ++n; + } + addRemapping(in, out, n); + } + + fclose(f); +} + +// Determine the location in sMap to insert/replace the entry for [u]. +int UnicodeRemapping::findSMap(Unicode u) { + int a, b, m; + + a = -1; + b = sMapLen; + // invariant: sMap[a].in < u <= sMap[b].in + while (b - a > 1) { + m = (a + b) / 2; + if (sMap[m].in < u) { + a = m; + } else { + b = m; + } + } + return b; +} + +int UnicodeRemapping::map(Unicode in, Unicode *out, int size) { + int a, b, m, i; + + if (in < 256 && page0[in] != 0xffffffff) { + out[0] = page0[in]; + return 1; + } + + a = -1; + b = sMapLen; + // invariant: sMap[a].in < in < sMap[b].in + while (b - a > 1) { + m = (a + b) / 2; + if (sMap[m].in < in) { + a = m; + } else if (in < sMap[m].in) { + b = m; + } else { + for (i = 0; i < sMap[m].len && i < size; ++i) { + out[i] = sMap[m].out[i]; + } + return i; + } + } + + out[0] = in; + return 1; +} diff --git a/xpdf/UnicodeRemapping.h b/xpdf/UnicodeRemapping.h new file mode 100644 index 0000000..dbf435e --- /dev/null +++ b/xpdf/UnicodeRemapping.h @@ -0,0 +1,53 @@ +//======================================================================== +// +// UnicodeRemapping.h +// +// Sparse remapping of Unicode characters. +// +// Copyright 2018 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef UNICODEREMAPPING_H +#define UNICODEREMAPPING_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "CharTypes.h" + +struct UnicodeRemappingString; + +//------------------------------------------------------------------------ + +class UnicodeRemapping { +public: + + // Create an empty (i.e., identity) remapping. + UnicodeRemapping(); + + ~UnicodeRemapping(); + + // Add a remapping for . + void addRemapping(Unicode in, Unicode *out, int len); + + // Add entries from the specified file to this UnicodeRemapping. + void parseFile(GString *fileName); + + // Map to zero or more (up to ) output characters in + // . Returns the number of output characters. + int map(Unicode in, Unicode *out, int size); + +private: + + int findSMap(Unicode u); + + Unicode page0[256]; + UnicodeRemappingString *sMap; + int sMapLen, sMapSize; +}; + +#endif diff --git a/xpdf/UnicodeTypeTable.cc b/xpdf/UnicodeTypeTable.cc new file mode 100644 index 0000000..e6a91af --- /dev/null +++ b/xpdf/UnicodeTypeTable.cc @@ -0,0 +1,1876 @@ +//======================================================================== +// +// UnicodeTypeTable.cc +// +// Copyright 2004-2021 Glyph & Cog, LLC +// +//======================================================================== + +#include +#include +#include "gmempp.h" +#include "CharTypes.h" +#include "UnicodeTypeTable.h" + +struct UnicodeMapTableEntry { + const char *vector; + char type; +}; + +struct UnicodeCaseTableVector { + Unicode codes[256]; +}; + +static UnicodeMapTableEntry typeTable[256] = { + { "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN...NNNNN.....##########.NNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN.N....NNNNLNNNNN..##NLNNN#LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLL", 'X' }, + { NULL, 'L' }, + { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLLNNNNNNNNNNNNNNLLNNNNNNNNNNNNNNLLLLLNNNNNNNNNLNNNNNNNNNNNNNNNNN", 'X' }, + { "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNLLLLNNLLLLLLLLNLNNNNNNLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLL", 'X' }, + { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, + { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNN.NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNRNRNNRNNRNRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR###########", 'X' }, + { "######NNR..R.RNNNNNNNNNNNNNRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRNNNNNNNNNNNNNNNNNNNNN##########.##RRRNRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRNNNNNNN#NNNNNNNRRNNNNNNNRR##########RRRRRR", 'X' }, + { "RRRRRRRRRRRRRRRRRNRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRNNNNNNNNNNNNNNNNNNNNNNNNNNNRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRNNNNNNNNNNNRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRNNNNNNNNNRRNNNNRNNNRR", 'X' }, + { "RRRRRRRRRRRRRRRRRRRRRRNNNNRNNNNNNNNNRNNNRNNNNNRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRNNNRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRNNNNNNNNNNNNNNNNNNNNNNNNNN#NNNNNNNNNNNNNNNNNNNNNNNNNNNNN", 'X' }, + { "NNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLNLLLLNNNNNNNNLLLLNLLLNNNNNNNLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLLLNNNNLLLLLLLLNLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLL..LLLLLLL.LLNN", 'X' }, + { "NNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLLLNNNNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLNLNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLLLNNNNNNNNLLLLNLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLL.LLLLLLLLNNNNNN", 'X' }, + { "NNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLNLNNNNLLLLLLLLNNNNNNNNNNLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNN.NNNNNN", 'X' }, + { "NLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLLLNNNNNNNNNNNNNNNNNNLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLNNNNNNNLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLNNNNNNNNNNNNN", 'X' }, + { "NNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLNNNNLLLLLLLLNLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNLLLLLLLNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, + { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLNNNNNNN.....LLLLLLLNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLNNNNNNNNNLLLLLLLLLLNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, + { "LLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLNLNLNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNLNNNNNLNNLLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, + { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNLNNNNNNLNNLLNNLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLNNNLLLLLLLLLLLLLLLLNNNNLLLLLLLLLLLLLNLLNNLLLLLLNLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, + { NULL, 'L' }, + { NULL, 'L' }, + { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNN", 'X' }, + { "NLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, + { NULL, 'L' }, + { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, + { "LLLLLLLLLLLLLLLLLLNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLNNNNNNNLLLLLLLLNLLNNNNNNNNNNNLLLLLLL.LNLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNN", 'X' }, + { "NNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, + { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNLLLLNNLLLLLLLLLNLLLLLLNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN", 'X' }, + { "LLLLLLLLLLLLLLLLLLLLLLLNNLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLNNNNNNNNNLNLLNNNNNNNNLLLLLLNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN", 'X' }, + { "NNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLNNNNNLNLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNLLLLLLLLLNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNLLNNLNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLNNLLLNLNNNLLLLLLLLLLLLLL", 'X' }, + { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNLNNNNNNNNNNNNNLNNNNNNNLLLLNLLLLLLNLLLNNLLLLLL", 'X' }, + { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN", 'X' }, + { NULL, 'L' }, + { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLNNNLLLLLLLLLLLNNNLLLLLLLLLLLLNNNNLLLLLLLLLLLLLNNNLLLLLLLLLLLLLNNN", 'X' }, + { "NNNNNNNNNNNNNNLRNNNNNNNNNNNNNNNNNNNNNNNNNNLRNLR......NNNNNNNNNNNNNNN.NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNLLRNNNNNNNN#L########..NNNL##########..NNNLLLLLLLLLLLLLL...................................NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN", 'X' }, + { "NNLNNNNLNNLLLLLLLLLLNLNNNLLLLLNNNNNNLNLNLNLLLL.LLLLLLLLLLLNNLLLLNNNNNLLLLLNNNNLLNNNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN", 'X' }, + { "NNNNNNNNNNNNNNNNNN..NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN", 'X' }, + { "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN", 'X' }, + { "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN####################LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNN", 'X' }, + { NULL, 'N' }, + { "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN", 'X' }, + { NULL, 'N' }, + { NULL, 'L' }, + { NULL, 'N' }, + { NULL, 'N' }, + { NULL, 'N' }, + { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLNNNLLNNNNNNNNNNNN", 'X' }, + { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN", 'X' }, + { NULL, 'N' }, + { NULL, 'N' }, + { "NNNNNLLLNNNNNNNNNNNNNNNNNNNNNNNNNLLLLLLLLLNNNNLLNLLLLLNNLLLLLNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLL", 'X' }, + { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, + { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNLLLLLLLLLLLLNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, + { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLN", 'X' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN", 'X' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, + { NULL, 'L' }, + { "LLLLLLLLLLLLLNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLNNNNNNNN", 'X' }, + { "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, + { "LLNLLLNLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLNNLNNNNNLLLLLLLLLLL..LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNNNNLLLLLLLLLLLLLN", 'X' }, + { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLNNNNLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, + { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLNNLLNNLLLLLLLLLLLLNLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLNNNLLNNLLLLLNNLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLNLLLLLLLLL", 'X' }, + { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLNLLLLNLLLLLLLLLLLLLLLLLL", 'X' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { "LLLLLLLLLLLLLLLLLLLLLLLLRRRRRRNRRRRRRRRRR.RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR", 'X' }, + { NULL, 'R' }, + { "RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRNNRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRNNN", 'X' }, + { "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN.N.NN.NNNNNNNNN.NN..NNNNN..NRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRNNN", 'X' }, + { "NNN...NNNNN.....##########.NNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL.....NNN..NNNNNNNNNNNNNNNNNNNNNNNLL", 'X' } +}; + +static UnicodeCaseTableVector caseTable00 = {{ + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, + 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, + 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, + 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, + 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, + 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, + 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, + 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, + 0x0040, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, + 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f, + 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, + 0x0078, 0x0079, 0x007a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, + 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, + 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f, + 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, + 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f, + 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, + 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f, + 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, + 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f, + 0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7, + 0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af, + 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x03bc, 0x00b6, 0x00b7, + 0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf, + 0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7, + 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef, + 0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00d7, + 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00df, + 0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7, + 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef, + 0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7, + 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff +}}; +static UnicodeCaseTableVector caseTable01 = {{ + 0x0101, 0x0101, 0x0103, 0x0103, 0x0105, 0x0105, 0x0107, 0x0107, + 0x0109, 0x0109, 0x010b, 0x010b, 0x010d, 0x010d, 0x010f, 0x010f, + 0x0111, 0x0111, 0x0113, 0x0113, 0x0115, 0x0115, 0x0117, 0x0117, + 0x0119, 0x0119, 0x011b, 0x011b, 0x011d, 0x011d, 0x011f, 0x011f, + 0x0121, 0x0121, 0x0123, 0x0123, 0x0125, 0x0125, 0x0127, 0x0127, + 0x0129, 0x0129, 0x012b, 0x012b, 0x012d, 0x012d, 0x012f, 0x012f, + 0x0130, 0x0131, 0x0133, 0x0133, 0x0135, 0x0135, 0x0137, 0x0137, + 0x0138, 0x013a, 0x013a, 0x013c, 0x013c, 0x013e, 0x013e, 0x0140, + 0x0140, 0x0142, 0x0142, 0x0144, 0x0144, 0x0146, 0x0146, 0x0148, + 0x0148, 0x0149, 0x014b, 0x014b, 0x014d, 0x014d, 0x014f, 0x014f, + 0x0151, 0x0151, 0x0153, 0x0153, 0x0155, 0x0155, 0x0157, 0x0157, + 0x0159, 0x0159, 0x015b, 0x015b, 0x015d, 0x015d, 0x015f, 0x015f, + 0x0161, 0x0161, 0x0163, 0x0163, 0x0165, 0x0165, 0x0167, 0x0167, + 0x0169, 0x0169, 0x016b, 0x016b, 0x016d, 0x016d, 0x016f, 0x016f, + 0x0171, 0x0171, 0x0173, 0x0173, 0x0175, 0x0175, 0x0177, 0x0177, + 0x00ff, 0x017a, 0x017a, 0x017c, 0x017c, 0x017e, 0x017e, 0x0073, + 0x0180, 0x0253, 0x0183, 0x0183, 0x0185, 0x0185, 0x0254, 0x0188, + 0x0188, 0x0256, 0x0257, 0x018c, 0x018c, 0x018d, 0x01dd, 0x0259, + 0x025b, 0x0192, 0x0192, 0x0260, 0x0263, 0x0195, 0x0269, 0x0268, + 0x0199, 0x0199, 0x019a, 0x019b, 0x026f, 0x0272, 0x019e, 0x0275, + 0x01a1, 0x01a1, 0x01a3, 0x01a3, 0x01a5, 0x01a5, 0x0280, 0x01a8, + 0x01a8, 0x0283, 0x01aa, 0x01ab, 0x01ad, 0x01ad, 0x0288, 0x01b0, + 0x01b0, 0x028a, 0x028b, 0x01b4, 0x01b4, 0x01b6, 0x01b6, 0x0292, + 0x01b9, 0x01b9, 0x01ba, 0x01bb, 0x01bd, 0x01bd, 0x01be, 0x01bf, + 0x01c0, 0x01c1, 0x01c2, 0x01c3, 0x01c6, 0x01c6, 0x01c6, 0x01c9, + 0x01c9, 0x01c9, 0x01cc, 0x01cc, 0x01cc, 0x01ce, 0x01ce, 0x01d0, + 0x01d0, 0x01d2, 0x01d2, 0x01d4, 0x01d4, 0x01d6, 0x01d6, 0x01d8, + 0x01d8, 0x01da, 0x01da, 0x01dc, 0x01dc, 0x01dd, 0x01df, 0x01df, + 0x01e1, 0x01e1, 0x01e3, 0x01e3, 0x01e5, 0x01e5, 0x01e7, 0x01e7, + 0x01e9, 0x01e9, 0x01eb, 0x01eb, 0x01ed, 0x01ed, 0x01ef, 0x01ef, + 0x01f0, 0x01f3, 0x01f3, 0x01f3, 0x01f5, 0x01f5, 0x0195, 0x01bf, + 0x01f9, 0x01f9, 0x01fb, 0x01fb, 0x01fd, 0x01fd, 0x01ff, 0x01ff +}}; +static UnicodeCaseTableVector caseTable02 = {{ + 0x0201, 0x0201, 0x0203, 0x0203, 0x0205, 0x0205, 0x0207, 0x0207, + 0x0209, 0x0209, 0x020b, 0x020b, 0x020d, 0x020d, 0x020f, 0x020f, + 0x0211, 0x0211, 0x0213, 0x0213, 0x0215, 0x0215, 0x0217, 0x0217, + 0x0219, 0x0219, 0x021b, 0x021b, 0x021d, 0x021d, 0x021f, 0x021f, + 0x019e, 0x0221, 0x0223, 0x0223, 0x0225, 0x0225, 0x0227, 0x0227, + 0x0229, 0x0229, 0x022b, 0x022b, 0x022d, 0x022d, 0x022f, 0x022f, + 0x0231, 0x0231, 0x0233, 0x0233, 0x0234, 0x0235, 0x0236, 0x0237, + 0x0238, 0x0239, 0x2c65, 0x023c, 0x023c, 0x019a, 0x2c66, 0x023f, + 0x0240, 0x0242, 0x0242, 0x0180, 0x0289, 0x028c, 0x0247, 0x0247, + 0x0249, 0x0249, 0x024b, 0x024b, 0x024d, 0x024d, 0x024f, 0x024f, + 0x0250, 0x0251, 0x0252, 0x0253, 0x0254, 0x0255, 0x0256, 0x0257, + 0x0258, 0x0259, 0x025a, 0x025b, 0x025c, 0x025d, 0x025e, 0x025f, + 0x0260, 0x0261, 0x0262, 0x0263, 0x0264, 0x0265, 0x0266, 0x0267, + 0x0268, 0x0269, 0x026a, 0x026b, 0x026c, 0x026d, 0x026e, 0x026f, + 0x0270, 0x0271, 0x0272, 0x0273, 0x0274, 0x0275, 0x0276, 0x0277, + 0x0278, 0x0279, 0x027a, 0x027b, 0x027c, 0x027d, 0x027e, 0x027f, + 0x0280, 0x0281, 0x0282, 0x0283, 0x0284, 0x0285, 0x0286, 0x0287, + 0x0288, 0x0289, 0x028a, 0x028b, 0x028c, 0x028d, 0x028e, 0x028f, + 0x0290, 0x0291, 0x0292, 0x0293, 0x0294, 0x0295, 0x0296, 0x0297, + 0x0298, 0x0299, 0x029a, 0x029b, 0x029c, 0x029d, 0x029e, 0x029f, + 0x02a0, 0x02a1, 0x02a2, 0x02a3, 0x02a4, 0x02a5, 0x02a6, 0x02a7, + 0x02a8, 0x02a9, 0x02aa, 0x02ab, 0x02ac, 0x02ad, 0x02ae, 0x02af, + 0x02b0, 0x02b1, 0x02b2, 0x02b3, 0x02b4, 0x02b5, 0x02b6, 0x02b7, + 0x02b8, 0x02b9, 0x02ba, 0x02bb, 0x02bc, 0x02bd, 0x02be, 0x02bf, + 0x02c0, 0x02c1, 0x02c2, 0x02c3, 0x02c4, 0x02c5, 0x02c6, 0x02c7, + 0x02c8, 0x02c9, 0x02ca, 0x02cb, 0x02cc, 0x02cd, 0x02ce, 0x02cf, + 0x02d0, 0x02d1, 0x02d2, 0x02d3, 0x02d4, 0x02d5, 0x02d6, 0x02d7, + 0x02d8, 0x02d9, 0x02da, 0x02db, 0x02dc, 0x02dd, 0x02de, 0x02df, + 0x02e0, 0x02e1, 0x02e2, 0x02e3, 0x02e4, 0x02e5, 0x02e6, 0x02e7, + 0x02e8, 0x02e9, 0x02ea, 0x02eb, 0x02ec, 0x02ed, 0x02ee, 0x02ef, + 0x02f0, 0x02f1, 0x02f2, 0x02f3, 0x02f4, 0x02f5, 0x02f6, 0x02f7, + 0x02f8, 0x02f9, 0x02fa, 0x02fb, 0x02fc, 0x02fd, 0x02fe, 0x02ff +}}; +static UnicodeCaseTableVector caseTable03 = {{ + 0x0300, 0x0301, 0x0302, 0x0303, 0x0304, 0x0305, 0x0306, 0x0307, + 0x0308, 0x0309, 0x030a, 0x030b, 0x030c, 0x030d, 0x030e, 0x030f, + 0x0310, 0x0311, 0x0312, 0x0313, 0x0314, 0x0315, 0x0316, 0x0317, + 0x0318, 0x0319, 0x031a, 0x031b, 0x031c, 0x031d, 0x031e, 0x031f, + 0x0320, 0x0321, 0x0322, 0x0323, 0x0324, 0x0325, 0x0326, 0x0327, + 0x0328, 0x0329, 0x032a, 0x032b, 0x032c, 0x032d, 0x032e, 0x032f, + 0x0330, 0x0331, 0x0332, 0x0333, 0x0334, 0x0335, 0x0336, 0x0337, + 0x0338, 0x0339, 0x033a, 0x033b, 0x033c, 0x033d, 0x033e, 0x033f, + 0x0340, 0x0341, 0x0342, 0x0343, 0x0344, 0x03b9, 0x0346, 0x0347, + 0x0348, 0x0349, 0x034a, 0x034b, 0x034c, 0x034d, 0x034e, 0x034f, + 0x0350, 0x0351, 0x0352, 0x0353, 0x0354, 0x0355, 0x0356, 0x0357, + 0x0358, 0x0359, 0x035a, 0x035b, 0x035c, 0x035d, 0x035e, 0x035f, + 0x0360, 0x0361, 0x0362, 0x0363, 0x0364, 0x0365, 0x0366, 0x0367, + 0x0368, 0x0369, 0x036a, 0x036b, 0x036c, 0x036d, 0x036e, 0x036f, + 0x0371, 0x0371, 0x0373, 0x0373, 0x0374, 0x0375, 0x0377, 0x0377, + 0x0378, 0x0379, 0x037a, 0x037b, 0x037c, 0x037d, 0x037e, 0x03f3, + 0x0380, 0x0381, 0x0382, 0x0383, 0x0384, 0x0385, 0x03ac, 0x0387, + 0x03ad, 0x03ae, 0x03af, 0x038b, 0x03cc, 0x038d, 0x03cd, 0x03ce, + 0x0390, 0x03b1, 0x03b2, 0x03b3, 0x03b4, 0x03b5, 0x03b6, 0x03b7, + 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf, + 0x03c0, 0x03c1, 0x03a2, 0x03c3, 0x03c4, 0x03c5, 0x03c6, 0x03c7, + 0x03c8, 0x03c9, 0x03ca, 0x03cb, 0x03ac, 0x03ad, 0x03ae, 0x03af, + 0x03b0, 0x03b1, 0x03b2, 0x03b3, 0x03b4, 0x03b5, 0x03b6, 0x03b7, + 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf, + 0x03c0, 0x03c1, 0x03c3, 0x03c3, 0x03c4, 0x03c5, 0x03c6, 0x03c7, + 0x03c8, 0x03c9, 0x03ca, 0x03cb, 0x03cc, 0x03cd, 0x03ce, 0x03d7, + 0x03b2, 0x03b8, 0x03d2, 0x03d3, 0x03d4, 0x03c6, 0x03c0, 0x03d7, + 0x03d9, 0x03d9, 0x03db, 0x03db, 0x03dd, 0x03dd, 0x03df, 0x03df, + 0x03e1, 0x03e1, 0x03e3, 0x03e3, 0x03e5, 0x03e5, 0x03e7, 0x03e7, + 0x03e9, 0x03e9, 0x03eb, 0x03eb, 0x03ed, 0x03ed, 0x03ef, 0x03ef, + 0x03ba, 0x03c1, 0x03f2, 0x03f3, 0x03b8, 0x03b5, 0x03f6, 0x03f8, + 0x03f8, 0x03f2, 0x03fb, 0x03fb, 0x03fc, 0x037b, 0x037c, 0x037d +}}; +static UnicodeCaseTableVector caseTable04 = {{ + 0x0450, 0x0451, 0x0452, 0x0453, 0x0454, 0x0455, 0x0456, 0x0457, + 0x0458, 0x0459, 0x045a, 0x045b, 0x045c, 0x045d, 0x045e, 0x045f, + 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, + 0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d, 0x043e, 0x043f, + 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, + 0x0448, 0x0449, 0x044a, 0x044b, 0x044c, 0x044d, 0x044e, 0x044f, + 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, + 0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d, 0x043e, 0x043f, + 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, + 0x0448, 0x0449, 0x044a, 0x044b, 0x044c, 0x044d, 0x044e, 0x044f, + 0x0450, 0x0451, 0x0452, 0x0453, 0x0454, 0x0455, 0x0456, 0x0457, + 0x0458, 0x0459, 0x045a, 0x045b, 0x045c, 0x045d, 0x045e, 0x045f, + 0x0461, 0x0461, 0x0463, 0x0463, 0x0465, 0x0465, 0x0467, 0x0467, + 0x0469, 0x0469, 0x046b, 0x046b, 0x046d, 0x046d, 0x046f, 0x046f, + 0x0471, 0x0471, 0x0473, 0x0473, 0x0475, 0x0475, 0x0477, 0x0477, + 0x0479, 0x0479, 0x047b, 0x047b, 0x047d, 0x047d, 0x047f, 0x047f, + 0x0481, 0x0481, 0x0482, 0x0483, 0x0484, 0x0485, 0x0486, 0x0487, + 0x0488, 0x0489, 0x048b, 0x048b, 0x048d, 0x048d, 0x048f, 0x048f, + 0x0491, 0x0491, 0x0493, 0x0493, 0x0495, 0x0495, 0x0497, 0x0497, + 0x0499, 0x0499, 0x049b, 0x049b, 0x049d, 0x049d, 0x049f, 0x049f, + 0x04a1, 0x04a1, 0x04a3, 0x04a3, 0x04a5, 0x04a5, 0x04a7, 0x04a7, + 0x04a9, 0x04a9, 0x04ab, 0x04ab, 0x04ad, 0x04ad, 0x04af, 0x04af, + 0x04b1, 0x04b1, 0x04b3, 0x04b3, 0x04b5, 0x04b5, 0x04b7, 0x04b7, + 0x04b9, 0x04b9, 0x04bb, 0x04bb, 0x04bd, 0x04bd, 0x04bf, 0x04bf, + 0x04cf, 0x04c2, 0x04c2, 0x04c4, 0x04c4, 0x04c6, 0x04c6, 0x04c8, + 0x04c8, 0x04ca, 0x04ca, 0x04cc, 0x04cc, 0x04ce, 0x04ce, 0x04cf, + 0x04d1, 0x04d1, 0x04d3, 0x04d3, 0x04d5, 0x04d5, 0x04d7, 0x04d7, + 0x04d9, 0x04d9, 0x04db, 0x04db, 0x04dd, 0x04dd, 0x04df, 0x04df, + 0x04e1, 0x04e1, 0x04e3, 0x04e3, 0x04e5, 0x04e5, 0x04e7, 0x04e7, + 0x04e9, 0x04e9, 0x04eb, 0x04eb, 0x04ed, 0x04ed, 0x04ef, 0x04ef, + 0x04f1, 0x04f1, 0x04f3, 0x04f3, 0x04f5, 0x04f5, 0x04f7, 0x04f7, + 0x04f9, 0x04f9, 0x04fb, 0x04fb, 0x04fd, 0x04fd, 0x04ff, 0x04ff +}}; +static UnicodeCaseTableVector caseTable05 = {{ + 0x0501, 0x0501, 0x0503, 0x0503, 0x0505, 0x0505, 0x0507, 0x0507, + 0x0509, 0x0509, 0x050b, 0x050b, 0x050d, 0x050d, 0x050f, 0x050f, + 0x0511, 0x0511, 0x0513, 0x0513, 0x0515, 0x0515, 0x0517, 0x0517, + 0x0519, 0x0519, 0x051b, 0x051b, 0x051d, 0x051d, 0x051f, 0x051f, + 0x0521, 0x0521, 0x0523, 0x0523, 0x0525, 0x0525, 0x0527, 0x0527, + 0x0529, 0x0529, 0x052b, 0x052b, 0x052d, 0x052d, 0x052f, 0x052f, + 0x0530, 0x0561, 0x0562, 0x0563, 0x0564, 0x0565, 0x0566, 0x0567, + 0x0568, 0x0569, 0x056a, 0x056b, 0x056c, 0x056d, 0x056e, 0x056f, + 0x0570, 0x0571, 0x0572, 0x0573, 0x0574, 0x0575, 0x0576, 0x0577, + 0x0578, 0x0579, 0x057a, 0x057b, 0x057c, 0x057d, 0x057e, 0x057f, + 0x0580, 0x0581, 0x0582, 0x0583, 0x0584, 0x0585, 0x0586, 0x0557, + 0x0558, 0x0559, 0x055a, 0x055b, 0x055c, 0x055d, 0x055e, 0x055f, + 0x0560, 0x0561, 0x0562, 0x0563, 0x0564, 0x0565, 0x0566, 0x0567, + 0x0568, 0x0569, 0x056a, 0x056b, 0x056c, 0x056d, 0x056e, 0x056f, + 0x0570, 0x0571, 0x0572, 0x0573, 0x0574, 0x0575, 0x0576, 0x0577, + 0x0578, 0x0579, 0x057a, 0x057b, 0x057c, 0x057d, 0x057e, 0x057f, + 0x0580, 0x0581, 0x0582, 0x0583, 0x0584, 0x0585, 0x0586, 0x0587, + 0x0588, 0x0589, 0x058a, 0x058b, 0x058c, 0x058d, 0x058e, 0x058f, + 0x0590, 0x0591, 0x0592, 0x0593, 0x0594, 0x0595, 0x0596, 0x0597, + 0x0598, 0x0599, 0x059a, 0x059b, 0x059c, 0x059d, 0x059e, 0x059f, + 0x05a0, 0x05a1, 0x05a2, 0x05a3, 0x05a4, 0x05a5, 0x05a6, 0x05a7, + 0x05a8, 0x05a9, 0x05aa, 0x05ab, 0x05ac, 0x05ad, 0x05ae, 0x05af, + 0x05b0, 0x05b1, 0x05b2, 0x05b3, 0x05b4, 0x05b5, 0x05b6, 0x05b7, + 0x05b8, 0x05b9, 0x05ba, 0x05bb, 0x05bc, 0x05bd, 0x05be, 0x05bf, + 0x05c0, 0x05c1, 0x05c2, 0x05c3, 0x05c4, 0x05c5, 0x05c6, 0x05c7, + 0x05c8, 0x05c9, 0x05ca, 0x05cb, 0x05cc, 0x05cd, 0x05ce, 0x05cf, + 0x05d0, 0x05d1, 0x05d2, 0x05d3, 0x05d4, 0x05d5, 0x05d6, 0x05d7, + 0x05d8, 0x05d9, 0x05da, 0x05db, 0x05dc, 0x05dd, 0x05de, 0x05df, + 0x05e0, 0x05e1, 0x05e2, 0x05e3, 0x05e4, 0x05e5, 0x05e6, 0x05e7, + 0x05e8, 0x05e9, 0x05ea, 0x05eb, 0x05ec, 0x05ed, 0x05ee, 0x05ef, + 0x05f0, 0x05f1, 0x05f2, 0x05f3, 0x05f4, 0x05f5, 0x05f6, 0x05f7, + 0x05f8, 0x05f9, 0x05fa, 0x05fb, 0x05fc, 0x05fd, 0x05fe, 0x05ff +}}; +static UnicodeCaseTableVector caseTable10 = {{ + 0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005, 0x1006, 0x1007, + 0x1008, 0x1009, 0x100a, 0x100b, 0x100c, 0x100d, 0x100e, 0x100f, + 0x1010, 0x1011, 0x1012, 0x1013, 0x1014, 0x1015, 0x1016, 0x1017, + 0x1018, 0x1019, 0x101a, 0x101b, 0x101c, 0x101d, 0x101e, 0x101f, + 0x1020, 0x1021, 0x1022, 0x1023, 0x1024, 0x1025, 0x1026, 0x1027, + 0x1028, 0x1029, 0x102a, 0x102b, 0x102c, 0x102d, 0x102e, 0x102f, + 0x1030, 0x1031, 0x1032, 0x1033, 0x1034, 0x1035, 0x1036, 0x1037, + 0x1038, 0x1039, 0x103a, 0x103b, 0x103c, 0x103d, 0x103e, 0x103f, + 0x1040, 0x1041, 0x1042, 0x1043, 0x1044, 0x1045, 0x1046, 0x1047, + 0x1048, 0x1049, 0x104a, 0x104b, 0x104c, 0x104d, 0x104e, 0x104f, + 0x1050, 0x1051, 0x1052, 0x1053, 0x1054, 0x1055, 0x1056, 0x1057, + 0x1058, 0x1059, 0x105a, 0x105b, 0x105c, 0x105d, 0x105e, 0x105f, + 0x1060, 0x1061, 0x1062, 0x1063, 0x1064, 0x1065, 0x1066, 0x1067, + 0x1068, 0x1069, 0x106a, 0x106b, 0x106c, 0x106d, 0x106e, 0x106f, + 0x1070, 0x1071, 0x1072, 0x1073, 0x1074, 0x1075, 0x1076, 0x1077, + 0x1078, 0x1079, 0x107a, 0x107b, 0x107c, 0x107d, 0x107e, 0x107f, + 0x1080, 0x1081, 0x1082, 0x1083, 0x1084, 0x1085, 0x1086, 0x1087, + 0x1088, 0x1089, 0x108a, 0x108b, 0x108c, 0x108d, 0x108e, 0x108f, + 0x1090, 0x1091, 0x1092, 0x1093, 0x1094, 0x1095, 0x1096, 0x1097, + 0x1098, 0x1099, 0x109a, 0x109b, 0x109c, 0x109d, 0x109e, 0x109f, + 0x2d00, 0x2d01, 0x2d02, 0x2d03, 0x2d04, 0x2d05, 0x2d06, 0x2d07, + 0x2d08, 0x2d09, 0x2d0a, 0x2d0b, 0x2d0c, 0x2d0d, 0x2d0e, 0x2d0f, + 0x2d10, 0x2d11, 0x2d12, 0x2d13, 0x2d14, 0x2d15, 0x2d16, 0x2d17, + 0x2d18, 0x2d19, 0x2d1a, 0x2d1b, 0x2d1c, 0x2d1d, 0x2d1e, 0x2d1f, + 0x2d20, 0x2d21, 0x2d22, 0x2d23, 0x2d24, 0x2d25, 0x10c6, 0x2d27, + 0x10c8, 0x10c9, 0x10ca, 0x10cb, 0x10cc, 0x2d2d, 0x10ce, 0x10cf, + 0x10d0, 0x10d1, 0x10d2, 0x10d3, 0x10d4, 0x10d5, 0x10d6, 0x10d7, + 0x10d8, 0x10d9, 0x10da, 0x10db, 0x10dc, 0x10dd, 0x10de, 0x10df, + 0x10e0, 0x10e1, 0x10e2, 0x10e3, 0x10e4, 0x10e5, 0x10e6, 0x10e7, + 0x10e8, 0x10e9, 0x10ea, 0x10eb, 0x10ec, 0x10ed, 0x10ee, 0x10ef, + 0x10f0, 0x10f1, 0x10f2, 0x10f3, 0x10f4, 0x10f5, 0x10f6, 0x10f7, + 0x10f8, 0x10f9, 0x10fa, 0x10fb, 0x10fc, 0x10fd, 0x10fe, 0x10ff +}}; +static UnicodeCaseTableVector caseTable13 = {{ + 0x1300, 0x1301, 0x1302, 0x1303, 0x1304, 0x1305, 0x1306, 0x1307, + 0x1308, 0x1309, 0x130a, 0x130b, 0x130c, 0x130d, 0x130e, 0x130f, + 0x1310, 0x1311, 0x1312, 0x1313, 0x1314, 0x1315, 0x1316, 0x1317, + 0x1318, 0x1319, 0x131a, 0x131b, 0x131c, 0x131d, 0x131e, 0x131f, + 0x1320, 0x1321, 0x1322, 0x1323, 0x1324, 0x1325, 0x1326, 0x1327, + 0x1328, 0x1329, 0x132a, 0x132b, 0x132c, 0x132d, 0x132e, 0x132f, + 0x1330, 0x1331, 0x1332, 0x1333, 0x1334, 0x1335, 0x1336, 0x1337, + 0x1338, 0x1339, 0x133a, 0x133b, 0x133c, 0x133d, 0x133e, 0x133f, + 0x1340, 0x1341, 0x1342, 0x1343, 0x1344, 0x1345, 0x1346, 0x1347, + 0x1348, 0x1349, 0x134a, 0x134b, 0x134c, 0x134d, 0x134e, 0x134f, + 0x1350, 0x1351, 0x1352, 0x1353, 0x1354, 0x1355, 0x1356, 0x1357, + 0x1358, 0x1359, 0x135a, 0x135b, 0x135c, 0x135d, 0x135e, 0x135f, + 0x1360, 0x1361, 0x1362, 0x1363, 0x1364, 0x1365, 0x1366, 0x1367, + 0x1368, 0x1369, 0x136a, 0x136b, 0x136c, 0x136d, 0x136e, 0x136f, + 0x1370, 0x1371, 0x1372, 0x1373, 0x1374, 0x1375, 0x1376, 0x1377, + 0x1378, 0x1379, 0x137a, 0x137b, 0x137c, 0x137d, 0x137e, 0x137f, + 0x1380, 0x1381, 0x1382, 0x1383, 0x1384, 0x1385, 0x1386, 0x1387, + 0x1388, 0x1389, 0x138a, 0x138b, 0x138c, 0x138d, 0x138e, 0x138f, + 0x1390, 0x1391, 0x1392, 0x1393, 0x1394, 0x1395, 0x1396, 0x1397, + 0x1398, 0x1399, 0x139a, 0x139b, 0x139c, 0x139d, 0x139e, 0x139f, + 0x13a0, 0x13a1, 0x13a2, 0x13a3, 0x13a4, 0x13a5, 0x13a6, 0x13a7, + 0x13a8, 0x13a9, 0x13aa, 0x13ab, 0x13ac, 0x13ad, 0x13ae, 0x13af, + 0x13b0, 0x13b1, 0x13b2, 0x13b3, 0x13b4, 0x13b5, 0x13b6, 0x13b7, + 0x13b8, 0x13b9, 0x13ba, 0x13bb, 0x13bc, 0x13bd, 0x13be, 0x13bf, + 0x13c0, 0x13c1, 0x13c2, 0x13c3, 0x13c4, 0x13c5, 0x13c6, 0x13c7, + 0x13c8, 0x13c9, 0x13ca, 0x13cb, 0x13cc, 0x13cd, 0x13ce, 0x13cf, + 0x13d0, 0x13d1, 0x13d2, 0x13d3, 0x13d4, 0x13d5, 0x13d6, 0x13d7, + 0x13d8, 0x13d9, 0x13da, 0x13db, 0x13dc, 0x13dd, 0x13de, 0x13df, + 0x13e0, 0x13e1, 0x13e2, 0x13e3, 0x13e4, 0x13e5, 0x13e6, 0x13e7, + 0x13e8, 0x13e9, 0x13ea, 0x13eb, 0x13ec, 0x13ed, 0x13ee, 0x13ef, + 0x13f0, 0x13f1, 0x13f2, 0x13f3, 0x13f4, 0x13f5, 0x13f6, 0x13f7, + 0x13f0, 0x13f1, 0x13f2, 0x13f3, 0x13f4, 0x13f5, 0x13fe, 0x13ff +}}; +static UnicodeCaseTableVector caseTable1c = {{ + 0x1c00, 0x1c01, 0x1c02, 0x1c03, 0x1c04, 0x1c05, 0x1c06, 0x1c07, + 0x1c08, 0x1c09, 0x1c0a, 0x1c0b, 0x1c0c, 0x1c0d, 0x1c0e, 0x1c0f, + 0x1c10, 0x1c11, 0x1c12, 0x1c13, 0x1c14, 0x1c15, 0x1c16, 0x1c17, + 0x1c18, 0x1c19, 0x1c1a, 0x1c1b, 0x1c1c, 0x1c1d, 0x1c1e, 0x1c1f, + 0x1c20, 0x1c21, 0x1c22, 0x1c23, 0x1c24, 0x1c25, 0x1c26, 0x1c27, + 0x1c28, 0x1c29, 0x1c2a, 0x1c2b, 0x1c2c, 0x1c2d, 0x1c2e, 0x1c2f, + 0x1c30, 0x1c31, 0x1c32, 0x1c33, 0x1c34, 0x1c35, 0x1c36, 0x1c37, + 0x1c38, 0x1c39, 0x1c3a, 0x1c3b, 0x1c3c, 0x1c3d, 0x1c3e, 0x1c3f, + 0x1c40, 0x1c41, 0x1c42, 0x1c43, 0x1c44, 0x1c45, 0x1c46, 0x1c47, + 0x1c48, 0x1c49, 0x1c4a, 0x1c4b, 0x1c4c, 0x1c4d, 0x1c4e, 0x1c4f, + 0x1c50, 0x1c51, 0x1c52, 0x1c53, 0x1c54, 0x1c55, 0x1c56, 0x1c57, + 0x1c58, 0x1c59, 0x1c5a, 0x1c5b, 0x1c5c, 0x1c5d, 0x1c5e, 0x1c5f, + 0x1c60, 0x1c61, 0x1c62, 0x1c63, 0x1c64, 0x1c65, 0x1c66, 0x1c67, + 0x1c68, 0x1c69, 0x1c6a, 0x1c6b, 0x1c6c, 0x1c6d, 0x1c6e, 0x1c6f, + 0x1c70, 0x1c71, 0x1c72, 0x1c73, 0x1c74, 0x1c75, 0x1c76, 0x1c77, + 0x1c78, 0x1c79, 0x1c7a, 0x1c7b, 0x1c7c, 0x1c7d, 0x1c7e, 0x1c7f, + 0x0432, 0x0434, 0x043e, 0x0441, 0x0442, 0x0442, 0x044a, 0x0463, + 0xa64b, 0x1c89, 0x1c8a, 0x1c8b, 0x1c8c, 0x1c8d, 0x1c8e, 0x1c8f, + 0x10d0, 0x10d1, 0x10d2, 0x10d3, 0x10d4, 0x10d5, 0x10d6, 0x10d7, + 0x10d8, 0x10d9, 0x10da, 0x10db, 0x10dc, 0x10dd, 0x10de, 0x10df, + 0x10e0, 0x10e1, 0x10e2, 0x10e3, 0x10e4, 0x10e5, 0x10e6, 0x10e7, + 0x10e8, 0x10e9, 0x10ea, 0x10eb, 0x10ec, 0x10ed, 0x10ee, 0x10ef, + 0x10f0, 0x10f1, 0x10f2, 0x10f3, 0x10f4, 0x10f5, 0x10f6, 0x10f7, + 0x10f8, 0x10f9, 0x10fa, 0x1cbb, 0x1cbc, 0x10fd, 0x10fe, 0x10ff, + 0x1cc0, 0x1cc1, 0x1cc2, 0x1cc3, 0x1cc4, 0x1cc5, 0x1cc6, 0x1cc7, + 0x1cc8, 0x1cc9, 0x1cca, 0x1ccb, 0x1ccc, 0x1ccd, 0x1cce, 0x1ccf, + 0x1cd0, 0x1cd1, 0x1cd2, 0x1cd3, 0x1cd4, 0x1cd5, 0x1cd6, 0x1cd7, + 0x1cd8, 0x1cd9, 0x1cda, 0x1cdb, 0x1cdc, 0x1cdd, 0x1cde, 0x1cdf, + 0x1ce0, 0x1ce1, 0x1ce2, 0x1ce3, 0x1ce4, 0x1ce5, 0x1ce6, 0x1ce7, + 0x1ce8, 0x1ce9, 0x1cea, 0x1ceb, 0x1cec, 0x1ced, 0x1cee, 0x1cef, + 0x1cf0, 0x1cf1, 0x1cf2, 0x1cf3, 0x1cf4, 0x1cf5, 0x1cf6, 0x1cf7, + 0x1cf8, 0x1cf9, 0x1cfa, 0x1cfb, 0x1cfc, 0x1cfd, 0x1cfe, 0x1cff +}}; +static UnicodeCaseTableVector caseTable1e = {{ + 0x1e01, 0x1e01, 0x1e03, 0x1e03, 0x1e05, 0x1e05, 0x1e07, 0x1e07, + 0x1e09, 0x1e09, 0x1e0b, 0x1e0b, 0x1e0d, 0x1e0d, 0x1e0f, 0x1e0f, + 0x1e11, 0x1e11, 0x1e13, 0x1e13, 0x1e15, 0x1e15, 0x1e17, 0x1e17, + 0x1e19, 0x1e19, 0x1e1b, 0x1e1b, 0x1e1d, 0x1e1d, 0x1e1f, 0x1e1f, + 0x1e21, 0x1e21, 0x1e23, 0x1e23, 0x1e25, 0x1e25, 0x1e27, 0x1e27, + 0x1e29, 0x1e29, 0x1e2b, 0x1e2b, 0x1e2d, 0x1e2d, 0x1e2f, 0x1e2f, + 0x1e31, 0x1e31, 0x1e33, 0x1e33, 0x1e35, 0x1e35, 0x1e37, 0x1e37, + 0x1e39, 0x1e39, 0x1e3b, 0x1e3b, 0x1e3d, 0x1e3d, 0x1e3f, 0x1e3f, + 0x1e41, 0x1e41, 0x1e43, 0x1e43, 0x1e45, 0x1e45, 0x1e47, 0x1e47, + 0x1e49, 0x1e49, 0x1e4b, 0x1e4b, 0x1e4d, 0x1e4d, 0x1e4f, 0x1e4f, + 0x1e51, 0x1e51, 0x1e53, 0x1e53, 0x1e55, 0x1e55, 0x1e57, 0x1e57, + 0x1e59, 0x1e59, 0x1e5b, 0x1e5b, 0x1e5d, 0x1e5d, 0x1e5f, 0x1e5f, + 0x1e61, 0x1e61, 0x1e63, 0x1e63, 0x1e65, 0x1e65, 0x1e67, 0x1e67, + 0x1e69, 0x1e69, 0x1e6b, 0x1e6b, 0x1e6d, 0x1e6d, 0x1e6f, 0x1e6f, + 0x1e71, 0x1e71, 0x1e73, 0x1e73, 0x1e75, 0x1e75, 0x1e77, 0x1e77, + 0x1e79, 0x1e79, 0x1e7b, 0x1e7b, 0x1e7d, 0x1e7d, 0x1e7f, 0x1e7f, + 0x1e81, 0x1e81, 0x1e83, 0x1e83, 0x1e85, 0x1e85, 0x1e87, 0x1e87, + 0x1e89, 0x1e89, 0x1e8b, 0x1e8b, 0x1e8d, 0x1e8d, 0x1e8f, 0x1e8f, + 0x1e91, 0x1e91, 0x1e93, 0x1e93, 0x1e95, 0x1e95, 0x1e96, 0x1e97, + 0x1e98, 0x1e99, 0x1e9a, 0x1e61, 0x1e9c, 0x1e9d, 0x00df, 0x1e9f, + 0x1ea1, 0x1ea1, 0x1ea3, 0x1ea3, 0x1ea5, 0x1ea5, 0x1ea7, 0x1ea7, + 0x1ea9, 0x1ea9, 0x1eab, 0x1eab, 0x1ead, 0x1ead, 0x1eaf, 0x1eaf, + 0x1eb1, 0x1eb1, 0x1eb3, 0x1eb3, 0x1eb5, 0x1eb5, 0x1eb7, 0x1eb7, + 0x1eb9, 0x1eb9, 0x1ebb, 0x1ebb, 0x1ebd, 0x1ebd, 0x1ebf, 0x1ebf, + 0x1ec1, 0x1ec1, 0x1ec3, 0x1ec3, 0x1ec5, 0x1ec5, 0x1ec7, 0x1ec7, + 0x1ec9, 0x1ec9, 0x1ecb, 0x1ecb, 0x1ecd, 0x1ecd, 0x1ecf, 0x1ecf, + 0x1ed1, 0x1ed1, 0x1ed3, 0x1ed3, 0x1ed5, 0x1ed5, 0x1ed7, 0x1ed7, + 0x1ed9, 0x1ed9, 0x1edb, 0x1edb, 0x1edd, 0x1edd, 0x1edf, 0x1edf, + 0x1ee1, 0x1ee1, 0x1ee3, 0x1ee3, 0x1ee5, 0x1ee5, 0x1ee7, 0x1ee7, + 0x1ee9, 0x1ee9, 0x1eeb, 0x1eeb, 0x1eed, 0x1eed, 0x1eef, 0x1eef, + 0x1ef1, 0x1ef1, 0x1ef3, 0x1ef3, 0x1ef5, 0x1ef5, 0x1ef7, 0x1ef7, + 0x1ef9, 0x1ef9, 0x1efb, 0x1efb, 0x1efd, 0x1efd, 0x1eff, 0x1eff +}}; +static UnicodeCaseTableVector caseTable1f = {{ + 0x1f00, 0x1f01, 0x1f02, 0x1f03, 0x1f04, 0x1f05, 0x1f06, 0x1f07, + 0x1f00, 0x1f01, 0x1f02, 0x1f03, 0x1f04, 0x1f05, 0x1f06, 0x1f07, + 0x1f10, 0x1f11, 0x1f12, 0x1f13, 0x1f14, 0x1f15, 0x1f16, 0x1f17, + 0x1f10, 0x1f11, 0x1f12, 0x1f13, 0x1f14, 0x1f15, 0x1f1e, 0x1f1f, + 0x1f20, 0x1f21, 0x1f22, 0x1f23, 0x1f24, 0x1f25, 0x1f26, 0x1f27, + 0x1f20, 0x1f21, 0x1f22, 0x1f23, 0x1f24, 0x1f25, 0x1f26, 0x1f27, + 0x1f30, 0x1f31, 0x1f32, 0x1f33, 0x1f34, 0x1f35, 0x1f36, 0x1f37, + 0x1f30, 0x1f31, 0x1f32, 0x1f33, 0x1f34, 0x1f35, 0x1f36, 0x1f37, + 0x1f40, 0x1f41, 0x1f42, 0x1f43, 0x1f44, 0x1f45, 0x1f46, 0x1f47, + 0x1f40, 0x1f41, 0x1f42, 0x1f43, 0x1f44, 0x1f45, 0x1f4e, 0x1f4f, + 0x1f50, 0x1f51, 0x1f52, 0x1f53, 0x1f54, 0x1f55, 0x1f56, 0x1f57, + 0x1f58, 0x1f51, 0x1f5a, 0x1f53, 0x1f5c, 0x1f55, 0x1f5e, 0x1f57, + 0x1f60, 0x1f61, 0x1f62, 0x1f63, 0x1f64, 0x1f65, 0x1f66, 0x1f67, + 0x1f60, 0x1f61, 0x1f62, 0x1f63, 0x1f64, 0x1f65, 0x1f66, 0x1f67, + 0x1f70, 0x1f71, 0x1f72, 0x1f73, 0x1f74, 0x1f75, 0x1f76, 0x1f77, + 0x1f78, 0x1f79, 0x1f7a, 0x1f7b, 0x1f7c, 0x1f7d, 0x1f7e, 0x1f7f, + 0x1f80, 0x1f81, 0x1f82, 0x1f83, 0x1f84, 0x1f85, 0x1f86, 0x1f87, + 0x1f80, 0x1f81, 0x1f82, 0x1f83, 0x1f84, 0x1f85, 0x1f86, 0x1f87, + 0x1f90, 0x1f91, 0x1f92, 0x1f93, 0x1f94, 0x1f95, 0x1f96, 0x1f97, + 0x1f90, 0x1f91, 0x1f92, 0x1f93, 0x1f94, 0x1f95, 0x1f96, 0x1f97, + 0x1fa0, 0x1fa1, 0x1fa2, 0x1fa3, 0x1fa4, 0x1fa5, 0x1fa6, 0x1fa7, + 0x1fa0, 0x1fa1, 0x1fa2, 0x1fa3, 0x1fa4, 0x1fa5, 0x1fa6, 0x1fa7, + 0x1fb0, 0x1fb1, 0x1fb2, 0x1fb3, 0x1fb4, 0x1fb5, 0x1fb6, 0x1fb7, + 0x1fb0, 0x1fb1, 0x1f70, 0x1f71, 0x1fb3, 0x1fbd, 0x03b9, 0x1fbf, + 0x1fc0, 0x1fc1, 0x1fc2, 0x1fc3, 0x1fc4, 0x1fc5, 0x1fc6, 0x1fc7, + 0x1f72, 0x1f73, 0x1f74, 0x1f75, 0x1fc3, 0x1fcd, 0x1fce, 0x1fcf, + 0x1fd0, 0x1fd1, 0x1fd2, 0x1fd3, 0x1fd4, 0x1fd5, 0x1fd6, 0x1fd7, + 0x1fd0, 0x1fd1, 0x1f76, 0x1f77, 0x1fdc, 0x1fdd, 0x1fde, 0x1fdf, + 0x1fe0, 0x1fe1, 0x1fe2, 0x1fe3, 0x1fe4, 0x1fe5, 0x1fe6, 0x1fe7, + 0x1fe0, 0x1fe1, 0x1f7a, 0x1f7b, 0x1fe5, 0x1fed, 0x1fee, 0x1fef, + 0x1ff0, 0x1ff1, 0x1ff2, 0x1ff3, 0x1ff4, 0x1ff5, 0x1ff6, 0x1ff7, + 0x1f78, 0x1f79, 0x1f7c, 0x1f7d, 0x1ff3, 0x1ffd, 0x1ffe, 0x1fff +}}; +static UnicodeCaseTableVector caseTable21 = {{ + 0x2100, 0x2101, 0x2102, 0x2103, 0x2104, 0x2105, 0x2106, 0x2107, + 0x2108, 0x2109, 0x210a, 0x210b, 0x210c, 0x210d, 0x210e, 0x210f, + 0x2110, 0x2111, 0x2112, 0x2113, 0x2114, 0x2115, 0x2116, 0x2117, + 0x2118, 0x2119, 0x211a, 0x211b, 0x211c, 0x211d, 0x211e, 0x211f, + 0x2120, 0x2121, 0x2122, 0x2123, 0x2124, 0x2125, 0x03c9, 0x2127, + 0x2128, 0x2129, 0x006b, 0x00e5, 0x212c, 0x212d, 0x212e, 0x212f, + 0x2130, 0x2131, 0x214e, 0x2133, 0x2134, 0x2135, 0x2136, 0x2137, + 0x2138, 0x2139, 0x213a, 0x213b, 0x213c, 0x213d, 0x213e, 0x213f, + 0x2140, 0x2141, 0x2142, 0x2143, 0x2144, 0x2145, 0x2146, 0x2147, + 0x2148, 0x2149, 0x214a, 0x214b, 0x214c, 0x214d, 0x214e, 0x214f, + 0x2150, 0x2151, 0x2152, 0x2153, 0x2154, 0x2155, 0x2156, 0x2157, + 0x2158, 0x2159, 0x215a, 0x215b, 0x215c, 0x215d, 0x215e, 0x215f, + 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, 0x2177, + 0x2178, 0x2179, 0x217a, 0x217b, 0x217c, 0x217d, 0x217e, 0x217f, + 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, 0x2177, + 0x2178, 0x2179, 0x217a, 0x217b, 0x217c, 0x217d, 0x217e, 0x217f, + 0x2180, 0x2181, 0x2182, 0x2184, 0x2184, 0x2185, 0x2186, 0x2187, + 0x2188, 0x2189, 0x218a, 0x218b, 0x218c, 0x218d, 0x218e, 0x218f, + 0x2190, 0x2191, 0x2192, 0x2193, 0x2194, 0x2195, 0x2196, 0x2197, + 0x2198, 0x2199, 0x219a, 0x219b, 0x219c, 0x219d, 0x219e, 0x219f, + 0x21a0, 0x21a1, 0x21a2, 0x21a3, 0x21a4, 0x21a5, 0x21a6, 0x21a7, + 0x21a8, 0x21a9, 0x21aa, 0x21ab, 0x21ac, 0x21ad, 0x21ae, 0x21af, + 0x21b0, 0x21b1, 0x21b2, 0x21b3, 0x21b4, 0x21b5, 0x21b6, 0x21b7, + 0x21b8, 0x21b9, 0x21ba, 0x21bb, 0x21bc, 0x21bd, 0x21be, 0x21bf, + 0x21c0, 0x21c1, 0x21c2, 0x21c3, 0x21c4, 0x21c5, 0x21c6, 0x21c7, + 0x21c8, 0x21c9, 0x21ca, 0x21cb, 0x21cc, 0x21cd, 0x21ce, 0x21cf, + 0x21d0, 0x21d1, 0x21d2, 0x21d3, 0x21d4, 0x21d5, 0x21d6, 0x21d7, + 0x21d8, 0x21d9, 0x21da, 0x21db, 0x21dc, 0x21dd, 0x21de, 0x21df, + 0x21e0, 0x21e1, 0x21e2, 0x21e3, 0x21e4, 0x21e5, 0x21e6, 0x21e7, + 0x21e8, 0x21e9, 0x21ea, 0x21eb, 0x21ec, 0x21ed, 0x21ee, 0x21ef, + 0x21f0, 0x21f1, 0x21f2, 0x21f3, 0x21f4, 0x21f5, 0x21f6, 0x21f7, + 0x21f8, 0x21f9, 0x21fa, 0x21fb, 0x21fc, 0x21fd, 0x21fe, 0x21ff +}}; +static UnicodeCaseTableVector caseTable24 = {{ + 0x2400, 0x2401, 0x2402, 0x2403, 0x2404, 0x2405, 0x2406, 0x2407, + 0x2408, 0x2409, 0x240a, 0x240b, 0x240c, 0x240d, 0x240e, 0x240f, + 0x2410, 0x2411, 0x2412, 0x2413, 0x2414, 0x2415, 0x2416, 0x2417, + 0x2418, 0x2419, 0x241a, 0x241b, 0x241c, 0x241d, 0x241e, 0x241f, + 0x2420, 0x2421, 0x2422, 0x2423, 0x2424, 0x2425, 0x2426, 0x2427, + 0x2428, 0x2429, 0x242a, 0x242b, 0x242c, 0x242d, 0x242e, 0x242f, + 0x2430, 0x2431, 0x2432, 0x2433, 0x2434, 0x2435, 0x2436, 0x2437, + 0x2438, 0x2439, 0x243a, 0x243b, 0x243c, 0x243d, 0x243e, 0x243f, + 0x2440, 0x2441, 0x2442, 0x2443, 0x2444, 0x2445, 0x2446, 0x2447, + 0x2448, 0x2449, 0x244a, 0x244b, 0x244c, 0x244d, 0x244e, 0x244f, + 0x2450, 0x2451, 0x2452, 0x2453, 0x2454, 0x2455, 0x2456, 0x2457, + 0x2458, 0x2459, 0x245a, 0x245b, 0x245c, 0x245d, 0x245e, 0x245f, + 0x2460, 0x2461, 0x2462, 0x2463, 0x2464, 0x2465, 0x2466, 0x2467, + 0x2468, 0x2469, 0x246a, 0x246b, 0x246c, 0x246d, 0x246e, 0x246f, + 0x2470, 0x2471, 0x2472, 0x2473, 0x2474, 0x2475, 0x2476, 0x2477, + 0x2478, 0x2479, 0x247a, 0x247b, 0x247c, 0x247d, 0x247e, 0x247f, + 0x2480, 0x2481, 0x2482, 0x2483, 0x2484, 0x2485, 0x2486, 0x2487, + 0x2488, 0x2489, 0x248a, 0x248b, 0x248c, 0x248d, 0x248e, 0x248f, + 0x2490, 0x2491, 0x2492, 0x2493, 0x2494, 0x2495, 0x2496, 0x2497, + 0x2498, 0x2499, 0x249a, 0x249b, 0x249c, 0x249d, 0x249e, 0x249f, + 0x24a0, 0x24a1, 0x24a2, 0x24a3, 0x24a4, 0x24a5, 0x24a6, 0x24a7, + 0x24a8, 0x24a9, 0x24aa, 0x24ab, 0x24ac, 0x24ad, 0x24ae, 0x24af, + 0x24b0, 0x24b1, 0x24b2, 0x24b3, 0x24b4, 0x24b5, 0x24d0, 0x24d1, + 0x24d2, 0x24d3, 0x24d4, 0x24d5, 0x24d6, 0x24d7, 0x24d8, 0x24d9, + 0x24da, 0x24db, 0x24dc, 0x24dd, 0x24de, 0x24df, 0x24e0, 0x24e1, + 0x24e2, 0x24e3, 0x24e4, 0x24e5, 0x24e6, 0x24e7, 0x24e8, 0x24e9, + 0x24d0, 0x24d1, 0x24d2, 0x24d3, 0x24d4, 0x24d5, 0x24d6, 0x24d7, + 0x24d8, 0x24d9, 0x24da, 0x24db, 0x24dc, 0x24dd, 0x24de, 0x24df, + 0x24e0, 0x24e1, 0x24e2, 0x24e3, 0x24e4, 0x24e5, 0x24e6, 0x24e7, + 0x24e8, 0x24e9, 0x24ea, 0x24eb, 0x24ec, 0x24ed, 0x24ee, 0x24ef, + 0x24f0, 0x24f1, 0x24f2, 0x24f3, 0x24f4, 0x24f5, 0x24f6, 0x24f7, + 0x24f8, 0x24f9, 0x24fa, 0x24fb, 0x24fc, 0x24fd, 0x24fe, 0x24ff +}}; +static UnicodeCaseTableVector caseTable2c = {{ + 0x2c30, 0x2c31, 0x2c32, 0x2c33, 0x2c34, 0x2c35, 0x2c36, 0x2c37, + 0x2c38, 0x2c39, 0x2c3a, 0x2c3b, 0x2c3c, 0x2c3d, 0x2c3e, 0x2c3f, + 0x2c40, 0x2c41, 0x2c42, 0x2c43, 0x2c44, 0x2c45, 0x2c46, 0x2c47, + 0x2c48, 0x2c49, 0x2c4a, 0x2c4b, 0x2c4c, 0x2c4d, 0x2c4e, 0x2c4f, + 0x2c50, 0x2c51, 0x2c52, 0x2c53, 0x2c54, 0x2c55, 0x2c56, 0x2c57, + 0x2c58, 0x2c59, 0x2c5a, 0x2c5b, 0x2c5c, 0x2c5d, 0x2c5e, 0x2c2f, + 0x2c30, 0x2c31, 0x2c32, 0x2c33, 0x2c34, 0x2c35, 0x2c36, 0x2c37, + 0x2c38, 0x2c39, 0x2c3a, 0x2c3b, 0x2c3c, 0x2c3d, 0x2c3e, 0x2c3f, + 0x2c40, 0x2c41, 0x2c42, 0x2c43, 0x2c44, 0x2c45, 0x2c46, 0x2c47, + 0x2c48, 0x2c49, 0x2c4a, 0x2c4b, 0x2c4c, 0x2c4d, 0x2c4e, 0x2c4f, + 0x2c50, 0x2c51, 0x2c52, 0x2c53, 0x2c54, 0x2c55, 0x2c56, 0x2c57, + 0x2c58, 0x2c59, 0x2c5a, 0x2c5b, 0x2c5c, 0x2c5d, 0x2c5e, 0x2c5f, + 0x2c61, 0x2c61, 0x026b, 0x1d7d, 0x027d, 0x2c65, 0x2c66, 0x2c68, + 0x2c68, 0x2c6a, 0x2c6a, 0x2c6c, 0x2c6c, 0x0251, 0x0271, 0x0250, + 0x0252, 0x2c71, 0x2c73, 0x2c73, 0x2c74, 0x2c76, 0x2c76, 0x2c77, + 0x2c78, 0x2c79, 0x2c7a, 0x2c7b, 0x2c7c, 0x2c7d, 0x023f, 0x0240, + 0x2c81, 0x2c81, 0x2c83, 0x2c83, 0x2c85, 0x2c85, 0x2c87, 0x2c87, + 0x2c89, 0x2c89, 0x2c8b, 0x2c8b, 0x2c8d, 0x2c8d, 0x2c8f, 0x2c8f, + 0x2c91, 0x2c91, 0x2c93, 0x2c93, 0x2c95, 0x2c95, 0x2c97, 0x2c97, + 0x2c99, 0x2c99, 0x2c9b, 0x2c9b, 0x2c9d, 0x2c9d, 0x2c9f, 0x2c9f, + 0x2ca1, 0x2ca1, 0x2ca3, 0x2ca3, 0x2ca5, 0x2ca5, 0x2ca7, 0x2ca7, + 0x2ca9, 0x2ca9, 0x2cab, 0x2cab, 0x2cad, 0x2cad, 0x2caf, 0x2caf, + 0x2cb1, 0x2cb1, 0x2cb3, 0x2cb3, 0x2cb5, 0x2cb5, 0x2cb7, 0x2cb7, + 0x2cb9, 0x2cb9, 0x2cbb, 0x2cbb, 0x2cbd, 0x2cbd, 0x2cbf, 0x2cbf, + 0x2cc1, 0x2cc1, 0x2cc3, 0x2cc3, 0x2cc5, 0x2cc5, 0x2cc7, 0x2cc7, + 0x2cc9, 0x2cc9, 0x2ccb, 0x2ccb, 0x2ccd, 0x2ccd, 0x2ccf, 0x2ccf, + 0x2cd1, 0x2cd1, 0x2cd3, 0x2cd3, 0x2cd5, 0x2cd5, 0x2cd7, 0x2cd7, + 0x2cd9, 0x2cd9, 0x2cdb, 0x2cdb, 0x2cdd, 0x2cdd, 0x2cdf, 0x2cdf, + 0x2ce1, 0x2ce1, 0x2ce3, 0x2ce3, 0x2ce4, 0x2ce5, 0x2ce6, 0x2ce7, + 0x2ce8, 0x2ce9, 0x2cea, 0x2cec, 0x2cec, 0x2cee, 0x2cee, 0x2cef, + 0x2cf0, 0x2cf1, 0x2cf3, 0x2cf3, 0x2cf4, 0x2cf5, 0x2cf6, 0x2cf7, + 0x2cf8, 0x2cf9, 0x2cfa, 0x2cfb, 0x2cfc, 0x2cfd, 0x2cfe, 0x2cff +}}; +static UnicodeCaseTableVector caseTablea6 = {{ + 0xa600, 0xa601, 0xa602, 0xa603, 0xa604, 0xa605, 0xa606, 0xa607, + 0xa608, 0xa609, 0xa60a, 0xa60b, 0xa60c, 0xa60d, 0xa60e, 0xa60f, + 0xa610, 0xa611, 0xa612, 0xa613, 0xa614, 0xa615, 0xa616, 0xa617, + 0xa618, 0xa619, 0xa61a, 0xa61b, 0xa61c, 0xa61d, 0xa61e, 0xa61f, + 0xa620, 0xa621, 0xa622, 0xa623, 0xa624, 0xa625, 0xa626, 0xa627, + 0xa628, 0xa629, 0xa62a, 0xa62b, 0xa62c, 0xa62d, 0xa62e, 0xa62f, + 0xa630, 0xa631, 0xa632, 0xa633, 0xa634, 0xa635, 0xa636, 0xa637, + 0xa638, 0xa639, 0xa63a, 0xa63b, 0xa63c, 0xa63d, 0xa63e, 0xa63f, + 0xa641, 0xa641, 0xa643, 0xa643, 0xa645, 0xa645, 0xa647, 0xa647, + 0xa649, 0xa649, 0xa64b, 0xa64b, 0xa64d, 0xa64d, 0xa64f, 0xa64f, + 0xa651, 0xa651, 0xa653, 0xa653, 0xa655, 0xa655, 0xa657, 0xa657, + 0xa659, 0xa659, 0xa65b, 0xa65b, 0xa65d, 0xa65d, 0xa65f, 0xa65f, + 0xa661, 0xa661, 0xa663, 0xa663, 0xa665, 0xa665, 0xa667, 0xa667, + 0xa669, 0xa669, 0xa66b, 0xa66b, 0xa66d, 0xa66d, 0xa66e, 0xa66f, + 0xa670, 0xa671, 0xa672, 0xa673, 0xa674, 0xa675, 0xa676, 0xa677, + 0xa678, 0xa679, 0xa67a, 0xa67b, 0xa67c, 0xa67d, 0xa67e, 0xa67f, + 0xa681, 0xa681, 0xa683, 0xa683, 0xa685, 0xa685, 0xa687, 0xa687, + 0xa689, 0xa689, 0xa68b, 0xa68b, 0xa68d, 0xa68d, 0xa68f, 0xa68f, + 0xa691, 0xa691, 0xa693, 0xa693, 0xa695, 0xa695, 0xa697, 0xa697, + 0xa699, 0xa699, 0xa69b, 0xa69b, 0xa69c, 0xa69d, 0xa69e, 0xa69f, + 0xa6a0, 0xa6a1, 0xa6a2, 0xa6a3, 0xa6a4, 0xa6a5, 0xa6a6, 0xa6a7, + 0xa6a8, 0xa6a9, 0xa6aa, 0xa6ab, 0xa6ac, 0xa6ad, 0xa6ae, 0xa6af, + 0xa6b0, 0xa6b1, 0xa6b2, 0xa6b3, 0xa6b4, 0xa6b5, 0xa6b6, 0xa6b7, + 0xa6b8, 0xa6b9, 0xa6ba, 0xa6bb, 0xa6bc, 0xa6bd, 0xa6be, 0xa6bf, + 0xa6c0, 0xa6c1, 0xa6c2, 0xa6c3, 0xa6c4, 0xa6c5, 0xa6c6, 0xa6c7, + 0xa6c8, 0xa6c9, 0xa6ca, 0xa6cb, 0xa6cc, 0xa6cd, 0xa6ce, 0xa6cf, + 0xa6d0, 0xa6d1, 0xa6d2, 0xa6d3, 0xa6d4, 0xa6d5, 0xa6d6, 0xa6d7, + 0xa6d8, 0xa6d9, 0xa6da, 0xa6db, 0xa6dc, 0xa6dd, 0xa6de, 0xa6df, + 0xa6e0, 0xa6e1, 0xa6e2, 0xa6e3, 0xa6e4, 0xa6e5, 0xa6e6, 0xa6e7, + 0xa6e8, 0xa6e9, 0xa6ea, 0xa6eb, 0xa6ec, 0xa6ed, 0xa6ee, 0xa6ef, + 0xa6f0, 0xa6f1, 0xa6f2, 0xa6f3, 0xa6f4, 0xa6f5, 0xa6f6, 0xa6f7, + 0xa6f8, 0xa6f9, 0xa6fa, 0xa6fb, 0xa6fc, 0xa6fd, 0xa6fe, 0xa6ff +}}; +static UnicodeCaseTableVector caseTablea7 = {{ + 0xa700, 0xa701, 0xa702, 0xa703, 0xa704, 0xa705, 0xa706, 0xa707, + 0xa708, 0xa709, 0xa70a, 0xa70b, 0xa70c, 0xa70d, 0xa70e, 0xa70f, + 0xa710, 0xa711, 0xa712, 0xa713, 0xa714, 0xa715, 0xa716, 0xa717, + 0xa718, 0xa719, 0xa71a, 0xa71b, 0xa71c, 0xa71d, 0xa71e, 0xa71f, + 0xa720, 0xa721, 0xa723, 0xa723, 0xa725, 0xa725, 0xa727, 0xa727, + 0xa729, 0xa729, 0xa72b, 0xa72b, 0xa72d, 0xa72d, 0xa72f, 0xa72f, + 0xa730, 0xa731, 0xa733, 0xa733, 0xa735, 0xa735, 0xa737, 0xa737, + 0xa739, 0xa739, 0xa73b, 0xa73b, 0xa73d, 0xa73d, 0xa73f, 0xa73f, + 0xa741, 0xa741, 0xa743, 0xa743, 0xa745, 0xa745, 0xa747, 0xa747, + 0xa749, 0xa749, 0xa74b, 0xa74b, 0xa74d, 0xa74d, 0xa74f, 0xa74f, + 0xa751, 0xa751, 0xa753, 0xa753, 0xa755, 0xa755, 0xa757, 0xa757, + 0xa759, 0xa759, 0xa75b, 0xa75b, 0xa75d, 0xa75d, 0xa75f, 0xa75f, + 0xa761, 0xa761, 0xa763, 0xa763, 0xa765, 0xa765, 0xa767, 0xa767, + 0xa769, 0xa769, 0xa76b, 0xa76b, 0xa76d, 0xa76d, 0xa76f, 0xa76f, + 0xa770, 0xa771, 0xa772, 0xa773, 0xa774, 0xa775, 0xa776, 0xa777, + 0xa778, 0xa77a, 0xa77a, 0xa77c, 0xa77c, 0x1d79, 0xa77f, 0xa77f, + 0xa781, 0xa781, 0xa783, 0xa783, 0xa785, 0xa785, 0xa787, 0xa787, + 0xa788, 0xa789, 0xa78a, 0xa78c, 0xa78c, 0x0265, 0xa78e, 0xa78f, + 0xa791, 0xa791, 0xa793, 0xa793, 0xa794, 0xa795, 0xa797, 0xa797, + 0xa799, 0xa799, 0xa79b, 0xa79b, 0xa79d, 0xa79d, 0xa79f, 0xa79f, + 0xa7a1, 0xa7a1, 0xa7a3, 0xa7a3, 0xa7a5, 0xa7a5, 0xa7a7, 0xa7a7, + 0xa7a9, 0xa7a9, 0x0266, 0x025c, 0x0261, 0x026c, 0x026a, 0xa7af, + 0x029e, 0x0287, 0x029d, 0xab53, 0xa7b5, 0xa7b5, 0xa7b7, 0xa7b7, + 0xa7b9, 0xa7b9, 0xa7bb, 0xa7bb, 0xa7bd, 0xa7bd, 0xa7bf, 0xa7bf, + 0xa7c0, 0xa7c1, 0xa7c3, 0xa7c3, 0xa794, 0x0282, 0x1d8e, 0xa7c8, + 0xa7c8, 0xa7ca, 0xa7ca, 0xa7cb, 0xa7cc, 0xa7cd, 0xa7ce, 0xa7cf, + 0xa7d0, 0xa7d1, 0xa7d2, 0xa7d3, 0xa7d4, 0xa7d5, 0xa7d6, 0xa7d7, + 0xa7d8, 0xa7d9, 0xa7da, 0xa7db, 0xa7dc, 0xa7dd, 0xa7de, 0xa7df, + 0xa7e0, 0xa7e1, 0xa7e2, 0xa7e3, 0xa7e4, 0xa7e5, 0xa7e6, 0xa7e7, + 0xa7e8, 0xa7e9, 0xa7ea, 0xa7eb, 0xa7ec, 0xa7ed, 0xa7ee, 0xa7ef, + 0xa7f0, 0xa7f1, 0xa7f2, 0xa7f3, 0xa7f4, 0xa7f6, 0xa7f6, 0xa7f7, + 0xa7f8, 0xa7f9, 0xa7fa, 0xa7fb, 0xa7fc, 0xa7fd, 0xa7fe, 0xa7ff +}}; +static UnicodeCaseTableVector caseTableab = {{ + 0xab00, 0xab01, 0xab02, 0xab03, 0xab04, 0xab05, 0xab06, 0xab07, + 0xab08, 0xab09, 0xab0a, 0xab0b, 0xab0c, 0xab0d, 0xab0e, 0xab0f, + 0xab10, 0xab11, 0xab12, 0xab13, 0xab14, 0xab15, 0xab16, 0xab17, + 0xab18, 0xab19, 0xab1a, 0xab1b, 0xab1c, 0xab1d, 0xab1e, 0xab1f, + 0xab20, 0xab21, 0xab22, 0xab23, 0xab24, 0xab25, 0xab26, 0xab27, + 0xab28, 0xab29, 0xab2a, 0xab2b, 0xab2c, 0xab2d, 0xab2e, 0xab2f, + 0xab30, 0xab31, 0xab32, 0xab33, 0xab34, 0xab35, 0xab36, 0xab37, + 0xab38, 0xab39, 0xab3a, 0xab3b, 0xab3c, 0xab3d, 0xab3e, 0xab3f, + 0xab40, 0xab41, 0xab42, 0xab43, 0xab44, 0xab45, 0xab46, 0xab47, + 0xab48, 0xab49, 0xab4a, 0xab4b, 0xab4c, 0xab4d, 0xab4e, 0xab4f, + 0xab50, 0xab51, 0xab52, 0xab53, 0xab54, 0xab55, 0xab56, 0xab57, + 0xab58, 0xab59, 0xab5a, 0xab5b, 0xab5c, 0xab5d, 0xab5e, 0xab5f, + 0xab60, 0xab61, 0xab62, 0xab63, 0xab64, 0xab65, 0xab66, 0xab67, + 0xab68, 0xab69, 0xab6a, 0xab6b, 0xab6c, 0xab6d, 0xab6e, 0xab6f, + 0x13a0, 0x13a1, 0x13a2, 0x13a3, 0x13a4, 0x13a5, 0x13a6, 0x13a7, + 0x13a8, 0x13a9, 0x13aa, 0x13ab, 0x13ac, 0x13ad, 0x13ae, 0x13af, + 0x13b0, 0x13b1, 0x13b2, 0x13b3, 0x13b4, 0x13b5, 0x13b6, 0x13b7, + 0x13b8, 0x13b9, 0x13ba, 0x13bb, 0x13bc, 0x13bd, 0x13be, 0x13bf, + 0x13c0, 0x13c1, 0x13c2, 0x13c3, 0x13c4, 0x13c5, 0x13c6, 0x13c7, + 0x13c8, 0x13c9, 0x13ca, 0x13cb, 0x13cc, 0x13cd, 0x13ce, 0x13cf, + 0x13d0, 0x13d1, 0x13d2, 0x13d3, 0x13d4, 0x13d5, 0x13d6, 0x13d7, + 0x13d8, 0x13d9, 0x13da, 0x13db, 0x13dc, 0x13dd, 0x13de, 0x13df, + 0x13e0, 0x13e1, 0x13e2, 0x13e3, 0x13e4, 0x13e5, 0x13e6, 0x13e7, + 0x13e8, 0x13e9, 0x13ea, 0x13eb, 0x13ec, 0x13ed, 0x13ee, 0x13ef, + 0xabc0, 0xabc1, 0xabc2, 0xabc3, 0xabc4, 0xabc5, 0xabc6, 0xabc7, + 0xabc8, 0xabc9, 0xabca, 0xabcb, 0xabcc, 0xabcd, 0xabce, 0xabcf, + 0xabd0, 0xabd1, 0xabd2, 0xabd3, 0xabd4, 0xabd5, 0xabd6, 0xabd7, + 0xabd8, 0xabd9, 0xabda, 0xabdb, 0xabdc, 0xabdd, 0xabde, 0xabdf, + 0xabe0, 0xabe1, 0xabe2, 0xabe3, 0xabe4, 0xabe5, 0xabe6, 0xabe7, + 0xabe8, 0xabe9, 0xabea, 0xabeb, 0xabec, 0xabed, 0xabee, 0xabef, + 0xabf0, 0xabf1, 0xabf2, 0xabf3, 0xabf4, 0xabf5, 0xabf6, 0xabf7, + 0xabf8, 0xabf9, 0xabfa, 0xabfb, 0xabfc, 0xabfd, 0xabfe, 0xabff +}}; +static UnicodeCaseTableVector caseTableff = {{ + 0xff00, 0xff01, 0xff02, 0xff03, 0xff04, 0xff05, 0xff06, 0xff07, + 0xff08, 0xff09, 0xff0a, 0xff0b, 0xff0c, 0xff0d, 0xff0e, 0xff0f, + 0xff10, 0xff11, 0xff12, 0xff13, 0xff14, 0xff15, 0xff16, 0xff17, + 0xff18, 0xff19, 0xff1a, 0xff1b, 0xff1c, 0xff1d, 0xff1e, 0xff1f, + 0xff20, 0xff41, 0xff42, 0xff43, 0xff44, 0xff45, 0xff46, 0xff47, + 0xff48, 0xff49, 0xff4a, 0xff4b, 0xff4c, 0xff4d, 0xff4e, 0xff4f, + 0xff50, 0xff51, 0xff52, 0xff53, 0xff54, 0xff55, 0xff56, 0xff57, + 0xff58, 0xff59, 0xff5a, 0xff3b, 0xff3c, 0xff3d, 0xff3e, 0xff3f, + 0xff40, 0xff41, 0xff42, 0xff43, 0xff44, 0xff45, 0xff46, 0xff47, + 0xff48, 0xff49, 0xff4a, 0xff4b, 0xff4c, 0xff4d, 0xff4e, 0xff4f, + 0xff50, 0xff51, 0xff52, 0xff53, 0xff54, 0xff55, 0xff56, 0xff57, + 0xff58, 0xff59, 0xff5a, 0xff5b, 0xff5c, 0xff5d, 0xff5e, 0xff5f, + 0xff60, 0xff61, 0xff62, 0xff63, 0xff64, 0xff65, 0xff66, 0xff67, + 0xff68, 0xff69, 0xff6a, 0xff6b, 0xff6c, 0xff6d, 0xff6e, 0xff6f, + 0xff70, 0xff71, 0xff72, 0xff73, 0xff74, 0xff75, 0xff76, 0xff77, + 0xff78, 0xff79, 0xff7a, 0xff7b, 0xff7c, 0xff7d, 0xff7e, 0xff7f, + 0xff80, 0xff81, 0xff82, 0xff83, 0xff84, 0xff85, 0xff86, 0xff87, + 0xff88, 0xff89, 0xff8a, 0xff8b, 0xff8c, 0xff8d, 0xff8e, 0xff8f, + 0xff90, 0xff91, 0xff92, 0xff93, 0xff94, 0xff95, 0xff96, 0xff97, + 0xff98, 0xff99, 0xff9a, 0xff9b, 0xff9c, 0xff9d, 0xff9e, 0xff9f, + 0xffa0, 0xffa1, 0xffa2, 0xffa3, 0xffa4, 0xffa5, 0xffa6, 0xffa7, + 0xffa8, 0xffa9, 0xffaa, 0xffab, 0xffac, 0xffad, 0xffae, 0xffaf, + 0xffb0, 0xffb1, 0xffb2, 0xffb3, 0xffb4, 0xffb5, 0xffb6, 0xffb7, + 0xffb8, 0xffb9, 0xffba, 0xffbb, 0xffbc, 0xffbd, 0xffbe, 0xffbf, + 0xffc0, 0xffc1, 0xffc2, 0xffc3, 0xffc4, 0xffc5, 0xffc6, 0xffc7, + 0xffc8, 0xffc9, 0xffca, 0xffcb, 0xffcc, 0xffcd, 0xffce, 0xffcf, + 0xffd0, 0xffd1, 0xffd2, 0xffd3, 0xffd4, 0xffd5, 0xffd6, 0xffd7, + 0xffd8, 0xffd9, 0xffda, 0xffdb, 0xffdc, 0xffdd, 0xffde, 0xffdf, + 0xffe0, 0xffe1, 0xffe2, 0xffe3, 0xffe4, 0xffe5, 0xffe6, 0xffe7, + 0xffe8, 0xffe9, 0xffea, 0xffeb, 0xffec, 0xffed, 0xffee, 0xffef, + 0xfff0, 0xfff1, 0xfff2, 0xfff3, 0xfff4, 0xfff5, 0xfff6, 0xfff7, + 0xfff8, 0xfff9, 0xfffa, 0xfffb, 0xfffc, 0xfffd, 0xfffe, 0xffff +}}; +static UnicodeCaseTableVector *caseTable[256] = { + &caseTable00, + &caseTable01, + &caseTable02, + &caseTable03, + &caseTable04, + &caseTable05, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + &caseTable10, + NULL, + NULL, + &caseTable13, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + &caseTable1c, + NULL, + &caseTable1e, + &caseTable1f, + NULL, + &caseTable21, + NULL, + NULL, + &caseTable24, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + &caseTable2c, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + &caseTablea6, + &caseTablea7, + NULL, + NULL, + NULL, + &caseTableab, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + &caseTableff +}; + +static Unicode bracketTable00[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0x80000029, 0x0028, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0x8000005d, 0, 0x005b, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0x8000007d, 0, 0x007b, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 +}; +static Unicode bracketTable0f[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0x80000f3b, 0x0f3a, 0x80000f3d, 0x0f3c, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 +}; +static Unicode bracketTable16[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0x8000169c, 0x169b, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 +}; +static Unicode bracketTable20[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0x80002046, 0x2045, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0x8000207e, 0x207d, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0x8000208e, 0x208d, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 +}; +static Unicode bracketTable23[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0x80002309, 0x2308, 0x8000230b, 0x230a, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0x8000232a, 0x2329, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 +}; +static Unicode bracketTable27[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0x80002769, 0x2768, 0x8000276b, 0x276a, 0x8000276d, 0x276c, 0x8000276f, 0x276e, + 0x80002771, 0x2770, 0x80002773, 0x2772, 0x80002775, 0x2774, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0x800027c6, 0x27c5, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0x800027e7, 0x27e6, + 0x800027e9, 0x27e8, 0x800027eb, 0x27ea, 0x800027ed, 0x27ec, 0x800027ef, 0x27ee, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 +}; +static Unicode bracketTable29[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0x80002984, 0x2983, 0x80002986, 0x2985, 0x80002988, + 0x2987, 0x8000298a, 0x2989, 0x8000298c, 0x298b, 0x80002990, 0x298f, 0x8000298e, + 0x298d, 0x80002992, 0x2991, 0x80002994, 0x2993, 0x80002996, 0x2995, 0x80002998, + 0x2997, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0x800029d9, 0x29d8, 0x800029db, 0x29da, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0x800029fd, 0x29fc, 0, 0 +}; +static Unicode bracketTable2e[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0x80002e23, 0x2e22, 0x80002e25, 0x2e24, 0x80002e27, 0x2e26, + 0x80002e29, 0x2e28, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 +}; +static Unicode bracketTable30[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0x80003009, 0x3008, 0x8000300b, 0x300a, 0x8000300d, 0x300c, 0x8000300f, 0x300e, + 0x80003011, 0x3010, 0, 0, 0x80003015, 0x3014, 0x80003017, 0x3016, + 0x80003019, 0x3018, 0x8000301b, 0x301a, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 +}; +static Unicode bracketTablefe[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0x8000fe5a, 0xfe59, 0x8000fe5c, 0xfe5b, 0x8000fe5e, 0xfe5d, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 +}; +static Unicode bracketTableff[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0x8000ff09, 0xff08, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0x8000ff3d, 0, 0xff3b, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0x8000ff5d, 0, 0xff5b, 0, 0x8000ff60, + 0xff5f, 0, 0x8000ff63, 0xff62, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 +}; +static Unicode *bracketTable[256] = { + bracketTable00, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + bracketTable0f, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + bracketTable16, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + bracketTable20, + NULL, + NULL, + bracketTable23, + NULL, + NULL, + NULL, + bracketTable27, + NULL, + bracketTable29, + NULL, + NULL, + NULL, + NULL, + bracketTable2e, + NULL, + bracketTable30, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + bracketTablefe, + bracketTableff +}; + +static inline char getType(Unicode c) { + int i; + char type; + + if (c > 0xffff) { + type = 'X'; + } else { + i = (c >> 8) & 0xff; + if ((type = typeTable[i].type) == 'X') { + type = typeTable[i].vector[c & 0xff]; + } + } + return type; +} + +GBool unicodeTypeL(Unicode c) { + return getType(c) == 'L'; +} + +GBool unicodeTypeR(Unicode c) { + return getType(c) == 'R'; +} + +GBool unicodeTypeDigit(Unicode c) { + return getType(c) == '#'; +} + +GBool unicodeTypeNumSep(Unicode c) { + return getType(c) == '.'; +} + +GBool unicodeTypeNum(Unicode c) { + char t; + + t = getType(c); + return t == '#' || t == '.'; +} + +GBool unicodeTypeAlphaNum(Unicode c) { + char t; + + t = getType(c); + return t == 'L' || t == 'R' || t == '#' || t == '.'; +} + +GBool unicodeTypeWord(Unicode c) { + char t; + + t = getType(c); + return t == 'L' || t == 'R' || t == '#'; +} + +Unicode unicodeToLower(Unicode c) { + int i; + + if (c > 0xffff) { + return c; + } + i = (c >> 8) & 0xff; + if (caseTable[i]) { + return caseTable[i]->codes[c & 0xff]; + } + return c; +} + +GBool unicodeBracketInfo(Unicode c, GBool *open, Unicode *opposite) { + int i; + Unicode bracket; + + if (c > 0xffff) { + return gFalse; + } + i = (c >> 8) & 0xff; + if (!bracketTable[i]) { + return gFalse; + } + bracket = bracketTable[i][c & 0xff]; + if (!bracket) { + return gFalse; + } + if (bracket & 0x80000000) { + *open = gTrue; + *opposite = bracket & 0x7fffffff; + } else { + *open = gFalse; + *opposite = bracket; + } + return gTrue; +} + diff --git a/xpdf/UnicodeTypeTable.h b/xpdf/UnicodeTypeTable.h new file mode 100644 index 0000000..e1149fd --- /dev/null +++ b/xpdf/UnicodeTypeTable.h @@ -0,0 +1,32 @@ +//======================================================================== +// +// UnicodeTypeTable.h +// +// Copyright 2003-2013 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef UNICODETYPETABLE_H +#define UNICODETYPETABLE_H + +#include "gtypes.h" + +extern GBool unicodeTypeL(Unicode c); + +extern GBool unicodeTypeR(Unicode c); + +extern GBool unicodeTypeDigit(Unicode c); + +extern GBool unicodeTypeNumSep(Unicode c); + +extern GBool unicodeTypeNum(Unicode c); + +extern GBool unicodeTypeAlphaNum(Unicode c); + +extern GBool unicodeTypeWord(Unicode c); + +extern Unicode unicodeToLower(Unicode c); + +extern GBool unicodeBracketInfo(Unicode c, GBool *open, Unicode *opposite); + +#endif diff --git a/xpdf/WebFont.cc b/xpdf/WebFont.cc new file mode 100644 index 0000000..c04b52f --- /dev/null +++ b/xpdf/WebFont.cc @@ -0,0 +1,408 @@ +//======================================================================== +// +// WebFont.cc +// +// Copyright 2019 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include "gmem.h" +#include "gmempp.h" +#include "GHash.h" +#include "FoFiTrueType.h" +#include "FoFiType1C.h" +#include "CharCodeToUnicode.h" +#include "WebFont.h" + +WebFont::WebFont(GfxFont *gfxFontA, XRef *xref) { + GfxFontType type; + Ref id; + + gfxFont = gfxFontA; + fontBuf = NULL; + ffTrueType = NULL; + ffType1C = NULL; + isOpenType = gFalse; + + if (gfxFont->getEmbeddedFontID(&id)) { + type = gfxFont->getType(); + if (type == fontTrueType || + type == fontTrueTypeOT || + type == fontCIDType2 || + type == fontCIDType2OT) { + if ((fontBuf = gfxFont->readEmbFontFile(xref, &fontLength))) { + ffTrueType = FoFiTrueType::make(fontBuf, fontLength, 0); + } + } else if (type == fontType1C || + type == fontCIDType0C) { + if ((fontBuf = gfxFont->readEmbFontFile(xref, &fontLength))) { + ffType1C = FoFiType1C::make(fontBuf, fontLength); + } + } else if (type == fontType1COT || + type == fontCIDType0COT) { + if ((fontBuf = gfxFont->readEmbFontFile(xref, &fontLength))) { + isOpenType = gTrue; + } + } + } +} + +WebFont::~WebFont() { + delete ffTrueType; + delete ffType1C; + gfree(fontBuf); +} + +GBool WebFont::canWriteTTF() { + return ffTrueType != NULL; +} + +GBool WebFont::canWriteOTF() { + return ffType1C || isOpenType; +} + +static void writeToFile(void *stream, const char *data, int len) { + fwrite(data, 1, len, (FILE *)stream); +} + +static void writeToString(void *stream, const char *data, int len) { + ((GString *)stream)->append(data, len); +} + +GBool WebFont::generateTTF(FoFiOutputFunc outFunc, void *stream) { + int *codeToGID; + Guchar *cmapTable; + GBool freeCodeToGID; + int nCodes, cmapTableLength; + + if (!ffTrueType) { + return gFalse; + } + if (gfxFont->isCIDFont()) { + codeToGID = ((GfxCIDFont *)gfxFont)->getCIDToGID(); + nCodes = ((GfxCIDFont *)gfxFont)->getCIDToGIDLen(); + if (!codeToGID) { + nCodes = ffTrueType->getNumGlyphs(); + } + freeCodeToGID = gFalse; + } else { + codeToGID = ((Gfx8BitFont *)gfxFont)->getCodeToGIDMap(ffTrueType); + nCodes = 256; + freeCodeToGID = gTrue; + } + cmapTable = makeUnicodeCmapTable(codeToGID, nCodes, &cmapTableLength); + if (freeCodeToGID) { + gfree(codeToGID); + } + if (!cmapTable) { + return gFalse; + } + ffTrueType->writeTTF(outFunc, stream, NULL, NULL, + cmapTable, cmapTableLength); + gfree(cmapTable); + return gTrue; +} + +GBool WebFont::writeTTF(const char *fontFilePath) { + FILE *out = fopen(fontFilePath, "wb"); + if (!out) { + return gFalse; + } + GBool ret = generateTTF(writeToFile, out); + fclose(out); + return ret; +} + +GString *WebFont::getTTFData() { + GString *s = new GString(); + if (!generateTTF(writeToString, s)) { + delete s; + return NULL; + } + return s; +} + +GBool WebFont::generateOTF(FoFiOutputFunc outFunc, void *stream) { + int *codeToGID; + Gushort *widths; + Guchar *cmapTable; + int nCodes, nWidths, cmapTableLength; + + if (ffType1C) { + if (gfxFont->getType() == fontType1C) { + codeToGID = ((Gfx8BitFont *)gfxFont)->getCodeToGIDMap(ffType1C); + if (!(cmapTable = makeUnicodeCmapTable(codeToGID, 256, + &cmapTableLength))) { + gfree(codeToGID); + return gFalse; + } + widths = makeType1CWidths(codeToGID, 256, &nWidths); + gfree(codeToGID); + } else { // fontCIDType0C + codeToGID = ffType1C->getCIDToGIDMap(&nCodes); + if (!(cmapTable = makeUnicodeCmapTable(codeToGID, nCodes, + &cmapTableLength))) { + gfree(codeToGID); + return gFalse; + } + widths = makeCIDType0CWidths(codeToGID, nCodes, &nWidths); + gfree(codeToGID); + } + ffType1C->convertToOpenType(outFunc, stream, nWidths, widths, + cmapTable, cmapTableLength); + gfree(cmapTable); + gfree(widths); + + } else if (isOpenType) { + outFunc(stream, fontBuf, fontLength); + + } else { + return gFalse; + } + + return gTrue; +} + +GBool WebFont::writeOTF(const char *fontFilePath) { + FILE *out = fopen(fontFilePath, "wb"); + if (!out) { + return gFalse; + } + GBool ret = generateOTF(writeToFile, out); + fclose(out); + return ret; +} + +GString *WebFont::getOTFData() { + GString *s = new GString(); + if (!generateOTF(writeToString, s)) { + delete s; + return NULL; + } + return s; +} + +Gushort *WebFont::makeType1CWidths(int *codeToGID, int nCodes, + int *nWidths) { + Gushort *widths; + Gushort width; + int widthsLen, gid, i; + + widthsLen = ffType1C->getNumGlyphs(); + widths = (Gushort *)gmallocn(widthsLen, sizeof(Gushort)); + for (i = 0; i < widthsLen; ++i) { + widths[i] = 0; + } + for (i = 0; i < nCodes; ++i) { + gid = codeToGID[i]; + if (gid < 0 || gid >= widthsLen) { + continue; + } + width = (Gushort)(((Gfx8BitFont *)gfxFont)->getWidth((Guchar)i) + * 1000 + 0.5); + if (width == 0) { + continue; + } + widths[gid] = width; + } + *nWidths = widthsLen; + return widths; +} + +Gushort *WebFont::makeCIDType0CWidths(int *codeToGID, int nCodes, + int *nWidths) { + Gushort *widths; + Gushort width; + int widthsLen, gid, i; + + widthsLen = ffType1C->getNumGlyphs(); + widths = (Gushort *)gmallocn(widthsLen, sizeof(Gushort)); + for (i = 0 ; i < widthsLen; ++i) { + widths[i] = 0; + } + for (i = 0; i < nCodes; ++i) { + gid = codeToGID[i]; + if (gid < 0 || gid >= widthsLen) { + continue; + } + width = (Gushort)(((GfxCIDFont *)gfxFont)->getWidth((CID)i) + * 1000 + 0.5); + if (width == 0) { + continue; + } + widths[gid] = width; + } + *nWidths = widthsLen; + return widths; +} + +Guchar *WebFont::makeUnicodeCmapTable(int *codeToGID, int nCodes, + int *unicodeCmapLength) { + int *unicodeToGID; + Guchar *cmapTable; + int unicodeToGIDLength, nMappings, len; + int nSegs, searchRange, entrySelector, rangeShift; + int glyphIdOffset, idRangeOffset; + int start, end, c, i; + + if (!(unicodeToGID = makeUnicodeToGID(codeToGID, nCodes, + &unicodeToGIDLength))) { + return NULL; + } + + // count the valid code-to-glyph mappings, and the sequences of + // consecutive valid mappings + // (note: char code 65535 is used to mark the end of table) + nMappings = 0; + nSegs = 1; // count the last segment, mapping 65535 + for (c = 0; c < unicodeToGIDLength && c <= 65534; ++c) { + if (unicodeToGID[c]) { + ++nMappings; + if (c == 0 || !unicodeToGID[c-1]) { + ++nSegs; + } + } + } + + i = 1; + entrySelector = 0; + while (2 * i <= nSegs) { + i *= 2; + ++entrySelector; + } + searchRange = 1 << (entrySelector + 1); + rangeShift = 2 * nSegs - searchRange; + + len = 28 + nSegs * 8 + nMappings * 2; + cmapTable = (Guchar *)gmalloc(len); + + // header + cmapTable[ 0] = 0x00; // table version + cmapTable[ 1] = 0x00; + cmapTable[ 2] = 0x00; // number of cmaps + cmapTable[ 3] = 0x01; + cmapTable[ 4] = 0x00; // platform[0] + cmapTable[ 5] = 0x03; + cmapTable[ 6] = 0x00; // encoding[0] + cmapTable[ 7] = 0x01; + cmapTable[ 8] = 0x00; // offset[0] + cmapTable[ 9] = 0x00; + cmapTable[10] = 0x00; + cmapTable[11] = 0x0c; + + // table info + cmapTable[12] = 0x00; // cmap format + cmapTable[13] = 0x04; + cmapTable[14] = (Guchar)((len - 12) >> 8); // cmap length + cmapTable[15] = (Guchar)(len - 12); + cmapTable[16] = 0x00; // cmap version + cmapTable[17] = 0x00; + cmapTable[18] = (Guchar)(nSegs >> 7); // segCountX2 + cmapTable[19] = (Guchar)(nSegs << 1); + cmapTable[20] = (Guchar)(searchRange >> 8); // searchRange + cmapTable[21] = (Guchar)searchRange; + cmapTable[22] = (Guchar)(entrySelector >> 8); // entrySelector + cmapTable[23] = (Guchar)entrySelector; + cmapTable[24] = (Guchar)(rangeShift >> 8); // rangeShift + cmapTable[25] = (Guchar)rangeShift; + cmapTable[26 + nSegs*2 ] = 0; // reservedPad + cmapTable[26 + nSegs*2 + 1] = 0; + + i = 0; + glyphIdOffset = 28 + nSegs*8; + for (c = 0; c < unicodeToGIDLength && c <= 65534; ++c) { + if (unicodeToGID[c]) { + if (c == 0 || !unicodeToGID[c-1]) { + start = c; + cmapTable[28 + nSegs*2 + i*2 ] = (Guchar)(start >> 8); + cmapTable[28 + nSegs*2 + i*2 + 1] = (Guchar)start; + cmapTable[28 + nSegs*4 + i*2 ] = (Guchar)0; // idDelta + cmapTable[28 + nSegs*4 + i*2 + 1] = (Guchar)0; + idRangeOffset = glyphIdOffset - (28 + nSegs*6 + i*2); + cmapTable[28 + nSegs*6 + i*2 ] = (Guchar)(idRangeOffset >> 8); + cmapTable[28 + nSegs*6 + i*2 + 1] = (Guchar)idRangeOffset; + } + if (c == 65534 || !unicodeToGID[c+1]) { + end = c; + cmapTable[26 + i*2 ] = (Guchar)(end >> 8); + cmapTable[26 + i*2 + 1] = (Guchar)end; + ++i; + } + cmapTable[glyphIdOffset++] = (Guchar)(unicodeToGID[c] >> 8); + cmapTable[glyphIdOffset++] = (Guchar)unicodeToGID[c]; + } + } + + // last segment maps code 65535 to GID 0 + cmapTable[26 + i*2 ] = (Guchar)0xff; // end + cmapTable[26 + i*2 + 1] = (Guchar)0xff; + cmapTable[28 + nSegs*2 + i*2 ] = (Guchar)0xff; // start + cmapTable[28 + nSegs*2 + i*2 + 1] = (Guchar)0xff; + cmapTable[28 + nSegs*4 + i*2 ] = (Guchar)0; // idDelta + cmapTable[28 + nSegs*4 + i*2 + 1] = (Guchar)1; + cmapTable[28 + nSegs*6 + i*2 ] = (Guchar)0; // idRangeOffset + cmapTable[28 + nSegs*6 + i*2 + 1] = (Guchar)0; + + gfree(unicodeToGID); + + *unicodeCmapLength = len; + return cmapTable; +} + +int *WebFont::makeUnicodeToGID(int *codeToGID, int nCodes, + int *unicodeToGIDLength) { + int *unicodeToGID; + CharCodeToUnicode *ctu; + Unicode u[2]; + int len, size, newSize, uLen, c, gid; + + if (gfxFont->isCIDFont()) { + if (!(ctu = ((GfxCIDFont *)gfxFont)->getToUnicode())) { + return NULL; + } + } else { + ctu = ((Gfx8BitFont *)gfxFont)->getToUnicode(); + } + + len = 0; + size = 256; + unicodeToGID = (int *)gmallocn(size, sizeof(int)); + memset(unicodeToGID, 0, size * sizeof(int)); + for (c = 0; c < nCodes; ++c) { + gid = codeToGID ? codeToGID[c] : c; + if (gid < 0 || gid >= 65536) { + continue; + } + uLen = ctu->mapToUnicode(c, u, 2); + if (uLen != 1) { + continue; + } + if (u[0] >= 65536) { // sanity check + continue; + } + if ((int)u[0] >= size) { + newSize = 2 * size; + while ((int)u[0] >= newSize) { + newSize *= 2; + } + unicodeToGID = (int *)greallocn(unicodeToGID, newSize, sizeof(int)); + memset(unicodeToGID + size, 0, (newSize - size) * sizeof(int)); + size = newSize; + } + unicodeToGID[u[0]] = gid; + if ((int)u[0] >= len) { + len = u[0] + 1; + } + } + + ctu->decRefCnt(); + + *unicodeToGIDLength = len; + return unicodeToGID; +} diff --git a/xpdf/WebFont.h b/xpdf/WebFont.h new file mode 100644 index 0000000..283bdbe --- /dev/null +++ b/xpdf/WebFont.h @@ -0,0 +1,80 @@ +//======================================================================== +// +// WebFont.h +// +// Modify/convert embedded PDF fonts to a form usable by web browsers. +// +// Copyright 2019 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef WEBFONT_H +#define WEBFONT_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "gtypes.h" +#include "FoFiBase.h" +#include "GfxFont.h" + +class FoFiTrueType; +class FoFiType1C; +class XRef; + +//------------------------------------------------------------------------ + +class WebFont { +public: + + WebFont(GfxFont *gfxFontA, XRef *xref); + + ~WebFont(); + + // Returns true if the font is, or can be converted to, a TrueType + // font. + GBool canWriteTTF(); + + // Returns true if the font is, or can be converted to, an OpenType + // font. + GBool canWriteOTF(); + + // Write a TrueType (.ttf) file to [fontFilePath]. This can only be + // called if canWriteTTF() returns true. Returns true on success. + GBool writeTTF(const char *fontFilePath); + + // Return the TrueType file as a string. This can only be called if + // canWriteTTF() returns true. Returns null on error. + GString *getTTFData(); + + // Write an OpenType (.otf) file to [fontFilePath]. This can only + // be called if canWriteOTF() returns true. Returns true on + // success. + GBool writeOTF(const char *fontFilePath); + + // Return the OpenType file as a string. This can only be called if + // canWriteOTF() returns true. Returns null on error. + GString *getOTFData(); + +private: + + GBool generateTTF(FoFiOutputFunc outFunc, void *stream); + GBool generateOTF(FoFiOutputFunc outFunc, void *stream); + Gushort *makeType1CWidths(int *codeToGID, int nCodes, int *nWidths); + Gushort *makeCIDType0CWidths(int *codeToGID, int nCodes, int *nWidths); + Guchar *makeUnicodeCmapTable(int *codeToGID, int nCodes, + int *unicodeCmapLength); + int *makeUnicodeToGID(int *codeToGID, int nCodes, int *unicodeToGIDLength); + + GfxFont *gfxFont; + char *fontBuf; + int fontLength; + FoFiTrueType *ffTrueType; + FoFiType1C *ffType1C; + GBool isOpenType; +}; + +#endif diff --git a/xpdf/XFAScanner.cc b/xpdf/XFAScanner.cc new file mode 100644 index 0000000..8002a07 --- /dev/null +++ b/xpdf/XFAScanner.cc @@ -0,0 +1,677 @@ +//======================================================================== +// +// XFAScanner.cc +// +// Copyright 2020 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include "GString.h" +#include "GHash.h" +#include "Object.h" +#include "Error.h" +#include "Zoox.h" +#include "XFAScanner.h" + +//------------------------------------------------------------------------ + +// fields have two names: +// +// name: +// - nodes with bind=global set the index to 0 ("foo[0]") regardless +// of the number of nodes with the same name +// - nodes with bind=none are dropped from the name +// - nodes are dropped from the name +// - used for field value lookup in +// +// fullName: +// - all named nodes are treated the same, regardless of bind=global +// or bind=none +// - nodes are included in the name, but don't reset the +// numbering (i.e., nodes are "transparent" with respect to +// node numbering) +// - used for field value lookup in
+// - used for matching with AcroForm names +// +// Both names use indexes on all nodes, even if there's only one node +// with the name -- this isn't correct for XFA naming, but it matches +// the AcroForm behavior. + +//------------------------------------------------------------------------ + +XFAFieldLayoutInfo::XFAFieldLayoutInfo(XFAFieldLayoutHAlign hAlignA, + XFAFieldLayoutVAlign vAlignA) { + hAlign = hAlignA; + vAlign = vAlignA; +} + +//------------------------------------------------------------------------ + +XFAFieldPictureInfo::XFAFieldPictureInfo(XFAFieldPictureSubtype subtypeA, + GString *formatA) { + subtype = subtypeA; + format = formatA; +} + +XFAFieldPictureInfo::~XFAFieldPictureInfo() { + delete format; +} + +//------------------------------------------------------------------------ + +XFAFieldBarcodeInfo::XFAFieldBarcodeInfo(GString *barcodeTypeA, + double wideNarrowRatioA, + double moduleWidthA, + double moduleHeightA, + int dataLengthA, + int errorCorrectionLevelA, + GString *textLocationA) { + barcodeType = barcodeTypeA; + wideNarrowRatio = wideNarrowRatioA; + moduleWidth = moduleWidthA; + moduleHeight = moduleHeightA; + dataLength = dataLengthA; + errorCorrectionLevel = errorCorrectionLevelA; + textLocation = textLocationA; +} + +XFAFieldBarcodeInfo::~XFAFieldBarcodeInfo() { + delete barcodeType; + delete textLocation; +} + +//------------------------------------------------------------------------ + +XFAField::XFAField(GString *nameA, GString *fullNameA, GString *valueA, + XFAFieldLayoutInfo *layoutInfoA, + XFAFieldPictureInfo *pictureInfoA, + XFAFieldBarcodeInfo *barcodeInfoA) + : name(nameA) + , fullName(fullNameA) + , value(valueA) + , layoutInfo(layoutInfoA) + , pictureInfo(pictureInfoA) + , barcodeInfo(barcodeInfoA) +{ +} + +XFAField::~XFAField() { + delete name; + delete fullName; + delete value; + delete layoutInfo; + delete pictureInfo; + delete barcodeInfo; +} + +//------------------------------------------------------------------------ + +XFAScanner *XFAScanner::load(Object *xfaObj) { + GString *xfaData = readXFAStreams(xfaObj); + if (!xfaData) { + return NULL; + } + ZxDoc *xml = ZxDoc::loadMem(xfaData->getCString(), xfaData->getLength()); + delete xfaData; + if (!xml) { + error(errSyntaxError, -1, "Invalid XML in XFA form"); + return NULL; + } + + XFAScanner *scanner = new XFAScanner(); + + if (xml->getRoot()) { + GHash *formValues = scanner->scanFormValues(xml->getRoot()); + ZxElement *dataElem = NULL; + ZxElement *datasets = + xml->getRoot()->findFirstChildElement("xfa:datasets"); + if (datasets) { + dataElem = datasets->findFirstChildElement("xfa:data"); + } + ZxElement *tmpl = xml->getRoot()->findFirstChildElement("template"); + if (tmpl) { + scanner->scanNode(tmpl, NULL, NULL, NULL, NULL, NULL, + dataElem, formValues); + } + deleteGHash(formValues, GString); + } + + delete xml; + + return scanner; +} + +XFAScanner::XFAScanner() { + fields = new GHash(); +} + +XFAScanner::~XFAScanner() { + deleteGHash(fields, XFAField); +} + +XFAField *XFAScanner::findField(GString *acroFormFieldName) { + return (XFAField *)fields->lookup(acroFormFieldName); +} + +GString *XFAScanner::readXFAStreams(Object *xfaObj) { + GString *data = new GString(); + char buf[4096]; + int n; + if (xfaObj->isStream()) { + xfaObj->streamReset(); + while ((n = xfaObj->getStream()->getBlock(buf, sizeof(buf))) > 0) { + data->append(buf, n); + } + } else if (xfaObj->isArray()) { + for (int i = 1; i < xfaObj->arrayGetLength(); i += 2) { + Object obj; + if (!xfaObj->arrayGet(i, &obj)->isStream()) { + error(errSyntaxError, -1, "XFA array element is wrong type"); + obj.free(); + delete data; + return NULL; + } + obj.streamReset(); + while ((n = obj.getStream()->getBlock(buf, sizeof(buf))) > 0) { + data->append(buf, n); + } + obj.free(); + } + } else { + error(errSyntaxError, -1, "XFA object is wrong type"); + return NULL; + } + return data; +} + +GHash *XFAScanner::scanFormValues(ZxElement *xmlRoot) { + GHash *formValues = new GHash(gTrue); + ZxElement *formElem = xmlRoot->findFirstChildElement("form"); + if (formElem) { + scanFormNode(formElem, NULL, formValues); + } + return formValues; +} + +void XFAScanner::scanFormNode(ZxElement *elem, GString *fullName, + GHash *formValues) { + GHash *fullNameIdx = new GHash(); + for (ZxNode *node = elem->getFirstChild(); + node; + node = node->getNextChild()) { + if (node->isElement("value")) { + if (fullName) { + ZxNode *child1Node = ((ZxElement *)node)->getFirstChild(); + if (child1Node && child1Node->isElement()) { + ZxNode *child2Node = ((ZxElement *)child1Node)->getFirstChild(); + if (child2Node && child2Node->isCharData()) { + formValues->add(fullName->copy(), + ((ZxCharData *)child2Node)->getData()->copy()); + } + } + } + } else if (node->isElement()) { + ZxAttr *nameAttr = ((ZxElement *)node)->findAttr("name"); + if (nameAttr && (node->isElement("subform") || + node->isElement("field"))) { + GString *nodeName = nameAttr->getValue(); + GString *childFullName; + if (fullName) { + childFullName = GString::format("{0:t}.{1:t}", fullName, nodeName); + } else { + childFullName = nodeName->copy(); + } + int idx = fullNameIdx->lookupInt(nodeName); + childFullName->appendf("[{0:d}]", idx); + fullNameIdx->replace(nodeName, idx + 1); + scanFormNode((ZxElement *)node, childFullName, formValues); + delete childFullName; + } else if (node->isElement("subform")) { + scanFormNode((ZxElement *)node, fullName, formValues); + } + } + } + delete fullNameIdx; +} + +void XFAScanner::scanNode(ZxElement *elem, + GString *parentName, GString *parentFullName, + GHash *nameIdx, GHash *fullNameIdx, + GString *exclGroupName, ZxElement *dataElem, + GHash *formValues) { + GString *nodeName = getNodeName(elem); + GHash *childNameIdx; + if (!nameIdx || nodeName) { + childNameIdx = new GHash(); + } else { + childNameIdx = nameIdx; + } + GString *nodeFullName = getNodeFullName(elem); + GHash *childFullNameIdx; + if (!fullNameIdx || (nodeFullName && !elem->isElement("area"))) { + childFullNameIdx = new GHash(); + } else { + childFullNameIdx = fullNameIdx; + } + + GString *childName; + if (nodeName) { + if (parentName) { + childName = GString::format("{0:t}.{1:t}", parentName, nodeName); + } else { + childName = nodeName->copy(); + } + int idx = nameIdx->lookupInt(nodeName); + nameIdx->replace(nodeName, idx + 1); + if (nodeIsBindGlobal(elem)) { + childName->appendf("[0]"); + } else { + childName->appendf("[{0:d}]", idx); + } + } else { + childName = parentName; + } + GString *childFullName; + if (nodeFullName) { + if (parentFullName) { + childFullName = GString::format("{0:t}.{1:t}", + parentFullName, nodeFullName); + } else { + childFullName = nodeFullName->copy(); + } + int idx = fullNameIdx->lookupInt(nodeFullName); + fullNameIdx->replace(nodeFullName, idx + 1); + childFullName->appendf("[{0:d}]", idx); + } else { + childFullName = parentFullName; + } + + if (elem->isElement("field")) { + if (childName && childFullName) { + scanField(elem, childName, childFullName, exclGroupName, + dataElem, formValues); + } + } else { + GString *childExclGroupName; + if (elem->isElement("exclGroup")) { + childExclGroupName = childName; + } else { + childExclGroupName = NULL; + } + for (ZxNode *child = elem->getFirstChild(); + child; + child = child->getNextChild()) { + if (child->isElement()) { + scanNode((ZxElement *)child, childName, childFullName, + childNameIdx, childFullNameIdx, childExclGroupName, + dataElem, formValues); + } + } + } + + if (childName != parentName) { + delete childName; + } + if (childFullName != parentFullName) { + delete childFullName; + } + if (childNameIdx != nameIdx) { + delete childNameIdx; + } + if (childFullNameIdx != fullNameIdx) { + delete childFullNameIdx; + } +} + +void XFAScanner::scanField(ZxElement *elem, GString *name, GString *fullName, + GString *exclGroupName, ZxElement *dataElem, + GHash *formValues) { + GString *value = getFieldValue(elem, name, fullName, exclGroupName, + dataElem, formValues); + XFAFieldLayoutInfo *layoutInfo = getFieldLayoutInfo(elem); + XFAFieldPictureInfo *pictureInfo = getFieldPictureInfo(elem); + XFAFieldBarcodeInfo *barcodeInfo = getFieldBarcodeInfo(elem); + XFAField *field = new XFAField(name->copy(), fullName->copy(), value, + layoutInfo, pictureInfo, barcodeInfo); + fields->add(field->fullName, field); +} + +GString *XFAScanner::getFieldValue(ZxElement *elem, GString *name, + GString *fullName, GString *exclGroupName, + ZxElement *dataElem, GHash *formValues) { + GString *val = NULL; + + //--- check the packet + val = getDatasetsValue(name->getCString(), dataElem); + if (!val && exclGroupName) { + val = (GString *)getDatasetsValue(exclGroupName->getCString(), dataElem); + } + + //--- check the element + if (!val) { + val = (GString *)formValues->lookup(fullName); + } + + //--- check the element within the field + if (!val) { + ZxElement *valueElem = elem->findFirstChildElement("value"); + if (valueElem) { + ZxNode *child1Node = valueElem->getFirstChild(); + if (child1Node && child1Node->isElement()) { + ZxNode *child2Node = ((ZxElement *)child1Node)->getFirstChild(); + if (child2Node && child2Node->isCharData()) { + val = ((ZxCharData *)child2Node)->getData(); + } + } + } + } + + //--- get the checkbutton item value + GString *checkbuttonItem = NULL; + ZxElement *uiElem = elem->findFirstChildElement("ui"); + if (uiElem) { + ZxNode *uiChild = uiElem->getFirstChild(); + if (uiChild && uiChild->isElement("checkButton")) { + ZxElement *itemsElem = elem->findFirstChildElement("items"); + if (itemsElem) { + ZxNode *node1 = itemsElem->getFirstChild(); + if (node1 && node1->isElement()) { + ZxNode *node2 = ((ZxElement *)node1)->getFirstChild(); + if (node2 && node2->isCharData()) { + checkbuttonItem = ((ZxCharData *)node2)->getData(); + } + } + } + } + } + // convert XFA checkbutton value to AcroForm-style On/Off value + if (checkbuttonItem && val) { + if (val->cmp(checkbuttonItem)) { + val = new GString("Off"); + } else { + val = new GString("On"); + } + } else if (val) { + val = val->copy(); + } + + return val; +} + +GString *XFAScanner::getDatasetsValue(char *partName, ZxElement *elem) { + if (!elem) { + return NULL; + } + + // partName = xxxx[nn].yyyy---- + char *p = strchr(partName, '['); + if (!p) { + return NULL; + } + int partLen = (int)(p - partName); + int idx = atoi(p + 1); + p = strchr(p + 1, '.'); + if (p) { + ++p; + } + + int curIdx = 0; + for (ZxNode *node = elem->getFirstChild(); + node; + node = node->getNextChild()) { + if (!node->isElement()) { + continue; + } + GString *nodeName = ((ZxElement *)node)->getType(); + if (nodeName->getLength() != partLen || + strncmp(nodeName->getCString(), partName, partLen)) { + continue; + } + if (curIdx != idx) { + ++curIdx; + continue; + } + if (p) { + GString *val = getDatasetsValue(p, (ZxElement *)node); + if (val) { + return val; + } + break; + } else { + ZxNode *child = ((ZxElement *)node)->getFirstChild(); + if (!child || !child->isCharData()) { + return NULL; + } + return ((ZxCharData *)child)->getData(); + } + } + + // search for an 'ancestor match' + if (p) { + return getDatasetsValue(p, elem); + } + + return NULL; +} + +XFAFieldLayoutInfo *XFAScanner::getFieldLayoutInfo(ZxElement *elem) { + ZxElement *paraElem = elem->findFirstChildElement("para"); + if (!paraElem) { + return NULL; + } + XFAFieldLayoutHAlign hAlign = xfaFieldLayoutHAlignLeft; + ZxAttr *hAlignAttr = paraElem->findAttr("hAlign"); + if (hAlignAttr) { + if (!hAlignAttr->getValue()->cmp("left")) { + hAlign = xfaFieldLayoutHAlignLeft; + } else if (!hAlignAttr->getValue()->cmp("center")) { + hAlign = xfaFieldLayoutHAlignCenter; + } else if (!hAlignAttr->getValue()->cmp("right")) { + hAlign = xfaFieldLayoutHAlignRight; + } + } + XFAFieldLayoutVAlign vAlign = xfaFieldLayoutVAlignTop; + ZxAttr *vAlignAttr = paraElem->findAttr("vAlign"); + if (vAlignAttr) { + if (!vAlignAttr->getValue()->cmp("top")) { + vAlign = xfaFieldLayoutVAlignTop; + } else if (!vAlignAttr->getValue()->cmp("middle")) { + vAlign = xfaFieldLayoutVAlignMiddle; + } else if (!vAlignAttr->getValue()->cmp("bottom")) { + vAlign = xfaFieldLayoutVAlignBottom; + } + } + return new XFAFieldLayoutInfo(hAlign, vAlign); +} + +XFAFieldPictureInfo *XFAScanner::getFieldPictureInfo(ZxElement *elem) { + ZxElement *uiElem = elem->findFirstChildElement("ui"); + if (!uiElem) { + return NULL; + } + XFAFieldPictureSubtype subtype; + if (uiElem->findFirstChildElement("dateTimeEdit")) { + subtype = xfaFieldPictureDateTime; + } else if (uiElem->findFirstChildElement("numericEdit")) { + subtype = xfaFieldPictureNumeric; + } else if (uiElem->findFirstChildElement("textEdit")) { + subtype = xfaFieldPictureText; + } else { + return NULL; + } + + ZxElement *formatElem, *pictureElem; + ZxNode *pictureChildNode; + if (!(formatElem = elem->findFirstChildElement("format")) || + !(pictureElem = formatElem->findFirstChildElement("picture")) || + !(pictureChildNode = pictureElem->getFirstChild()) || + !pictureChildNode->isCharData()) { + return NULL; + } + GString *format = ((ZxCharData *)pictureChildNode)->getData()->copy(); + + return new XFAFieldPictureInfo(subtype, format); +} + +XFAFieldBarcodeInfo *XFAScanner::getFieldBarcodeInfo(ZxElement *elem) { + ZxElement *uiElem, *barcodeElem; + if (!(uiElem = elem->findFirstChildElement("ui")) || + !(barcodeElem = uiElem->findFirstChildElement("barcode"))) { + return NULL; + } + + ZxAttr *attr; + if (!(attr = barcodeElem->findAttr("type"))) { + return NULL; + } + GString *barcodeType = attr->getValue()->copy(); + + double wideNarrowRatio = 3; + if ((attr = barcodeElem->findAttr("wideNarrowRatio"))) { + char *s = attr->getValue()->getCString(); + char *colon = strchr(s, ':'); + if (colon) { + GString *numStr = new GString(s, (int)(colon - s)); + double num = atof(numStr->getCString()); + delete numStr; + double den = atof(colon + 1); + if (den == 0) { + wideNarrowRatio = num; + } else { + wideNarrowRatio = num / den; + } + } else { + wideNarrowRatio = atof(s); + } + } + + double moduleWidth = (0.25 / 25.4) * 72.0; // 0.25mm + if ((attr = barcodeElem->findAttr("moduleWidth"))) { + moduleWidth = getMeasurement(attr->getValue()); + } + + double moduleHeight = (5.0 / 25.4) * 72.0; // 5mm + if ((attr = barcodeElem->findAttr("moduleHeight"))) { + moduleHeight = getMeasurement(attr->getValue()); + } + + int dataLength = 0; + if ((attr = barcodeElem->findAttr("dataLength"))) { + dataLength = atoi(attr->getValue()->getCString()); + } + + int errorCorrectionLevel = 0; + if ((attr = barcodeElem->findAttr("errorCorrectionLevel"))) { + errorCorrectionLevel = atoi(attr->getValue()->getCString()); + } + + GString *textLocation; + if ((attr = barcodeElem->findAttr("textLocation"))) { + textLocation = attr->getValue()->copy(); + } else { + textLocation = new GString("below"); + } + + return new XFAFieldBarcodeInfo(barcodeType, wideNarrowRatio, + moduleWidth, moduleHeight, dataLength, + errorCorrectionLevel, textLocation); +} + +double XFAScanner::getMeasurement(GString *s) { + int i = 0; + GBool neg = gFalse; + if (i < s->getLength() && s->getChar(i) == '+') { + ++i; + } else if (i < s->getLength() && s->getChar(i) == '-') { + neg = gTrue; + ++i; + } + double val = 0; + while (i < s->getLength() && s->getChar(i) >= '0' && s->getChar(i) <= '9') { + val = val * 10 + s->getChar(i) - '0'; + ++i; + } + if (i < s->getLength() && s->getChar(i) == '.') { + ++i; + double mul = 0.1; + while (i < s->getLength() && + s->getChar(i) >= '0' && s->getChar(i) <= '9') { + val += mul * (s->getChar(i) - '0'); + mul *= 0.1; + ++i; + } + } + if (neg) { + val = -val; + } + if (i+1 < s->getLength()) { + if (s->getChar(i) == 'i' && s->getChar(i+1) == 'n') { + val *= 72; + } else if (s->getChar(i) == 'p' && s->getChar(i+1) == 't') { + // no change + } else if (s->getChar(i) == 'c' && s->getChar(i+1) == 'm') { + val *= 72 / 2.54; + } else if (s->getChar(i) == 'm' && s->getChar(i+1) == 'm') { + val *= 72 / 25.4; + } else { + // default to inches + val *= 72; + } + } else { + // default to inches + val *= 72; + } + return val; +} + +GString *XFAScanner::getNodeName(ZxElement *elem) { + if (elem->isElement("template") || + elem->isElement("area") || + elem->isElement("draw")) { + return NULL; + } + if (!elem->isElement("field") && nodeIsBindNone(elem)) { + return NULL; + } + ZxAttr *nameAttr = elem->findAttr("name"); + if (!nameAttr) { + return NULL; + } + return nameAttr->getValue(); +} + +GString *XFAScanner::getNodeFullName(ZxElement *elem) { + if (elem->isElement("template") || + elem->isElement("draw")) { + return NULL; + } + ZxAttr *nameAttr = elem->findAttr("name"); + if (!nameAttr) { + return NULL; + } + return nameAttr->getValue(); +} + +GBool XFAScanner::nodeIsBindGlobal(ZxElement *elem) { + ZxElement *bindElem = elem->findFirstChildElement("bind"); + if (!bindElem) { + return gFalse; + } + ZxAttr *attr = bindElem->findAttr("match"); + return attr && !attr->getValue()->cmp("global"); +} + +GBool XFAScanner::nodeIsBindNone(ZxElement *elem) { + ZxElement *bindElem = elem->findFirstChildElement("bind"); + if (!bindElem) { + return gFalse; + } + ZxAttr *attr = bindElem->findAttr("match"); + return attr && !attr->getValue()->cmp("none"); +} diff --git a/xpdf/XFAScanner.h b/xpdf/XFAScanner.h new file mode 100644 index 0000000..00ee6f7 --- /dev/null +++ b/xpdf/XFAScanner.h @@ -0,0 +1,166 @@ +//======================================================================== +// +// XFAScanner.h +// +// Copyright 2020 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef XFASCANNER_H +#define XFASCANNER_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +class GHash; +class ZxElement; + +//------------------------------------------------------------------------ + +enum XFAFieldLayoutHAlign { + xfaFieldLayoutHAlignLeft, + xfaFieldLayoutHAlignCenter, + xfaFieldLayoutHAlignRight +}; + +enum XFAFieldLayoutVAlign { + xfaFieldLayoutVAlignTop, + xfaFieldLayoutVAlignMiddle, + xfaFieldLayoutVAlignBottom +}; + +class XFAFieldLayoutInfo { +public: + + XFAFieldLayoutInfo(XFAFieldLayoutHAlign hAlignA, + XFAFieldLayoutVAlign vAlignA); + + XFAFieldLayoutHAlign hAlign; + XFAFieldLayoutVAlign vAlign; +}; + +//------------------------------------------------------------------------ + +enum XFAFieldPictureSubtype { + xfaFieldPictureDateTime, + xfaFieldPictureNumeric, + xfaFieldPictureText +}; + +class XFAFieldPictureInfo { +public: + + XFAFieldPictureInfo(XFAFieldPictureSubtype subtypeA, GString *formatA); + ~XFAFieldPictureInfo(); + + XFAFieldPictureSubtype subtype; + GString *format; // picture format string +}; + +//------------------------------------------------------------------------ + +class XFAFieldBarcodeInfo { +public: + + XFAFieldBarcodeInfo(GString *barcodeTypeA, double wideNarrowRatioA, + double moduleWidthA, double moduleHeightA, + int dataLengthA, int errorCorrectionLevelA, + GString *textLocationA); + ~XFAFieldBarcodeInfo(); + + GString *barcodeType; + double wideNarrowRatio; + double moduleWidth; + double moduleHeight; + int dataLength; + int errorCorrectionLevel; + GString *textLocation; +}; + +//------------------------------------------------------------------------ + +class XFAField { +public: + + XFAField(GString *nameA, GString *fullNameA, GString *valueA, + XFAFieldLayoutInfo *layoutInfoA, + XFAFieldPictureInfo *pictureInfoA, + XFAFieldBarcodeInfo *barcodeInfoA); + ~XFAField(); + + // Get the field's value, or NULL if it doesn't have a value. Sets + // *[length] to the length of the Unicode string. + GString *getValue() { return value; } + + // Return a pointer to the field's picture formatting info object, + // or NULL if the field doesn't have picture formatting. + XFAFieldPictureInfo *getPictureInfo() { return pictureInfo; } + + // Return a pointer to the field's layout info object, or NULL if + // the field doesn't have layout info. + XFAFieldLayoutInfo *getLayoutInfo() { return layoutInfo; } + + // Return a pointer to the field's barcode info object, or NULL if + // the field isn't a barcode. + XFAFieldBarcodeInfo *getBarcodeInfo() { return barcodeInfo; } + +private: + + friend class XFAScanner; + + GString *name; // UTF-8 + GString *fullName; // UTF-8 + GString *value; // UTF-8 + XFAFieldLayoutInfo *layoutInfo; + XFAFieldPictureInfo *pictureInfo; + XFAFieldBarcodeInfo *barcodeInfo; +}; + +//------------------------------------------------------------------------ + +class XFAScanner { +public: + + static XFAScanner *load(Object *xfaObj); + + virtual ~XFAScanner(); + + // Find an XFA field matchined the specified AcroForm field name. + // Returns NULL if there is no matching field. + XFAField *findField(GString *acroFormFieldName); + +private: + + XFAScanner(); + static GString *readXFAStreams(Object *xfaObj); + GHash *scanFormValues(ZxElement *xmlRoot); + void scanFormNode(ZxElement *elem, GString *fullName, + GHash *formValues); + void scanNode(ZxElement *elem, + GString *parentName, GString *parentFullName, + GHash *nameIdx, GHash *fullNameIdx, + GString *exclGroupName, ZxElement *xmlRoot, + GHash *formValues); + void scanField(ZxElement *elem, GString *name, GString *fullName, + GString *exclGroupName, ZxElement *xmlRoot, + GHash *formValues); + GString *getFieldValue(ZxElement *elem, GString *name, + GString *fullName, GString *exclGroupName, + ZxElement *xmlRoot, GHash *formValues); + GString *getDatasetsValue(char *partName, ZxElement *elem); + XFAFieldLayoutInfo *getFieldLayoutInfo(ZxElement *elem); + XFAFieldPictureInfo *getFieldPictureInfo(ZxElement *elem); + XFAFieldBarcodeInfo *getFieldBarcodeInfo(ZxElement *elem); + double getMeasurement(GString *s); + GString *getNodeName(ZxElement *elem); + GString *getNodeFullName(ZxElement *elem); + GBool nodeIsBindGlobal(ZxElement *elem); + GBool nodeIsBindNone(ZxElement *elem); + + GHash *fields; // [XFAField] +}; + +#endif diff --git a/xpdf/XRef.cc b/xpdf/XRef.cc new file mode 100644 index 0000000..51af86d --- /dev/null +++ b/xpdf/XRef.cc @@ -0,0 +1,1431 @@ +//======================================================================== +// +// XRef.cc +// +// Copyright 1996-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include +#include +#include +#include +#include "gmem.h" +#include "gmempp.h" +#include "gfile.h" +#include "Object.h" +#include "Stream.h" +#include "Lexer.h" +#include "Parser.h" +#include "Dict.h" +#include "Error.h" +#include "ErrorCodes.h" +#include "XRef.h" + +//------------------------------------------------------------------------ + +#define xrefSearchSize 1024 // read this many bytes at end of file + // to look for 'startxref' + +//------------------------------------------------------------------------ +// Permission bits +//------------------------------------------------------------------------ + +#define permPrint (1<<2) +#define permChange (1<<3) +#define permCopy (1<<4) +#define permNotes (1<<5) +#define defPermFlags 0xfffc + +//------------------------------------------------------------------------ +// XRefPosSet +//------------------------------------------------------------------------ + +class XRefPosSet { +public: + + XRefPosSet(); + ~XRefPosSet(); + void add(GFileOffset pos); + GBool check(GFileOffset pos); + int getLength() { return len; } + GFileOffset get(int idx) { return tab[idx]; } + +private: + + int find(GFileOffset pos); + + GFileOffset *tab; + int size; + int len; +}; + +XRefPosSet::XRefPosSet() { + size = 16; + len = 0; + tab = (GFileOffset *)gmallocn(size, sizeof(GFileOffset)); +} + +XRefPosSet::~XRefPosSet() { + gfree(tab); +} + +void XRefPosSet::add(GFileOffset pos) { + int i; + + i = find(pos); + if (i < len && tab[i] == pos) { + return; + } + if (len == size) { + if (size > INT_MAX / 2) { + gMemError("Integer overflow in XRefPosSet::add()"); + } + size *= 2; + tab = (GFileOffset *)greallocn(tab, size, sizeof(GFileOffset)); + } + if (i < len) { + memmove(&tab[i + 1], &tab[i], (len - i) * sizeof(GFileOffset)); + } + tab[i] = pos; + ++len; +} + +GBool XRefPosSet::check(GFileOffset pos) { + int i; + + i = find(pos); + return i < len && tab[i] == pos; +} + +int XRefPosSet::find(GFileOffset pos) { + int a, b, m; + + a = - 1; + b = len; + // invariant: tab[a] < pos < tab[b] + while (b - a > 1) { + m = (a + b) / 2; + if (tab[m] < pos) { + a = m; + } else if (tab[m] > pos) { + b = m; + } else { + return m; + } + } + return b; +} + +//------------------------------------------------------------------------ +// ObjectStream +//------------------------------------------------------------------------ + +class ObjectStream { +public: + + // Create an object stream, using object number , + // generation 0. + ObjectStream(XRef *xref, int objStrNumA); + + GBool isOk() { return ok; } + + ~ObjectStream(); + + // Return the object number of this object stream. + int getObjStrNum() { return objStrNum; } + + // Get the th object from this stream, which should be + // object number , generation 0. + Object *getObject(int objIdx, int objNum, Object *obj); + +private: + + int objStrNum; // object number of the object stream + 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) { + Stream *str; + Lexer *lexer; + Parser *parser; + int *offsets; + Object objStr, obj1, obj2; + int first, i; + + objStrNum = objStrNumA; + nObjects = 0; + objs = NULL; + objNums = NULL; + ok = gFalse; + + if (!xref->fetch(objStrNum, 0, &objStr)->isStream()) { + goto err1; + } + + if (!objStr.streamGetDict()->lookup("N", &obj1)->isInt()) { + obj1.free(); + goto err1; + } + nObjects = obj1.getInt(); + obj1.free(); + if (nObjects <= 0) { + goto err1; + } + + if (!objStr.streamGetDict()->lookup("First", &obj1)->isInt()) { + obj1.free(); + goto err1; + } + first = obj1.getInt(); + obj1.free(); + if (first < 0) { + 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)); + + // parse the header: object numbers and offsets + objStr.streamReset(); + obj1.initNull(); + str = new EmbedStream(objStr.getStream(), &obj1, gTrue, first); + lexer = new Lexer(xref, str); + parser = new Parser(xref, lexer, gFalse); + for (i = 0; i < nObjects; ++i) { + parser->getObj(&obj1, gTrue); + parser->getObj(&obj2, gTrue); + if (!obj1.isInt() || !obj2.isInt()) { + obj1.free(); + obj2.free(); + delete parser; + gfree(offsets); + goto err2; + } + objNums[i] = obj1.getInt(); + offsets[i] = obj2.getInt(); + obj1.free(); + obj2.free(); + if (objNums[i] < 0 || offsets[i] < 0 || + (i > 0 && offsets[i] < offsets[i-1])) { + delete parser; + gfree(offsets); + goto err2; + } + } + lexer->skipToEOF(); + delete parser; + + // skip to the first object - this shouldn't be necessary because + // the First key is supposed to be equal to offsets[0], but just in + // case... + if (first < offsets[0]) { + objStr.getStream()->discardChars(offsets[0] - first); + } + + // parse the objects + for (i = 0; i < nObjects; ++i) { + obj1.initNull(); + if (i == nObjects - 1) { + str = new EmbedStream(objStr.getStream(), &obj1, gFalse, 0); + } else { + str = new EmbedStream(objStr.getStream(), &obj1, gTrue, + offsets[i+1] - offsets[i]); + } + lexer = new Lexer(xref, str); + parser = new Parser(xref, lexer, gFalse); + parser->getObj(&objs[i]); + lexer->skipToEOF(); + delete parser; + } + + gfree(offsets); + ok = gTrue; + + err2: + objStr.streamClose(); + err1: + objStr.free(); +} + +ObjectStream::~ObjectStream() { + int i; + + if (objs) { + for (i = 0; i < nObjects; ++i) { + objs[i].free(); + } + delete[] objs; + } + gfree(objNums); +} + +Object *ObjectStream::getObject(int objIdx, int objNum, Object *obj) { + if (objIdx < 0 || objIdx >= nObjects || objNum != objNums[objIdx]) { + obj->initNull(); + } else { + objs[objIdx].copy(obj); + } + return obj; +} + +//------------------------------------------------------------------------ +// XRef +//------------------------------------------------------------------------ + +XRef::XRef(BaseStream *strA, GBool repair) { + GFileOffset pos; + Object obj; + XRefPosSet *posSet; + int i; + + ok = gTrue; + errCode = errNone; + repaired = gFalse; + size = 0; + last = -1; + entries = NULL; + lastStartxrefPos = 0; + xrefTablePos = NULL; + xrefTablePosLen = 0; + streamEnds = NULL; + streamEndsLen = 0; + for (i = 0; i < objStrCacheSize; ++i) { + objStrs[i] = NULL; + objStrLastUse[i] = 0; + } + objStrCacheLength = 0; + objStrTime = 0; + + encrypted = gFalse; + permFlags = defPermFlags; + ownerPasswordOk = gFalse; + + for (i = 0; i < xrefCacheSize; ++i) { + cache[i].num = -1; + } + +#if MULTITHREADED + gInitMutex(&objStrsMutex); + gInitMutex(&cacheMutex); +#endif + + str = strA; + start = str->getStart(); + + // if the 'repair' flag is set, try to reconstruct the xref table + if (repair) { + if (!(ok = constructXRef())) { + errCode = errDamaged; + return; + } + repaired = gTrue; + + // if the 'repair' flag is not set, read the xref table + } else { + + // read the trailer + pos = getStartXref(); + if (pos == 0) { + errCode = errDamaged; + ok = gFalse; + return; + } + + // read the xref table + posSet = new XRefPosSet(); + while (readXRef(&pos, posSet, gFalse)) ; + xrefTablePosLen = posSet->getLength(); + xrefTablePos = (GFileOffset *)gmallocn(xrefTablePosLen, + sizeof(GFileOffset)); + for (i = 0; i < xrefTablePosLen; ++i) { + xrefTablePos[i] = posSet->get(i); + } + delete posSet; + if (!ok) { + errCode = errDamaged; + return; + } + } + + // get the root dictionary (catalog) object + trailerDict.dictLookupNF("Root", &obj); + if (obj.isRef()) { + rootNum = obj.getRefNum(); + rootGen = obj.getRefGen(); + obj.free(); + } else { + obj.free(); + if (!(ok = constructXRef())) { + errCode = errDamaged; + return; + } + } + + // now set the trailer dictionary's xref pointer so we can fetch + // indirect objects from it + trailerDict.getDict()->setXRef(this); +} + +XRef::~XRef() { + int i; + + for (i = 0; i < xrefCacheSize; ++i) { + if (cache[i].num >= 0) { + cache[i].obj.free(); + } + } + gfree(entries); + trailerDict.free(); + if (xrefTablePos) { + gfree(xrefTablePos); + } + if (streamEnds) { + gfree(streamEnds); + } + for (i = 0; i < objStrCacheSize; ++i) { + if (objStrs[i]) { + delete objStrs[i]; + } + } +#if MULTITHREADED + gDestroyMutex(&objStrsMutex); + gDestroyMutex(&cacheMutex); +#endif +} + +// Read the 'startxref' position. +GFileOffset XRef::getStartXref() { + char buf[xrefSearchSize+1]; + char *p; + int n, i; + + // read last xrefSearchSize bytes + str->setPos(xrefSearchSize, -1); + n = str->getBlock(buf, xrefSearchSize); + buf[n] = '\0'; + + // find startxref + for (i = n - 9; i >= 0; --i) { + if (!strncmp(&buf[i], "startxref", 9)) { + break; + } + } + if (i < 0) { + return 0; + } + for (p = &buf[i+9]; isspace(*p & 0xff); ++p) ; + lastXRefPos = strToFileOffset(p); + lastStartxrefPos = str->getPos() - n + i; + + return lastXRefPos; +} + +// Read one xref table section. Also reads the associated trailer +// dictionary, and returns the prev pointer (if any). The [hybrid] +// flag is true when following the XRefStm link in a hybrid-reference +// file. +GBool XRef::readXRef(GFileOffset *pos, XRefPosSet *posSet, GBool hybrid) { + Parser *parser; + Object obj; + GBool more; + char buf[100]; + int n, i; + + // check for a loop in the xref tables + if (posSet->check(*pos)) { + error(errSyntaxWarning, -1, "Infinite loop in xref table"); + return gFalse; + } + posSet->add(*pos); + + // the xref data should either be "xref ..." (for an xref table) or + // "nn gg obj << ... >> stream ..." (for an xref stream); possibly + // preceded by whitespace + str->setPos(start + *pos); + n = str->getBlock(buf, 100); + for (i = 0; i < n && Lexer::isSpace(buf[i]); ++i) ; + + // parse an old-style xref table + if (!hybrid && + i + 4 < n && + buf[i] == 'x' && buf[i+1] == 'r' && buf[i+2] == 'e' && buf[i+3] == 'f' && + Lexer::isSpace(buf[i+4])) { + more = readXRefTable(pos, i + 5, posSet); + + // parse an xref stream + } else { + obj.initNull(); + parser = new Parser(NULL, + new Lexer(NULL, + str->makeSubStream(start + *pos, gFalse, 0, &obj)), + gTrue); + if (!parser->getObj(&obj, gTrue)->isInt()) { + goto err; + } + obj.free(); + if (!parser->getObj(&obj, gTrue)->isInt()) { + goto err; + } + obj.free(); + if (!parser->getObj(&obj, gTrue)->isCmd("obj")) { + goto err; + } + obj.free(); + if (!parser->getObj(&obj)->isStream()) { + goto err; + } + more = readXRefStream(obj.getStream(), pos, hybrid); + obj.free(); + delete parser; + } + + return more; + + err: + obj.free(); + delete parser; + ok = gFalse; + return gFalse; +} + +GBool XRef::readXRefTable(GFileOffset *pos, int offset, XRefPosSet *posSet) { + XRefEntry entry; + Parser *parser; + Object obj, obj2; + char buf[6]; + GFileOffset off, pos2; + GBool more; + int first, n, digit, newSize, gen, i, c; + + str->setPos(start + *pos + offset); + + while (1) { + do { + c = str->getChar(); + } while (Lexer::isSpace(c)); + if (c == 't') { + if (str->getBlock(buf, 6) != 6 || memcmp(buf, "railer", 6)) { + goto err1; + } + break; + } + if (c < '0' || c > '9') { + goto err1; + } + first = 0; + do { + digit = c - '0'; + if (first > (INT_MAX - digit) / 10) { + goto err1; + } + first = (first * 10) + digit; + c = str->getChar(); + } while (c >= '0' && c <= '9'); + if (!Lexer::isSpace(c)) { + goto err1; + } + do { + c = str->getChar(); + } while (Lexer::isSpace(c)); + n = 0; + do { + digit = c - '0'; + if (n > (INT_MAX - digit) / 10) { + goto err1; + } + n = (n * 10) + digit; + c = str->getChar(); + } while (c >= '0' && c <= '9'); + if (!Lexer::isSpace(c)) { + goto err1; + } + if (first > INT_MAX - n) { + goto err1; + } + if (first + n > size) { + for (newSize = size ? 2 * size : 1024; + first + n > newSize && newSize > 0; + newSize <<= 1) ; + if (newSize < 0) { + goto err1; + } + entries = (XRefEntry *)greallocn(entries, newSize, sizeof(XRefEntry)); + for (i = size; i < newSize; ++i) { + entries[i].offset = (GFileOffset)-1; + entries[i].type = xrefEntryFree; + } + size = newSize; + } + for (i = first; i < first + n; ++i) { + do { + c = str->getChar(); + } while (Lexer::isSpace(c)); + off = 0; + do { + off = (off * 10) + (c - '0'); + c = str->getChar(); + } while (c >= '0' && c <= '9'); + if (!Lexer::isSpace(c)) { + goto err1; + } + entry.offset = off; + do { + c = str->getChar(); + } while (Lexer::isSpace(c)); + gen = 0; + do { + gen = (gen * 10) + (c - '0'); + c = str->getChar(); + } while (c >= '0' && c <= '9'); + if (!Lexer::isSpace(c)) { + goto err1; + } + entry.gen = gen; + do { + c = str->getChar(); + } while (Lexer::isSpace(c)); + if (c == 'n') { + entry.type = xrefEntryUncompressed; + } else if (c == 'f') { + entry.type = xrefEntryFree; + } else { + goto err1; + } + c = str->getChar(); + if (!Lexer::isSpace(c)) { + goto err1; + } + if (entries[i].offset == (GFileOffset)-1) { + entries[i] = entry; + // PDF files of patents from the IBM Intellectual Property + // Network have a bug: the xref table claims to start at 1 + // instead of 0. + if (i == 1 && first == 1 && + entries[1].offset == 0 && entries[1].gen == 65535 && + entries[1].type == xrefEntryFree) { + i = first = 0; + entries[0] = entries[1]; + entries[1].offset = (GFileOffset)-1; + } + if (i > last) { + last = i; + } + } + } + } + + // read the trailer dictionary + obj.initNull(); + parser = new Parser(NULL, + new Lexer(NULL, + str->makeSubStream(str->getPos(), gFalse, 0, &obj)), + gTrue); + parser->getObj(&obj); + delete parser; + if (!obj.isDict()) { + obj.free(); + goto err1; + } + + // get the 'Prev' pointer + //~ this can be a 64-bit int (?) + obj.getDict()->lookupNF("Prev", &obj2); + if (obj2.isInt()) { + *pos = (GFileOffset)(Guint)obj2.getInt(); + more = gTrue; + } else if (obj2.isRef()) { + // certain buggy PDF generators generate "/Prev NNN 0 R" instead + // of "/Prev NNN" + *pos = (GFileOffset)(Guint)obj2.getRefNum(); + more = gTrue; + } else { + more = gFalse; + } + obj2.free(); + + // save the first trailer dictionary + if (trailerDict.isNone()) { + obj.copy(&trailerDict); + } + + // check for an 'XRefStm' key + //~ this can be a 64-bit int (?) + if (obj.getDict()->lookup("XRefStm", &obj2)->isInt()) { + pos2 = (GFileOffset)(Guint)obj2.getInt(); + readXRef(&pos2, posSet, gTrue); + if (!ok) { + obj2.free(); + obj.free(); + goto err1; + } + } + obj2.free(); + + obj.free(); + return more; + + err1: + ok = gFalse; + return gFalse; +} + +GBool XRef::readXRefStream(Stream *xrefStr, GFileOffset *pos, GBool hybrid) { + Dict *dict; + int w[3]; + GBool more; + Object obj, obj2, idx; + int newSize, first, n, i; + + dict = xrefStr->getDict(); + + if (!dict->lookupNF("Size", &obj)->isInt()) { + goto err1; + } + newSize = obj.getInt(); + obj.free(); + if (newSize < 0) { + goto err1; + } + if (newSize > size) { + entries = (XRefEntry *)greallocn(entries, newSize, sizeof(XRefEntry)); + for (i = size; i < newSize; ++i) { + entries[i].offset = (GFileOffset)-1; + entries[i].type = xrefEntryFree; + } + size = newSize; + } + + if (!dict->lookupNF("W", &obj)->isArray() || + obj.arrayGetLength() < 3) { + goto err1; + } + for (i = 0; i < 3; ++i) { + if (!obj.arrayGet(i, &obj2)->isInt()) { + obj2.free(); + goto err1; + } + w[i] = obj2.getInt(); + obj2.free(); + } + obj.free(); + if (w[0] < 0 || w[0] > 8 || + w[1] < 0 || w[1] > 8 || + w[2] < 0 || w[2] > 8) { + goto err0; + } + + xrefStr->reset(); + dict->lookupNF("Index", &idx); + if (idx.isArray()) { + for (i = 0; i+1 < idx.arrayGetLength(); i += 2) { + if (!idx.arrayGet(i, &obj)->isInt()) { + idx.free(); + goto err1; + } + first = obj.getInt(); + obj.free(); + if (!idx.arrayGet(i+1, &obj)->isInt()) { + idx.free(); + goto err1; + } + n = obj.getInt(); + obj.free(); + if (first < 0 || n < 0 || + !readXRefStreamSection(xrefStr, w, first, n)) { + idx.free(); + goto err0; + } + } + } else { + if (!readXRefStreamSection(xrefStr, w, 0, newSize)) { + idx.free(); + goto err0; + } + } + idx.free(); + + //~ this can be a 64-bit int (?) + dict->lookupNF("Prev", &obj); + if (obj.isInt()) { + *pos = (GFileOffset)(Guint)obj.getInt(); + more = gTrue; + } else { + more = gFalse; + } + obj.free(); + if (trailerDict.isNone()) { + trailerDict.initDict(dict); + } + + return more; + + err1: + obj.free(); + err0: + ok = gFalse; + return gFalse; +} + +GBool XRef::readXRefStreamSection(Stream *xrefStr, int *w, int first, int n) { + long long type, gen, offset; + int c, newSize, i, j; + + if (first + n < 0) { + return gFalse; + } + if (first + n > size) { + for (newSize = size ? 2 * size : 1024; + first + n > newSize && newSize > 0; + newSize <<= 1) ; + if (newSize < 0) { + return gFalse; + } + entries = (XRefEntry *)greallocn(entries, newSize, sizeof(XRefEntry)); + for (i = size; i < newSize; ++i) { + entries[i].offset = (GFileOffset)-1; + entries[i].type = xrefEntryFree; + } + size = newSize; + } + for (i = first; i < first + n; ++i) { + if (w[0] == 0) { + type = 1; + } else { + for (type = 0, j = 0; j < w[0]; ++j) { + if ((c = xrefStr->getChar()) == EOF) { + return gFalse; + } + type = (type << 8) + c; + } + } + for (offset = 0, j = 0; j < w[1]; ++j) { + if ((c = xrefStr->getChar()) == EOF) { + return gFalse; + } + offset = (offset << 8) + c; + } + if (offset < 0 || offset > GFILEOFFSET_MAX) { + return gFalse; + } + for (gen = 0, j = 0; j < w[2]; ++j) { + if ((c = xrefStr->getChar()) == EOF) { + return gFalse; + } + gen = (gen << 8) + c; + } + // some PDF generators include a free entry with gen=0xffffffff + if ((gen < 0 || gen > INT_MAX) && type != 0) { + return gFalse; + } + if (entries[i].offset == (GFileOffset)-1) { + switch (type) { + case 0: + entries[i].offset = (GFileOffset)offset; + entries[i].gen = (int)gen; + entries[i].type = xrefEntryFree; + break; + case 1: + entries[i].offset = (GFileOffset)offset; + entries[i].gen = (int)gen; + entries[i].type = xrefEntryUncompressed; + break; + case 2: + entries[i].offset = (GFileOffset)offset; + entries[i].gen = (int)gen; + entries[i].type = xrefEntryCompressed; + break; + default: + return gFalse; + } + if (i > last) { + last = i; + } + } + } + + return gTrue; +} + +// Attempt to construct an xref table for a damaged file. +GBool XRef::constructXRef() { + int *streamObjNums = NULL; + int streamObjNumsLen = 0; + int streamObjNumsSize = 0; + int lastObjNum = -1; + rootNum = -1; + int streamEndsSize = 0; + streamEndsLen = 0; + char buf[4096 + 1]; + str->reset(); + GFileOffset bufPos = start; + char *p = buf; + char *end = buf; + GBool startOfLine = gTrue; + GBool eof = gFalse; + while (1) { + if (end - p < 256 && !eof) { + memcpy(buf, p, end - p); + bufPos += p - buf; + p = buf + (end - p); + int n = (int)(buf + 4096 - p); + int m = str->getBlock(p, n); + end = p + m; + *end = '\0'; + p = buf; + eof = m < n; + } + if (p == end && eof) { + break; + } + if (startOfLine && !strncmp(p, "trailer", 7)) { + constructTrailerDict((GFileOffset)(bufPos + (p + 7 - buf))); + p += 7; + startOfLine = gFalse; + } else if (startOfLine && !strncmp(p, "endstream", 9)) { + if (streamEndsLen == streamEndsSize) { + streamEndsSize += 64; + streamEnds = (GFileOffset *)greallocn(streamEnds, streamEndsSize, + sizeof(GFileOffset)); + } + streamEnds[streamEndsLen++] = (GFileOffset)(bufPos + (p - buf)); + p += 9; + startOfLine = gFalse; + } else if (startOfLine && *p >= '0' && *p <= '9') { + p = constructObjectEntry(p, (GFileOffset)(bufPos + (p - buf)), + &lastObjNum); + startOfLine = gFalse; + } else if (p[0] == '>' && p[1] == '>') { + p += 2; + startOfLine = gFalse; + // skip any PDF whitespace except for '\0' + while (*p == '\t' || *p == '\n' || *p == '\x0c' || + *p == '\r' || *p == ' ') { + if (*p == '\n' || *p == '\r') { + startOfLine = gTrue; + } + ++p; + } + if (!strncmp(p, "stream", 6)) { + if (lastObjNum >= 0) { + if (streamObjNumsLen == streamObjNumsSize) { + streamObjNumsSize += 64; + streamObjNums = (int *)greallocn(streamObjNums, streamObjNumsSize, + sizeof(int)); + } + streamObjNums[streamObjNumsLen++] = lastObjNum; + } + p += 6; + startOfLine = gFalse; + } + } else { + if (*p == '\n' || *p == '\r') { + startOfLine = gTrue; + } else if (!Lexer::isSpace(*p & 0xff)) { + startOfLine = gFalse; + } + ++p; + } + } + + // read each stream object, check for xref or object stream + for (int i = 0; i < streamObjNumsLen; ++i) { + Object obj; + fetch(streamObjNums[i], entries[streamObjNums[i]].gen, &obj); + if (obj.isStream()) { + Dict *dict = obj.streamGetDict(); + Object type; + dict->lookup("Type", &type); + if (type.isName("XRef")) { + saveTrailerDict(dict, gTrue); + } else if (type.isName("ObjStm")) { + constructObjectStreamEntries(&obj, streamObjNums[i]); + } + type.free(); + } + obj.free(); + } + + gfree(streamObjNums); + + // if the file is encrypted, then any objects fetched here will be + // incorrect (because decryption is not yet enabled), so clear the + // cache to avoid that problem + for (int i = 0; i < xrefCacheSize; ++i) { + if (cache[i].num >= 0) { + cache[i].obj.free(); + cache[i].num = -1; + } + } + + if (rootNum < 0) { + error(errSyntaxError, -1, "Couldn't find trailer dictionary"); + return gFalse; + } + return gTrue; +} + +// Attempt to construct a trailer dict at [pos] in the stream. +void XRef::constructTrailerDict(GFileOffset pos) { + Object newTrailerDict, obj; + obj.initNull(); + Parser *parser = + new Parser(NULL, + new Lexer(NULL, + str->makeSubStream(pos, gFalse, 0, &obj)), + gFalse); + parser->getObj(&newTrailerDict); + if (newTrailerDict.isDict()) { + saveTrailerDict(newTrailerDict.getDict(), gFalse); + } + newTrailerDict.free(); + delete parser; +} + +// If [dict] "looks like" a trailer dict (i.e., has a Root entry), +// save it as the trailer dict. +void XRef::saveTrailerDict(Dict *dict, GBool isXRefStream) { + Object obj; + dict->lookupNF("Root", &obj); + if (obj.isRef()) { + int newRootNum = obj.getRefNum(); + // the xref stream scanning code runs after all objects are found, + // so we can check for a valid root object number at that point + if (!isXRefStream || newRootNum <= last) { + rootNum = newRootNum; + rootGen = obj.getRefGen(); + if (!trailerDict.isNone()) { + trailerDict.free(); + } + trailerDict.initDict(dict); + } + } + obj.free(); +} + +// Look for an object header ("nnn ggg obj") at [p]. The first +// character at *[p] is a digit. [pos] is the position of *[p]. +char *XRef::constructObjectEntry(char *p, GFileOffset pos, int *objNum) { + // we look for non-end-of-line space characters here, to deal with + // situations like: + // nnn <-- garbage digits on a line + // nnn nnn obj <-- actual object + // and we also ignore '\0' (because it's used to terminate the + // buffer in this damage-scanning code) + int num = 0; + do { + num = (num * 10) + (*p - '0'); + ++p; + } while (*p >= '0' && *p <= '9' && num < 100000000); + if (*p != '\t' && *p != '\x0c' && *p != ' ') { + return p; + } + do { + ++p; + } while (*p == '\t' || *p == '\x0c' || *p == ' '); + if (!(*p >= '0' && *p <= '9')) { + return p; + } + int gen = 0; + do { + gen = (gen * 10) + (*p - '0'); + ++p; + } while (*p >= '0' && *p <= '9' && gen < 100000000); + if (*p != '\t' && *p != '\x0c' && *p != ' ') { + return p; + } + do { + ++p; + } while (*p == '\t' || *p == '\x0c' || *p == ' '); + if (strncmp(p, "obj", 3)) { + return p; + } + + if (constructXRefEntry(num, gen, pos - start, xrefEntryUncompressed)) { + *objNum = num; + } + + return p; +} + +// Read the header from an object stream, and add xref entries for all +// of its objects. +void XRef::constructObjectStreamEntries(Object *objStr, int objStrObjNum) { + Object obj1, obj2; + + // get the object count + if (!objStr->streamGetDict()->lookup("N", &obj1)->isInt()) { + obj1.free(); + return; + } + int nObjects = obj1.getInt(); + obj1.free(); + if (nObjects <= 0 || nObjects > 1000000) { + return; + } + + // parse the header: object numbers and offsets + Parser *parser = new Parser(NULL, + new Lexer(NULL, objStr->getStream()->copy()), + gFalse); + for (int i = 0; i < nObjects; ++i) { + parser->getObj(&obj1, gTrue); + parser->getObj(&obj2, gTrue); + if (obj1.isInt() && obj2.isInt()) { + int num = obj1.getInt(); + if (num >= 0 && num < 1000000) { + constructXRefEntry(num, i, objStrObjNum, xrefEntryCompressed); + } + } + obj2.free(); + obj1.free(); + } + delete parser; +} + +GBool XRef::constructXRefEntry(int num, int gen, GFileOffset pos, + XRefEntryType type) { + if (num >= size) { + int newSize = (num + 1 + 255) & ~255; + if (newSize < 0) { + return gFalse; + } + entries = (XRefEntry *)greallocn(entries, newSize, sizeof(XRefEntry)); + for (int i = size; i < newSize; ++i) { + entries[i].offset = (GFileOffset)-1; + entries[i].type = xrefEntryFree; + } + size = newSize; + } + + if (entries[num].type == xrefEntryFree || + gen >= entries[num].gen) { + entries[num].offset = pos; + entries[num].gen = gen; + entries[num].type = type; + if (num > last) { + last = num; + } + } + + return gTrue; +} + +void XRef::setEncryption(int permFlagsA, GBool ownerPasswordOkA, + Guchar *fileKeyA, int keyLengthA, int encVersionA, + CryptAlgorithm encAlgorithmA) { + int i; + + encrypted = gTrue; + permFlags = permFlagsA; + ownerPasswordOk = ownerPasswordOkA; + if (keyLengthA <= 32) { + keyLength = keyLengthA; + } else { + keyLength = 32; + } + for (i = 0; i < keyLength; ++i) { + fileKey[i] = fileKeyA[i]; + } + encVersion = encVersionA; + encAlgorithm = encAlgorithmA; +} + +GBool XRef::getEncryption(int *permFlagsA, GBool *ownerPasswordOkA, + int *keyLengthA, int *encVersionA, + CryptAlgorithm *encAlgorithmA) { + if (!encrypted) { + return gFalse; + } + *permFlagsA = permFlags; + *ownerPasswordOkA = ownerPasswordOk; + *keyLengthA = keyLength; + *encVersionA = encVersion; + *encAlgorithmA = encAlgorithm; + return gTrue; +} + +GBool XRef::okToPrint(GBool ignoreOwnerPW) { + return (!ignoreOwnerPW && ownerPasswordOk) || (permFlags & permPrint); +} + +GBool XRef::okToChange(GBool ignoreOwnerPW) { + return (!ignoreOwnerPW && ownerPasswordOk) || (permFlags & permChange); +} + +GBool XRef::okToCopy(GBool ignoreOwnerPW) { + return (!ignoreOwnerPW && ownerPasswordOk) || (permFlags & permCopy); +} + +GBool XRef::okToAddNotes(GBool ignoreOwnerPW) { + return (!ignoreOwnerPW && ownerPasswordOk) || (permFlags & permNotes); +} + +Object *XRef::fetch(int num, int gen, Object *obj, int recursion) { + XRefEntry *e; + Parser *parser; + Object obj1, obj2, obj3; + XRefCacheEntry tmp; + int i, j; + + // check for bogus ref - this can happen in corrupted PDF files + if (num < 0 || num >= size) { + goto err; + } + + // check the cache +#if MULTITHREADED + gLockMutex(&cacheMutex); +#endif + if (cache[0].num == num && cache[0].gen == gen) { + cache[0].obj.copy(obj); +#if MULTITHREADED + gUnlockMutex(&cacheMutex); +#endif + return obj; + } + for (i = 1; i < xrefCacheSize; ++i) { + if (cache[i].num == num && cache[i].gen == gen) { + tmp = cache[i]; + for (j = i; j > 0; --j) { + cache[j] = cache[j - 1]; + } + cache[0] = tmp; + cache[0].obj.copy(obj); +#if MULTITHREADED + gUnlockMutex(&cacheMutex); +#endif + return obj; + } + } +#if MULTITHREADED + gUnlockMutex(&cacheMutex); +#endif + + e = &entries[num]; + switch (e->type) { + + case xrefEntryUncompressed: + if (e->gen != gen) { + goto err; + } + obj1.initNull(); + parser = new Parser(this, + new Lexer(this, + str->makeSubStream(start + e->offset, gFalse, 0, &obj1)), + gTrue); + 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")) { + obj1.free(); + obj2.free(); + obj3.free(); + delete parser; + goto err; + } + parser->getObj(obj, gFalse, encrypted ? fileKey : (Guchar *)NULL, + encAlgorithm, keyLength, num, gen, recursion); + obj1.free(); + obj2.free(); + obj3.free(); + delete parser; + break; + + case xrefEntryCompressed: +#if 0 // Adobe apparently ignores the generation number on compressed objects + if (gen != 0) { + goto err; + } +#endif + if (e->offset >= (GFileOffset)size || + entries[e->offset].type != xrefEntryUncompressed) { + error(errSyntaxError, -1, "Invalid object stream"); + goto err; + } + if (!getObjectStreamObject((int)e->offset, e->gen, num, obj)) { + goto err; + } + break; + + default: + goto err; + } + + // put the new object in the cache, throwing away the oldest object + // currently in the cache +#if MULTITHREADED + gLockMutex(&cacheMutex); +#endif + if (cache[xrefCacheSize - 1].num >= 0) { + cache[xrefCacheSize - 1].obj.free(); + } + for (i = xrefCacheSize - 1; i > 0; --i) { + cache[i] = cache[i - 1]; + } + cache[0].num = num; + cache[0].gen = gen; + obj->copy(&cache[0].obj); +#if MULTITHREADED + gUnlockMutex(&cacheMutex); +#endif + + return obj; + + err: + return obj->initNull(); +} + +GBool XRef::getObjectStreamObject(int objStrNum, int objIdx, + int objNum, Object *obj) { + ObjectStream *objStr; + +#if MULTITHREADED + gLockMutex(&objStrsMutex); +#endif + if (!(objStr = getObjectStream(objStrNum))) { +#if MULTITHREADED + gUnlockMutex(&objStrsMutex); +#endif + return gFalse; + } + cleanObjectStreamCache(); + objStr->getObject(objIdx, objNum, obj); +#if MULTITHREADED + gUnlockMutex(&objStrsMutex); +#endif + return gTrue; +} + +// NB: objStrsMutex must be locked when calling this function. +ObjectStream *XRef::getObjectStream(int objStrNum) { + ObjectStream *objStr; + int i, j; + + // check the MRU entry in the cache + if (objStrs[0] && objStrs[0]->getObjStrNum() == objStrNum) { + objStr = objStrs[0]; + objStrLastUse[0] = objStrTime++; + return objStr; + } + + // check the rest of the cache + for (i = 1; i < objStrCacheLength; ++i) { + if (objStrs[i] && objStrs[i]->getObjStrNum() == objStrNum) { + objStr = objStrs[i]; + for (j = i; j > 0; --j) { + objStrs[j] = objStrs[j - 1]; + objStrLastUse[j] = objStrLastUse[j - 1]; + } + objStrs[0] = objStr; + objStrLastUse[0] = objStrTime++; + return objStr; + } + } + + // load a new ObjectStream + objStr = new ObjectStream(this, objStrNum); + if (!objStr->isOk()) { + delete objStr; + return NULL; + } + + // add to the cache + if (objStrCacheLength == objStrCacheSize) { + delete objStrs[objStrCacheSize - 1]; + --objStrCacheLength; + } + for (j = objStrCacheLength; j > 0; --j) { + objStrs[j] = objStrs[j - 1]; + objStrLastUse[j] = objStrLastUse[j - 1]; + } + ++objStrCacheLength; + objStrs[0] = objStr; + objStrLastUse[0] = objStrTime++; + + return objStr; +} + +// If the oldest (least recently used) entry in the object stream +// cache is more than objStrCacheTimeout accesses old (hasn't been +// used in the last objStrCacheTimeout accesses), eject it from the +// cache. +void XRef::cleanObjectStreamCache() { + // NB: objStrTime and objStrLastUse[] are unsigned ints, so the + // mod-2^32 arithmetic makes the subtraction work out, even if the + // time wraps around. + if (objStrCacheLength > 1 && + objStrTime - objStrLastUse[objStrCacheLength - 1] + > objStrCacheTimeout) { + delete objStrs[objStrCacheLength - 1]; + objStrs[objStrCacheLength - 1] = NULL; + --objStrCacheLength; + } +} + +Object *XRef::getDocInfo(Object *obj) { + return trailerDict.dictLookup("Info", obj); +} + +// Added for the pdftex project. +Object *XRef::getDocInfoNF(Object *obj) { + return trailerDict.dictLookupNF("Info", obj); +} + +GBool XRef::getStreamEnd(GFileOffset streamStart, GFileOffset *streamEnd) { + int a, b, m; + + if (streamEndsLen == 0 || + streamStart > streamEnds[streamEndsLen - 1]) { + return gFalse; + } + + a = -1; + b = streamEndsLen - 1; + // invariant: streamEnds[a] < streamStart <= streamEnds[b] + while (b - a > 1) { + m = (a + b) / 2; + if (streamStart <= streamEnds[m]) { + b = m; + } else { + a = m; + } + } + *streamEnd = streamEnds[b]; + return gTrue; +} + +GFileOffset XRef::strToFileOffset(char *s) { + GFileOffset x, d; + char *p; + + x = 0; + for (p = s; *p && isdigit(*p & 0xff); ++p) { + d = *p - '0'; + if (x > (GFILEOFFSET_MAX - d) / 10) { + break; + } + x = 10 * x + d; + } + return x; +} diff --git a/xpdf/XRef.h b/xpdf/XRef.h new file mode 100644 index 0000000..10e4e6a --- /dev/null +++ b/xpdf/XRef.h @@ -0,0 +1,192 @@ +//======================================================================== +// +// XRef.h +// +// Copyright 1996-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef XREF_H +#define XREF_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "gtypes.h" +#include "gfile.h" +#include "Object.h" +#if MULTITHREADED +#include "GMutex.h" +#endif + +class Dict; +class Stream; +class Parser; +class ObjectStream; +class XRefPosSet; + +//------------------------------------------------------------------------ +// XRef +//------------------------------------------------------------------------ + +enum XRefEntryType { + xrefEntryFree, + xrefEntryUncompressed, + xrefEntryCompressed +}; + +struct XRefEntry { + GFileOffset offset; + int gen; + XRefEntryType type; +}; + +struct XRefCacheEntry { + int num; + int gen; + Object obj; +}; + +#define xrefCacheSize 16 + +#define objStrCacheSize 128 +#define objStrCacheTimeout 1000 + +class XRef { +public: + + // Constructor. Read xref table from stream. + XRef(BaseStream *strA, GBool repair); + + // Destructor. + ~XRef(); + + // Is xref table valid? + GBool isOk() { return ok; } + + // Get the error code (if isOk() returns false). + int getErrorCode() { return errCode; } + + // Was the xref constructed by the repair code? + GBool isRepaired() { return repaired; } + + // Set the encryption parameters. + void setEncryption(int permFlagsA, GBool ownerPasswordOkA, + Guchar *fileKeyA, int keyLengthA, int encVersionA, + CryptAlgorithm encAlgorithmA); + + // Is the file encrypted? + GBool isEncrypted() { return encrypted; } + GBool getEncryption(int *permFlagsA, GBool *ownerPasswordOkA, + int *keyLengthA, int *encVersionA, + CryptAlgorithm *encAlgorithmA); + + // Check various permissions. + GBool okToPrint(GBool ignoreOwnerPW = gFalse); + 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, 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 last + 1; } + + // Return the offset of the last xref table. + GFileOffset getLastXRefPos() { return lastXRefPos; } + + // Return the offset of the 'startxref' at the end of the file. + GFileOffset getLastStartxrefPos() { return lastStartxrefPos; } + + // Return the catalog object reference. + int getRootNum() { return rootNum; } + int getRootGen() { return rootGen; } + + // Get the xref table positions. + int getNumXRefTables() { return xrefTablePosLen; } + GFileOffset getXRefTablePos(int idx) { return xrefTablePos[idx]; } + + // Get end position for a stream in a damaged file. + // Returns false if unknown or file is not damaged. + GBool getStreamEnd(GFileOffset streamStart, GFileOffset *streamEnd); + + // Direct access. + int getSize() { return size; } + XRefEntry *getEntry(int i) { return &entries[i]; } + Object *getTrailerDict() { return &trailerDict; } + +private: + + BaseStream *str; // input stream + GFileOffset start; // offset in file (to allow for garbage + // at beginning of file) + XRefEntry *entries; // xref entries + int size; // size of array + int last; // last used index in + int rootNum, rootGen; // catalog dict + GBool ok; // true if xref table is valid + int errCode; // error code (if is false) + GBool repaired; // set if the xref table was constructed by + // the repair code + Object trailerDict; // trailer dictionary + GFileOffset lastXRefPos; // offset of last xref table + GFileOffset lastStartxrefPos; // offset of 'startxref' at end of file + GFileOffset *xrefTablePos; // positions of all xref tables + int xrefTablePosLen; // number of xref table positions + GFileOffset *streamEnds; // 'endstream' positions - only used in + // damaged files + int streamEndsLen; // number of valid entries in streamEnds + ObjectStream * // cached object streams + objStrs[objStrCacheSize]; + int objStrCacheLength; // number of valid entries in objStrs[] + Guint // time of last use for each obj stream + objStrLastUse[objStrCacheSize]; + Guint objStrTime; // current time for the obj stream cache +#if MULTITHREADED + GMutex objStrsMutex; +#endif + GBool encrypted; // true if file is encrypted + int permFlags; // permission bits + GBool ownerPasswordOk; // true if owner password is correct + Guchar fileKey[32]; // file decryption key + int keyLength; // length of key, in bytes + int encVersion; // encryption version + CryptAlgorithm encAlgorithm; // encryption algorithm + XRefCacheEntry // cache of recently accessed objects + cache[xrefCacheSize]; +#if MULTITHREADED + GMutex cacheMutex; +#endif + + GFileOffset getStartXref(); + GBool readXRef(GFileOffset *pos, XRefPosSet *posSet, GBool hybrid); + GBool readXRefTable(GFileOffset *pos, int offset, XRefPosSet *posSet); + GBool readXRefStream(Stream *xrefStr, GFileOffset *pos, GBool hybrid); + GBool readXRefStreamSection(Stream *xrefStr, int *w, int first, int n); + GBool constructXRef(); + void constructTrailerDict(GFileOffset pos); + void saveTrailerDict(Dict *dict, GBool isXRefStream); + char *constructObjectEntry(char *p, GFileOffset pos, int *objNum); + void constructObjectStreamEntries(Object *objStr, int objStrObjNum); + GBool constructXRefEntry(int num, int gen, GFileOffset pos, + XRefEntryType type); + GBool getObjectStreamObject(int objStrNum, int objIdx, + int objNum, Object *obj); + ObjectStream *getObjectStream(int objStrNum); + void cleanObjectStreamCache(); + GFileOffset strToFileOffset(char *s); +}; + +#endif diff --git a/xpdf/Zoox.cc b/xpdf/Zoox.cc new file mode 100644 index 0000000..9e4fb47 --- /dev/null +++ b/xpdf/Zoox.cc @@ -0,0 +1,1072 @@ +//======================================================================== +// +// Zoox.cc +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include +#include +#include "gmem.h" +#include "gmempp.h" +#include "GString.h" +#include "GList.h" +#include "GHash.h" +#include "Zoox.h" + +//~ all of this code assumes the encoding is UTF-8 or ASCII or something +//~ similar (ISO-8859-*) + +//------------------------------------------------------------------------ + +static char nameStartChar[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 00 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 10 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, // 30 + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 40 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, // 50 + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 60 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, // 70 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 80 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 90 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // a0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // b0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // c0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // d0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // e0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // f0 +}; + +static char nameChar[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 00 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 10 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, // 20 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, // 30 + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 40 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, // 50 + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 60 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, // 70 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 80 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 90 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // a0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // b0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // c0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // d0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // e0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // f0 +}; + +//------------------------------------------------------------------------ + +ZxNode::ZxNode() { + next = NULL; + parent = NULL; + firstChild = lastChild = NULL; +} + +ZxNode::~ZxNode() { + ZxNode *child; + + while (firstChild) { + child = firstChild; + firstChild = firstChild->next; + delete child; + } +} + +ZxNode *ZxNode::deleteChild(ZxNode *child) { + ZxNode *p1, *p2; + + for (p1 = NULL, p2 = firstChild; + p2 && p2 != child; + p1 = p2, p2 = p2->next) ; + if (!p2) { + return NULL; + } + if (p1) { + p1->next = child->next; + } else { + firstChild = child->next; + } + child->parent = NULL; + child->next = NULL; + return child; +} + +void ZxNode::appendChild(ZxNode *child) { + ZxNode *p1; + + if (child->parent || child->next) { + return; + } + if (firstChild) { + for (p1 = firstChild; p1->next; p1 = p1->next) ; + p1->next = child; + } else { + firstChild = child; + } + child->parent = this; +} + +void ZxNode::insertChildAfter(ZxNode *child, ZxNode *prev) { + if (child->parent || child->next || (prev && prev->parent != this)) { + return; + } + if (prev) { + child->next = prev->next; + prev->next = child; + } else { + child->next = firstChild; + firstChild = child; + } + child->parent = this; +} + +ZxElement *ZxNode::findFirstElement(const char *type) { + ZxNode *child; + ZxElement *result; + + if (isElement(type)) { + return (ZxElement *)this; + } + for (child = firstChild; child; child = child->next) { + if ((result = child->findFirstElement(type))) { + return result; + } + } + return NULL; +} + +ZxElement *ZxNode::findFirstChildElement(const char *type) { + ZxNode *child; + + for (child = firstChild; child; child = child->next) { + if (child->isElement(type)) { + return (ZxElement *)child; + } + } + return NULL; +} + +GList *ZxNode::findAllElements(const char *type) { + GList *results; + + results = new GList(); + findAllElements(type, results); + return results; +} + +void ZxNode::findAllElements(const char *type, GList *results) { + ZxNode *child; + + if (isElement(type)) { + results->append(this); + } + for (child = firstChild; child; child = child->next) { + child->findAllElements(type, results); + } +} + +GList *ZxNode::findAllChildElements(const char *type) { + GList *results; + ZxNode *child; + + results = new GList(); + for (child = firstChild; child; child = child->next) { + if (child->isElement(type)) { + results->append(child); + } + } + return results; +} + +void ZxNode::addChild(ZxNode *child) { + if (lastChild) { + lastChild->next = child; + lastChild = child; + } else { + firstChild = lastChild = child; + } + child->parent = this; + child->next = NULL; +} + +//------------------------------------------------------------------------ + +ZxDoc::ZxDoc() { + xmlDecl = NULL; + docTypeDecl = NULL; + root = NULL; +} + +ZxDoc *ZxDoc::loadMem(const char *data, Guint dataLen) { + ZxDoc *doc; + + doc = new ZxDoc(); + if (!doc->parse(data, dataLen)) { + delete doc; + return NULL; + } + return doc; +} + +ZxDoc *ZxDoc::loadFile(const char *fileName) { + ZxDoc *doc; + FILE *f; + char *data; + Guint dataLen; + + if (!(f = fopen(fileName, "rb"))) { + return NULL; + } + fseek(f, 0, SEEK_END); + dataLen = (Guint)ftell(f); + if (!dataLen) { + fclose(f); + return NULL; + } + fseek(f, 0, SEEK_SET); + data = (char *)gmalloc(dataLen); + if (fread(data, 1, dataLen, f) != dataLen) { + fclose(f); + gfree(data); + return NULL; + } + fclose(f); + doc = loadMem(data, dataLen); + gfree(data); + return doc; +} + +ZxDoc::~ZxDoc() { +} + +static bool writeToFileFunc(void *stream, const char *data, int length) { + return (int)fwrite(data, 1, length, (FILE *)stream) == length; +} + +bool ZxDoc::writeFile(const char *fileName) { + FILE *f; + + if (!(f = fopen(fileName, "wb"))) { + return false; + } + write(&writeToFileFunc, f); + fclose(f); + return true; +} + +void ZxDoc::addChild(ZxNode *node) { + if (node->isXMLDecl() && !xmlDecl) { + xmlDecl = (ZxXMLDecl *)node; + } else if (node->isDocTypeDecl() && !docTypeDecl) { + docTypeDecl = (ZxDocTypeDecl *)node; + } else if (node->isElement() && !root) { + root = (ZxElement *)node; + } + ZxNode::addChild(node); +} + +bool ZxDoc::parse(const char *data, Guint dataLen) { + parsePtr = data; + parseEnd = data + dataLen; + + parseSpace(); + parseXMLDecl(this); + parseMisc(this); + parseDocTypeDecl(this); + parseMisc(this); + if (match("<")) { + parseElement(this); + } + parseMisc(this); + return root != NULL; +} + +void ZxDoc::parseXMLDecl(ZxNode *par) { + GString *version, *encoding, *s; + bool standalone; + + if (!match("cmp("yes"); + delete s; + } + } + parseSpace(); + + if (match("?>")) { + parsePtr += 2; + } + + par->addChild(new ZxXMLDecl(version, encoding, standalone)); +} + +//~ this just skips everything after the name +void ZxDoc::parseDocTypeDecl(ZxNode *par) { + GString *name; + int state; + char c, quote; + + if (!match("') { + state = 4; + } else if (c == '"' || c == '\'') { + state = 1; + } else if (c == '[') { + state = 2; + } + break; + case 1: // not in square brackets; in quotes + if (c == quote) { + state = 0; + } + break; + case 2: // in square brackets; not in quotes + if (c == ']') { + state = 0; + } else if (c == '"' || c == '\'') { + state = 3; + } + break; + case 3: // in square brackets; in quotes + if (c == quote) { + state = 2; + } + break; + } + } + + par->addChild(new ZxDocTypeDecl(name)); +} + +// assumes match("<") +void ZxDoc::parseElement(ZxNode *par) { + GString *type; + ZxElement *elem; + ZxAttr *attr; + + ++parsePtr; + type = parseName(); + elem = new ZxElement(type); + parseSpace(); + while ((attr = parseAttr())) { + elem->addAttr(attr); + parseSpace(); + } + if (match("/>")) { + parsePtr += 2; + } else if (match(">")) { + ++parsePtr; + parseContent(elem); + } + par->addChild(elem); +} + +ZxAttr *ZxDoc::parseAttr() { + GString *name, *value; + const char *start; + char quote, c; + unsigned int x; + int n; + + name = parseName(); + parseSpace(); + if (!match("=")) { + delete name; + return NULL; + } + ++parsePtr; + parseSpace(); + if (!(parsePtr < parseEnd && (*parsePtr == '"' || *parsePtr == '\''))) { + delete name; + return NULL; + } + quote = *parsePtr++; + value = new GString(); + while (parsePtr < parseEnd && *parsePtr != quote) { + if (*parsePtr == '&') { + ++parsePtr; + if (parsePtr < parseEnd && *parsePtr == '#') { + ++parsePtr; + if (parsePtr < parseEnd && *parsePtr == 'x') { + ++parsePtr; + x = 0; + while (parsePtr < parseEnd) { + c = *parsePtr; + if (c >= '0' && c <= '9') { + x = (x << 4) + (c - '0'); + } else if (c >= 'a' && c <= 'f') { + x = (x << 4) + (10 + c - 'a'); + } else if (c >= 'A' && c <= 'F') { + x = (x << 4) + (10 + c - 'A'); + } else { + break; + } + ++parsePtr; + } + if (parsePtr < parseEnd && *parsePtr == ';') { + ++parsePtr; + } + appendUTF8(value, x); + } else { + x = 0; + while (parsePtr < parseEnd) { + c = *parsePtr; + if (c >= '0' && c <= '9') { + x = x * 10 + (c - '0'); + } else { + break; + } + ++parsePtr; + } + if (parsePtr < parseEnd && *parsePtr == ';') { + ++parsePtr; + } + appendUTF8(value, x); + } + } else { + start = parsePtr; + for (++parsePtr; + parsePtr < parseEnd && *parsePtr != ';' && + *parsePtr != quote && *parsePtr != '&'; + ++parsePtr) ; + n = (int)(parsePtr - start); + if (parsePtr < parseEnd && *parsePtr == ';') { + ++parsePtr; + } + if (n == 2 && !strncmp(start, "lt", 2)) { + value->append('<'); + } else if (n == 2 && !strncmp(start, "gt", 2)) { + value->append('>'); + } else if (n == 3 && !strncmp(start, "amp", 3)) { + value->append('&'); + } else if (n == 4 && !strncmp(start, "apos", 4)) { + value->append('\''); + } else if (n == 4 && !strncmp(start, "quot", 4)) { + value->append('"'); + } else { + value->append(start - 1, (int)(parsePtr - start) + 1); + } + } + } else { + start = parsePtr; + for (++parsePtr; + parsePtr < parseEnd && *parsePtr != quote && *parsePtr != '&'; + ++parsePtr) ; + value->append(start, (int)(parsePtr - start)); + } + } + if (parsePtr < parseEnd && *parsePtr == quote) { + ++parsePtr; + } + return new ZxAttr(name, value); +} + +// this consumes the end tag +void ZxDoc::parseContent(ZxElement *par) { + GString *endType; + + endType = (new GString("append(par->getType()); + + while (parsePtr < parseEnd) { + if (match(endType->getCString())) { + parsePtr += endType->getLength(); + parseSpace(); + if (match(">")) { + ++parsePtr; + } + break; + } else if (match("= '0' && c <= '9') { + x = (x << 4) + (c - '0'); + } else if (c >= 'a' && c <= 'f') { + x = (x << 4) + (10 + c - 'a'); + } else if (c >= 'A' && c <= 'F') { + x = (x << 4) + (10 + c - 'A'); + } else { + break; + } + ++parsePtr; + } + if (parsePtr < parseEnd && *parsePtr == ';') { + ++parsePtr; + } + appendUTF8(data, x); + } else { + x = 0; + while (parsePtr < parseEnd) { + c = *parsePtr; + if (c >= '0' && c <= '9') { + x = x * 10 + (c - '0'); + } else { + break; + } + ++parsePtr; + } + if (parsePtr < parseEnd && *parsePtr == ';') { + ++parsePtr; + } + appendUTF8(data, x); + } + } else { + start = parsePtr; + for (++parsePtr; + parsePtr < parseEnd && *parsePtr != ';' && + *parsePtr != '<' && *parsePtr != '&'; + ++parsePtr) ; + n = (int)(parsePtr - start); + if (parsePtr < parseEnd && *parsePtr == ';') { + ++parsePtr; + } + if (n == 2 && !strncmp(start, "lt", 2)) { + data->append('<'); + } else if (n == 2 && !strncmp(start, "gt", 2)) { + data->append('>'); + } else if (n == 3 && !strncmp(start, "amp", 3)) { + data->append('&'); + } else if (n == 4 && !strncmp(start, "apos", 4)) { + data->append('\''); + } else if (n == 4 && !strncmp(start, "quot", 4)) { + data->append('"'); + } else { + data->append(start - 1, (int)(parsePtr - start) + 1); + } + } + } else { + start = parsePtr; + for (++parsePtr; + parsePtr < parseEnd && *parsePtr != '<' && *parsePtr != '&'; + ++parsePtr) ; + data->append(start, (int)(parsePtr - start)); + } + } + par->addChild(new ZxCharData(data, true)); +} + +void ZxDoc::appendUTF8(GString *s, unsigned int c) { + if (c <= 0x7f) { + s->append((char)c); + } else if (c <= 0x7ff) { + s->append((char)(0xc0 + (c >> 6))); + s->append((char)(0x80 + (c & 0x3f))); + } else if (c <= 0xffff) { + s->append((char)(0xe0 + (c >> 12))); + s->append((char)(0x80 + ((c >> 6) & 0x3f))); + s->append((char)(0x80 + (c & 0x3f))); + } else if (c <= 0x1fffff) { + s->append((char)(0xf0 + (c >> 18))); + s->append((char)(0x80 + ((c >> 12) & 0x3f))); + s->append((char)(0x80 + ((c >> 6) & 0x3f))); + s->append((char)(0x80 + (c & 0x3f))); + } else if (c <= 0x3ffffff) { + s->append((char)(0xf8 + (c >> 24))); + s->append((char)(0x80 + ((c >> 18) & 0x3f))); + s->append((char)(0x80 + ((c >> 12) & 0x3f))); + s->append((char)(0x80 + ((c >> 6) & 0x3f))); + s->append((char)(0x80 + (c & 0x3f))); + } else if (c <= 0x7fffffff) { + s->append((char)(0xfc + (c >> 30))); + s->append((char)(0x80 + ((c >> 24) & 0x3f))); + s->append((char)(0x80 + ((c >> 18) & 0x3f))); + s->append((char)(0x80 + ((c >> 12) & 0x3f))); + s->append((char)(0x80 + ((c >> 6) & 0x3f))); + s->append((char)(0x80 + (c & 0x3f))); + } +} + +// assumes match("", 3)) { + par->addChild(new ZxCharData(new GString(start, (int)(parsePtr - start)), + false)); + parsePtr += 3; + return; + } + ++parsePtr; + } + parsePtr = parseEnd; + par->addChild(new ZxCharData(new GString(start, (int)(parsePtr - start)), + false)); +} + +void ZxDoc::parseMisc(ZxNode *par) { + while (1) { + if (match("", 3)) { + par->addChild(new ZxComment(new GString(start, (int)(parsePtr - start)))); + parsePtr += 3; + return; + } + ++parsePtr; + } + parsePtr = parseEnd; +} + +// assumes match("", 2)) { + par->addChild(new ZxPI(target, new GString(start, + (int)(parsePtr - start)))); + parsePtr += 2; + return; + } + ++parsePtr; + } + parsePtr = parseEnd; + par->addChild(new ZxPI(target, new GString(start, (int)(parsePtr - start)))); +} + +//~ this accepts all chars >= 0x80 +//~ this doesn't check for properly-formed UTF-8 +GString *ZxDoc::parseName() { + GString *name; + + name = new GString(); + if (parsePtr < parseEnd && nameStartChar[*parsePtr & 0xff]) { + name->append(*parsePtr++); + while (parsePtr < parseEnd && nameChar[*parsePtr & 0xff]) { + name->append(*parsePtr++); + } + } + return name; +} + +GString *ZxDoc::parseQuotedString() { + GString *s; + const char *start; + char quote; + + if (parsePtr < parseEnd && (*parsePtr == '"' || *parsePtr == '\'')) { + quote = *parsePtr++; + start = parsePtr; + while (parsePtr < parseEnd && *parsePtr != quote) { + ++parsePtr; + } + s = new GString(start, (int)(parsePtr - start)); + if (parsePtr < parseEnd && *parsePtr == quote) { + ++parsePtr; + } + } else { + s = new GString(); + } + return s; +} + +void ZxDoc::parseSpace() { + while (parsePtr < parseEnd && (*parsePtr == '\x20' || + *parsePtr == '\x09' || + *parsePtr == '\x0d' || + *parsePtr == '\x0a')) { + ++parsePtr; + } +} + +bool ZxDoc::match(const char *s) { + int n; + + n = (int)strlen(s); + return parseEnd - parsePtr >= n && !strncmp(parsePtr, s, n); +} + +bool ZxDoc::write(ZxWriteFunc writeFunc, void *stream) { + ZxNode *child; + + for (child = getFirstChild(); child; child = child->getNextChild()) { + if (!child->write(writeFunc, stream)) { + return false; + } + if (!(*writeFunc)(stream, "\n", 1)) { + return false; + } + } + return true; +} + +//------------------------------------------------------------------------ + +ZxXMLDecl::ZxXMLDecl(GString *versionA, GString *encodingA, bool standaloneA) { + version = versionA; + encoding = encodingA; + standalone = standaloneA; +} + +ZxXMLDecl::~ZxXMLDecl() { + delete version; + if (encoding) { + delete encoding; + } +} + +bool ZxXMLDecl::write(ZxWriteFunc writeFunc, void *stream) { + GString *s; + bool ok; + + s = new GString("append(version); + s->append("\""); + if (encoding) { + s->append(" encoding=\""); + s->append(encoding); + s->append("\""); + } + if (standalone) { + s->append(" standlone=\"yes\""); + } + s->append("?>"); + ok = (*writeFunc)(stream, s->getCString(), s->getLength()); + delete s; + return ok; +} + +//------------------------------------------------------------------------ + +ZxDocTypeDecl::ZxDocTypeDecl(GString *nameA) { + name = nameA; +} + +ZxDocTypeDecl::~ZxDocTypeDecl() { + delete name; +} + +bool ZxDocTypeDecl::write(ZxWriteFunc writeFunc, void *stream) { + GString *s; + bool ok; + + s = new GString("append(name); + s->append(">"); + ok = (*writeFunc)(stream, s->getCString(), s->getLength()); + delete s; + return ok; +} + +//------------------------------------------------------------------------ + +ZxComment::ZxComment(GString *textA) { + text = textA; +} + +ZxComment::~ZxComment() { + delete text; +} + +bool ZxComment::write(ZxWriteFunc writeFunc, void *stream) { + GString *s; + bool ok; + + s = new GString(""); + ok = (*writeFunc)(stream, s->getCString(), s->getLength()); + delete s; + return ok; +} + +//------------------------------------------------------------------------ + +ZxPI::ZxPI(GString *targetA, GString *textA) { + target = targetA; + text = textA; +} + +ZxPI::~ZxPI() { + delete target; + delete text; +} + +bool ZxPI::write(ZxWriteFunc writeFunc, void *stream) { + GString *s; + bool ok; + + s = new GString("append(target); + s->append(" "); + s->append(text); + s->append("?>"); + ok = (*writeFunc)(stream, s->getCString(), s->getLength()); + delete s; + return ok; +} + +//------------------------------------------------------------------------ + +ZxElement::ZxElement(GString *typeA) { + type = typeA; + attrs = new GHash(); + firstAttr = lastAttr = NULL; +} + +ZxElement::~ZxElement() { + delete type; + deleteGHash(attrs, ZxAttr); +} + +bool ZxElement::isElement(const char *typeA) { + return !type->cmp(typeA); +} + +ZxAttr *ZxElement::findAttr(const char *attrName) { + return (ZxAttr *)attrs->lookup(attrName); +} + +void ZxElement::addAttr(ZxAttr *attr) { + attrs->add(attr->getName(), attr); + if (lastAttr) { + lastAttr->next = attr; + lastAttr= attr; + } else { + firstAttr = lastAttr = attr; + } + attr->parent = this; + attr->next = NULL; +} + +bool ZxElement::write(ZxWriteFunc writeFunc, void *stream) { + GString *s; + ZxAttr *attr; + ZxNode *child; + bool ok; + + s = new GString("<"); + s->append(type); + for (attr = firstAttr; attr; attr = attr->getNextAttr()) { + s->append(" "); + s->append(attr->name); + s->append("=\""); + appendEscapedAttrValue(s, attr->value); + s->append("\""); + } + if ((child = getFirstChild())) { + s->append(">"); + } else { + s->append("/>"); + } + ok = (*writeFunc)(stream, s->getCString(), s->getLength()); + delete s; + if (!ok) { + return false; + } + if (child) { + for (; child; child = child->getNextChild()) { + if (!child->write(writeFunc, stream)) { + return false; + } + } + s = new GString(); + s->append("append(type); + s->append(">"); + ok = (*writeFunc)(stream, s->getCString(), s->getLength()); + delete s; + if (!ok) { + return false; + } + } + return true; +} + +void ZxElement::appendEscapedAttrValue(GString *out, GString *s) { + char c; + int i; + + for (i = 0; i < s->getLength(); ++i) { + c = s->getChar(i); + if (c == '<') { + out->append("<"); + } else if (c == '>') { + out->append(">"); + } else if (c == '&') { + out->append("&"); + } else if (c == '"') { + out->append("""); + } else { + out->append(c); + } + } +} + +//------------------------------------------------------------------------ + +ZxAttr::ZxAttr(GString *nameA, GString *valueA) { + name = nameA; + value = valueA; + parent = NULL; + next = NULL; +} + +ZxAttr::~ZxAttr() { + delete name; + delete value; +} + +//------------------------------------------------------------------------ + +ZxCharData::ZxCharData(GString *dataA, bool parsedA) { + data = dataA; + parsed = parsedA; +} + +ZxCharData::~ZxCharData() { + delete data; +} + +bool ZxCharData::write(ZxWriteFunc writeFunc, void *stream) { + GString *s; + char c; + int i; + bool ok; + + s = new GString(); + if (parsed) { + for (i = 0; i < data->getLength(); ++i) { + c = data->getChar(i); + if (c == '<') { + s->append("<"); + } else if (c == '>') { + s->append(">"); + } else if (c == '&') { + s->append("&"); + } else { + s->append(c); + } + } + } else { + s->append("append(data); + s->append("]]>"); + } + ok = (*writeFunc)(stream, s->getCString(), s->getLength()); + delete s; + return ok; +} diff --git a/xpdf/Zoox.h b/xpdf/Zoox.h new file mode 100644 index 0000000..c04ca95 --- /dev/null +++ b/xpdf/Zoox.h @@ -0,0 +1,271 @@ +//======================================================================== +// +// Zoox.h +// +//======================================================================== + +#ifndef ZOOX_H +#define ZOOX_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "gtypes.h" + +class GString; +class GList; +class GHash; + +class ZxAttr; +class ZxDocTypeDecl; +class ZxElement; +class ZxXMLDecl; + +//------------------------------------------------------------------------ + +typedef bool (*ZxWriteFunc)(void *stream, const char *data, int length); + +//------------------------------------------------------------------------ + +class ZxNode { +public: + + ZxNode(); + virtual ~ZxNode(); + + virtual bool isDoc() { return false; } + virtual bool isXMLDecl() { return false; } + virtual bool isDocTypeDecl() { return false; } + virtual bool isComment() { return false; } + virtual bool isPI() { return false; } + virtual bool isElement() { return false; } + virtual bool isElement(const char *type) { return false; } + virtual bool isCharData() { return false; } + virtual ZxNode *getFirstChild() { return firstChild; } + virtual ZxNode *getNextChild() { return next; } + ZxNode *getParent() { return parent; } + ZxNode *deleteChild(ZxNode *child); + void appendChild(ZxNode *child); + void insertChildAfter(ZxNode *child, ZxNode *prev); + ZxElement *findFirstElement(const char *type); + ZxElement *findFirstChildElement(const char *type); + GList *findAllElements(const char *type); + GList *findAllChildElements(const char *type); + virtual void addChild(ZxNode *child); + + virtual bool write(ZxWriteFunc writeFunc, void *stream) = 0; + +protected: + + void findAllElements(const char *type, GList *results); + + ZxNode *next; + ZxNode *parent; + ZxNode *firstChild, + *lastChild; +}; + +//------------------------------------------------------------------------ + +class ZxDoc: public ZxNode { +public: + + ZxDoc(); + + // Parse from memory. Returns NULL on error. + static ZxDoc *loadMem(const char *data, Guint dataLen); + + // Parse from disk. Returns NULL on error. + static ZxDoc *loadFile(const char *fileName); + + virtual ~ZxDoc(); + + // Write to disk. Returns false on error. + bool writeFile(const char *fileName); + + virtual bool isDoc() { return true; } + ZxXMLDecl *getXMLDecl() { return xmlDecl; } + ZxDocTypeDecl *getDocTypeDecl() { return docTypeDecl; } + ZxElement *getRoot() { return root; } + virtual void addChild(ZxNode *node); + + virtual bool write(ZxWriteFunc writeFunc, void *stream); + +private: + + bool parse(const char *data, Guint dataLen); + void parseXMLDecl(ZxNode *par); + void parseDocTypeDecl(ZxNode *par); + void parseElement(ZxNode *par); + ZxAttr *parseAttr(); + void parseContent(ZxElement *par); + void parseCharData(ZxElement *par); + void appendUTF8(GString *s, unsigned int c); + void parseCDSect(ZxNode *par); + void parseMisc(ZxNode *par); + void parseComment(ZxNode *par); + void parsePI(ZxNode *par); + GString *parseName(); + GString *parseQuotedString(); + void parseSpace(); + bool match(const char *s); + + ZxXMLDecl *xmlDecl; // may be NULL + ZxDocTypeDecl *docTypeDecl; // may be NULL + ZxElement *root; // may be NULL + + const char *parsePtr; + const char *parseEnd; +}; + +//------------------------------------------------------------------------ + +class ZxXMLDecl: public ZxNode { +public: + + ZxXMLDecl(GString *versionA, GString *encodingA, bool standaloneA); + virtual ~ZxXMLDecl(); + + virtual bool isXMLDecl() { return true; } + GString *getVersion() { return version; } + GString *getEncoding() { return encoding; } + bool getStandalone() { return standalone; } + + virtual bool write(ZxWriteFunc writeFunc, void *stream); + +private: + + GString *version; + GString *encoding; // may be NULL + bool standalone; +}; + +//------------------------------------------------------------------------ + +class ZxDocTypeDecl: public ZxNode { +public: + + ZxDocTypeDecl(GString *nameA); + virtual ~ZxDocTypeDecl(); + + virtual bool isDocTypeDecl() { return true; } + GString *getName() { return name; } + + virtual bool write(ZxWriteFunc writeFunc, void *stream); + +private: + + GString *name; +}; + +//------------------------------------------------------------------------ + +class ZxComment: public ZxNode { +public: + + ZxComment(GString *textA); + virtual ~ZxComment(); + + virtual bool isComment() { return true; } + GString *getText() { return text; } + + virtual bool write(ZxWriteFunc writeFunc, void *stream); + +private: + + GString *text; +}; + +//------------------------------------------------------------------------ + +class ZxPI: public ZxNode { +public: + + ZxPI(GString *targetA, GString *textA); + virtual ~ZxPI(); + + virtual bool isPI() { return true; } + GString *getTarget() { return target; } + GString *getText() { return text; } + + virtual bool write(ZxWriteFunc writeFunc, void *stream); + +private: + + GString *target; + GString *text; +}; + +//------------------------------------------------------------------------ + +class ZxElement: public ZxNode { +public: + + ZxElement(GString *typeA); + virtual ~ZxElement(); + + virtual bool isElement() { return true; } + virtual bool isElement(const char *typeA); + GString *getType() { return type; } + ZxAttr *findAttr(const char *attrName); + ZxAttr *getFirstAttr() { return firstAttr; } + void addAttr(ZxAttr *attr); + + virtual bool write(ZxWriteFunc writeFunc, void *stream); + +private: + + void appendEscapedAttrValue(GString *out, GString *s); + + GString *type; + GHash *attrs; // [ZxAttr] + ZxAttr *firstAttr, *lastAttr; +}; + +//------------------------------------------------------------------------ + +class ZxAttr { +public: + + ZxAttr(GString *nameA, GString *valueA); + ~ZxAttr(); + + GString *getName() { return name; } + GString *getValue() { return value; } + ZxAttr *getNextAttr() { return next; } + ZxNode *getParent() { return parent; } + +private: + + GString *name; + GString *value; + ZxElement *parent; + ZxAttr *next; + + friend class ZxElement; +}; + +//------------------------------------------------------------------------ + +class ZxCharData: public ZxNode { +public: + + ZxCharData(GString *dataA, bool parsedA); + virtual ~ZxCharData(); + + virtual bool isCharData() { return true; } + GString *getData() { return data; } + bool isParsed() { return parsed; } + + virtual bool write(ZxWriteFunc writeFunc, void *stream); + +private: + + GString *data; // in UTF-8 format + bool parsed; +}; + +#endif diff --git a/xpdf/cmake_install.cmake b/xpdf/cmake_install.cmake new file mode 100644 index 0000000..f50b228 --- /dev/null +++ b/xpdf/cmake_install.cmake @@ -0,0 +1,228 @@ +# Install script for directory: /home/calvin/src/xpdf-4.04/xpdf + +# Set the install prefix +if(NOT DEFINED CMAKE_INSTALL_PREFIX) + set(CMAKE_INSTALL_PREFIX "/usr/local") +endif() +string(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") + +# Set the install configuration name. +if(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) + if(BUILD_TYPE) + string(REGEX REPLACE "^[^A-Za-z0-9_]+" "" + CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") + else() + set(CMAKE_INSTALL_CONFIG_NAME "") + endif() + message(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") +endif() + +# Set the component getting installed. +if(NOT CMAKE_INSTALL_COMPONENT) + if(COMPONENT) + message(STATUS "Install component: \"${COMPONENT}\"") + set(CMAKE_INSTALL_COMPONENT "${COMPONENT}") + else() + set(CMAKE_INSTALL_COMPONENT) + endif() +endif() + +# Install shared libraries without execute permission? +if(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE) + set(CMAKE_INSTALL_SO_NO_EXE "1") +endif() + +# Is this installation the result of a crosscompile? +if(NOT DEFINED CMAKE_CROSSCOMPILING) + set(CMAKE_CROSSCOMPILING "FALSE") +endif() + +# Set default install directory permissions. +if(NOT DEFINED CMAKE_OBJDUMP) + set(CMAKE_OBJDUMP "/usr/bin/objdump") +endif() + +if("x${CMAKE_INSTALL_COMPONENT}x" STREQUAL "xUnspecifiedx" OR NOT CMAKE_INSTALL_COMPONENT) + if(EXISTS "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/pdftops" AND + NOT IS_SYMLINK "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/pdftops") + file(RPATH_CHECK + FILE "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/pdftops" + RPATH "") + endif() + file(INSTALL DESTINATION "${CMAKE_INSTALL_PREFIX}/bin" TYPE EXECUTABLE FILES "/home/calvin/src/xpdf-4.04/xpdf/pdftops") + if(EXISTS "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/pdftops" AND + NOT IS_SYMLINK "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/pdftops") + if(CMAKE_INSTALL_DO_STRIP) + execute_process(COMMAND "/usr/bin/strip" "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/pdftops") + endif() + endif() +endif() + +if("x${CMAKE_INSTALL_COMPONENT}x" STREQUAL "xUnspecifiedx" OR NOT CMAKE_INSTALL_COMPONENT) + file(INSTALL DESTINATION "${CMAKE_INSTALL_PREFIX}/share/man/man1" TYPE FILE FILES "/home/calvin/src/xpdf-4.04/doc/pdftops.1") +endif() + +if("x${CMAKE_INSTALL_COMPONENT}x" STREQUAL "xUnspecifiedx" OR NOT CMAKE_INSTALL_COMPONENT) + if(EXISTS "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/pdftotext" AND + NOT IS_SYMLINK "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/pdftotext") + file(RPATH_CHECK + FILE "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/pdftotext" + RPATH "") + endif() + file(INSTALL DESTINATION "${CMAKE_INSTALL_PREFIX}/bin" TYPE EXECUTABLE FILES "/home/calvin/src/xpdf-4.04/xpdf/pdftotext") + if(EXISTS "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/pdftotext" AND + NOT IS_SYMLINK "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/pdftotext") + if(CMAKE_INSTALL_DO_STRIP) + execute_process(COMMAND "/usr/bin/strip" "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/pdftotext") + endif() + endif() +endif() + +if("x${CMAKE_INSTALL_COMPONENT}x" STREQUAL "xUnspecifiedx" OR NOT CMAKE_INSTALL_COMPONENT) + file(INSTALL DESTINATION "${CMAKE_INSTALL_PREFIX}/share/man/man1" TYPE FILE FILES "/home/calvin/src/xpdf-4.04/doc/pdftotext.1") +endif() + +if("x${CMAKE_INSTALL_COMPONENT}x" STREQUAL "xUnspecifiedx" OR NOT CMAKE_INSTALL_COMPONENT) + if(EXISTS "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/pdftohtml" AND + NOT IS_SYMLINK "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/pdftohtml") + file(RPATH_CHECK + FILE "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/pdftohtml" + RPATH "") + endif() + file(INSTALL DESTINATION "${CMAKE_INSTALL_PREFIX}/bin" TYPE EXECUTABLE FILES "/home/calvin/src/xpdf-4.04/xpdf/pdftohtml") + if(EXISTS "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/pdftohtml" AND + NOT IS_SYMLINK "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/pdftohtml") + if(CMAKE_INSTALL_DO_STRIP) + execute_process(COMMAND "/usr/bin/strip" "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/pdftohtml") + endif() + endif() +endif() + +if("x${CMAKE_INSTALL_COMPONENT}x" STREQUAL "xUnspecifiedx" OR NOT CMAKE_INSTALL_COMPONENT) + file(INSTALL DESTINATION "${CMAKE_INSTALL_PREFIX}/share/man/man1" TYPE FILE FILES "/home/calvin/src/xpdf-4.04/doc/pdftohtml.1") +endif() + +if("x${CMAKE_INSTALL_COMPONENT}x" STREQUAL "xUnspecifiedx" OR NOT CMAKE_INSTALL_COMPONENT) + if(EXISTS "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/pdfinfo" AND + NOT IS_SYMLINK "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/pdfinfo") + file(RPATH_CHECK + FILE "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/pdfinfo" + RPATH "") + endif() + file(INSTALL DESTINATION "${CMAKE_INSTALL_PREFIX}/bin" TYPE EXECUTABLE FILES "/home/calvin/src/xpdf-4.04/xpdf/pdfinfo") + if(EXISTS "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/pdfinfo" AND + NOT IS_SYMLINK "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/pdfinfo") + if(CMAKE_INSTALL_DO_STRIP) + execute_process(COMMAND "/usr/bin/strip" "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/pdfinfo") + endif() + endif() +endif() + +if("x${CMAKE_INSTALL_COMPONENT}x" STREQUAL "xUnspecifiedx" OR NOT CMAKE_INSTALL_COMPONENT) + file(INSTALL DESTINATION "${CMAKE_INSTALL_PREFIX}/share/man/man1" TYPE FILE FILES "/home/calvin/src/xpdf-4.04/doc/pdfinfo.1") +endif() + +if("x${CMAKE_INSTALL_COMPONENT}x" STREQUAL "xUnspecifiedx" OR NOT CMAKE_INSTALL_COMPONENT) + if(EXISTS "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/pdffonts" AND + NOT IS_SYMLINK "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/pdffonts") + file(RPATH_CHECK + FILE "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/pdffonts" + RPATH "") + endif() + file(INSTALL DESTINATION "${CMAKE_INSTALL_PREFIX}/bin" TYPE EXECUTABLE FILES "/home/calvin/src/xpdf-4.04/xpdf/pdffonts") + if(EXISTS "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/pdffonts" AND + NOT IS_SYMLINK "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/pdffonts") + if(CMAKE_INSTALL_DO_STRIP) + execute_process(COMMAND "/usr/bin/strip" "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/pdffonts") + endif() + endif() +endif() + +if("x${CMAKE_INSTALL_COMPONENT}x" STREQUAL "xUnspecifiedx" OR NOT CMAKE_INSTALL_COMPONENT) + file(INSTALL DESTINATION "${CMAKE_INSTALL_PREFIX}/share/man/man1" TYPE FILE FILES "/home/calvin/src/xpdf-4.04/doc/pdffonts.1") +endif() + +if("x${CMAKE_INSTALL_COMPONENT}x" STREQUAL "xUnspecifiedx" OR NOT CMAKE_INSTALL_COMPONENT) + if(EXISTS "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/pdfdetach" AND + NOT IS_SYMLINK "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/pdfdetach") + file(RPATH_CHECK + FILE "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/pdfdetach" + RPATH "") + endif() + file(INSTALL DESTINATION "${CMAKE_INSTALL_PREFIX}/bin" TYPE EXECUTABLE FILES "/home/calvin/src/xpdf-4.04/xpdf/pdfdetach") + if(EXISTS "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/pdfdetach" AND + NOT IS_SYMLINK "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/pdfdetach") + if(CMAKE_INSTALL_DO_STRIP) + execute_process(COMMAND "/usr/bin/strip" "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/pdfdetach") + endif() + endif() +endif() + +if("x${CMAKE_INSTALL_COMPONENT}x" STREQUAL "xUnspecifiedx" OR NOT CMAKE_INSTALL_COMPONENT) + file(INSTALL DESTINATION "${CMAKE_INSTALL_PREFIX}/share/man/man1" TYPE FILE FILES "/home/calvin/src/xpdf-4.04/doc/pdfdetach.1") +endif() + +if("x${CMAKE_INSTALL_COMPONENT}x" STREQUAL "xUnspecifiedx" OR NOT CMAKE_INSTALL_COMPONENT) + if(EXISTS "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/pdftoppm" AND + NOT IS_SYMLINK "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/pdftoppm") + file(RPATH_CHECK + FILE "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/pdftoppm" + RPATH "") + endif() + file(INSTALL DESTINATION "${CMAKE_INSTALL_PREFIX}/bin" TYPE EXECUTABLE FILES "/home/calvin/src/xpdf-4.04/xpdf/pdftoppm") + if(EXISTS "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/pdftoppm" AND + NOT IS_SYMLINK "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/pdftoppm") + if(CMAKE_INSTALL_DO_STRIP) + execute_process(COMMAND "/usr/bin/strip" "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/pdftoppm") + endif() + endif() +endif() + +if("x${CMAKE_INSTALL_COMPONENT}x" STREQUAL "xUnspecifiedx" OR NOT CMAKE_INSTALL_COMPONENT) + file(INSTALL DESTINATION "${CMAKE_INSTALL_PREFIX}/share/man/man1" TYPE FILE FILES "/home/calvin/src/xpdf-4.04/doc/pdftoppm.1") +endif() + +if("x${CMAKE_INSTALL_COMPONENT}x" STREQUAL "xUnspecifiedx" OR NOT CMAKE_INSTALL_COMPONENT) + if(EXISTS "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/pdftopng" AND + NOT IS_SYMLINK "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/pdftopng") + file(RPATH_CHECK + FILE "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/pdftopng" + RPATH "") + endif() + file(INSTALL DESTINATION "${CMAKE_INSTALL_PREFIX}/bin" TYPE EXECUTABLE FILES "/home/calvin/src/xpdf-4.04/xpdf/pdftopng") + if(EXISTS "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/pdftopng" AND + NOT IS_SYMLINK "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/pdftopng") + if(CMAKE_INSTALL_DO_STRIP) + execute_process(COMMAND "/usr/bin/strip" "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/pdftopng") + endif() + endif() +endif() + +if("x${CMAKE_INSTALL_COMPONENT}x" STREQUAL "xUnspecifiedx" OR NOT CMAKE_INSTALL_COMPONENT) + file(INSTALL DESTINATION "${CMAKE_INSTALL_PREFIX}/share/man/man1" TYPE FILE FILES "/home/calvin/src/xpdf-4.04/doc/pdftopng.1") +endif() + +if("x${CMAKE_INSTALL_COMPONENT}x" STREQUAL "xUnspecifiedx" OR NOT CMAKE_INSTALL_COMPONENT) + if(EXISTS "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/pdfimages" AND + NOT IS_SYMLINK "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/pdfimages") + file(RPATH_CHECK + FILE "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/pdfimages" + RPATH "") + endif() + file(INSTALL DESTINATION "${CMAKE_INSTALL_PREFIX}/bin" TYPE EXECUTABLE FILES "/home/calvin/src/xpdf-4.04/xpdf/pdfimages") + if(EXISTS "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/pdfimages" AND + NOT IS_SYMLINK "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/pdfimages") + if(CMAKE_INSTALL_DO_STRIP) + execute_process(COMMAND "/usr/bin/strip" "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/pdfimages") + endif() + endif() +endif() + +if("x${CMAKE_INSTALL_COMPONENT}x" STREQUAL "xUnspecifiedx" OR NOT CMAKE_INSTALL_COMPONENT) + file(INSTALL DESTINATION "${CMAKE_INSTALL_PREFIX}/share/man/man1" TYPE FILE FILES "/home/calvin/src/xpdf-4.04/doc/pdfimages.1") +endif() + +if("x${CMAKE_INSTALL_COMPONENT}x" STREQUAL "xUnspecifiedx" OR NOT CMAKE_INSTALL_COMPONENT) + file(INSTALL DESTINATION "${CMAKE_INSTALL_PREFIX}/share/man/man5" TYPE FILE FILES "/home/calvin/src/xpdf-4.04/doc/xpdfrc.5") +endif() + diff --git a/xpdf/config.h b/xpdf/config.h new file mode 100644 index 0000000..cfb79f7 --- /dev/null +++ b/xpdf/config.h @@ -0,0 +1,108 @@ +//======================================================================== +// +// config.h +// +// Copyright 1996-2022 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef CONFIG_H +#define CONFIG_H + +//------------------------------------------------------------------------ +// version +//------------------------------------------------------------------------ + +// xpdf version +#define xpdfVersion "4.04" +#define xpdfVersionNum 4.04 +#define xpdfMajorVersion 4 +#define xpdfMinorVersion 4 +#define xpdfUpdateVersion 0 +#define xpdfMajorVersionStr "4" +#define xpdfMinorVersionStr "4" +#define xpdfUpdateVersionStr "0" + +// supported PDF version +#define supportedPDFVersionStr "2.0" +#define supportedPDFVersionNum 2.0 + +// copyright notice +#define xpdfCopyright "Copyright 1996-2022 Glyph & Cog, LLC" + +// Windows resource file stuff +#define winxpdfVersion "WinXpdf 4.04" +#define xpdfCopyrightAmp "Copyright 1996-2022 Glyph && Cog, LLC" + +//------------------------------------------------------------------------ +// paper size +//------------------------------------------------------------------------ + +// default paper size (in points) for PostScript output +#ifdef A4_PAPER +#define defPaperWidth 595 // ISO A4 (210x297 mm) +#define defPaperHeight 842 +#else +#define defPaperWidth 612 // American letter (8.5x11") +#define defPaperHeight 792 +#endif + +//------------------------------------------------------------------------ +// config file (xpdfrc) path +//------------------------------------------------------------------------ + +// user config file name, relative to the user's home directory +#if defined(VMS) || defined(_WIN32) +#define xpdfUserConfigFile "xpdfrc" +#else +#define xpdfUserConfigFile ".xpdfrc" +#endif + +// system config file name (set via the configure script) +#if defined(_WIN32) +// under Windows, we get the directory with the executable and then +// append this file name +#define xpdfSysConfigFile "xpdfrc" +#elif defined(SYSTEM_XPDFRC) +#define xpdfSysConfigFile SYSTEM_XPDFRC +#else +#define xpdfSysConfigFile "/etc/xpdfrc" +#endif + +//------------------------------------------------------------------------ +// X-related constants +//------------------------------------------------------------------------ + +// default maximum size of color cube to allocate +#define defaultRGBCube 5 + +//------------------------------------------------------------------------ +// popen +//------------------------------------------------------------------------ + +#if defined(_MSC_VER) || defined(__BORLANDC__) +#define popen _popen +#define pclose _pclose +#endif + +#if defined(VMS) || defined(VMCMS) || defined(DOS) || defined(OS2) || defined(__EMX__) || defined(_WIN32) || defined(__DJGPP__) +#define POPEN_READ_MODE "rb" +#else +#define POPEN_READ_MODE "r" +#endif + +//------------------------------------------------------------------------ +// Win32 stuff +//------------------------------------------------------------------------ + +#ifdef CDECL +#undef CDECL +#endif + +#if defined(_MSC_VER) || defined(__BORLANDC__) +#define CDECL __cdecl +#else +#define CDECL +#endif + +#endif diff --git a/xpdf/pdfdetach b/xpdf/pdfdetach new file mode 100755 index 0000000..310e3a9 Binary files /dev/null and b/xpdf/pdfdetach differ diff --git a/xpdf/pdfdetach.cc b/xpdf/pdfdetach.cc new file mode 100644 index 0000000..581383f --- /dev/null +++ b/xpdf/pdfdetach.cc @@ -0,0 +1,216 @@ +//======================================================================== +// +// pdfdetach.cc +// +// Copyright 2010 Glyph & Cog, LLC +// +//======================================================================== + +#include +#include +#include "gtypes.h" +#include "gmem.h" +#include "gmempp.h" +#include "parseargs.h" +#include "GlobalParams.h" +#include "PDFDoc.h" +#include "CharTypes.h" +#include "UnicodeMap.h" +#include "UTF8.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[]) { + char *fileName; + UnicodeMap *uMap; + GString *ownerPW, *userPW; + PDFDoc *doc; + Unicode *name; + char uBuf[8]; + GString *path; + GBool ok; + int exitCode; + int nFiles, nameLen, n, i, j; + + exitCode = 99; + + // parse args + fixCommandLine(&argc, &argv); + 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 [www.xpdfreader.com]\n", xpdfVersion); + fprintf(stderr, "%s\n", xpdfCopyright); + if (!printVersion) { + printUsage("pdfdetach", "", argDesc); + } + goto err0; + } + fileName = argv[1]; + + // read config file + if (cfgFileName[0] && !pathIsFile(cfgFileName)) { + error(errConfig, -1, "Config file '{0:s}' doesn't exist or isn't a file", + cfgFileName); + } + globalParams = new GlobalParams(cfgFileName); + if (textEncName[0]) { + globalParams->setTextEncoding(textEncName); + } + + // get mapping to output encoding + if (!(uMap = globalParams->getTextEncoding())) { + error(errConfig, -1, "Couldn't get text encoding"); + 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]) { + path = new GString(savePath); + path->append('/'); + } else { + path = new GString(); + } + name = doc->getEmbeddedFileName(i); + nameLen = doc->getEmbeddedFileNameLength(i); + for (j = 0; j < nameLen; ++j) { + n = mapUTF8(name[j], uBuf, sizeof(uBuf)); + path->append(uBuf, n); + } + if (!doc->saveEmbeddedFileU(i, path->getCString())) { + error(errIO, -1, "Error saving embedded file as '{0:t}'", path); + delete path; + exitCode = 2; + goto err2; + } + delete path; + } + + // save an embedded file + } else { + if (saveNum < 1 || saveNum > nFiles) { + error(errCommandLine, -1, "Invalid file number"); + goto err2; + } + if (savePath[0]) { + path = new GString(savePath); + } else { + name = doc->getEmbeddedFileName(saveNum - 1); + nameLen = doc->getEmbeddedFileNameLength(saveNum - 1); + path = new GString(); + for (j = 0; j < nameLen; ++j) { + n = mapUTF8(name[j], uBuf, sizeof(uBuf)); + path->append(uBuf, n); + } + } + if (!doc->saveEmbeddedFileU(saveNum - 1, path->getCString())) { + error(errIO, -1, "Error saving embedded file as '{0:t}'", path); + delete path; + exitCode = 2; + goto err2; + } + delete path; + } + + 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 b/xpdf/pdffonts new file mode 100755 index 0000000..1a5dacc Binary files /dev/null and b/xpdf/pdffonts differ diff --git a/xpdf/pdffonts.cc b/xpdf/pdffonts.cc new file mode 100644 index 0000000..bde5755 --- /dev/null +++ b/xpdf/pdffonts.cc @@ -0,0 +1,455 @@ +//======================================================================== +// +// pdffonts.cc +// +// Copyright 2001-2007 Glyph & Cog, LLC +// +//======================================================================== + +#include +#include +#include +#include +#include +#include +#include +#include "gmem.h" +#include "gmempp.h" +#include "parseargs.h" +#include "GString.h" +#include "GlobalParams.h" +#include "Error.h" +#include "Object.h" +#include "Dict.h" +#include "GfxFont.h" +#include "Annot.h" +#include "AcroForm.h" +#include "PDFDoc.h" +#include "config.h" + +// NB: this must match the definition of GfxFontType in GfxFont.h. +static const char *fontTypeNames[] = { + "unknown", + "Type 1", + "Type 1C", + "Type 1C (OT)", + "Type 3", + "TrueType", + "TrueType (OT)", + "CID Type 0", + "CID Type 0C", + "CID Type 0C (OT)", + "CID TrueType", + "CID TrueType (OT)" +}; + +static void scanFonts(Object *obj, PDFDoc *doc); +static void scanFonts(Dict *resDict, PDFDoc *doc); +static void scanFont(GfxFont *font, PDFDoc *doc); +static GBool checkObject(Object *in, Object *out); + +static int firstPage = 1; +static int lastPage = 0; +static GBool showFontLoc = gFalse; +static GBool showFontLocPS = gFalse; +static char ownerPassword[33] = "\001"; +static char userPassword[33] = "\001"; +static char cfgFileName[256] = ""; +static GBool printVersion = gFalse; +static GBool printHelp = gFalse; + +static ArgDesc argDesc[] = { + {"-f", argInt, &firstPage, 0, + "first page to examine"}, + {"-l", argInt, &lastPage, 0, + "last page to examine"}, + {"-loc", argFlag, &showFontLoc, 0, + "print extended info on font location"}, + {"-locPS", argFlag, &showFontLocPS, 0, + "print extended info on font location for PostScript conversion"}, + {"-opw", argString, ownerPassword, sizeof(ownerPassword), + "owner password (for encrypted files)"}, + {"-upw", argString, userPassword, sizeof(userPassword), + "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} +}; + +static PDFDoc *doc; + +static Ref *fonts; +static int fontsLen; +static int fontsSize; + +static char *seenObjs; +static int numObjects; + +int main(int argc, char *argv[]) { + char *fileName; + GString *ownerPW, *userPW; + GBool ok; + Page *page; + Dict *resDict; + Annots *annots; + AcroForm *form; + Object obj1, obj2; + int pg, i, j; + int exitCode; + + exitCode = 99; + + // parse args + fixCommandLine(&argc, &argv); + ok = parseArgs(argDesc, &argc, argv); + if (!ok || argc != 2 || printVersion || printHelp) { + fprintf(stderr, "pdffonts version %s [www.xpdfreader.com]\n", xpdfVersion); + fprintf(stderr, "%s\n", xpdfCopyright); + if (!printVersion) { + printUsage("pdffonts", "", argDesc); + } + goto err0; + } + fileName = argv[1]; + + // read config file + if (cfgFileName[0] && !pathIsFile(cfgFileName)) { + error(errConfig, -1, "Config file '{0:s}' doesn't exist or isn't a file", + cfgFileName); + } + globalParams = new GlobalParams(cfgFileName); + globalParams->setupBaseFonts(NULL); + + // open PDF file + if (ownerPassword[0] != '\001') { + ownerPW = new GString(ownerPassword); + } else { + ownerPW = NULL; + } + if (userPassword[0] != '\001') { + userPW = new GString(userPassword); + } else { + userPW = NULL; + } + doc = new PDFDoc(fileName, ownerPW, userPW); + if (userPW) { + delete userPW; + } + if (ownerPW) { + delete ownerPW; + } + if (!doc->isOk()) { + exitCode = 1; + goto err1; + } + + // get page range + if (firstPage < 1) { + firstPage = 1; + } + if (lastPage < 1 || lastPage > doc->getNumPages()) { + lastPage = doc->getNumPages(); + } + + // scan the fonts + if (showFontLoc || showFontLocPS) { + printf("name type emb sub uni prob object ID location\n"); + printf("---------------------------------------------- ----------------- --- --- --- ---- --------- --------\n"); + } else { + printf("name type emb sub uni prob object ID\n"); + printf("---------------------------------------------- ----------------- --- --- --- ---- ---------\n"); + } + fonts = NULL; + fontsLen = fontsSize = 0; + numObjects = doc->getXRef()->getNumObjects(); + seenObjs = (char *)gmalloc(numObjects); + memset(seenObjs, 0, numObjects); + for (pg = firstPage; pg <= lastPage; ++pg) { + page = doc->getCatalog()->getPage(pg); + if ((resDict = page->getResourceDict())) { + scanFonts(resDict, doc); + } + annots = new Annots(doc, page->getAnnots(&obj1)); + obj1.free(); + for (i = 0; i < annots->getNumAnnots(); ++i) { + if (annots->getAnnot(i)->getAppearance(&obj1)->isStream()) { + obj1.streamGetDict()->lookupNF("Resources", &obj2); + scanFonts(&obj2, doc); + obj2.free(); + } + obj1.free(); + } + delete annots; + } + if ((form = doc->getCatalog()->getForm())) { + for (i = 0; i < form->getNumFields(); ++i) { + form->getField(i)->getResources(&obj1); + if (obj1.isArray()) { + for (j = 0; j < obj1.arrayGetLength(); ++j) { + obj1.arrayGetNF(j, &obj2); + scanFonts(&obj2, doc); + obj2.free(); + } + } else if (obj1.isDict()) { + scanFonts(obj1.getDict(), doc); + } + obj1.free(); + } + } + + exitCode = 0; + + // clean up + gfree(fonts); + gfree(seenObjs); + err1: + delete doc; + delete globalParams; + err0: + + // check for memory leaks + Object::memCheck(stderr); + gMemReport(stderr); + + return exitCode; +} + +static void scanFonts(Object *obj, PDFDoc *doc) { + Object obj2; + + if (checkObject(obj, &obj2) && obj2.isDict()) { + scanFonts(obj2.getDict(), doc); + } + obj2.free(); +} + +static void scanFonts(Dict *resDict, PDFDoc *doc) { + Object fontDict1, fontDict2, xObjDict1, xObjDict2, xObj1, xObj2; + Object patternDict1, patternDict2, pattern1, pattern2; + Object gsDict1, gsDict2, gs1, gs2, smask1, smask2, smaskGroup1, smaskGroup2; + Object resObj; + Ref r; + GfxFontDict *gfxFontDict; + GfxFont *font; + int i; + + // scan the fonts in this resource dictionary + gfxFontDict = NULL; + resDict->lookupNF("Font", &fontDict1); + if (checkObject(&fontDict1, &fontDict2) && fontDict2.isDict()) { + if (fontDict1.isRef()) { + r = fontDict1.getRef(); + gfxFontDict = new GfxFontDict(doc->getXRef(), &r, fontDict2.getDict()); + } else { + gfxFontDict = new GfxFontDict(doc->getXRef(), NULL, fontDict2.getDict()); + } + if (gfxFontDict) { + for (i = 0; i < gfxFontDict->getNumFonts(); ++i) { + if ((font = gfxFontDict->getFont(i))) { + scanFont(font, doc); + } + } + delete gfxFontDict; + } + } + fontDict2.free(); + fontDict1.free(); + + // recursively scan any resource dictionaries in XObjects in this + // resource dictionary + resDict->lookupNF("XObject", &xObjDict1); + if (checkObject(&xObjDict1, &xObjDict2) && xObjDict2.isDict()) { + for (i = 0; i < xObjDict2.dictGetLength(); ++i) { + xObjDict2.dictGetValNF(i, &xObj1); + if (checkObject(&xObj1, &xObj2) && xObj2.isStream()) { + xObj2.streamGetDict()->lookupNF("Resources", &resObj); + scanFonts(&resObj, doc); + resObj.free(); + } + xObj2.free(); + xObj1.free(); + } + } + xObjDict2.free(); + xObjDict1.free(); + + // recursively scan any resource dictionaries in Patterns in this + // resource dictionary + resDict->lookupNF("Pattern", &patternDict1); + if (checkObject(&patternDict1, &patternDict2) && patternDict2.isDict()) { + for (i = 0; i < patternDict2.dictGetLength(); ++i) { + patternDict2.dictGetValNF(i, &pattern1); + if (checkObject(&pattern1, &pattern2) && pattern2.isStream()) { + pattern2.streamGetDict()->lookupNF("Resources", &resObj); + scanFonts(&resObj, doc); + resObj.free(); + } + pattern2.free(); + pattern1.free(); + } + } + patternDict2.free(); + patternDict1.free(); + + // recursively scan any resource dictionaries in ExtGStates in this + // resource dictionary + resDict->lookupNF("ExtGState", &gsDict1); + if (checkObject(&gsDict1, &gsDict2) && gsDict2.isDict()) { + for (i = 0; i < gsDict2.dictGetLength(); ++i) { + gsDict2.dictGetValNF(i, &gs1); + if (checkObject(&gs1, &gs2) && gs2.isDict()) { + gs2.dictLookupNF("SMask", &smask1); + if (checkObject(&smask1, &smask2) && smask2.isDict()) { + smask2.dictLookupNF("G", &smaskGroup1); + if (checkObject(&smaskGroup1, &smaskGroup2) && + smaskGroup2.isStream()) { + smaskGroup2.streamGetDict()->lookupNF("Resources", &resObj); + scanFonts(&resObj, doc); + resObj.free(); + } + smaskGroup2.free(); + smaskGroup1.free(); + } + smask2.free(); + smask1.free(); + } + gs2.free(); + gs1.free(); + } + } + gsDict2.free(); + gsDict1.free(); +} + +static void scanFont(GfxFont *font, PDFDoc *doc) { + Ref fontRef, embRef; + Object fontObj, toUnicodeObj; + GString *name; + GBool emb, subset, hasToUnicode; + GfxFontLoc *loc; + int i; + + fontRef = *font->getID(); + + // check for an already-seen font + for (i = 0; i < fontsLen; ++i) { + if (fontRef.num == fonts[i].num && fontRef.gen == fonts[i].gen) { + return; + } + } + + // font name + name = font->getName(); + + // check for an embedded font + if (font->getType() == fontType3) { + emb = gTrue; + } else { + emb = font->getEmbeddedFontID(&embRef); + } + + // look for a ToUnicode map + hasToUnicode = gFalse; + if (doc->getXRef()->fetch(fontRef.num, fontRef.gen, &fontObj)->isDict()) { + hasToUnicode = fontObj.dictLookup("ToUnicode", &toUnicodeObj)->isStream(); + toUnicodeObj.free(); + } + fontObj.free(); + + // check for a font subset name: capital letters followed by a '+' + // sign + subset = gFalse; + if (name) { + for (i = 0; i < name->getLength(); ++i) { + if (name->getChar(i) < 'A' || name->getChar(i) > 'Z') { + break; + } + } + subset = i > 0 && i < name->getLength() && name->getChar(i) == '+'; + } + + // print the font info + printf("%-46s %-17s %-3s %-3s %-3s %-4s", + name ? name->getCString() : "[none]", + fontTypeNames[font->getType()], + emb ? "yes" : "no", + subset ? "yes" : "no", + hasToUnicode ? "yes" : "no", + font->problematicForUnicode() ? " X" : ""); + if (fontRef.gen >= 100000) { + printf(" [none]"); + } else { + printf(" %6d %2d", fontRef.num, fontRef.gen); + } + if (showFontLoc || showFontLocPS) { + if (font->getType() == fontType3) { + printf(" embedded"); + } else { + loc = font->locateFont(doc->getXRef(), showFontLocPS); + if (loc) { + if (loc->locType == gfxFontLocEmbedded) { + printf(" embedded"); + } else if (loc->locType == gfxFontLocExternal) { + if (loc->path) { + printf(" external: %s", loc->path->getCString()); + } else { + printf(" unavailable"); + } + } else if (loc->locType == gfxFontLocResident) { + if (loc->path) { + printf(" resident: %s", loc->path->getCString()); + } else { + printf(" unavailable"); + } + } + } else { + printf(" unknown"); + } + delete loc; + } + } + printf("\n"); + + // add this font to the list + if (fontsLen == fontsSize) { + 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(); +} + +static GBool checkObject(Object *in, Object *out) { + int objNum; + + if (!in->isRef()) { + in->copy(out); + return gTrue; + } + objNum = in->getRefNum(); + if (objNum < 0 || objNum >= numObjects) { + out->initNull(); + return gTrue; + } + if (seenObjs[objNum]) { + out->initNull(); + return gFalse; + } + seenObjs[objNum] = (char)1; + in->fetch(doc->getXRef(), out); + return gTrue; +} diff --git a/xpdf/pdfimages b/xpdf/pdfimages new file mode 100755 index 0000000..2c83a85 Binary files /dev/null and b/xpdf/pdfimages differ diff --git a/xpdf/pdfimages.cc b/xpdf/pdfimages.cc new file mode 100644 index 0000000..346346b --- /dev/null +++ b/xpdf/pdfimages.cc @@ -0,0 +1,174 @@ +//======================================================================== +// +// pdfimages.cc +// +// Copyright 1998-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include +#include +#include +#include +#include +#include "gmem.h" +#include "gmempp.h" +#include "parseargs.h" +#include "GString.h" +#include "GlobalParams.h" +#include "Object.h" +#include "Stream.h" +#include "Array.h" +#include "Dict.h" +#include "XRef.h" +#include "Catalog.h" +#include "Page.h" +#include "PDFDoc.h" +#include "ImageOutputDev.h" +#include "Error.h" +#include "config.h" + +static int firstPage = 1; +static int lastPage = 0; +static GBool dumpJPEG = gFalse; +static GBool dumpRaw = gFalse; +static GBool list = gFalse; +static char ownerPassword[33] = "\001"; +static char userPassword[33] = "\001"; +static GBool verbose = gFalse; +static GBool quiet = gFalse; +static char cfgFileName[256] = ""; +static GBool printVersion = gFalse; +static GBool printHelp = gFalse; + +static ArgDesc argDesc[] = { + {"-f", argInt, &firstPage, 0, + "first page to convert"}, + {"-l", argInt, &lastPage, 0, + "last page to convert"}, + {"-j", argFlag, &dumpJPEG, 0, + "write JPEG images as JPEG files"}, + {"-raw", argFlag, &dumpRaw, 0, + "write raw data in PDF-native formats"}, + {"-list", argFlag, &list, 0, + "write information to stdout for each image"}, + {"-opw", argString, ownerPassword, sizeof(ownerPassword), + "owner password (for encrypted files)"}, + {"-upw", argString, userPassword, sizeof(userPassword), + "user password (for encrypted files)"}, + {"-verbose", argFlag, &verbose, 0, + "print per-page status information"}, + {"-q", argFlag, &quiet, 0, + "don't print any messages or errors"}, + {"-cfg", argString, cfgFileName, sizeof(cfgFileName), + "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[]) { + PDFDoc *doc; + char *fileName; + char *imgRoot; + GString *ownerPW, *userPW; + ImageOutputDev *imgOut; + GBool ok; + int exitCode; + + exitCode = 99; + + // parse args + fixCommandLine(&argc, &argv); + ok = parseArgs(argDesc, &argc, argv); + if (!ok || argc != 3 || printVersion || printHelp) { + fprintf(stderr, "pdfimages version %s [www.xpdfreader.com]\n", xpdfVersion); + fprintf(stderr, "%s\n", xpdfCopyright); + if (!printVersion) { + printUsage("pdfimages", " ", argDesc); + } + goto err0; + } + fileName = argv[1]; + imgRoot = argv[2]; + + // read config file + if (cfgFileName[0] && !pathIsFile(cfgFileName)) { + error(errConfig, -1, "Config file '{0:s}' doesn't exist or isn't a file", + cfgFileName); + } + globalParams = new GlobalParams(cfgFileName); + if (verbose) { + globalParams->setPrintStatusInfo(verbose); + } + if (quiet) { + globalParams->setErrQuiet(quiet); + } + + // open PDF file + if (ownerPassword[0] != '\001') { + ownerPW = new GString(ownerPassword); + } else { + ownerPW = NULL; + } + if (userPassword[0] != '\001') { + userPW = new GString(userPassword); + } else { + userPW = NULL; + } + doc = new PDFDoc(fileName, ownerPW, userPW); + if (userPW) { + delete userPW; + } + if (ownerPW) { + delete ownerPW; + } + if (!doc->isOk()) { + exitCode = 1; + goto err1; + } + + // check for copy permission + if (!doc->okToCopy()) { + error(errNotAllowed, -1, + "Copying of images from this document is not allowed."); + exitCode = 3; + goto err1; + } + + // get page range + if (firstPage < 1) + firstPage = 1; + if (lastPage < 1 || lastPage > doc->getNumPages()) + lastPage = doc->getNumPages(); + + // write image files + imgOut = new ImageOutputDev(imgRoot, dumpJPEG, dumpRaw, list); + if (imgOut->isOk()) { + doc->displayPages(imgOut, firstPage, lastPage, 72, 72, 0, + gFalse, gTrue, gFalse); + } + delete imgOut; + + exitCode = 0; + + // clean up + err1: + delete doc; + delete globalParams; + err0: + + // check for memory leaks + Object::memCheck(stderr); + gMemReport(stderr); + + return exitCode; +} diff --git a/xpdf/pdfinfo b/xpdf/pdfinfo new file mode 100755 index 0000000..ddd0ba2 Binary files /dev/null and b/xpdf/pdfinfo differ diff --git a/xpdf/pdfinfo.cc b/xpdf/pdfinfo.cc new file mode 100644 index 0000000..88829b9 --- /dev/null +++ b/xpdf/pdfinfo.cc @@ -0,0 +1,555 @@ +//======================================================================== +// +// pdfinfo.cc +// +// Copyright 1998-2013 Glyph & Cog, LLC +// +//======================================================================== + +#include +#include +#include +#include +#include +#include +#include +#include +#include "gmem.h" +#include "gmempp.h" +#include "parseargs.h" +#include "GString.h" +#include "gfile.h" +#include "GlobalParams.h" +#include "Object.h" +#include "Stream.h" +#include "Array.h" +#include "Dict.h" +#include "XRef.h" +#include "Catalog.h" +#include "Page.h" +#include "PDFDoc.h" +#include "CharTypes.h" +#include "UnicodeMap.h" +#include "TextString.h" +#include "UTF8.h" +#include "Zoox.h" +#include "Error.h" +#include "config.h" + +static void printInfoString(Object *infoDict, const char *infoKey, + ZxDoc *xmp, const char *xmpKey1, + const char *xmpKey2, + const char *text, GBool parseDate, + UnicodeMap *uMap); +static GString *parseInfoDate(GString *s); +static GString *parseXMPDate(GString *s); +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"; +static char cfgFileName[256] = ""; +static GBool printVersion = gFalse; +static GBool printHelp = gFalse; + +static ArgDesc argDesc[] = { + {"-f", argInt, &firstPage, 0, + "first page to convert"}, + {"-l", argInt, &lastPage, 0, + "last page to convert"}, + {"-box", argFlag, &printBoxes, 0, + "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), + "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[]) { + PDFDoc *doc; + char *fileName; + GString *ownerPW, *userPW; + UnicodeMap *uMap; + Page *page; + Object info, xfa; + Object *acroForm; + char buf[256]; + double w, h, wISO, hISO; + FILE *f; + GString *metadata; + ZxDoc *xmp; + int permFlags, keyLength, encVersion; + GBool ownerPasswordOk; + CryptAlgorithm encAlgorithm; + GBool ok; + int exitCode; + int pg, i; + GBool multiPage; + + exitCode = 99; + + // parse args + fixCommandLine(&argc, &argv); + ok = parseArgs(argDesc, &argc, argv); + if (!ok || argc != 2 || printVersion || printHelp) { + fprintf(stderr, "pdfinfo version %s [www.xpdfreader.com]\n", xpdfVersion); + fprintf(stderr, "%s\n", xpdfCopyright); + if (!printVersion) { + printUsage("pdfinfo", "", argDesc); + } + goto err0; + } + fileName = argv[1]; + + // read config file + if (cfgFileName[0] && !pathIsFile(cfgFileName)) { + error(errConfig, -1, "Config file '{0:s}' doesn't exist or isn't a file", + cfgFileName); + } + globalParams = new GlobalParams(cfgFileName); + if (textEncName[0]) { + globalParams->setTextEncoding(textEncName); + } + + // get mapping to output encoding + if (!(uMap = globalParams->getTextEncoding())) { + error(errConfig, -1, "Couldn't get text encoding"); + 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; + } + + // get page range + if (firstPage < 1) { + firstPage = 1; + } + if (lastPage == 0) { + multiPage = gFalse; + lastPage = 1; + } else { + multiPage = gTrue; + } + if (lastPage < 1 || lastPage > doc->getNumPages()) { + lastPage = doc->getNumPages(); + } + + // print doc info + doc->getDocInfo(&info); + if ((metadata = doc->readMetadata())) { + xmp = ZxDoc::loadMem(metadata->getCString(), metadata->getLength()); + } else { + xmp = NULL; + } + printInfoString(&info, "Title", xmp, "dc:title", NULL, "Title: ", gFalse, uMap); + printInfoString(&info, "Subject", xmp, "dc:description", NULL, "Subject: ", gFalse, uMap); + printInfoString(&info, "Keywords", xmp, "pdf:Keywords", NULL, "Keywords: ", gFalse, uMap); + printInfoString(&info, "Author", xmp, "dc:creator", NULL, "Author: ", gFalse, uMap); + printInfoString(&info, "Creator", xmp, "xmp:CreatorTool", NULL, "Creator: ", gFalse, uMap); + printInfoString(&info, "Producer", xmp, "pdf:Producer", NULL, "Producer: ", gFalse, uMap); + printInfoString(&info, "CreationDate", xmp, "xap:CreateDate", "xmp:CreateDate", "CreationDate: ", !rawDates, uMap); + printInfoString(&info, "ModDate", xmp, "xap:ModifyDate", "xmp:ModifyDate", "ModDate: ", !rawDates, uMap); + info.free(); + if (xmp) { + delete xmp; + } + + // print tagging info + 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()) { + if (doc->getCatalog()->getNeedsRendering()) { + printf("Form: dynamic XFA\n"); + } else { + printf("Form: static XFA\n"); + } + } else { + printf("Form: AcroForm\n"); + } + xfa.free(); + } else { + printf("Form: none\n"); + } + + // print page count + printf("Pages: %d\n", doc->getNumPages()); + + // print encryption info + if (doc->isEncrypted()) { + doc->getXRef()->getEncryption(&permFlags, &ownerPasswordOk, &keyLength, + &encVersion, &encAlgorithm); + printf("Encrypted: %s %d-bit\n", + encAlgorithm == cryptRC4 ? "RC4" : "AES", + keyLength * 8); + printf("Permissions: print:%s copy:%s change:%s addNotes:%s\n", + doc->okToPrint(gTrue) ? "yes" : "no", + doc->okToCopy(gTrue) ? "yes" : "no", + doc->okToChange(gTrue) ? "yes" : "no", + doc->okToAddNotes(gTrue) ? "yes" : "no"); + } else { + printf("Encrypted: no\n"); + } + + // print page size + for (pg = firstPage; pg <= lastPage; ++pg) { + w = doc->getPageCropWidth(pg); + h = doc->getPageCropHeight(pg); + if (multiPage) { + printf("Page %4d size: %g x %g pts", pg, w, h); + } else { + printf("Page size: %g x %g pts", w, h); + } + if ((fabs(w - 612) < 0.1 && fabs(h - 792) < 0.1) || + (fabs(w - 792) < 0.1 && fabs(h - 612) < 0.1)) { + printf(" (letter)"); + } else { + hISO = sqrt(sqrt(2.0)) * 7200 / 2.54; + wISO = hISO / sqrt(2.0); + for (i = 0; i <= 6; ++i) { + if ((fabs(w - wISO) < 1 && fabs(h - hISO) < 1) || + (fabs(w - hISO) < 1 && fabs(h - wISO) < 1)) { + printf(" (A%d)", i); + break; + } + hISO = wISO; + wISO /= sqrt(2.0); + } + } + printf(" (rotated %d degrees)", doc->getPageRotate(pg)); + printf("\n"); + } + + // print the boxes + if (printBoxes) { + if (multiPage) { + for (pg = firstPage; pg <= lastPage; ++pg) { + page = doc->getCatalog()->getPage(pg); + snprintf(buf, sizeof(buf), "Page %4d MediaBox: ", pg); + printBox(buf, page->getMediaBox()); + snprintf(buf, sizeof(buf), "Page %4d CropBox: ", pg); + printBox(buf, page->getCropBox()); + snprintf(buf, sizeof(buf), "Page %4d BleedBox: ", pg); + printBox(buf, page->getBleedBox()); + snprintf(buf, sizeof(buf), "Page %4d TrimBox: ", pg); + printBox(buf, page->getTrimBox()); + snprintf(buf, sizeof(buf), "Page %4d ArtBox: ", pg); + printBox(buf, page->getArtBox()); + } + } else if (doc->getNumPages() > 0) { + page = doc->getCatalog()->getPage(firstPage); + printBox("MediaBox: ", page->getMediaBox()); + printBox("CropBox: ", page->getCropBox()); + printBox("BleedBox: ", page->getBleedBox()); + printBox("TrimBox: ", page->getTrimBox()); + printBox("ArtBox: ", page->getArtBox()); + } + } + + // print file size + f = openFile(fileName, "rb"); + if (f) { + gfseek(f, 0, SEEK_END); + printf("File size: %u bytes\n", (Guint)gftell(f)); + fclose(f); + } + + // print linearization info + printf("Optimized: %s\n", doc->isLinearized() ? "yes" : "no"); + + // print PDF version + printf("PDF version: %.1f\n", doc->getPDFVersion()); + + // print the metadata + if (printMetadata && metadata) { + fputs("Metadata:\n", stdout); + fputs(metadata->getCString(), stdout); + fputc('\n', stdout); + } + + if (metadata) { + delete metadata; + } + + exitCode = 0; + + // clean up + err2: + uMap->decRefCnt(); + delete doc; + err1: + delete globalParams; + err0: + + // check for memory leaks + Object::memCheck(stderr); + gMemReport(stderr); + + return exitCode; +} + +static void printInfoString(Object *infoDict, const char *infoKey, + ZxDoc *xmp, const char *xmpKey1, + const char *xmpKey2, + const char *text, GBool parseDate, + UnicodeMap *uMap) { + Object obj; + TextString *s; + Unicode *u; + Unicode uu; + char buf[8]; + GString *value, *tmp; + ZxElement *rdf, *elem, *child; + ZxNode *node, *node2; + int i, n; + + value = NULL; + + //-- check the info dictionary + if (infoDict->isDict()) { + if (infoDict->dictLookup(infoKey, &obj)->isString()) { + if (!parseDate || !(value = parseInfoDate(obj.getString()))) { + s = new TextString(obj.getString()); + u = s->getUnicode(); + value = new GString(); + for (i = 0; i < s->getLength(); ++i) { + n = uMap->mapUnicode(u[i], buf, sizeof(buf)); + value->append(buf, n); + } + delete s; + } + } + obj.free(); + } + + //-- check the XMP metadata + if (xmp) { + rdf = xmp->getRoot(); + if (rdf->isElement("x:xmpmeta")) { + rdf = rdf->findFirstChildElement("rdf:RDF"); + } + if (rdf && rdf->isElement("rdf:RDF")) { + for (node = rdf->getFirstChild(); node; node = node->getNextChild()) { + if (node->isElement("rdf:Description")) { + if (!(elem = node->findFirstChildElement(xmpKey1)) && xmpKey2) { + elem = node->findFirstChildElement(xmpKey2); + } + if (elem) { + if ((child = elem->findFirstChildElement("rdf:Alt")) || + (child = elem->findFirstChildElement("rdf:Seq"))) { + if ((node2 = child->findFirstChildElement("rdf:li"))) { + node2 = node2->getFirstChild(); + } + } else { + node2 = elem->getFirstChild(); + } + if (node2 && node2->isCharData()) { + if (value) { + delete value; + } + if (!parseDate || + !(value = parseXMPDate(((ZxCharData *)node2)->getData()))) { + tmp = ((ZxCharData *)node2)->getData(); + int i = 0; + value = new GString(); + while (getUTF8(tmp, &i, &uu)) { + n = uMap->mapUnicode(uu, buf, sizeof(buf)); + value->append(buf, n); + } + } + } + break; + } + } + } + } + } + + if (value) { + fputs(text, stdout); + fwrite(value->getCString(), 1, value->getLength(), stdout); + fputc('\n', stdout); + delete value; + } +} + +static GString *parseInfoDate(GString *s) { + int year, mon, day, hour, min, sec, n; + struct tm tmStruct; + char buf[256]; + char *p; + + p = s->getCString(); + if (p[0] == 'D' && p[1] == ':') { + p += 2; + } + if ((n = sscanf(p, "%4d%2d%2d%2d%2d%2d", + &year, &mon, &day, &hour, &min, &sec)) < 1) { + return NULL; + } + switch (n) { + case 1: mon = 1; + case 2: day = 1; + case 3: hour = 0; + case 4: min = 0; + case 5: sec = 0; + } + tmStruct.tm_year = year - 1900; + tmStruct.tm_mon = mon - 1; + tmStruct.tm_mday = day; + tmStruct.tm_hour = hour; + tmStruct.tm_min = min; + tmStruct.tm_sec = sec; + tmStruct.tm_wday = -1; + tmStruct.tm_yday = -1; + tmStruct.tm_isdst = -1; + // compute the tm_wday and tm_yday fields + if (!(mktime(&tmStruct) != (time_t)-1 && + strftime(buf, sizeof(buf), "%c", &tmStruct))) { + return NULL; + } + return new GString(buf); +} + +static GString *parseXMPDate(GString *s) { + int year, mon, day, hour, min, sec, tz; + struct tm tmStruct; + char buf[256]; + char *p; + + p = s->getCString(); + if (isdigit(p[0]) && isdigit(p[1]) && isdigit(p[2]) && isdigit(p[3])) { + buf[0] = p[0]; + buf[1] = p[1]; + buf[2] = p[2]; + buf[3] = p[3]; + buf[4] = '\0'; + year = atoi(buf); + p += 4; + } else { + return NULL; + } + mon = day = 1; + hour = min = sec = 0; + tz = 2000; + if (p[0] == '-' && isdigit(p[1]) && isdigit(p[2])) { + buf[0] = p[1]; + buf[1] = p[2]; + buf[2] = '\0'; + mon = atoi(buf); + p += 3; + if (p[0] == '-' && isdigit(p[1]) && isdigit(p[2])) { + buf[0] = p[1]; + buf[1] = p[2]; + buf[2] = '\0'; + day = atoi(buf); + p += 3; + if (p[0] == 'T' && isdigit(p[1]) && isdigit(p[2]) && + p[3] == ':' && isdigit(p[4]) && isdigit(p[5])) { + buf[0] = p[1]; + buf[1] = p[2]; + buf[2] = '\0'; + hour = atoi(buf); + buf[0] = p[4]; + buf[1] = p[5]; + buf[2] = '\0'; + min = atoi(buf); + p += 6; + if (p[0] == ':' && isdigit(p[1]) && isdigit(p[2])) { + buf[0] = p[1]; + buf[1] = p[2]; + buf[2] = '\0'; + sec = atoi(buf); + if (p[0] == '.' && isdigit(p[1])) { + p += 2; + } + } + if ((p[0] == '+' || p[0] == '-') && + isdigit(p[1]) && isdigit(p[2]) && p[3] == ':' && + isdigit(p[4]) && isdigit(p[5])) { + buf[0] = p[1]; + buf[1] = p[2]; + buf[2] = '\0'; + tz = atoi(buf); + buf[0] = p[4]; + buf[1] = p[5]; + buf[2] = '\0'; + tz = tz * 60 + atoi(buf); + tz = tz * 60; + if (p[0] == '-') { + tz = -tz; + } + } + } + } + } + + tmStruct.tm_year = year - 1900; + tmStruct.tm_mon = mon - 1; + tmStruct.tm_mday = day; + tmStruct.tm_hour = hour; + tmStruct.tm_min = min; + tmStruct.tm_sec = sec; + tmStruct.tm_wday = -1; + tmStruct.tm_yday = -1; + tmStruct.tm_isdst = -1; + // compute the tm_wday and tm_yday fields + //~ this ignores the timezone + if (!(mktime(&tmStruct) != (time_t)-1 && + strftime(buf, sizeof(buf), "%c", &tmStruct))) { + return NULL; + } + return new GString(buf); +} + +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/pdftohtml b/xpdf/pdftohtml new file mode 100755 index 0000000..668be19 Binary files /dev/null and b/xpdf/pdftohtml differ diff --git a/xpdf/pdftohtml.cc b/xpdf/pdftohtml.cc new file mode 100644 index 0000000..4c98afe --- /dev/null +++ b/xpdf/pdftohtml.cc @@ -0,0 +1,300 @@ +//======================================================================== +// +// pdftohtml.cc +// +// Copyright 2005 Glyph & Cog, LLC +// +//======================================================================== + +#include +#include +#include +#include "gmem.h" +#include "gmempp.h" +#include "parseargs.h" +#include "gfile.h" +#include "GString.h" +#include "GlobalParams.h" +#include "PDFDoc.h" +#include "HTMLGen.h" +#include "Error.h" +#include "ErrorCodes.h" +#include "config.h" + +//------------------------------------------------------------------------ + +static GBool createIndex(char *htmlDir); + +//------------------------------------------------------------------------ + +static int firstPage = 1; +static int lastPage = 0; +static double zoom = 1; +static int resolution = 150; +static double vStretch = 1; +static GBool embedBackground = gFalse; +static GBool noFonts = gFalse; +static GBool embedFonts = gFalse; +static GBool skipInvisible = gFalse; +static GBool allInvisible = gFalse; +static GBool formFields = gFalse; +static GBool tableMode = gFalse; +static char ownerPassword[33] = "\001"; +static char userPassword[33] = "\001"; +static GBool verbose = gFalse; +static GBool quiet = gFalse; +static char cfgFileName[256] = ""; +static GBool printVersion = gFalse; +static GBool printHelp = gFalse; + +static ArgDesc argDesc[] = { + {"-f", argInt, &firstPage, 0, + "first page to convert"}, + {"-l", argInt, &lastPage, 0, + "last page to convert"}, + {"-z", argFP, &zoom, 0, + "initial zoom level (1.0 means 72dpi)"}, + {"-r", argInt, &resolution, 0, + "resolution, in DPI (default is 150)"}, + {"-vstretch", argFP, &vStretch, 0, + "vertical stretch factor (1.0 means no stretching)"}, + {"-embedbackground", argFlag, &embedBackground, 0, + "embed the background image as base64-encoded data" }, + {"-nofonts", argFlag, &noFonts, 0, + "do not extract embedded fonts"}, + {"-embedfonts", argFlag, &embedFonts, 0, + "embed the fonts as base64-encoded data" }, + {"-skipinvisible", argFlag, &skipInvisible, 0, + "do not draw invisible text"}, + {"-allinvisible", argFlag, &allInvisible, 0, + "treat all text as invisible"}, + {"-formfields", argFlag, &formFields, 0, + "convert form fields to HTML"}, + {"-table", argFlag, &tableMode, 0, + "use table mode for text extraction"}, + {"-opw", argString, ownerPassword, sizeof(ownerPassword), + "owner password (for encrypted files)"}, + {"-upw", argString, userPassword, sizeof(userPassword), + "user password (for encrypted files)"}, + {"-verbose", argFlag, &verbose, 0, + "print per-page status information"}, + {"-q", argFlag, &quiet, 0, + "don't print any messages or errors"}, + {"-cfg", argString, cfgFileName, sizeof(cfgFileName), + "configuration file to use in place of .xpdfrc"}, + {"-v", argFlag, &printVersion, 0, + "print copyright and version info"}, + {"-h", argFlag, &printHelp, 0, + "print usage information"}, + {"-help", argFlag, &printHelp, 0, + "print usage information"}, + {"--help", argFlag, &printHelp, 0, + "print usage information"}, + {"-?", argFlag, &printHelp, 0, + "print usage information"}, + {NULL} +}; + +//------------------------------------------------------------------------ + +static int writeToFile(void *file, const char *data, int size) { + return (int)fwrite(data, 1, size, (FILE *)file); +} + +int main(int argc, char *argv[]) { + PDFDoc *doc; + char *fileName; + char *htmlDir; + GString *ownerPW, *userPW; + HTMLGen *htmlGen; + GString *htmlFileName, *pngFileName, *pngURL; + FILE *htmlFile, *pngFile; + int pg, err, exitCode; + GBool ok; + + exitCode = 99; + + // parse args + fixCommandLine(&argc, &argv); + ok = parseArgs(argDesc, &argc, argv); + if (!ok || argc != 3 || printVersion || printHelp) { + fprintf(stderr, "pdftohtml version %s [www.xpdfreader.com]\n", xpdfVersion); + fprintf(stderr, "%s\n", xpdfCopyright); + if (!printVersion) { + printUsage("pdftohtml", " ", argDesc); + } + goto err0; + } + fileName = argv[1]; + htmlDir = argv[2]; + + // read config file + if (cfgFileName[0] && !pathIsFile(cfgFileName)) { + error(errConfig, -1, "Config file '{0:s}' doesn't exist or isn't a file", + cfgFileName); + } + globalParams = new GlobalParams(cfgFileName); + if (verbose) { + globalParams->setPrintStatusInfo(verbose); + } + if (quiet) { + globalParams->setErrQuiet(quiet); + } + globalParams->setupBaseFonts(NULL); + globalParams->setTextEncoding("UTF-8"); + + // open PDF file + if (ownerPassword[0] != '\001') { + ownerPW = new GString(ownerPassword); + } else { + ownerPW = NULL; + } + if (userPassword[0] != '\001') { + userPW = new GString(userPassword); + } else { + userPW = NULL; + } + doc = new PDFDoc(fileName, ownerPW, userPW); + if (userPW) { + delete userPW; + } + if (ownerPW) { + delete ownerPW; + } + if (!doc->isOk()) { + exitCode = 1; + goto err1; + } + + // check for copy permission + if (!doc->okToCopy()) { + error(errNotAllowed, -1, + "Copying of text from this document is not allowed."); + exitCode = 3; + goto err1; + } + + // get page range + if (firstPage < 1) { + firstPage = 1; + } + if (lastPage < 1 || lastPage > doc->getNumPages()) { + lastPage = doc->getNumPages(); + } + + // create HTML directory + if (makeDir(htmlDir, 0755)) { + error(errIO, -1, "Couldn't create HTML output directory '{0:s}'", + htmlDir); + exitCode = 2; + goto err1; + } + + // set up the HTMLGen object + htmlGen = new HTMLGen(resolution, tableMode); + if (!htmlGen->isOk()) { + exitCode = 99; + goto err1; + } + htmlGen->setZoom(zoom); + htmlGen->setVStretch(vStretch); + htmlGen->setDrawInvisibleText(!skipInvisible); + htmlGen->setAllTextInvisible(allInvisible); + htmlGen->setEmbedBackgroundImage(embedBackground); + htmlGen->setExtractFontFiles(!noFonts); + htmlGen->setEmbedFonts(embedFonts); + htmlGen->setConvertFormFields(formFields); + htmlGen->startDoc(doc); + + // convert the pages + for (pg = firstPage; pg <= lastPage; ++pg) { + if (globalParams->getPrintStatusInfo()) { + fflush(stderr); + printf("[processing page %d]\n", pg); + fflush(stdout); + } + htmlFileName = GString::format("{0:s}/page{1:d}.html", htmlDir, pg); + pngFileName = GString::format("{0:s}/page{1:d}.png", htmlDir, pg); + if (!(htmlFile = openFile(htmlFileName->getCString(), "wb"))) { + error(errIO, -1, "Couldn't open HTML file '{0:t}'", htmlFileName); + delete htmlFileName; + delete pngFileName; + goto err2; + } + if (embedBackground) { + pngFile = NULL; + } else { + if (!(pngFile = openFile(pngFileName->getCString(), "wb"))) { + error(errIO, -1, "Couldn't open PNG file '{0:t}'", pngFileName); + fclose(htmlFile); + delete htmlFileName; + delete pngFileName; + goto err2; + } + } + pngURL = GString::format("page{0:d}.png", pg); + err = htmlGen->convertPage(pg, pngURL->getCString(), htmlDir, + &writeToFile, htmlFile, + &writeToFile, pngFile); + delete pngURL; + fclose(htmlFile); + if (!embedBackground) { + fclose(pngFile); + } + delete htmlFileName; + delete pngFileName; + if (err != errNone) { + error(errIO, -1, "Error converting page {0:d}", pg); + exitCode = 2; + goto err2; + } + } + + // create the master index + if (!createIndex(htmlDir)) { + exitCode = 2; + goto err2; + } + + exitCode = 0; + + // clean up + err2: + delete htmlGen; + err1: + delete doc; + delete globalParams; + err0: + + // check for memory leaks + Object::memCheck(stderr); + gMemReport(stderr); + + return exitCode; +} + +static GBool createIndex(char *htmlDir) { + GString *htmlFileName; + FILE *html; + int pg; + + htmlFileName = GString::format("{0:s}/index.html", htmlDir); + html = openFile(htmlFileName->getCString(), "w"); + delete htmlFileName; + if (!html) { + error(errIO, -1, "Couldn't open HTML file '{0:t}'", htmlFileName); + return gFalse; + } + + fprintf(html, "\n"); + fprintf(html, "\n"); + for (pg = firstPage; pg <= lastPage; ++pg) { + fprintf(html, "page %d
\n", pg, pg); + } + fprintf(html, "\n"); + fprintf(html, "\n"); + + fclose(html); + + return gTrue; +} diff --git a/xpdf/pdftopng b/xpdf/pdftopng new file mode 100755 index 0000000..f3120c5 Binary files /dev/null and b/xpdf/pdftopng differ diff --git a/xpdf/pdftopng.cc b/xpdf/pdftopng.cc new file mode 100644 index 0000000..7f3b97b --- /dev/null +++ b/xpdf/pdftopng.cc @@ -0,0 +1,386 @@ +//======================================================================== +// +// pdftopng.cc +// +// Copyright 2009 Glyph & Cog, LLC +// +//======================================================================== + +#include +#include +#include +#include +#ifdef _WIN32 +# include +# include +#endif +#include "gmem.h" +#include "gmempp.h" +#include "parseargs.h" +#include "GString.h" +#include "gfile.h" +#include "GlobalParams.h" +#include "Object.h" +#include "PDFDoc.h" +#include "SplashBitmap.h" +#include "Splash.h" +#include "SplashOutputDev.h" +#include "Error.h" +#include "config.h" + +static int firstPage = 1; +static int lastPage = 0; +static double resolution = 150; +static GBool mono = gFalse; +static GBool gray = gFalse; +static GBool pngAlpha = gFalse; +static int rotate = 0; +static char enableFreeTypeStr[16] = ""; +static char antialiasStr[16] = ""; +static char vectorAntialiasStr[16] = ""; +static char ownerPassword[33] = ""; +static char userPassword[33] = ""; +static GBool verbose = gFalse; +static GBool quiet = gFalse; +static char cfgFileName[256] = ""; +static GBool printVersion = gFalse; +static GBool printHelp = gFalse; + +static ArgDesc argDesc[] = { + {"-f", argInt, &firstPage, 0, + "first page to print"}, + {"-l", argInt, &lastPage, 0, + "last page to print"}, + {"-r", argFP, &resolution, 0, + "resolution, in DPI (default is 150)"}, + {"-mono", argFlag, &mono, 0, + "generate a monochrome PNG file"}, + {"-gray", argFlag, &gray, 0, + "generate a grayscale PNG file"}, + {"-alpha", argFlag, &pngAlpha, 0, + "include an alpha channel in the PNG file"}, + {"-rot", argInt, &rotate, 0, + "set page rotation: 0, 90, 180, or 270"}, +#if HAVE_FREETYPE_H + {"-freetype", argString, enableFreeTypeStr, sizeof(enableFreeTypeStr), + "enable FreeType font rasterizer: yes, no"}, +#endif + {"-aa", argString, antialiasStr, sizeof(antialiasStr), + "enable font anti-aliasing: yes, no"}, + {"-aaVector", argString, vectorAntialiasStr, sizeof(vectorAntialiasStr), + "enable vector anti-aliasing: yes, no"}, + {"-opw", argString, ownerPassword, sizeof(ownerPassword), + "owner password (for encrypted files)"}, + {"-upw", argString, userPassword, sizeof(userPassword), + "user password (for encrypted files)"}, + {"-verbose", argFlag, &verbose, 0, + "print per-page status information"}, + {"-q", argFlag, &quiet, 0, + "don't print any messages or errors"}, + {"-cfg", argString, cfgFileName, sizeof(cfgFileName), + "configuration file to use in place of .xpdfrc"}, + {"-v", argFlag, &printVersion, 0, + "print copyright and version info"}, + {"-h", argFlag, &printHelp, 0, + "print usage information"}, + {"-help", argFlag, &printHelp, 0, + "print usage information"}, + {"--help", argFlag, &printHelp, 0, + "print usage information"}, + {"-?", argFlag, &printHelp, 0, + "print usage information"}, + {NULL} +}; + +static void setupPNG(png_structp *png, png_infop *pngInfo, FILE *f, + int bitDepth, int colorType, double res, + SplashBitmap *bitmap); +static void writePNGData(png_structp png, SplashBitmap *bitmap); +static void finishPNG(png_structp *png, png_infop *pngInfo); + +int main(int argc, char *argv[]) { + PDFDoc *doc; + char *fileName; + char *pngRoot; + GString *pngFile; + GString *ownerPW, *userPW; + SplashColor paperColor; + SplashOutputDev *splashOut; + GBool ok, toStdout, printStatusInfo; + int exitCode; + int pg; + png_structp png; + png_infop pngInfo; + FILE *f; + + exitCode = 99; + + // parse args + fixCommandLine(&argc, &argv); + ok = parseArgs(argDesc, &argc, argv); + if (mono && gray) { + fprintf(stderr, "Specify one of -mono or -gray\n"); + goto err0; + } + if (mono && pngAlpha) { + fprintf(stderr, "The -alpha flag cannot be used with -mono\n"); + goto err0; + } + if (!ok || argc != 3 || printVersion || printHelp) { + fprintf(stderr, "pdftopng version %s [www.xpdfreader.com]\n", xpdfVersion); + fprintf(stderr, "%s\n", xpdfCopyright); + if (!printVersion) { + printUsage("pdftopng", " ", argDesc); + } + goto err0; + } + fileName = argv[1]; + pngRoot = argv[2]; + + // read config file + if (cfgFileName[0] && !pathIsFile(cfgFileName)) { + error(errConfig, -1, "Config file '{0:s}' doesn't exist or isn't a file", + cfgFileName); + } + globalParams = new GlobalParams(cfgFileName); + globalParams->setupBaseFonts(NULL); + if (enableFreeTypeStr[0]) { + if (!globalParams->setEnableFreeType(enableFreeTypeStr)) { + fprintf(stderr, "Bad '-freetype' value on command line\n"); + } + } + if (antialiasStr[0]) { + if (!globalParams->setAntialias(antialiasStr)) { + fprintf(stderr, "Bad '-aa' value on command line\n"); + } + } + if (vectorAntialiasStr[0]) { + if (!globalParams->setVectorAntialias(vectorAntialiasStr)) { + fprintf(stderr, "Bad '-aaVector' value on command line\n"); + } + } + if (verbose) { + globalParams->setPrintStatusInfo(verbose); + } + if (quiet) { + globalParams->setErrQuiet(quiet); + } + + // open PDF file + if (ownerPassword[0]) { + ownerPW = new GString(ownerPassword); + } else { + ownerPW = NULL; + } + if (userPassword[0]) { + userPW = new GString(userPassword); + } else { + userPW = NULL; + } + doc = new PDFDoc(fileName, ownerPW, userPW); + if (userPW) { + delete userPW; + } + if (ownerPW) { + delete ownerPW; + } + if (!doc->isOk()) { + exitCode = 1; + goto err1; + } + + // get page range + if (firstPage < 1) + firstPage = 1; + if (lastPage < 1 || lastPage > doc->getNumPages()) + lastPage = doc->getNumPages(); + + + // check for stdout; set up to print per-page status info + toStdout = !strcmp(pngRoot, "-"); + printStatusInfo = !toStdout && globalParams->getPrintStatusInfo(); + + // write PNG files + if (mono) { + paperColor[0] = 0xff; + splashOut = new SplashOutputDev(splashModeMono1, 1, gFalse, paperColor); + } else if (gray) { + paperColor[0] = 0xff; + splashOut = new SplashOutputDev(splashModeMono8, 1, gFalse, paperColor); + } else { + paperColor[0] = paperColor[1] = paperColor[2] = 0xff; + splashOut = new SplashOutputDev(splashModeRGB8, 1, gFalse, paperColor); + } + if (pngAlpha) { + splashOut->setNoComposite(gTrue); + } + splashOut->startDoc(doc->getXRef()); + for (pg = firstPage; pg <= lastPage; ++pg) { + if (printStatusInfo) { + fflush(stderr); + printf("[processing page %d]\n", pg); + fflush(stdout); + } + doc->displayPage(splashOut, pg, resolution, resolution, rotate, + gFalse, gTrue, gFalse); + if (mono) { + if (toStdout) { + f = stdout; +#ifdef _WIN32 + _setmode(_fileno(f), _O_BINARY); +#endif + } else { + pngFile = GString::format("{0:s}-{1:06d}.png", pngRoot, pg); + if (!(f = openFile(pngFile->getCString(), "wb"))) { + exit(2); + } + delete pngFile; + } + setupPNG(&png, &pngInfo, f, + 1, PNG_COLOR_TYPE_GRAY, resolution, splashOut->getBitmap()); + writePNGData(png, splashOut->getBitmap()); + finishPNG(&png, &pngInfo); + fclose(f); + } else if (gray) { + if (toStdout) { + f = stdout; +#ifdef _WIN32 + _setmode(_fileno(f), _O_BINARY); +#endif + } else { + pngFile = GString::format("{0:s}-{1:06d}.png", pngRoot, pg); + if (!(f = openFile(pngFile->getCString(), "wb"))) { + exit(2); + } + delete pngFile; + } + setupPNG(&png, &pngInfo, f, + 8, pngAlpha ? PNG_COLOR_TYPE_GRAY_ALPHA : PNG_COLOR_TYPE_GRAY, + resolution, splashOut->getBitmap()); + writePNGData(png, splashOut->getBitmap()); + finishPNG(&png, &pngInfo); + fclose(f); + } else { // RGB + if (toStdout) { + f = stdout; +#ifdef _WIN32 + _setmode(_fileno(f), _O_BINARY); +#endif + } else { + pngFile = GString::format("{0:s}-{1:06d}.png", pngRoot, pg); + if (!(f = openFile(pngFile->getCString(), "wb"))) { + exit(2); + } + delete pngFile; + } + setupPNG(&png, &pngInfo, f, + 8, pngAlpha ? PNG_COLOR_TYPE_RGB_ALPHA : PNG_COLOR_TYPE_RGB, + resolution, splashOut->getBitmap()); + writePNGData(png, splashOut->getBitmap()); + finishPNG(&png, &pngInfo); + fclose(f); + } + } + delete splashOut; + + exitCode = 0; + + // clean up + err1: + delete doc; + delete globalParams; + err0: + + // check for memory leaks + Object::memCheck(stderr); + gMemReport(stderr); + + return exitCode; +} + +static void setupPNG(png_structp *png, png_infop *pngInfo, FILE *f, + int bitDepth, int colorType, double res, + SplashBitmap *bitmap) { + png_color_16 background; + int pixelsPerMeter; + + if (!(*png = png_create_write_struct(PNG_LIBPNG_VER_STRING, + NULL, NULL, NULL)) || + !(*pngInfo = png_create_info_struct(*png))) { + exit(2); + } + if (setjmp(png_jmpbuf(*png))) { + exit(2); + } + png_init_io(*png, f); + png_set_IHDR(*png, *pngInfo, bitmap->getWidth(), bitmap->getHeight(), + bitDepth, colorType, PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); + if (colorType == PNG_COLOR_TYPE_GRAY_ALPHA || + colorType == PNG_COLOR_TYPE_RGB_ALPHA) { + background.index = 0; + background.red = 0xff; + background.green = 0xff; + background.blue = 0xff; + background.gray = 0xff; + png_set_bKGD(*png, *pngInfo, &background); + } + pixelsPerMeter = (int)(res * (1000 / 25.4) + 0.5); + png_set_pHYs(*png, *pngInfo, pixelsPerMeter, pixelsPerMeter, + PNG_RESOLUTION_METER); + png_write_info(*png, *pngInfo); +} + +static void writePNGData(png_structp png, SplashBitmap *bitmap) { + Guchar *p, *alpha, *rowBuf, *rowBufPtr; + int y, x; + + if (setjmp(png_jmpbuf(png))) { + exit(2); + } + p = bitmap->getDataPtr(); + if (pngAlpha) { + alpha = bitmap->getAlphaPtr(); + if (bitmap->getMode() == splashModeMono8) { + rowBuf = (Guchar *)gmallocn(bitmap->getWidth(), 2); + for (y = 0; y < bitmap->getHeight(); ++y) { + rowBufPtr = rowBuf; + for (x = 0; x < bitmap->getWidth(); ++x) { + *rowBufPtr++ = *p++; + *rowBufPtr++ = *alpha++; + } + png_write_row(png, (png_bytep)rowBuf); + } + gfree(rowBuf); + } else { // splashModeRGB8 + rowBuf = (Guchar *)gmallocn(bitmap->getWidth(), 4); + for (y = 0; y < bitmap->getHeight(); ++y) { + rowBufPtr = rowBuf; + for (x = 0; x < bitmap->getWidth(); ++x) { + *rowBufPtr++ = *p++; + *rowBufPtr++ = *p++; + *rowBufPtr++ = *p++; + *rowBufPtr++ = *alpha++; + } + png_write_row(png, (png_bytep)rowBuf); + } + gfree(rowBuf); + } + } else { + for (y = 0; y < bitmap->getHeight(); ++y) { + png_write_row(png, (png_bytep)p); + p += bitmap->getRowSize(); + } + } +} + + + + +static void finishPNG(png_structp *png, png_infop *pngInfo) { + if (setjmp(png_jmpbuf(*png))) { + exit(2); + } + png_write_end(*png, *pngInfo); + png_destroy_write_struct(png, pngInfo); +} diff --git a/xpdf/pdftoppm b/xpdf/pdftoppm new file mode 100755 index 0000000..dfda75d Binary files /dev/null and b/xpdf/pdftoppm differ diff --git a/xpdf/pdftoppm.cc b/xpdf/pdftoppm.cc new file mode 100644 index 0000000..28861ef --- /dev/null +++ b/xpdf/pdftoppm.cc @@ -0,0 +1,280 @@ +//======================================================================== +// +// pdftoppm.cc +// +// Copyright 2003 Glyph & Cog, LLC +// +//======================================================================== + +#include +#include +#ifdef _WIN32 +# include +# include +#endif +#ifdef DEBUG_FP_LINUX +# include +# include +#endif +#include "gmem.h" +#include "gmempp.h" +#include "parseargs.h" +#include "GString.h" +#include "GlobalParams.h" +#include "Object.h" +#include "PDFDoc.h" +#include "SplashBitmap.h" +#include "Splash.h" +#include "SplashOutputDev.h" +#include "Error.h" +#include "config.h" + +static int firstPage = 1; +static int lastPage = 0; +static double resolution = 150; +static GBool mono = gFalse; +static GBool gray = gFalse; +#if SPLASH_CMYK +static GBool cmyk = gFalse; +#endif +static int rotate = 0; +static char enableFreeTypeStr[16] = ""; +static char antialiasStr[16] = ""; +static char vectorAntialiasStr[16] = ""; +static char ownerPassword[33] = ""; +static char userPassword[33] = ""; +static GBool verbose = gFalse; +static GBool quiet = gFalse; +static char cfgFileName[256] = ""; +static GBool printVersion = gFalse; +static GBool printHelp = gFalse; + +static ArgDesc argDesc[] = { + {"-f", argInt, &firstPage, 0, + "first page to print"}, + {"-l", argInt, &lastPage, 0, + "last page to print"}, + {"-r", argFP, &resolution, 0, + "resolution, in DPI (default is 150)"}, + {"-mono", argFlag, &mono, 0, + "generate a monochrome PBM file"}, + {"-gray", argFlag, &gray, 0, + "generate a grayscale PGM file"}, +#if SPLASH_CMYK + {"-cmyk", argFlag, &cmyk, 0, + "generate a CMYK PAM file"}, +#endif + {"-rot", argInt, &rotate, 0, + "set page rotation: 0, 90, 180, or 270"}, +#if HAVE_FREETYPE_H + {"-freetype", argString, enableFreeTypeStr, sizeof(enableFreeTypeStr), + "enable FreeType font rasterizer: yes, no"}, +#endif + {"-aa", argString, antialiasStr, sizeof(antialiasStr), + "enable font anti-aliasing: yes, no"}, + {"-aaVector", argString, vectorAntialiasStr, sizeof(vectorAntialiasStr), + "enable vector anti-aliasing: yes, no"}, + {"-opw", argString, ownerPassword, sizeof(ownerPassword), + "owner password (for encrypted files)"}, + {"-upw", argString, userPassword, sizeof(userPassword), + "user password (for encrypted files)"}, + {"-verbose", argFlag, &verbose, 0, + "print per-page status information"}, + {"-q", argFlag, &quiet, 0, + "don't print any messages or errors"}, + {"-cfg", argString, cfgFileName, sizeof(cfgFileName), + "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[]) { + PDFDoc *doc; + char *fileName; + char *ppmRoot; + GString *ppmFile; + GString *ownerPW, *userPW; + SplashColor paperColor; + SplashOutputDev *splashOut; + GBool ok, toStdout, printStatusInfo; + int exitCode; + int pg, n; + const char *ext; + +#ifdef DEBUG_FP_LINUX + // enable exceptions on floating point div-by-zero + feenableexcept(FE_DIVBYZERO); + // force 64-bit rounding: this avoids changes in output when minor + // code changes result in spills of x87 registers; it also avoids + // differences in output with valgrind's 64-bit floating point + // emulation (yes, this is a kludge; but it's pretty much + // unavoidable given the x87 instruction set; see gcc bug 323 for + // more info) + fpu_control_t cw; + _FPU_GETCW(cw); + cw = (fpu_control_t)((cw & ~_FPU_EXTENDED) | _FPU_DOUBLE); + _FPU_SETCW(cw); +#endif + + exitCode = 99; + + // parse args + fixCommandLine(&argc, &argv); + ok = parseArgs(argDesc, &argc, argv); + n = 0; + n += mono ? 1 : 0; + n += gray ? 1 : 0; +#if SPLASH_CMYK + n += cmyk ? 1 : 0; +#endif + if (n > 1) { + ok = gFalse; + } + if (!ok || argc != 3 || printVersion || printHelp) { + fprintf(stderr, "pdftoppm version %s [www.xpdfreader.com]\n", xpdfVersion); + fprintf(stderr, "%s\n", xpdfCopyright); + if (!printVersion) { + printUsage("pdftoppm", " ", argDesc); + } + goto err0; + } + fileName = argv[1]; + ppmRoot = argv[2]; + + // read config file + if (cfgFileName[0] && !pathIsFile(cfgFileName)) { + error(errConfig, -1, "Config file '{0:s}' doesn't exist or isn't a file", + cfgFileName); + } + globalParams = new GlobalParams(cfgFileName); + globalParams->setupBaseFonts(NULL); + if (enableFreeTypeStr[0]) { + if (!globalParams->setEnableFreeType(enableFreeTypeStr)) { + fprintf(stderr, "Bad '-freetype' value on command line\n"); + } + } + if (antialiasStr[0]) { + if (!globalParams->setAntialias(antialiasStr)) { + fprintf(stderr, "Bad '-aa' value on command line\n"); + } + } + if (vectorAntialiasStr[0]) { + if (!globalParams->setVectorAntialias(vectorAntialiasStr)) { + fprintf(stderr, "Bad '-aaVector' value on command line\n"); + } + } + if (verbose) { + globalParams->setPrintStatusInfo(verbose); + } + if (quiet) { + globalParams->setErrQuiet(quiet); + } + + // open PDF file + if (ownerPassword[0]) { + ownerPW = new GString(ownerPassword); + } else { + ownerPW = NULL; + } + if (userPassword[0]) { + userPW = new GString(userPassword); + } else { + userPW = NULL; + } + doc = new PDFDoc(fileName, ownerPW, userPW); + if (userPW) { + delete userPW; + } + if (ownerPW) { + delete ownerPW; + } + if (!doc->isOk()) { + exitCode = 1; + goto err1; + } + + // get page range + if (firstPage < 1) + firstPage = 1; + if (lastPage < 1 || lastPage > doc->getNumPages()) + lastPage = doc->getNumPages(); + + // file name extension + if (mono) { + ext = "pbm"; + } else if (gray) { + ext = "pgm"; +#if SPLASH_CMYK + } else if (cmyk) { + ext = "pam"; +#endif + } else { + ext = "ppm"; + } + + + // check for stdout; set up to print per-page status info + toStdout = !strcmp(ppmRoot, "-"); + printStatusInfo = !toStdout && globalParams->getPrintStatusInfo(); + + // write PPM files + if (mono) { + paperColor[0] = 0xff; + splashOut = new SplashOutputDev(splashModeMono1, 1, gFalse, paperColor); + } else if (gray) { + paperColor[0] = 0xff; + splashOut = new SplashOutputDev(splashModeMono8, 1, gFalse, paperColor); +#if SPLASH_CMYK + } else if (cmyk) { + paperColor[0] = paperColor[1] = paperColor[2] = paperColor[3] = 0; + splashOut = new SplashOutputDev(splashModeCMYK8, 1, gFalse, paperColor); +#endif // SPLASH_CMYK + } else { + paperColor[0] = paperColor[1] = paperColor[2] = 0xff; + splashOut = new SplashOutputDev(splashModeRGB8, 1, gFalse, paperColor); + } + splashOut->startDoc(doc->getXRef()); + for (pg = firstPage; pg <= lastPage; ++pg) { + if (printStatusInfo) { + fflush(stderr); + printf("[processing page %d]\n", pg); + fflush(stdout); + } + doc->displayPage(splashOut, pg, resolution, resolution, rotate, + gFalse, gTrue, gFalse); + if (toStdout) { +#ifdef _WIN32 + _setmode(_fileno(stdout), _O_BINARY); +#endif + splashOut->getBitmap()->writePNMFile(stdout); + } else { + ppmFile = GString::format("{0:s}-{1:06d}.{2:s}", ppmRoot, pg, ext); + splashOut->getBitmap()->writePNMFile(ppmFile->getCString()); + delete ppmFile; + } + } + delete splashOut; + + exitCode = 0; + + // clean up + err1: + delete doc; + delete globalParams; + err0: + + // check for memory leaks + Object::memCheck(stderr); + gMemReport(stderr); + + return exitCode; +} diff --git a/xpdf/pdftops b/xpdf/pdftops new file mode 100755 index 0000000..a4c63cc Binary files /dev/null and b/xpdf/pdftops differ diff --git a/xpdf/pdftops.cc b/xpdf/pdftops.cc new file mode 100644 index 0000000..77e90fe --- /dev/null +++ b/xpdf/pdftops.cc @@ -0,0 +1,399 @@ +//======================================================================== +// +// pdftops.cc +// +// Copyright 1996-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include +#include +#include +#include +#include +#ifdef DEBUG_FP_LINUX +# include +# include +#endif +#include "gmem.h" +#include "gmempp.h" +#include "parseargs.h" +#include "GString.h" +#include "GlobalParams.h" +#include "Object.h" +#include "Stream.h" +#include "Array.h" +#include "Dict.h" +#include "XRef.h" +#include "Catalog.h" +#include "Page.h" +#include "PDFDoc.h" +#include "PSOutputDev.h" +#include "Error.h" +#include "config.h" + +static int firstPage = 1; +static int lastPage = 0; +static GBool level1 = gFalse; +static GBool level1Sep = gFalse; +static GBool level2 = gFalse; +static GBool level2Gray = gFalse; +static GBool level2Sep = gFalse; +static GBool level3 = gFalse; +static GBool level3Gray = gFalse; +static GBool level3Sep = gFalse; +static GBool doEPS = gFalse; +static GBool doForm = gFalse; +#if OPI_SUPPORT +static GBool doOPI = gFalse; +#endif +static GBool noEmbedT1Fonts = gFalse; +static GBool noEmbedTTFonts = gFalse; +static GBool noEmbedCIDPSFonts = gFalse; +static GBool noEmbedCIDTTFonts = gFalse; +static GBool preload = gFalse; +static char paperSize[15] = ""; +static int paperWidth = 0; +static int paperHeight = 0; +static GBool noCrop = gFalse; +static GBool expand = gFalse; +static GBool noShrink = gFalse; +static GBool noCenter = gFalse; +static GBool pageCrop = gFalse; +static GBool userUnit = gFalse; +static GBool duplex = gFalse; +static char ownerPassword[33] = "\001"; +static char userPassword[33] = "\001"; +static GBool verbose = gFalse; +static GBool quiet = gFalse; +static char cfgFileName[256] = ""; +static GBool printVersion = gFalse; +static GBool printHelp = gFalse; + +static ArgDesc argDesc[] = { + {"-f", argInt, &firstPage, 0, + "first page to print"}, + {"-l", argInt, &lastPage, 0, + "last page to print"}, + {"-level1", argFlag, &level1, 0, + "generate Level 1 PostScript"}, + {"-level1sep", argFlag, &level1Sep, 0, + "generate Level 1 separable PostScript"}, + {"-level2", argFlag, &level2, 0, + "generate Level 2 PostScript"}, + {"-level2gray", argFlag, &level2Gray, 0, + "generate Level 2 grayscale PostScript"}, + {"-level2sep", argFlag, &level2Sep, 0, + "generate Level 2 separable PostScript"}, + {"-level3", argFlag, &level3, 0, + "generate Level 3 PostScript"}, + {"-level3gray", argFlag, &level3Gray, 0, + "generate Level 3 grayscale PostScript"}, + {"-level3sep", argFlag, &level3Sep, 0, + "generate Level 3 separable PostScript"}, + {"-eps", argFlag, &doEPS, 0, + "generate Encapsulated PostScript (EPS)"}, + {"-form", argFlag, &doForm, 0, + "generate a PostScript form"}, +#if OPI_SUPPORT + {"-opi", argFlag, &doOPI, 0, + "generate OPI comments"}, +#endif + {"-noembt1", argFlag, &noEmbedT1Fonts, 0, + "don't embed Type 1 fonts"}, + {"-noembtt", argFlag, &noEmbedTTFonts, 0, + "don't embed TrueType fonts"}, + {"-noembcidps", argFlag, &noEmbedCIDPSFonts, 0, + "don't embed CID PostScript fonts"}, + {"-noembcidtt", argFlag, &noEmbedCIDTTFonts, 0, + "don't embed CID TrueType fonts"}, + {"-preload", argFlag, &preload, 0, + "preload images and forms"}, + {"-paper", argString, paperSize, sizeof(paperSize), + "paper size (letter, legal, A4, A3, match)"}, + {"-paperw", argInt, &paperWidth, 0, + "paper width, in points"}, + {"-paperh", argInt, &paperHeight, 0, + "paper height, in points"}, + {"-nocrop", argFlag, &noCrop, 0, + "don't crop pages to CropBox"}, + {"-expand", argFlag, &expand, 0, + "expand pages smaller than the paper size"}, + {"-noshrink", argFlag, &noShrink, 0, + "don't shrink pages larger than the paper size"}, + {"-nocenter", argFlag, &noCenter, 0, + "don't center pages smaller than the paper size"}, + {"-pagecrop", argFlag, &pageCrop, 0, + "treat the CropBox as the page size"}, + {"-userunit", argFlag, &userUnit, 0, + "honor the UserUnit"}, + {"-duplex", argFlag, &duplex, 0, + "enable duplex printing"}, + {"-opw", argString, ownerPassword, sizeof(ownerPassword), + "owner password (for encrypted files)"}, + {"-upw", argString, userPassword, sizeof(userPassword), + "user password (for encrypted files)"}, + {"-verbose", argFlag, &verbose, 0, + "print per-page status information"}, + {"-q", argFlag, &quiet, 0, + "don't print any messages or errors"}, + {"-cfg", argString, cfgFileName, sizeof(cfgFileName), + "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[]) { + PDFDoc *doc; + char *fileName; + GString *psFileName; + PSLevel level; + PSOutMode mode; + GString *ownerPW, *userPW; + PSOutputDev *psOut; + GBool ok; + char *p; + int exitCode; + +#ifdef DEBUG_FP_LINUX + // enable exceptions on floating point div-by-zero + feenableexcept(FE_DIVBYZERO); + // force 64-bit rounding: this avoids changes in output when minor + // code changes result in spills of x87 registers; it also avoids + // differences in output with valgrind's 64-bit floating point + // emulation (yes, this is a kludge; but it's pretty much + // unavoidable given the x87 instruction set; see gcc bug 323 for + // more info) + fpu_control_t cw; + _FPU_GETCW(cw); + cw = (fpu_control_t)((cw & ~_FPU_EXTENDED) | _FPU_DOUBLE); + _FPU_SETCW(cw); +#endif + + exitCode = 99; + + // parse args + fixCommandLine(&argc, &argv); + ok = parseArgs(argDesc, &argc, argv); + if (!ok || argc < 2 || argc > 3 || printVersion || printHelp) { + fprintf(stderr, "pdftops version %s [www.xpdfreader.com]\n", xpdfVersion); + fprintf(stderr, "%s\n", xpdfCopyright); + if (!printVersion) { + printUsage("pdftops", " []", argDesc); + } + exit(1); + } + if ((level1 ? 1 : 0) + + (level1Sep ? 1 : 0) + + (level2 ? 1 : 0) + + (level2Gray ? 1 : 0) + + (level2Sep ? 1 : 0) + + (level3 ? 1 : 0) + + (level3Gray ? 1 : 0) + + (level3Sep ? 1 : 0) > 1) { + fprintf(stderr, "Error: use only one of the 'level' options.\n"); + exit(1); + } + if (doEPS && doForm) { + fprintf(stderr, "Error: use only one of -eps and -form\n"); + exit(1); + } + if (level1) { + level = psLevel1; + } else if (level1Sep) { + level = psLevel1Sep; + } else if (level2Gray) { + level = psLevel2Gray; + } else if (level2Sep) { + level = psLevel2Sep; + } else if (level3) { + level = psLevel3; + } else if (level3Gray) { + level = psLevel3Gray; + } else if (level3Sep) { + level = psLevel3Sep; + } else { + level = psLevel2; + } + if (doForm && level < psLevel2) { + fprintf(stderr, "Error: forms are only available with Level 2 output.\n"); + exit(1); + } + mode = doEPS ? psModeEPS + : doForm ? psModeForm + : psModePS; + fileName = argv[1]; + + // read config file + if (cfgFileName[0] && !pathIsFile(cfgFileName)) { + error(errConfig, -1, "Config file '{0:s}' doesn't exist or isn't a file", + cfgFileName); + } + globalParams = new GlobalParams(cfgFileName); +#if HAVE_SPLASH + globalParams->setupBaseFonts(NULL); +#endif + if (paperSize[0]) { + if (!globalParams->setPSPaperSize(paperSize)) { + fprintf(stderr, "Invalid paper size\n"); + goto err0; + } + } else { + if (paperWidth) { + globalParams->setPSPaperWidth(paperWidth); + } + if (paperHeight) { + globalParams->setPSPaperHeight(paperHeight); + } + } + if (noCrop) { + globalParams->setPSCrop(gFalse); + } + if (pageCrop) { + globalParams->setPSUseCropBoxAsPage(gTrue); + } + if (expand) { + globalParams->setPSExpandSmaller(gTrue); + } + if (noShrink) { + globalParams->setPSShrinkLarger(gFalse); + } + if (noCenter) { + globalParams->setPSCenter(gFalse); + } + if (duplex) { + globalParams->setPSDuplex(duplex); + } + if (level1 || level1Sep || + level2 || level2Gray || level2Sep || + level3 || level3Gray || level3Sep) { + globalParams->setPSLevel(level); + } + if (noEmbedT1Fonts) { + globalParams->setPSEmbedType1(!noEmbedT1Fonts); + } + if (noEmbedTTFonts) { + globalParams->setPSEmbedTrueType(!noEmbedTTFonts); + } + if (noEmbedCIDPSFonts) { + globalParams->setPSEmbedCIDPostScript(!noEmbedCIDPSFonts); + } + if (noEmbedCIDTTFonts) { + globalParams->setPSEmbedCIDTrueType(!noEmbedCIDTTFonts); + } + if (preload) { + globalParams->setPSPreload(preload); + } +#if OPI_SUPPORT + if (doOPI) { + globalParams->setPSOPI(doOPI); + } +#endif + if (verbose) { + globalParams->setPrintStatusInfo(verbose); + } + if (quiet) { + globalParams->setErrQuiet(quiet); + } + + // open PDF file + if (ownerPassword[0] != '\001') { + ownerPW = new GString(ownerPassword); + } else { + ownerPW = NULL; + } + if (userPassword[0] != '\001') { + userPW = new GString(userPassword); + } else { + userPW = NULL; + } + doc = new PDFDoc(fileName, ownerPW, userPW); + if (userPW) { + delete userPW; + } + if (ownerPW) { + delete ownerPW; + } + if (!doc->isOk()) { + exitCode = 1; + goto err1; + } + + // check for print permission + if (!doc->okToPrint()) { + error(errNotAllowed, -1, "Printing this document is not allowed."); + exitCode = 3; + goto err1; + } + + // construct PostScript file name + if (argc == 3) { + psFileName = new GString(argv[2]); + } else { + p = fileName + strlen(fileName) - 4; + if (strlen(fileName) > 4 && (!strcmp(p, ".pdf") || !strcmp(p, ".PDF"))) { + psFileName = new GString(fileName, (int)strlen(fileName) - 4); + } else { + psFileName = new GString(fileName); + } + psFileName->append(doEPS ? ".eps" : ".ps"); + } + if (psFileName->cmp("-") == 0) { + globalParams->setPrintStatusInfo(gFalse); + } + + // get page range + if (firstPage < 1) { + firstPage = 1; + } + if (lastPage < 1 || lastPage > doc->getNumPages()) { + lastPage = doc->getNumPages(); + } + + // check for multi-page EPS or form + if ((doEPS || doForm) && firstPage != lastPage) { + error(errCommandLine, -1, "EPS and form files can only contain one page."); + goto err2; + } + + // write PostScript file + psOut = new PSOutputDev(psFileName->getCString(), doc, + firstPage, lastPage, mode, + 0, 0, 0, 0, gFalse, NULL, NULL, userUnit, gTrue); + if (!psOut->isOk()) { + delete psOut; + exitCode = 2; + goto err2; + } + doc->displayPages(psOut, firstPage, lastPage, 72, 72, + 0, !globalParams->getPSUseCropBoxAsPage(), + globalParams->getPSCrop(), gTrue); + exitCode = 0; + if (!psOut->checkIO()) { + exitCode = 2; + } + delete psOut; + + // clean up + err2: + delete psFileName; + err1: + delete doc; + err0: + delete globalParams; + + // check for memory leaks + Object::memCheck(stderr); + gMemReport(stderr); + + return exitCode; +} diff --git a/xpdf/pdftotext b/xpdf/pdftotext new file mode 100755 index 0000000..1153dac Binary files /dev/null and b/xpdf/pdftotext differ diff --git a/xpdf/pdftotext.cc b/xpdf/pdftotext.cc new file mode 100644 index 0000000..d8bf6df --- /dev/null +++ b/xpdf/pdftotext.cc @@ -0,0 +1,332 @@ +//======================================================================== +// +// pdftotext.cc +// +// Copyright 1997-2013 Glyph & Cog, LLC +// +//======================================================================== + +#include +#include +#include +#include +#include +#ifdef DEBUG_FP_LINUX +# include +# include +#endif +#include "gmem.h" +#include "gmempp.h" +#include "parseargs.h" +#include "GString.h" +#include "GList.h" +#include "GlobalParams.h" +#include "Object.h" +#include "Stream.h" +#include "Array.h" +#include "Dict.h" +#include "XRef.h" +#include "Catalog.h" +#include "Page.h" +#include "PDFDoc.h" +#include "TextOutputDev.h" +#include "CharTypes.h" +#include "UnicodeMap.h" +#include "TextString.h" +#include "Error.h" +#include "config.h" + +static int firstPage = 1; +static int lastPage = 0; +static GBool physLayout = gFalse; +static GBool simpleLayout = gFalse; +static GBool simple2Layout = gFalse; +static GBool tableLayout = gFalse; +static GBool linePrinter = gFalse; +static GBool rawOrder = gFalse; +static double fixedPitch = 0; +static double fixedLineSpacing = 0; +static GBool clipText = gFalse; +static GBool discardDiag = gFalse; +static char textEncName[128] = ""; +static char textEOL[16] = ""; +static GBool noPageBreaks = gFalse; +static GBool insertBOM = gFalse; +static double marginLeft = 0; +static double marginRight = 0; +static double marginTop = 0; +static double marginBottom = 0; +static char ownerPassword[33] = "\001"; +static char userPassword[33] = "\001"; +static GBool verbose = gFalse; +static GBool quiet = gFalse; +static char cfgFileName[256] = ""; +static GBool listEncodings = gFalse; +static GBool printVersion = gFalse; +static GBool printHelp = gFalse; + +static ArgDesc argDesc[] = { + {"-f", argInt, &firstPage, 0, + "first page to convert"}, + {"-l", argInt, &lastPage, 0, + "last page to convert"}, + {"-layout", argFlag, &physLayout, 0, + "maintain original physical layout"}, + {"-simple", argFlag, &simpleLayout, 0, + "simple one-column page layout"}, + {"-simple2", argFlag, &simple2Layout, 0, + "simple one-column page layout, version 2"}, + {"-table", argFlag, &tableLayout, 0, + "similar to -layout, but optimized for tables"}, + {"-lineprinter", argFlag, &linePrinter, 0, + "use strict fixed-pitch/height layout"}, + {"-raw", argFlag, &rawOrder, 0, + "keep strings in content stream order"}, + {"-fixed", argFP, &fixedPitch, 0, + "assume fixed-pitch (or tabular) text"}, + {"-linespacing", argFP, &fixedLineSpacing, 0, + "fixed line spacing for LinePrinter mode"}, + {"-clip", argFlag, &clipText, 0, + "separate clipped text"}, + {"-nodiag", argFlag, &discardDiag, 0, + "discard diagonal text"}, + {"-enc", argString, textEncName, sizeof(textEncName), + "output text encoding name"}, + {"-eol", argString, textEOL, sizeof(textEOL), + "output end-of-line convention (unix, dos, or mac)"}, + {"-nopgbrk", argFlag, &noPageBreaks, 0, + "don't insert a page break at the end of each page"}, + {"-bom", argFlag, &insertBOM, 0, + "insert a Unicode BOM at the start of the text file"}, + {"-marginl", argFP, &marginLeft, 0, + "left page margin"}, + {"-marginr", argFP, &marginRight, 0, + "right page margin"}, + {"-margint", argFP, &marginTop, 0, + "top page margin"}, + {"-marginb", argFP, &marginBottom, 0, + "bottom page margin"}, + {"-opw", argString, ownerPassword, sizeof(ownerPassword), + "owner password (for encrypted files)"}, + {"-upw", argString, userPassword, sizeof(userPassword), + "user password (for encrypted files)"}, + {"-verbose", argFlag, &verbose, 0, + "print per-page status information"}, + {"-q", argFlag, &quiet, 0, + "don't print any messages or errors"}, + {"-cfg", argString, cfgFileName, sizeof(cfgFileName), + "configuration file to use in place of .xpdfrc"}, + {"-listencodings", argFlag, &listEncodings, 0, + "list all available output text encodings"}, + {"-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[]) { + PDFDoc *doc; + char *fileName; + GString *textFileName; + GString *ownerPW, *userPW; + TextOutputControl textOutControl; + TextOutputDev *textOut; + UnicodeMap *uMap; + GBool ok; + char *p; + int exitCode; + +#ifdef DEBUG_FP_LINUX + // enable exceptions on floating point div-by-zero + feenableexcept(FE_DIVBYZERO); + // force 64-bit rounding: this avoids changes in output when minor + // code changes result in spills of x87 registers; it also avoids + // differences in output with valgrind's 64-bit floating point + // emulation (yes, this is a kludge; but it's pretty much + // unavoidable given the x87 instruction set; see gcc bug 323 for + // more info) + fpu_control_t cw; + _FPU_GETCW(cw); + cw = (fpu_control_t)((cw & ~_FPU_EXTENDED) | _FPU_DOUBLE); + _FPU_SETCW(cw); +#endif + + exitCode = 99; + + // parse args + fixCommandLine(&argc, &argv); + ok = parseArgs(argDesc, &argc, argv); + if (ok && listEncodings) { + // list available encodings + if (cfgFileName[0] && !pathIsFile(cfgFileName)) { + error(errConfig, -1, "Config file '{0:s}' doesn't exist or isn't a file", + cfgFileName); + } + globalParams = new GlobalParams(cfgFileName); + GList *encs = globalParams->getAvailableTextEncodings(); + for (int i = 0; i < encs->getLength(); ++i) { + printf("%s\n", ((GString *)encs->get(i))->getCString()); + } + deleteGList(encs, GString); + delete globalParams; + goto err0; + } + if (!ok || argc < 2 || argc > 3 || printVersion || printHelp) { + fprintf(stderr, "pdftotext version %s [www.xpdfreader.com]\n", xpdfVersion); + fprintf(stderr, "%s\n", xpdfCopyright); + if (!printVersion) { + printUsage("pdftotext", " []", argDesc); + } + goto err0; + } + fileName = argv[1]; + + // read config file + if (cfgFileName[0] && !pathIsFile(cfgFileName)) { + error(errConfig, -1, "Config file '{0:s}' doesn't exist or isn't a file", + cfgFileName); + } + globalParams = new GlobalParams(cfgFileName); + if (textEncName[0]) { + globalParams->setTextEncoding(textEncName); + } + if (textEOL[0]) { + if (!globalParams->setTextEOL(textEOL)) { + fprintf(stderr, "Bad '-eol' value on command line\n"); + } + } + if (noPageBreaks) { + globalParams->setTextPageBreaks(gFalse); + } + if (verbose) { + globalParams->setPrintStatusInfo(verbose); + } + if (quiet) { + globalParams->setErrQuiet(quiet); + } + + // get mapping to output encoding + if (!(uMap = globalParams->getTextEncoding())) { + error(errConfig, -1, "Couldn't get text encoding"); + 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; + } + + // check for copy permission + if (!doc->okToCopy()) { + error(errNotAllowed, -1, + "Copying of text from this document is not allowed."); + exitCode = 3; + goto err2; + } + + // construct text file name + if (argc == 3) { + textFileName = new GString(argv[2]); + } else { + p = fileName + strlen(fileName) - 4; + if (strlen(fileName) > 4 && (!strcmp(p, ".pdf") || !strcmp(p, ".PDF"))) { + textFileName = new GString(fileName, (int)strlen(fileName) - 4); + } else { + textFileName = new GString(fileName); + } + textFileName->append(".txt"); + } + if (textFileName->cmp("-") == 0) { + globalParams->setPrintStatusInfo(gFalse); + } + + // get page range + if (firstPage < 1) { + firstPage = 1; + } + if (lastPage < 1 || lastPage > doc->getNumPages()) { + lastPage = doc->getNumPages(); + } + + // write text file + if (tableLayout) { + textOutControl.mode = textOutTableLayout; + textOutControl.fixedPitch = fixedPitch; + } else if (physLayout) { + textOutControl.mode = textOutPhysLayout; + textOutControl.fixedPitch = fixedPitch; + } else if (simpleLayout) { + textOutControl.mode = textOutSimpleLayout; + } else if (simple2Layout) { + textOutControl.mode = textOutSimple2Layout; + } else if (linePrinter) { + textOutControl.mode = textOutLinePrinter; + textOutControl.fixedPitch = fixedPitch; + textOutControl.fixedLineSpacing = fixedLineSpacing; + } else if (rawOrder) { + textOutControl.mode = textOutRawOrder; + } else { + textOutControl.mode = textOutReadingOrder; + } + textOutControl.clipText = clipText; + textOutControl.discardDiagonalText = discardDiag; + textOutControl.insertBOM = insertBOM; + textOutControl.marginLeft = marginLeft; + textOutControl.marginRight = marginRight; + textOutControl.marginTop = marginTop; + textOutControl.marginBottom = marginBottom; + textOut = new TextOutputDev(textFileName->getCString(), &textOutControl, + gFalse, gTrue); + if (textOut->isOk()) { + doc->displayPages(textOut, firstPage, lastPage, 72, 72, 0, + gFalse, gTrue, gFalse); + } else { + delete textOut; + exitCode = 2; + goto err3; + } + delete textOut; + + exitCode = 0; + + // clean up + err3: + delete textFileName; + err2: + delete doc; + uMap->decRefCnt(); + err1: + delete globalParams; + err0: + + // check for memory leaks + Object::memCheck(stderr); + gMemReport(stderr); + + return exitCode; +} diff --git a/xpdf/winLongPath.exe.manifest b/xpdf/winLongPath.exe.manifest new file mode 100644 index 0000000..f460546 --- /dev/null +++ b/xpdf/winLongPath.exe.manifest @@ -0,0 +1,15 @@ + + + + + + + + + + + + true + + + -- cgit v1.2.3