aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ANNOUNCE37
-rw-r--r--CHANGES2812
-rw-r--r--CMakeCache.txt608
-rw-r--r--CMakeFiles/3.18.4/CMakeCCompiler.cmake77
-rw-r--r--CMakeFiles/3.18.4/CMakeCXXCompiler.cmake89
-rwxr-xr-xCMakeFiles/3.18.4/CMakeDetermineCompilerABI_C.binbin0 -> 16544 bytes
-rwxr-xr-xCMakeFiles/3.18.4/CMakeDetermineCompilerABI_CXX.binbin0 -> 16560 bytes
-rw-r--r--CMakeFiles/3.18.4/CMakeSystem.cmake15
-rw-r--r--CMakeFiles/3.18.4/CompilerIdC/CMakeCCompilerId.c674
-rwxr-xr-xCMakeFiles/3.18.4/CompilerIdC/a.outbin0 -> 16704 bytes
-rw-r--r--CMakeFiles/3.18.4/CompilerIdCXX/CMakeCXXCompilerId.cpp663
-rwxr-xr-xCMakeFiles/3.18.4/CompilerIdCXX/a.outbin0 -> 16712 bytes
-rw-r--r--CMakeFiles/CMakeDirectoryInformation.cmake16
-rw-r--r--CMakeFiles/CMakeError.log98
-rw-r--r--CMakeFiles/CMakeOutput.log541
-rw-r--r--CMakeFiles/CMakeRuleHashes.txt5
-rw-r--r--CMakeFiles/Makefile.cmake214
-rw-r--r--CMakeFiles/Makefile2738
-rw-r--r--CMakeFiles/TargetDirectories.txt54
-rw-r--r--CMakeFiles/cmake.check_cache1
-rw-r--r--CMakeFiles/progress.marks1
-rw-r--r--CMakeLists.txt41
-rw-r--r--COPYING339
-rw-r--r--COPYING3674
-rw-r--r--INSTALL196
-rw-r--r--Makefile455
-rw-r--r--README392
-rw-r--r--aconf.h124
-rw-r--r--aconf.h.in124
-rw-r--r--aconf2.h41
-rw-r--r--cmake-config.txt333
-rw-r--r--cmake_install.cmake64
-rw-r--r--doc/pdfdetach.1106
-rw-r--r--doc/pdfdetach.cat92
-rw-r--r--doc/pdffonts.1163
-rw-r--r--doc/pdffonts.cat118
-rw-r--r--doc/pdfimages.1122
-rw-r--r--doc/pdfimages.cat102
-rw-r--r--doc/pdfinfo.1167
-rw-r--r--doc/pdfinfo.cat117
-rw-r--r--doc/pdftohtml.1158
-rw-r--r--doc/pdftohtml.cat144
-rw-r--r--doc/pdftopng.1130
-rw-r--r--doc/pdftopng.cat107
-rw-r--r--doc/pdftoppm.1130
-rw-r--r--doc/pdftoppm.cat106
-rw-r--r--doc/pdftops.1257
-rw-r--r--doc/pdftops.cat218
-rw-r--r--doc/pdftotext.1222
-rw-r--r--doc/pdftotext.cat184
-rw-r--r--doc/sample-xpdfrc86
-rw-r--r--doc/xpdf.1965
-rw-r--r--doc/xpdf.cat871
-rw-r--r--doc/xpdfrc.5854
-rw-r--r--doc/xpdfrc.cat786
-rw-r--r--fofi/CMakeFiles/CMakeDirectoryInformation.cmake16
-rw-r--r--fofi/CMakeFiles/fofi.dir/DependInfo.cmake11
-rw-r--r--fofi/CMakeFiles/fofi.dir/build.make115
-rw-r--r--fofi/CMakeFiles/fofi.dir/cmake_clean.cmake9
-rw-r--r--fofi/CMakeFiles/fofi.dir/cmake_clean_target.cmake3
-rw-r--r--fofi/CMakeFiles/fofi.dir/depend.internal3
-rw-r--r--fofi/CMakeFiles/fofi.dir/depend.make3
-rw-r--r--fofi/CMakeFiles/fofi.dir/flags.make10
-rw-r--r--fofi/CMakeFiles/fofi.dir/link.txt2
-rw-r--r--fofi/CMakeFiles/fofi.dir/progress.make2
-rw-r--r--fofi/CMakeFiles/fofi_objs.dir/CXX.includecache198
-rw-r--r--fofi/CMakeFiles/fofi_objs.dir/DependInfo.cmake27
-rw-r--r--fofi/CMakeFiles/fofi_objs.dir/FoFiBase.cc.obin0 -> 6952 bytes
-rw-r--r--fofi/CMakeFiles/fofi_objs.dir/FoFiEncodings.cc.obin0 -> 30136 bytes
-rw-r--r--fofi/CMakeFiles/fofi_objs.dir/FoFiIdentifier.cc.obin0 -> 28664 bytes
-rw-r--r--fofi/CMakeFiles/fofi_objs.dir/FoFiTrueType.cc.obin0 -> 149320 bytes
-rw-r--r--fofi/CMakeFiles/fofi_objs.dir/FoFiType1.cc.obin0 -> 13376 bytes
-rw-r--r--fofi/CMakeFiles/fofi_objs.dir/FoFiType1C.cc.obin0 -> 113248 bytes
-rw-r--r--fofi/CMakeFiles/fofi_objs.dir/build.make179
-rw-r--r--fofi/CMakeFiles/fofi_objs.dir/cmake_clean.cmake13
-rw-r--r--fofi/CMakeFiles/fofi_objs.dir/depend.internal62
-rw-r--r--fofi/CMakeFiles/fofi_objs.dir/depend.make62
-rw-r--r--fofi/CMakeFiles/fofi_objs.dir/flags.make10
-rw-r--r--fofi/CMakeFiles/fofi_objs.dir/progress.make7
-rw-r--r--fofi/CMakeFiles/progress.marks1
-rw-r--r--fofi/CMakeLists.txt28
-rw-r--r--fofi/FoFiBase.cc177
-rw-r--r--fofi/FoFiBase.h58
-rw-r--r--fofi/FoFiEncodings.cc995
-rw-r--r--fofi/FoFiEncodings.h36
-rw-r--r--fofi/FoFiIdentifier.cc887
-rw-r--r--fofi/FoFiIdentifier.h55
-rw-r--r--fofi/FoFiTrueType.cc2461
-rw-r--r--fofi/FoFiTrueType.h216
-rw-r--r--fofi/FoFiType1.cc359
-rw-r--r--fofi/FoFiType1.h64
-rw-r--r--fofi/FoFiType1C.cc3405
-rw-r--r--fofi/FoFiType1C.h281
-rw-r--r--fofi/Makefile415
-rw-r--r--fofi/cmake_install.cmake44
-rw-r--r--fofi/libfofi.abin0 -> 360458 bytes
-rw-r--r--goo/CMakeFiles/CMakeDirectoryInformation.cmake16
-rw-r--r--goo/CMakeFiles/goo.dir/DependInfo.cmake11
-rw-r--r--goo/CMakeFiles/goo.dir/build.make121
-rw-r--r--goo/CMakeFiles/goo.dir/cmake_clean.cmake9
-rw-r--r--goo/CMakeFiles/goo.dir/cmake_clean_target.cmake3
-rw-r--r--goo/CMakeFiles/goo.dir/depend.internal3
-rw-r--r--goo/CMakeFiles/goo.dir/depend.make3
-rw-r--r--goo/CMakeFiles/goo.dir/flags.make17
-rw-r--r--goo/CMakeFiles/goo.dir/link.txt2
-rw-r--r--goo/CMakeFiles/goo.dir/progress.make2
-rw-r--r--goo/CMakeFiles/goo_objs.dir/C.includecache28
-rw-r--r--goo/CMakeFiles/goo_objs.dir/CXX.includecache226
-rw-r--r--goo/CMakeFiles/goo_objs.dir/DependInfo.cmake38
-rw-r--r--goo/CMakeFiles/goo_objs.dir/FixedPoint.cc.obin0 -> 936 bytes
-rw-r--r--goo/CMakeFiles/goo_objs.dir/GHash.cc.obin0 -> 10144 bytes
-rw-r--r--goo/CMakeFiles/goo_objs.dir/GList.cc.obin0 -> 6720 bytes
-rw-r--r--goo/CMakeFiles/goo_objs.dir/GString.cc.obin0 -> 27360 bytes
-rw-r--r--goo/CMakeFiles/goo_objs.dir/Trace.cc.obin0 -> 928 bytes
-rw-r--r--goo/CMakeFiles/goo_objs.dir/build.make221
-rw-r--r--goo/CMakeFiles/goo_objs.dir/cmake_clean.cmake16
-rw-r--r--goo/CMakeFiles/goo_objs.dir/depend.internal65
-rw-r--r--goo/CMakeFiles/goo_objs.dir/depend.make65
-rw-r--r--goo/CMakeFiles/goo_objs.dir/flags.make17
-rw-r--r--goo/CMakeFiles/goo_objs.dir/gfile.cc.obin0 -> 11064 bytes
-rw-r--r--goo/CMakeFiles/goo_objs.dir/gmem.cc.obin0 -> 5680 bytes
-rw-r--r--goo/CMakeFiles/goo_objs.dir/gmempp.cc.obin0 -> 928 bytes
-rw-r--r--goo/CMakeFiles/goo_objs.dir/parseargs.c.obin0 -> 5688 bytes
-rw-r--r--goo/CMakeFiles/goo_objs.dir/progress.make10
-rw-r--r--goo/CMakeFiles/progress.marks1
-rw-r--r--goo/CMakeLists.txt30
-rw-r--r--goo/FixedPoint.cc134
-rw-r--r--goo/FixedPoint.h180
-rw-r--r--goo/GHash.cc385
-rw-r--r--goo/GHash.h78
-rw-r--r--goo/GList.cc123
-rw-r--r--goo/GList.h106
-rw-r--r--goo/GMutex.h101
-rw-r--r--goo/GString.cc853
-rw-r--r--goo/GString.h151
-rw-r--r--goo/Makefile505
-rw-r--r--goo/Trace.cc114
-rw-r--r--goo/Trace.h43
-rw-r--r--goo/cmake_install.cmake44
-rw-r--r--goo/gfile.cc779
-rw-r--r--goo/gfile.h144
-rw-r--r--goo/gmem.cc396
-rw-r--r--goo/gmem.h95
-rw-r--r--goo/gmempp.cc51
-rw-r--r--goo/gmempp.h48
-rw-r--r--goo/gtypes.h29
-rw-r--r--goo/libgoo.abin0 -> 73528 bytes
-rw-r--r--goo/parseargs.c195
-rw-r--r--goo/parseargs.h72
-rw-r--r--splash/CMakeFiles/CMakeDirectoryInformation.cmake16
-rw-r--r--splash/CMakeFiles/progress.marks1
-rw-r--r--splash/CMakeFiles/splash.dir/DependInfo.cmake11
-rw-r--r--splash/CMakeFiles/splash.dir/build.make135
-rw-r--r--splash/CMakeFiles/splash.dir/cmake_clean.cmake9
-rw-r--r--splash/CMakeFiles/splash.dir/cmake_clean_target.cmake3
-rw-r--r--splash/CMakeFiles/splash.dir/depend.internal3
-rw-r--r--splash/CMakeFiles/splash.dir/depend.make3
-rw-r--r--splash/CMakeFiles/splash.dir/flags.make10
-rw-r--r--splash/CMakeFiles/splash.dir/link.txt2
-rw-r--r--splash/CMakeFiles/splash.dir/progress.make2
-rw-r--r--splash/CMakeFiles/splash_objs.dir/CXX.includecache596
-rw-r--r--splash/CMakeFiles/splash_objs.dir/DependInfo.cmake39
-rw-r--r--splash/CMakeFiles/splash_objs.dir/Splash.cc.obin0 -> 176808 bytes
-rw-r--r--splash/CMakeFiles/splash_objs.dir/SplashBitmap.cc.obin0 -> 11120 bytes
-rw-r--r--splash/CMakeFiles/splash_objs.dir/SplashClip.cc.obin0 -> 16168 bytes
-rw-r--r--splash/CMakeFiles/splash_objs.dir/SplashFTFont.cc.obin0 -> 13104 bytes
-rw-r--r--splash/CMakeFiles/splash_objs.dir/SplashFTFontEngine.cc.obin0 -> 8632 bytes
-rw-r--r--splash/CMakeFiles/splash_objs.dir/SplashFTFontFile.cc.obin0 -> 6984 bytes
-rw-r--r--splash/CMakeFiles/splash_objs.dir/SplashFont.cc.obin0 -> 9920 bytes
-rw-r--r--splash/CMakeFiles/splash_objs.dir/SplashFontEngine.cc.obin0 -> 9064 bytes
-rw-r--r--splash/CMakeFiles/splash_objs.dir/SplashFontFile.cc.obin0 -> 5448 bytes
-rw-r--r--splash/CMakeFiles/splash_objs.dir/SplashFontFileID.cc.obin0 -> 3136 bytes
-rw-r--r--splash/CMakeFiles/splash_objs.dir/SplashPath.cc.obin0 -> 9976 bytes
-rw-r--r--splash/CMakeFiles/splash_objs.dir/SplashPattern.cc.obin0 -> 7200 bytes
-rw-r--r--splash/CMakeFiles/splash_objs.dir/SplashScreen.cc.obin0 -> 40064 bytes
-rw-r--r--splash/CMakeFiles/splash_objs.dir/SplashState.cc.obin0 -> 11904 bytes
-rw-r--r--splash/CMakeFiles/splash_objs.dir/SplashXPath.cc.obin0 -> 48912 bytes
-rw-r--r--splash/CMakeFiles/splash_objs.dir/SplashXPathScanner.cc.obin0 -> 39672 bytes
-rw-r--r--splash/CMakeFiles/splash_objs.dir/build.make319
-rw-r--r--splash/CMakeFiles/splash_objs.dir/cmake_clean.cmake23
-rw-r--r--splash/CMakeFiles/splash_objs.dir/depend.internal240
-rw-r--r--splash/CMakeFiles/splash_objs.dir/depend.make240
-rw-r--r--splash/CMakeFiles/splash_objs.dir/flags.make10
-rw-r--r--splash/CMakeFiles/splash_objs.dir/progress.make17
-rw-r--r--splash/CMakeLists.txt49
-rw-r--r--splash/Makefile715
-rw-r--r--splash/Splash.cc8521
-rw-r--r--splash/Splash.h537
-rw-r--r--splash/SplashBitmap.cc288
-rw-r--r--splash/SplashBitmap.h98
-rw-r--r--splash/SplashClip.cc521
-rw-r--r--splash/SplashClip.h130
-rw-r--r--splash/SplashErrorCodes.h34
-rw-r--r--splash/SplashFTFont.cc460
-rw-r--r--splash/SplashFTFont.h60
-rw-r--r--splash/SplashFTFontEngine.cc392
-rw-r--r--splash/SplashFTFontEngine.h99
-rw-r--r--splash/SplashFTFontFile.cc171
-rw-r--r--splash/SplashFTFontFile.h95
-rw-r--r--splash/SplashFont.cc195
-rw-r--r--splash/SplashFont.h111
-rw-r--r--splash/SplashFontEngine.cc409
-rw-r--r--splash/SplashFontEngine.h129
-rw-r--r--splash/SplashFontFile.cc84
-rw-r--r--splash/SplashFontFile.h95
-rw-r--r--splash/SplashFontFileID.cc26
-rw-r--r--splash/SplashFontFileID.h32
-rw-r--r--splash/SplashGlyphBitmap.h28
-rw-r--r--splash/SplashMath.h378
-rw-r--r--splash/SplashPath.cc213
-rw-r--r--splash/SplashPath.h133
-rw-r--r--splash/SplashPattern.cc44
-rw-r--r--splash/SplashPattern.h69
-rw-r--r--splash/SplashScreen.cc383
-rw-r--r--splash/SplashScreen.h81
-rw-r--r--splash/SplashState.cc349
-rw-r--r--splash/SplashState.h136
-rw-r--r--splash/SplashTypes.h145
-rw-r--r--splash/SplashXPath.cc645
-rw-r--r--splash/SplashXPath.h143
-rw-r--r--splash/SplashXPathScanner.cc620
-rw-r--r--splash/SplashXPathScanner.h84
-rw-r--r--splash/cmake_install.cmake44
-rw-r--r--splash/libsplash.abin0 -> 450324 bytes
-rw-r--r--xpdf-qt/CMakeCache.txt376
-rw-r--r--xpdf-qt/CMakeFiles/3.18.4/CMakeCCompiler.cmake77
-rw-r--r--xpdf-qt/CMakeFiles/3.18.4/CMakeCXXCompiler.cmake89
-rwxr-xr-xxpdf-qt/CMakeFiles/3.18.4/CMakeDetermineCompilerABI_C.binbin0 -> 16544 bytes
-rwxr-xr-xxpdf-qt/CMakeFiles/3.18.4/CMakeDetermineCompilerABI_CXX.binbin0 -> 16560 bytes
-rw-r--r--xpdf-qt/CMakeFiles/3.18.4/CMakeSystem.cmake15
-rw-r--r--xpdf-qt/CMakeFiles/3.18.4/CompilerIdC/CMakeCCompilerId.c674
-rwxr-xr-xxpdf-qt/CMakeFiles/3.18.4/CompilerIdC/a.outbin0 -> 16704 bytes
-rw-r--r--xpdf-qt/CMakeFiles/3.18.4/CompilerIdCXX/CMakeCXXCompilerId.cpp663
-rwxr-xr-xxpdf-qt/CMakeFiles/3.18.4/CompilerIdCXX/a.outbin0 -> 16712 bytes
-rw-r--r--xpdf-qt/CMakeFiles/CMakeDirectoryInformation.cmake16
-rw-r--r--xpdf-qt/CMakeFiles/CMakeOutput.log439
-rw-r--r--xpdf-qt/CMakeFiles/Makefile.cmake119
-rw-r--r--xpdf-qt/CMakeFiles/Makefile298
-rw-r--r--xpdf-qt/CMakeFiles/TargetDirectories.txt2
-rw-r--r--xpdf-qt/CMakeFiles/cmake.check_cache1
-rw-r--r--xpdf-qt/CMakeFiles/progress.marks1
-rw-r--r--xpdf-qt/CMakeFiles/xpdf.dir/CXX.includecache1784
-rw-r--r--xpdf-qt/CMakeFiles/xpdf.dir/DependInfo.cmake53
-rw-r--r--xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.obin0 -> 127792 bytes
-rw-r--r--xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.obin0 -> 73152 bytes
-rw-r--r--xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.obin0 -> 500840 bytes
-rw-r--r--xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.obin0 -> 179736 bytes
-rw-r--r--xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.obin0 -> 35608 bytes
-rw-r--r--xpdf-qt/CMakeFiles/xpdf.dir/build.make479
-rw-r--r--xpdf-qt/CMakeFiles/xpdf.dir/cmake_clean.cmake23
-rw-r--r--xpdf-qt/CMakeFiles/xpdf.dir/depend.internal1412
-rw-r--r--xpdf-qt/CMakeFiles/xpdf.dir/depend.make1412
-rw-r--r--xpdf-qt/CMakeFiles/xpdf.dir/flags.make17
-rw-r--r--xpdf-qt/CMakeFiles/xpdf.dir/link.txt1
-rw-r--r--xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.obin0 -> 19352 bytes
-rw-r--r--xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.obin0 -> 54032 bytes
-rw-r--r--xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.obin0 -> 33280 bytes
-rw-r--r--xpdf-qt/CMakeFiles/xpdf.dir/progress.make16
-rw-r--r--xpdf-qt/CMakeFiles/xpdf.dir/qrc_icons.cpp.obin0 -> 20136 bytes
-rw-r--r--xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.obin0 -> 16152 bytes
-rw-r--r--xpdf-qt/CMakeLists.txt115
-rw-r--r--xpdf-qt/Makefile519
-rw-r--r--xpdf-qt/QtPDFCore.cc1176
-rw-r--r--xpdf-qt/QtPDFCore.h227
-rw-r--r--xpdf-qt/XpdfApp.cc499
-rw-r--r--xpdf-qt/XpdfApp.h99
-rw-r--r--xpdf-qt/XpdfViewer.cc4940
-rw-r--r--xpdf-qt/XpdfViewer.h508
-rw-r--r--xpdf-qt/XpdfWidget.cc2256
-rw-r--r--xpdf-qt/XpdfWidget.h1029
-rw-r--r--xpdf-qt/XpdfWidgetPrint.cc500
-rw-r--r--xpdf-qt/XpdfWidgetPrint.h24
-rw-r--r--xpdf-qt/back.svg10
-rw-r--r--xpdf-qt/cmake_install.cmake64
-rw-r--r--xpdf-qt/findNext.svg8
-rw-r--r--xpdf-qt/findPrevious.svg8
-rw-r--r--xpdf-qt/findSettings.svg9
-rw-r--r--xpdf-qt/fitPage.svg20
-rw-r--r--xpdf-qt/fitPageOn.svg20
-rw-r--r--xpdf-qt/fitWidth.svg14
-rw-r--r--xpdf-qt/fitWidthOn.svg14
-rw-r--r--xpdf-qt/forward.svg10
-rw-r--r--xpdf-qt/icons.qrc35
-rw-r--r--xpdf-qt/icons.qrc.depends35
-rw-r--r--xpdf-qt/indicator-icon-err0.svg12
-rw-r--r--xpdf-qt/indicator-icon-err1.svg12
-rw-r--r--xpdf-qt/indicator-icon-err2.svg12
-rw-r--r--xpdf-qt/indicator-icon-err3.svg12
-rw-r--r--xpdf-qt/indicator-icon-err4.svg12
-rw-r--r--xpdf-qt/indicator-icon-err5.svg12
-rw-r--r--xpdf-qt/indicator-icon-err6.svg12
-rw-r--r--xpdf-qt/indicator-icon-err7.svg12
-rw-r--r--xpdf-qt/indicator-icon0.svg10
-rw-r--r--xpdf-qt/indicator-icon1.svg10
-rw-r--r--xpdf-qt/indicator-icon2.svg10
-rw-r--r--xpdf-qt/indicator-icon3.svg10
-rw-r--r--xpdf-qt/indicator-icon4.svg10
-rw-r--r--xpdf-qt/indicator-icon5.svg10
-rw-r--r--xpdf-qt/indicator-icon6.svg10
-rw-r--r--xpdf-qt/indicator-icon7.svg10
-rw-r--r--xpdf-qt/moc_XpdfApp.cpp95
-rw-r--r--xpdf-qt/moc_XpdfApp.cpp_parameters28
-rw-r--r--xpdf-qt/moc_XpdfViewer.cpp654
-rw-r--r--xpdf-qt/moc_XpdfViewer.cpp_parameters28
-rw-r--r--xpdf-qt/moc_XpdfWidget.cpp463
-rw-r--r--xpdf-qt/moc_XpdfWidget.cpp_parameters28
-rw-r--r--xpdf-qt/qrc_icons.cpp1325
-rw-r--r--xpdf-qt/selectModeBlock.svg8
-rw-r--r--xpdf-qt/selectModeLinear.svg25
-rw-r--r--xpdf-qt/toggleSidebar.svg17
-rwxr-xr-xxpdf-qt/xpdfbin0 -> 3836272 bytes
-rw-r--r--xpdf-qt/xpdf-icon.icobin0 -> 8936 bytes
-rw-r--r--xpdf-qt/xpdf-icon.svg20
-rw-r--r--xpdf-qt/xpdf.cc59
-rw-r--r--xpdf-qt/xpdf.rc1
-rw-r--r--xpdf-qt/zoomIn.svg10
-rw-r--r--xpdf-qt/zoomOut.svg8
-rw-r--r--xpdf/AcroForm.cc3889
-rw-r--r--xpdf/AcroForm.h169
-rw-r--r--xpdf/Annot.cc1448
-rw-r--r--xpdf/Annot.h185
-rw-r--r--xpdf/Array.cc74
-rw-r--r--xpdf/Array.h70
-rw-r--r--xpdf/BuiltinFont.cc67
-rw-r--r--xpdf/BuiltinFont.h58
-rw-r--r--xpdf/BuiltinFontTables.cc4285
-rw-r--r--xpdf/BuiltinFontTables.h23
-rw-r--r--xpdf/CMakeFiles/CMakeDirectoryInformation.cmake16
-rw-r--r--xpdf/CMakeFiles/pdfdetach.dir/CXX.includecache244
-rw-r--r--xpdf/CMakeFiles/pdfdetach.dir/DependInfo.cmake26
-rw-r--r--xpdf/CMakeFiles/pdfdetach.dir/build.make206
-rw-r--r--xpdf/CMakeFiles/pdfdetach.dir/cmake_clean.cmake10
-rw-r--r--xpdf/CMakeFiles/pdfdetach.dir/depend.internal28
-rw-r--r--xpdf/CMakeFiles/pdfdetach.dir/depend.make28
-rw-r--r--xpdf/CMakeFiles/pdfdetach.dir/flags.make10
-rw-r--r--xpdf/CMakeFiles/pdfdetach.dir/link.txt1
-rw-r--r--xpdf/CMakeFiles/pdfdetach.dir/pdfdetach.cc.obin0 -> 12160 bytes
-rw-r--r--xpdf/CMakeFiles/pdfdetach.dir/progress.make3
-rw-r--r--xpdf/CMakeFiles/pdffonts.dir/CXX.includecache258
-rw-r--r--xpdf/CMakeFiles/pdffonts.dir/DependInfo.cmake26
-rw-r--r--xpdf/CMakeFiles/pdffonts.dir/build.make206
-rw-r--r--xpdf/CMakeFiles/pdffonts.dir/cmake_clean.cmake10
-rw-r--r--xpdf/CMakeFiles/pdffonts.dir/depend.internal29
-rw-r--r--xpdf/CMakeFiles/pdffonts.dir/depend.make29
-rw-r--r--xpdf/CMakeFiles/pdffonts.dir/flags.make10
-rw-r--r--xpdf/CMakeFiles/pdffonts.dir/link.txt1
-rw-r--r--xpdf/CMakeFiles/pdffonts.dir/pdffonts.cc.obin0 -> 24000 bytes
-rw-r--r--xpdf/CMakeFiles/pdffonts.dir/progress.make3
-rw-r--r--xpdf/CMakeFiles/pdfimages.dir/CXX.includecache306
-rw-r--r--xpdf/CMakeFiles/pdfimages.dir/DependInfo.cmake27
-rw-r--r--xpdf/CMakeFiles/pdfimages.dir/ImageOutputDev.cc.obin0 -> 27856 bytes
-rw-r--r--xpdf/CMakeFiles/pdfimages.dir/build.make221
-rw-r--r--xpdf/CMakeFiles/pdfimages.dir/cmake_clean.cmake11
-rw-r--r--xpdf/CMakeFiles/pdfimages.dir/depend.internal49
-rw-r--r--xpdf/CMakeFiles/pdfimages.dir/depend.make49
-rw-r--r--xpdf/CMakeFiles/pdfimages.dir/flags.make10
-rw-r--r--xpdf/CMakeFiles/pdfimages.dir/link.txt1
-rw-r--r--xpdf/CMakeFiles/pdfimages.dir/pdfimages.cc.obin0 -> 9904 bytes
-rw-r--r--xpdf/CMakeFiles/pdfimages.dir/progress.make4
-rw-r--r--xpdf/CMakeFiles/pdfinfo.dir/CXX.includecache288
-rw-r--r--xpdf/CMakeFiles/pdfinfo.dir/DependInfo.cmake26
-rw-r--r--xpdf/CMakeFiles/pdfinfo.dir/build.make206
-rw-r--r--xpdf/CMakeFiles/pdfinfo.dir/cmake_clean.cmake10
-rw-r--r--xpdf/CMakeFiles/pdfinfo.dir/depend.internal30
-rw-r--r--xpdf/CMakeFiles/pdfinfo.dir/depend.make30
-rw-r--r--xpdf/CMakeFiles/pdfinfo.dir/flags.make10
-rw-r--r--xpdf/CMakeFiles/pdfinfo.dir/link.txt1
-rw-r--r--xpdf/CMakeFiles/pdfinfo.dir/pdfinfo.cc.obin0 -> 27168 bytes
-rw-r--r--xpdf/CMakeFiles/pdfinfo.dir/progress.make3
-rw-r--r--xpdf/CMakeFiles/pdftohtml.dir/CXX.includecache734
-rw-r--r--xpdf/CMakeFiles/pdftohtml.dir/DependInfo.cmake32
-rw-r--r--xpdf/CMakeFiles/pdftohtml.dir/HTMLGen.cc.obin0 -> 47208 bytes
-rw-r--r--xpdf/CMakeFiles/pdftohtml.dir/ShadingImage.cc.obin0 -> 43568 bytes
-rw-r--r--xpdf/CMakeFiles/pdftohtml.dir/SplashOutputDev.cc.obin0 -> 149112 bytes
-rw-r--r--xpdf/CMakeFiles/pdftohtml.dir/TextOutputDev.cc.obin0 -> 208392 bytes
-rw-r--r--xpdf/CMakeFiles/pdftohtml.dir/WebFont.cc.obin0 -> 11992 bytes
-rw-r--r--xpdf/CMakeFiles/pdftohtml.dir/build.make285
-rw-r--r--xpdf/CMakeFiles/pdftohtml.dir/cmake_clean.cmake15
-rw-r--r--xpdf/CMakeFiles/pdftohtml.dir/depend.internal189
-rw-r--r--xpdf/CMakeFiles/pdftohtml.dir/depend.make189
-rw-r--r--xpdf/CMakeFiles/pdftohtml.dir/flags.make10
-rw-r--r--xpdf/CMakeFiles/pdftohtml.dir/link.txt1
-rw-r--r--xpdf/CMakeFiles/pdftohtml.dir/pdftohtml.cc.obin0 -> 16736 bytes
-rw-r--r--xpdf/CMakeFiles/pdftohtml.dir/progress.make8
-rw-r--r--xpdf/CMakeFiles/pdftopng.dir/CXX.includecache580
-rw-r--r--xpdf/CMakeFiles/pdftopng.dir/DependInfo.cmake29
-rw-r--r--xpdf/CMakeFiles/pdftopng.dir/ShadingImage.cc.obin0 -> 43568 bytes
-rw-r--r--xpdf/CMakeFiles/pdftopng.dir/SplashOutputDev.cc.obin0 -> 149112 bytes
-rw-r--r--xpdf/CMakeFiles/pdftopng.dir/build.make240
-rw-r--r--xpdf/CMakeFiles/pdftopng.dir/cmake_clean.cmake12
-rw-r--r--xpdf/CMakeFiles/pdftopng.dir/depend.internal112
-rw-r--r--xpdf/CMakeFiles/pdftopng.dir/depend.make112
-rw-r--r--xpdf/CMakeFiles/pdftopng.dir/flags.make10
-rw-r--r--xpdf/CMakeFiles/pdftopng.dir/link.txt1
-rw-r--r--xpdf/CMakeFiles/pdftopng.dir/pdftopng.cc.obin0 -> 19472 bytes
-rw-r--r--xpdf/CMakeFiles/pdftopng.dir/progress.make5
-rw-r--r--xpdf/CMakeFiles/pdftoppm.dir/CXX.includecache578
-rw-r--r--xpdf/CMakeFiles/pdftoppm.dir/DependInfo.cmake29
-rw-r--r--xpdf/CMakeFiles/pdftoppm.dir/ShadingImage.cc.obin0 -> 43568 bytes
-rw-r--r--xpdf/CMakeFiles/pdftoppm.dir/SplashOutputDev.cc.obin0 -> 149112 bytes
-rw-r--r--xpdf/CMakeFiles/pdftoppm.dir/build.make238
-rw-r--r--xpdf/CMakeFiles/pdftoppm.dir/cmake_clean.cmake12
-rw-r--r--xpdf/CMakeFiles/pdftoppm.dir/depend.internal112
-rw-r--r--xpdf/CMakeFiles/pdftoppm.dir/depend.make112
-rw-r--r--xpdf/CMakeFiles/pdftoppm.dir/flags.make10
-rw-r--r--xpdf/CMakeFiles/pdftoppm.dir/link.txt1
-rw-r--r--xpdf/CMakeFiles/pdftoppm.dir/pdftoppm.cc.obin0 -> 13760 bytes
-rw-r--r--xpdf/CMakeFiles/pdftoppm.dir/progress.make5
-rw-r--r--xpdf/CMakeFiles/pdftops.dir/CXX.includecache740
-rw-r--r--xpdf/CMakeFiles/pdftops.dir/DependInfo.cmake31
-rw-r--r--xpdf/CMakeFiles/pdftops.dir/PSOutputDev.cc.obin0 -> 322304 bytes
-rw-r--r--xpdf/CMakeFiles/pdftops.dir/PreScanOutputDev.cc.obin0 -> 23112 bytes
-rw-r--r--xpdf/CMakeFiles/pdftops.dir/ShadingImage.cc.obin0 -> 43568 bytes
-rw-r--r--xpdf/CMakeFiles/pdftops.dir/SplashOutputDev.cc.obin0 -> 149112 bytes
-rw-r--r--xpdf/CMakeFiles/pdftops.dir/build.make268
-rw-r--r--xpdf/CMakeFiles/pdftops.dir/cmake_clean.cmake14
-rw-r--r--xpdf/CMakeFiles/pdftops.dir/depend.internal174
-rw-r--r--xpdf/CMakeFiles/pdftops.dir/depend.make174
-rw-r--r--xpdf/CMakeFiles/pdftops.dir/flags.make10
-rw-r--r--xpdf/CMakeFiles/pdftops.dir/link.txt1
-rw-r--r--xpdf/CMakeFiles/pdftops.dir/pdftops.cc.obin0 -> 21168 bytes
-rw-r--r--xpdf/CMakeFiles/pdftops.dir/progress.make7
-rw-r--r--xpdf/CMakeFiles/pdftotext.dir/CXX.includecache388
-rw-r--r--xpdf/CMakeFiles/pdftotext.dir/DependInfo.cmake27
-rw-r--r--xpdf/CMakeFiles/pdftotext.dir/TextOutputDev.cc.obin0 -> 208392 bytes
-rw-r--r--xpdf/CMakeFiles/pdftotext.dir/build.make221
-rw-r--r--xpdf/CMakeFiles/pdftotext.dir/cmake_clean.cmake11
-rw-r--r--xpdf/CMakeFiles/pdftotext.dir/depend.internal60
-rw-r--r--xpdf/CMakeFiles/pdftotext.dir/depend.make60
-rw-r--r--xpdf/CMakeFiles/pdftotext.dir/flags.make10
-rw-r--r--xpdf/CMakeFiles/pdftotext.dir/link.txt1
-rw-r--r--xpdf/CMakeFiles/pdftotext.dir/pdftotext.cc.obin0 -> 17584 bytes
-rw-r--r--xpdf/CMakeFiles/pdftotext.dir/progress.make4
-rw-r--r--xpdf/CMakeFiles/progress.marks1
-rw-r--r--xpdf/CMakeFiles/xpdf_objs.dir/AcroForm.cc.obin0 -> 172512 bytes
-rw-r--r--xpdf/CMakeFiles/xpdf_objs.dir/Annot.cc.obin0 -> 72032 bytes
-rw-r--r--xpdf/CMakeFiles/xpdf_objs.dir/Array.cc.obin0 -> 5128 bytes
-rw-r--r--xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFont.cc.obin0 -> 3248 bytes
-rw-r--r--xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFontTables.cc.obin0 -> 214016 bytes
-rw-r--r--xpdf/CMakeFiles/xpdf_objs.dir/CMap.cc.obin0 -> 17400 bytes
-rw-r--r--xpdf/CMakeFiles/xpdf_objs.dir/CXX.includecache1596
-rw-r--r--xpdf/CMakeFiles/xpdf_objs.dir/Catalog.cc.obin0 -> 52016 bytes
-rw-r--r--xpdf/CMakeFiles/xpdf_objs.dir/CharCodeToUnicode.cc.obin0 -> 25312 bytes
-rw-r--r--xpdf/CMakeFiles/xpdf_objs.dir/Decrypt.cc.obin0 -> 42344 bytes
-rw-r--r--xpdf/CMakeFiles/xpdf_objs.dir/DependInfo.cmake66
-rw-r--r--xpdf/CMakeFiles/xpdf_objs.dir/Dict.cc.obin0 -> 8368 bytes
-rw-r--r--xpdf/CMakeFiles/xpdf_objs.dir/Error.cc.obin0 -> 5544 bytes
-rw-r--r--xpdf/CMakeFiles/xpdf_objs.dir/FontEncodingTables.cc.obin0 -> 52624 bytes
-rw-r--r--xpdf/CMakeFiles/xpdf_objs.dir/Function.cc.obin0 -> 73088 bytes
-rw-r--r--xpdf/CMakeFiles/xpdf_objs.dir/Gfx.cc.obin0 -> 207224 bytes
-rw-r--r--xpdf/CMakeFiles/xpdf_objs.dir/GfxFont.cc.obin0 -> 98704 bytes
-rw-r--r--xpdf/CMakeFiles/xpdf_objs.dir/GfxState.cc.obin0 -> 286648 bytes
-rw-r--r--xpdf/CMakeFiles/xpdf_objs.dir/GlobalParams.cc.obin0 -> 386824 bytes
-rw-r--r--xpdf/CMakeFiles/xpdf_objs.dir/JArithmeticDecoder.cc.obin0 -> 12288 bytes
-rw-r--r--xpdf/CMakeFiles/xpdf_objs.dir/JBIG2Stream.cc.obin0 -> 130112 bytes
-rw-r--r--xpdf/CMakeFiles/xpdf_objs.dir/JPXStream.cc.obin0 -> 92752 bytes
-rw-r--r--xpdf/CMakeFiles/xpdf_objs.dir/Lexer.cc.obin0 -> 21960 bytes
-rw-r--r--xpdf/CMakeFiles/xpdf_objs.dir/Link.cc.obin0 -> 74104 bytes
-rw-r--r--xpdf/CMakeFiles/xpdf_objs.dir/NameToCharCode.cc.obin0 -> 4016 bytes
-rw-r--r--xpdf/CMakeFiles/xpdf_objs.dir/Object.cc.obin0 -> 35464 bytes
-rw-r--r--xpdf/CMakeFiles/xpdf_objs.dir/OptionalContent.cc.obin0 -> 26656 bytes
-rw-r--r--xpdf/CMakeFiles/xpdf_objs.dir/Outline.cc.obin0 -> 12584 bytes
-rw-r--r--xpdf/CMakeFiles/xpdf_objs.dir/OutputDev.cc.obin0 -> 36896 bytes
-rw-r--r--xpdf/CMakeFiles/xpdf_objs.dir/PDF417Barcode.cc.obin0 -> 41840 bytes
-rw-r--r--xpdf/CMakeFiles/xpdf_objs.dir/PDFDoc.cc.obin0 -> 34704 bytes
-rw-r--r--xpdf/CMakeFiles/xpdf_objs.dir/PDFDocEncoding.cc.obin0 -> 2000 bytes
-rw-r--r--xpdf/CMakeFiles/xpdf_objs.dir/PSTokenizer.cc.obin0 -> 3224 bytes
-rw-r--r--xpdf/CMakeFiles/xpdf_objs.dir/Page.cc.obin0 -> 43304 bytes
-rw-r--r--xpdf/CMakeFiles/xpdf_objs.dir/Parser.cc.obin0 -> 14352 bytes
-rw-r--r--xpdf/CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.obin0 -> 22944 bytes
-rw-r--r--xpdf/CMakeFiles/xpdf_objs.dir/Stream.cc.obin0 -> 210688 bytes
-rw-r--r--xpdf/CMakeFiles/xpdf_objs.dir/TextString.cc.obin0 -> 8768 bytes
-rw-r--r--xpdf/CMakeFiles/xpdf_objs.dir/UTF8.cc.obin0 -> 5264 bytes
-rw-r--r--xpdf/CMakeFiles/xpdf_objs.dir/UnicodeMap.cc.obin0 -> 9936 bytes
-rw-r--r--xpdf/CMakeFiles/xpdf_objs.dir/UnicodeRemapping.cc.obin0 -> 6816 bytes
-rw-r--r--xpdf/CMakeFiles/xpdf_objs.dir/UnicodeTypeTable.cc.obin0 -> 57728 bytes
-rw-r--r--xpdf/CMakeFiles/xpdf_objs.dir/XFAScanner.cc.obin0 -> 30616 bytes
-rw-r--r--xpdf/CMakeFiles/xpdf_objs.dir/XRef.cc.obin0 -> 46408 bytes
-rw-r--r--xpdf/CMakeFiles/xpdf_objs.dir/Zoox.cc.obin0 -> 65240 bytes
-rw-r--r--xpdf/CMakeFiles/xpdf_objs.dir/build.make697
-rw-r--r--xpdf/CMakeFiles/xpdf_objs.dir/cmake_clean.cmake50
-rw-r--r--xpdf/CMakeFiles/xpdf_objs.dir/depend.internal786
-rw-r--r--xpdf/CMakeFiles/xpdf_objs.dir/depend.make786
-rw-r--r--xpdf/CMakeFiles/xpdf_objs.dir/flags.make10
-rw-r--r--xpdf/CMakeFiles/xpdf_objs.dir/progress.make44
-rw-r--r--xpdf/CMakeFiles/xpdf_widget_objs.dir/CXX.includecache952
-rw-r--r--xpdf/CMakeFiles/xpdf_widget_objs.dir/DependInfo.cmake33
-rw-r--r--xpdf/CMakeFiles/xpdf_widget_objs.dir/DisplayState.cc.obin0 -> 21096 bytes
-rw-r--r--xpdf/CMakeFiles/xpdf_widget_objs.dir/PDFCore.cc.obin0 -> 79888 bytes
-rw-r--r--xpdf/CMakeFiles/xpdf_widget_objs.dir/PSOutputDev.cc.obin0 -> 324512 bytes
-rw-r--r--xpdf/CMakeFiles/xpdf_widget_objs.dir/PreScanOutputDev.cc.obin0 -> 23848 bytes
-rw-r--r--xpdf/CMakeFiles/xpdf_widget_objs.dir/ShadingImage.cc.obin0 -> 43576 bytes
-rw-r--r--xpdf/CMakeFiles/xpdf_widget_objs.dir/SplashOutputDev.cc.obin0 -> 149072 bytes
-rw-r--r--xpdf/CMakeFiles/xpdf_widget_objs.dir/TextOutputDev.cc.obin0 -> 210256 bytes
-rw-r--r--xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCache.cc.obin0 -> 16888 bytes
-rw-r--r--xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCompositor.cc.obin0 -> 13776 bytes
-rw-r--r--xpdf/CMakeFiles/xpdf_widget_objs.dir/TileMap.cc.obin0 -> 54208 bytes
-rw-r--r--xpdf/CMakeFiles/xpdf_widget_objs.dir/build.make235
-rw-r--r--xpdf/CMakeFiles/xpdf_widget_objs.dir/cmake_clean.cmake17
-rw-r--r--xpdf/CMakeFiles/xpdf_widget_objs.dir/depend.internal308
-rw-r--r--xpdf/CMakeFiles/xpdf_widget_objs.dir/depend.make308
-rw-r--r--xpdf/CMakeFiles/xpdf_widget_objs.dir/flags.make10
-rw-r--r--xpdf/CMakeFiles/xpdf_widget_objs.dir/progress.make11
-rw-r--r--xpdf/CMakeLists.txt292
-rw-r--r--xpdf/CMap.cc440
-rw-r--r--xpdf/CMap.h115
-rw-r--r--xpdf/Catalog.cc1197
-rw-r--r--xpdf/Catalog.h166
-rw-r--r--xpdf/CharCodeToUnicode.cc755
-rw-r--r--xpdf/CharCodeToUnicode.h131
-rw-r--r--xpdf/CharTypes.h24
-rw-r--r--xpdf/CompactFontTables.h464
-rw-r--r--xpdf/Decrypt.cc1620
-rw-r--r--xpdf/Decrypt.h133
-rw-r--r--xpdf/Dict.cc145
-rw-r--r--xpdf/Dict.h89
-rw-r--r--xpdf/DisplayState.cc223
-rw-r--r--xpdf/DisplayState.h173
-rw-r--r--xpdf/Error.cc92
-rw-r--r--xpdf/Error.h48
-rw-r--r--xpdf/ErrorCodes.h36
-rw-r--r--xpdf/FontEncodingTables.cc1825
-rw-r--r--xpdf/FontEncodingTables.h20
-rw-r--r--xpdf/Function.cc1602
-rw-r--r--xpdf/Function.h240
-rw-r--r--xpdf/Gfx.cc5386
-rw-r--r--xpdf/Gfx.h363
-rw-r--r--xpdf/GfxFont.cc2415
-rw-r--r--xpdf/GfxFont.h417
-rw-r--r--xpdf/GfxState.cc4918
-rw-r--r--xpdf/GfxState.h1369
-rw-r--r--xpdf/GlobalParams.cc3858
-rw-r--r--xpdf/GlobalParams.h623
-rw-r--r--xpdf/HTMLGen.cc1120
-rw-r--r--xpdf/HTMLGen.h113
-rw-r--r--xpdf/ImageOutputDev.cc453
-rw-r--r--xpdf/ImageOutputDev.h116
-rw-r--r--xpdf/JArithmeticDecoder.cc370
-rw-r--r--xpdf/JArithmeticDecoder.h114
-rw-r--r--xpdf/JBIG2Stream.cc4234
-rw-r--r--xpdf/JBIG2Stream.h156
-rw-r--r--xpdf/JPXStream.cc3610
-rw-r--r--xpdf/JPXStream.h364
-rw-r--r--xpdf/Lexer.cc555
-rw-r--r--xpdf/Lexer.h85
-rw-r--r--xpdf/Link.cc926
-rw-r--r--xpdf/Link.h453
-rw-r--r--xpdf/Makefile2365
-rw-r--r--xpdf/NameToCharCode.cc117
-rw-r--r--xpdf/NameToCharCode.h42
-rw-r--r--xpdf/NameToUnicodeTable.h4257
-rw-r--r--xpdf/Object.cc245
-rw-r--r--xpdf/Object.h320
-rw-r--r--xpdf/OptionalContent.cc537
-rw-r--r--xpdf/OptionalContent.h139
-rw-r--r--xpdf/Outline.cc186
-rw-r--r--xpdf/Outline.h84
-rw-r--r--xpdf/OutputDev.cc140
-rw-r--r--xpdf/OutputDev.h251
-rw-r--r--xpdf/PDF417Barcode.cc1916
-rw-r--r--xpdf/PDF417Barcode.h32
-rw-r--r--xpdf/PDFCore.cc2024
-rw-r--r--xpdf/PDFCore.h357
-rw-r--r--xpdf/PDFDoc.cc679
-rw-r--r--xpdf/PDFDoc.h228
-rw-r--r--xpdf/PDFDocEncoding.cc46
-rw-r--r--xpdf/PDFDocEncoding.h16
-rw-r--r--xpdf/PSOutputDev.cc8448
-rw-r--r--xpdf/PSOutputDev.h513
-rw-r--r--xpdf/PSTokenizer.cc136
-rw-r--r--xpdf/PSTokenizer.h41
-rw-r--r--xpdf/Page.cc554
-rw-r--r--xpdf/Page.h207
-rw-r--r--xpdf/Parser.cc316
-rw-r--r--xpdf/Parser.h65
-rw-r--r--xpdf/PreScanOutputDev.cc309
-rw-r--r--xpdf/PreScanOutputDev.h149
-rw-r--r--xpdf/SecurityHandler.cc370
-rw-r--r--xpdf/SecurityHandler.h127
-rw-r--r--xpdf/ShadingImage.cc1327
-rw-r--r--xpdf/ShadingImage.h106
-rw-r--r--xpdf/SplashOutputDev.cc4550
-rw-r--r--xpdf/SplashOutputDev.h320
-rw-r--r--xpdf/Stream-CCITT.h464
-rw-r--r--xpdf/Stream.cc6064
-rw-r--r--xpdf/Stream.h1071
-rw-r--r--xpdf/TextOutputDev.cc6835
-rw-r--r--xpdf/TextOutputDev.h800
-rw-r--r--xpdf/TextString.cc213
-rw-r--r--xpdf/TextString.h71
-rw-r--r--xpdf/TileCache.cc562
-rw-r--r--xpdf/TileCache.h78
-rw-r--r--xpdf/TileCompositor.cc452
-rw-r--r--xpdf/TileCompositor.h77
-rw-r--r--xpdf/TileMap.cc1690
-rw-r--r--xpdf/TileMap.h247
-rw-r--r--xpdf/UTF8.cc183
-rw-r--r--xpdf/UTF8.h42
-rw-r--r--xpdf/UnicodeMap.cc281
-rw-r--r--xpdf/UnicodeMap.h124
-rw-r--r--xpdf/UnicodeMapTables.h366
-rw-r--r--xpdf/UnicodeRemapping.cc201
-rw-r--r--xpdf/UnicodeRemapping.h53
-rw-r--r--xpdf/UnicodeTypeTable.cc1876
-rw-r--r--xpdf/UnicodeTypeTable.h32
-rw-r--r--xpdf/WebFont.cc408
-rw-r--r--xpdf/WebFont.h80
-rw-r--r--xpdf/XFAScanner.cc677
-rw-r--r--xpdf/XFAScanner.h166
-rw-r--r--xpdf/XRef.cc1431
-rw-r--r--xpdf/XRef.h192
-rw-r--r--xpdf/Zoox.cc1072
-rw-r--r--xpdf/Zoox.h271
-rw-r--r--xpdf/cmake_install.cmake228
-rw-r--r--xpdf/config.h108
-rwxr-xr-xxpdf/pdfdetachbin0 -> 2307432 bytes
-rw-r--r--xpdf/pdfdetach.cc216
-rwxr-xr-xxpdf/pdffontsbin0 -> 2312072 bytes
-rw-r--r--xpdf/pdffonts.cc455
-rwxr-xr-xxpdf/pdfimagesbin0 -> 2317440 bytes
-rw-r--r--xpdf/pdfimages.cc174
-rwxr-xr-xxpdf/pdfinfobin0 -> 2311992 bytes
-rw-r--r--xpdf/pdfinfo.cc555
-rwxr-xr-xxpdf/pdftohtmlbin0 -> 2915168 bytes
-rw-r--r--xpdf/pdftohtml.cc300
-rwxr-xr-xxpdf/pdftopngbin0 -> 2733568 bytes
-rw-r--r--xpdf/pdftopng.cc386
-rwxr-xr-xxpdf/pdftoppmbin0 -> 2728328 bytes
-rw-r--r--xpdf/pdftoppm.cc280
-rwxr-xr-xxpdf/pdftopsbin0 -> 2954976 bytes
-rw-r--r--xpdf/pdftops.cc399
-rwxr-xr-xxpdf/pdftotextbin0 -> 2460304 bytes
-rw-r--r--xpdf/pdftotext.cc332
-rw-r--r--xpdf/winLongPath.exe.manifest15
634 files changed, 200011 insertions, 0 deletions
diff --git a/ANNOUNCE b/ANNOUNCE
new file mode 100644
index 0000000..c20dcaf
--- /dev/null
+++ b/ANNOUNCE
@@ -0,0 +1,37 @@
+Subject: ANNOUNCE: Xpdf 4.04 - a PDF viewer and related tools
+
+Glyph & Cog, LLC is pleased to announce a new version of Xpdf, the
+open source Portable Document Format (PDF) viewer. The Xpdf project
+also includes a PDF text extractor, PDF-to-PostScript converter, and
+various other utilities.
+
+Xpdf uses the Qt toolkit and runs on Linux and Windows. The
+non-graphical components (pdftops, pdftotext, etc.) run on Linux,
+Unix, Windows, MacOSX, and pretty much any other system with a decent
+C++ compiler.
+
+4.04 is primarily a bug fix release. There are some new features:
+
+* XpdfReader improvements:
+ - Implemented selection extension via shift-click, and word/line
+ selection via double/triple click.
+ - Added default bindings for ctrl-mousewheel-up/down to zoom in/out.
+ - Added a help menu item that shows all of the key bindings.
+
+* Various new command line options for pdftotext, pdftohtml, pdftoppm,
+ pdftopng, and xpdf.
+
+See the `CHANGES' file for a complete list of changes.
+
+Source (C++ and C) is available, and it should be fairly easy to
+compile for Linux and Windows.
+
+More information, source code, and precompiled binaries are on the
+xpdf web page:
+
+ http://www.xpdfreader.com/
+
+For information on commercial licensing and consulting, please see the
+Glyph & Cog web site:
+
+ http://www.glyphandcog.com/
diff --git a/CHANGES b/CHANGES
new file mode 100644
index 0000000..564aff3
--- /dev/null
+++ b/CHANGES
@@ -0,0 +1,2812 @@
+0.2 (95-dec-12)
+---------------
+First public release.
+
+
+0.3 (96-jan-13)
+---------------
+LZW patent workaround.
+Implemented inline images.
+Fixed (mostly) disjoint polygon fills.
+Added remote server stuff.
+Added page number on command line.
+Fixed problem with font encodings which caused character misalignment.
+Fixed inverted CCITT decoding and inverted image mask drawing.
+Now compiles under gcc 2.7.x (ignore those stupid 'unused parameter'
+ warnings).
+Many minor bug fixes and optimizations.
+
+
+0.4 (96-apr-24)
+---------------
+Implemented DCT filter.
+Implemented PostScript output; wrote pdftops program.
+Implemented links.
+Implemented font rotation -- I was wrong: X11R6 servers *do* support
+ font rotation (by specifying a matrix in place of a size).
+Added bindings for Home/End, Page Up/Down, arrow keys.
+Added initialZoom resource and -z option.
+Added geometry resource and -g option.
+Fixed image size off-by-one bug.
+Fixed bug where page content is reference to an array of streams.
+Cleaned up uninitialized variables which were causing random problems
+ on various platforms.
+Manually skip whitespace before calling atoi() for startxref.
+Replaced calls to XrmCombineFileDatabase() with calls to
+ XrmGetFileDatabase() and XrmMergeDatabases() so it will work under
+ older versions of X.
+Fixed problem with reading multiple xref tables in updated PDF files.
+Check for encryption and print appropriate error message.
+Rudimentary dithering of images.
+Fixed bug in CCITTFax filter (pass mode followed by horizontal mode).
+Optimized drawImage() and drawImageMask().
+Changed several things to ease porting:
+ - changed '__inline' to 'inline' (to adhere to the ANSI standard)
+ - surrounded interface/implementation pragmas with #ifdef _GNUC__
+ - got rid of empty array initializer lists
+ - moved Operator type definition from Gfx.cc to Gfx.h
+ - renamed String, uint, etc.
+ - ability to uncompress to file (NO_POPEN and USE_GZIP flags)
+ - added definitions of XK_Page_Up/Down and XPointer for old versions
+ of X
+For VMS port:
+ - use correct Xdefaults name for VMS, get rid of ltkGetHomeDir()
+ - added '#include <stddef.h>' before all X includes
+ - renamed files with multiple periods in their names
+Fixed window resizing infinite oscillation bug.
+Fixed problem with string-type (as opposed to stream-type) indexed
+ color space lookup tables (which are used in inline images).
+If an X font is not found, try smaller and then larger sizes (this is
+ useful for old or broken X servers which can't scale bitmap fonts).
+Added -rgb (color cube size) option.
+Various minor bug fixes.
+
+
+0.5 (96-may-23)
+---------------
+Fixed bug in LTKWindow which broke the remote server mode.
+Fixed PostScript output:
+ - doesn't seg fault if file is unwritable.
+ - incorrect DSC comment - need colon in '%%Page:'.
+ - use 'imagemask' command for masks.
+ - output filters in the correct order.
+ - Stream::isBinary() checks the next-to-bottom, not top, stream.
+ - if page width > height, rotate it 90 degrees.
+ - if page is larger than paper size, scale it down.
+Set default MediaBox to 8.5" x 11" to deal with non-compliant PDF
+ files which don't specify a MediaBox.
+Added DEBUG_MEM stuff in gmem.c and gmempp.cc.
+Fixed memory leaks:
+ - LTKWindow didn't delete the LTKBox.
+ - LinkAction needs a virtual destructor.
+Use $(RANLIB) variable in goo/Makefile and ltk/Makefile.
+Allocate image data after calling XCreateImage, using
+ image->bytes_per_line -- works in 24-bit mode now.
+DCTStream rounds width of rowBuf lines up to the next multiple of
+ mcuWidth, so last MCU doesn't run off end of buffer.
+Increase size of block (from 255 to 1024 bytes) read at end of file to
+ search for 'startxref'.
+Skip past garbage at start of file, look for '%PDF'.
+Moved more compiler options out of Makefiles into Makefile.config.
+Top-level Makefile uses '$(MAKE)' instead of 'make' for making
+ subdirectories.
+Space/PageDown/Next and Backspace/PageUp/Previous now moves to
+ next/previous page if already scrolled to bottom/top of current
+ page.
+
+
+0.5a (96-jul-09)
+----------------
+[not a public release]
+For PDF 1.2 (a.k.a. Amber, a.k.a. Acrobat 3) support:
+ - look for trailer after first xref instead of at end of file.
+Deal with font subsets by converting character names of the form
+ 'Cnnnn' to the appropriate character from the standard encoding.
+Extract encoding from embedded Type 1 fonts.
+Kludge to fill one-pixel thick polygons.
+Changed X font encoding to use endash for hyphen (gets rid of too-long
+ hyphens).
+Handle Resources key in Pages dictionaries (needed for pstoedit
+ output).
+Fix comment handling in Parser (needed for pstoedit output).
+Move Bezier curve conversion from GfxState to XOutputDev; look at
+ flatness parameter in GfxState.
+Change all of the path functions in XOutputDev (stroke, fill, clip) to
+ use the same path transformation/conversion function.
+Rewrote PostScript output driver as a subclass of OutputDev; removed
+ duplicated code (ps_ functions) from Gfx.
+Fixed bug in xref code with small (< 1024 bytes) PDF files.
+Implemented BX/EX operators.
+Added PDFDoc class.
+
+
+0.6 (96-nov-12)
+---------------
+Add support for PostScript output to stdout (-) and to a command
+ (|lpr); added -ps option and psFile resource.
+Decryption is implemented but not included in the distribution due to
+ legal restrictions: the decryption algorithm is a trade secret of
+ RSA, Inc., and the U.S.A. still has bogus export controls on
+ cryptography software.
+Added .xpdfrc config file:
+ - Added fontmap parameter: user can map PDF font names to X fonts.
+ - Added fontpath parameter: search for Type 1 font if encoding is
+ not in PDF file.
+Incremental display: display is updated after every 200 commands.
+Added forward and backward by-10-page buttons.
+Links:
+ - Implement links with "Launch" actions that point to PDF files.
+ - Draw borders around links.
+ - Handle links with named destinations.
+ - GoToR links specify a page number instead of a page reference.
+Optimizations:
+ - Rewrote Stream to use buffering, and added lookChar() functions;
+ rewrote Lexer to take advantage of this.
+ - Use hash tables for name->code mapping in font encodings.
+ - Made XOutputDev::doCurve() iterative, changed /2 to *0.5, and
+ changed the flatness test.
+Added file name to window title.
+Implemented RunLength filter.
+Implemented forms.
+Convert ObjType to an enum.
+Changed isDict("Pages") to isDict() (in Catalog.cc) to deal with
+ incorrect PDF files.
+Changed color selection so that very pale colors don't map to white.
+Fixed bug in CCITTFax filter (multiple make-up codes).
+In GString::clear(): need to set length to 0 before calling resize().
+Base initial window size on first displayed page, not page 1; deal
+ correctly with rotated pages.
+Added ltkGetIntResource() and LTKApp::getIntResource().
+PostScript output fixes:
+ - Escape backslashes in strings.
+ - When doing ASCII85 encoding, keep both chars of EOF marker ('~>')
+ on same line.
+ - Add extra line '%-EOD-' after image data streams; call wrapper
+ functions for image and imagemask which look for this line -- this
+ should fix the 'too much data in stream' bug.
+ - Font tags can be reused for different fonts on different pages --
+ so use font object reference (number/generation) instead.
+Initialize character widths to zero (this caused crashes on OSF/1).
+Handle image masks which go outside of pixmap.
+Makefile.config changes:
+ - Remove -o in C++ compile rule.
+ - Add $(AR) variable.
+Code which read char widths from font dictionary read all but the last
+ width.
+Add 'return 0;' to main() in xpdf and pdftops.
+Allow fonts to use StandardEncoding.
+Convert man pages to VMS help files.
+
+0.7 (97-may-28)
+---------------
+Implemented FlateDecode filter (for PDF 1.2).
+Basic xref table reconstruction for damaged files
+New pdftotext program converts PDF to plain text.
+Implemented menus in LTK; added a menu to xpdf.
+Added open and save functions; allow xpdf to start without any PDF
+ file.
+Implemented text find.
+Implemented text select/copy.
+Change mouse cursor when it's over a link.
+Embed Type 1 fonts in PostScript output.
+Moved rotate functions to menu; added quit to menu.
+Fixed stroke color bug in PostScript output (was using fill color
+ instead of stroke color; this sometimes caused lines to be missing
+ (white) in PostScript output).
+Support Launch-type links -- pops up a dialog before executing
+ anything. Expects the A (action) dictionary to contain a Unix
+ dictionary with F (file) and P (paremeter) keys just like the Win
+ dictionary.
+A moveto op all by itself should just be discarded, instead of
+ generating a subpath with one point (this was causing seg faults).
+Balanced parentheses in strings don't need to be escaped.
+Tj operator in PostScript prolog didn't check for zero when dividing
+ by length of string.
+Implemented selection in LTK; TextIn widgets support dragging/copy/
+ paste.
+Handle font subsets that use hex character codes.
+Added icon pixmap; added the XPMLIB and NO_XPM variables to
+ Makefile.config.
+Fixed subtle bug in use of horizontal scaling parameter (it affects
+ only the width of drawn characters, not positioning done in text
+ space).
+Memory testing (with DEBUG_MEM):
+ - gmalloc now fills memory blocks with garbage to catch unitialized
+ fields.
+ - gfree fills memory blocks with garbage to catch uses of freed
+ blocks.
+Handle image masks which go off the pixmap on the top and/or left.
+Fixed inline functions which had two return statements (to make the
+ HP, SCO, and other cfront-based compilers happy).
+Fixed bug which caused seg faults when following a link to a different
+ file (info in LinkGoto object was used after link was deleted by
+ loadFile).
+If page content is an array of streams, the streams are concatenated;
+ objects and commands can span multiple streams.
+If file open fails, try lower-casing and upper-casing the file name.
+Commands should end when lexer sees a '/' character.
+GString::append(char *, int) was broken.
+Changed LTKScrollingCanvas redraw to be more efficient: copy as much
+ as possible from window before copying from off-screen pixmap.
+Ignore gs (set extended graphics state) operator.
+Handle colorspaces (CalGray/RGB are treated as DeviceGray/RGB; the
+ weird colorspaces are not yet implemented).
+Named destinations (for links) can be strings as well as names; deal
+ with the names tree in the catalog.
+Clip to the page CropBox.
+Added '-q' to gzip options (to suppress warnings, in case user has -v
+ in GZIP env var).
+Added 'include Makefile.config' to top-level Makefile.
+Added INSTALL variable to Makefile.config; used in top-level
+ Makefile.
+Always initialize LinkDest left/bottom/top/right/zoom fields (bogus
+ floating point values were causing crashes on Alpha).
+Added Makefile.config options for Digital Unix (DEC compilers), HP-UX
+ (HP compilers), SCO Unix, and Evans & Sutherland ES/OS.
+Added flag to set stream mode in fopen call for VMS.
+Rewrote Link module.
+Pages with no contents shouldn't cause an error message.
+In PostScript output: pdfImM needs to set fill color before doing
+ imagemask.
+If font doesn't specify character widths, use widths from built-in
+ font, based on font flags.
+Fixed LTK scrollbar to delay before repeating and to control the
+ period between repeats.
+Removed window/widget copy() methods (they were untested and unused).
+Unknown filter types produce a single error message instead of a
+ stream of errors.
+Added a dummy target in top-level Makefile so making individual
+ executables (e.g., 'make pdftops') should now work.
+Added optional xpdf-flip.ltk with buttons on right side instead of
+ bottom of window.
+
+0.7a (98-feb-22)
+----------------
+Moved find command from menu to toolbar button ('f' key still works).
+Support TrueColor visuals.
+Added a -cmap option and a installCmap resource to install a private
+ colormap.
+Mouse button 2 pans the window.
+Selecting a URI link now executes a configurable command (from the
+ urlCommand resource).
+Added a "link info" display which shows the URL or file for the link
+ under the mouse.
+Don't draw (or convert to PostScript) text drawn in render modes 3 and
+ 7 -- this is invisible text, used by Acrobat Capture; this text is
+ still passed to the TextPage object so that selection works.
+Recognize (and quietly ignore) marked content operators (BMC, BDC,
+ EMC, MP, DP).
+Recognize new color-setting operators (scn, SCN).
+Added A4_PAPER option.
+Embed external Type 1 font files (this currently only works with PFA
+ files).
+Added "-level1" option (in xpdf and pdftops) to generate Level 1
+ PostScript.
+Setup autoconf -- replaced Makefile.config. Added SELECT_TAKES_INT
+ flag, and use configure to autodetect (for HP-UX).
+Fixed appendToPath() to behave reasonably when appending ".." to root
+ directory.
+Fixed array size in FlateStream::compHuffmanCodes() (was causing xpdf
+ to crash under OSF/1).
+ASCII85Stream, ASCIIHexStream, and DCTStream didn't check for EOF and
+ could run past the end of the stream in damaged files.
+Handle hex escapes (#xx) in names. Still allow the name /# for
+ backward-compatibility.
+Check for NULL characters in encoding array in GfxFont.cc (was calling
+ strcmp() with NULL which crashed under Solaris).
+PageAttrs::PageAttrs() didn't initialize crop box boundaries.
+Changed uses of lookup() to lookupNF() in XRef.cc.
+Fixed type checking of operators which take a variable number of
+ args.
+Gfx::buildImageStream() doesn't need to check for parser (since I got
+ rid of the bogus array-of-command thing).
+XOutputFont matches on font reference instead of font tag (similar to
+ PSOutputDev fix).
+Fixed bug in position calculation for multi-char substitutions in
+ XOutputDev.
+Cleaned up local variables which hid class variables.
+Optimized variable length decoding in CCITTFaxStream.
+Set link border width to zero if Border dictionary entry is missing.
+Throw away zero-length strings in TextOutputDev -- they don't have
+ valid xMin/xMax values.
+Swapped order of XLIBS and XPMLIB in xpdf/Makefile.
+Deleted 'LTKApp::' in function declaration in LTKApp.h.
+Changed '(XKeyEvent *)&event' to '&event.xkey' in LTKApp.cc.
+Check that the link rectangle coordinates are in the correct order,
+ and swap if necessary.
+TextOutputDev didn't set text to NULL, which caused pdftotext to
+ segfault if it couldn't open it's output file.
+Fixed a hash table search bug in GfxFontEncoding::getCharCode().
+Cleaned up colorspace code: rewrote GfxColorSpace and added
+ GfxImageColorMap; cleaned up PSOutputDev::doImage.
+Handle named colorspaces in images.
+Correctly set the default color after a colorspace change.
+Old setcolor operators now set the colorspace.
+Fixed bug with uncompressed blocks in FlateStream.
+Fixed bug with fixed Huffman code table in FlateStream.
+Added hash table of X windows (for LTKWindow and LTKWidget) to LTKApp
+ and replaced calls to XQueryTree with hash table searches -- this
+ avoids a roundtrip to the server for each event and also fixes the
+ problem where XQueryTree crashed if the window no longer existed
+ (with leftover events from a destroyed window). (Thanks to Yair
+ Lenga for the suggestion.)
+Create a new GC for selection -- xor black and white (instead of LTK
+ foreground and background).
+Fixed crash with blank lines in .xpdfrc.
+Allow spaces in font descriptors in fontmap lines in .xpdfrc.
+Check for bogus object number in XRef::fetch().
+Use MacRomanEncoding for TrueType fonts that don't specify an
+ encoding.
+Certain PDF generators apparently don't include FontDescriptors for
+ Arial, TimesNewRoman, and CourierNew -- set GfxFont flags
+ appropriately.
+Fixed a bug in width guessing in GfxFont -- sans serif and serif were
+ swapped.
+Rewrote XRef::readXRef() to avoid using a parser to read the xref
+ entries.
+Added NO_TEXT_SELECT option.
+Ignore APPn/COM/etc. markers in DCT streams.
+Replaced select() with XMultiplexInput() in LTKApp.cc for VMS.
+Handle WM_DELETE_WINDOW protocol -- if you ask the window manager to
+ delete the xpdf window, xpdf will exit cleanly; other
+ windows/dialogs are simply closed.
+Optimized DCT decoder; switched to integer arithmetic.
+The "/Type /Annots" field in an annotation dictionary is optional.
+Check for null nameTree in Catalog::findDest().
+In XOutputDev, search user font map before default font map.
+Added "normal" SETWIDTH parameter to all font descriptors in
+ XOutputDev (some systems have a narrow-width Helvetica font).
+Added FOPEN_READ_BIN and FOPEN_WRITE_BIN to support Win32.
+Added a hack which allows better font substitution for some Type 3
+ fonts. Also allow character names of the form /nn and /nnn.
+Added <strings.h> and <bstring.h> to LTKApp.cc (needed by AIX and IRIX
+ for bzero() declaration for FD_ZERO).
+
+0.80 (98-nov-27)
+----------------
+Support for some Japanese fonts (Type 0 fonts using the Adobe-Japan1-2
+ character collection, horizontal only).
+Added pdfinfo application.
+Added pdftopbm application.
+Added pdfimages application.
+Added -papercolor option and .paperColor resource.
+Fixed divide-by-zero problem in XOutputDev Type 3 font matrix kludge.
+Font subset char names can be 'Bxx' as well as 'Cxx' and 'Gxx'.
+Fixed bug in color space conversion in DCTStream filter (YCC->RGB was
+ correct, YCCK->CMYK was broken).
+Added XRef::getDocInfo() and PDFDoc::getDocInfo() to support pdfinfo.
+Optimized GfxImageColorMap.
+Lexer::getStream(), getPos(), and setPos() check for null stream.
+Decryption code now does strings as well as streams.
+ASCII85 decoder rounds short tuples up instead of down.
+CropBox and MediaBox can be non-integers.
+PostScript output:
+ - Use a rectangle operator.
+ - Call setpagedevice with page size.
+ - Insert %%PageOrientation comments.
+ - Add paper size flags (-paperw and -paperh) to xpdf and pdftops.
+ - If HAVE_POPEN is not defined, and user tries to print to '|...',
+ the PSOutputDev destructor tried to write to the PS file.
+ - Added support for forms (pdftops -form).
+Removed error messages for empty paths in stroke, fill, etc. operators.
+Don't allow flatnesses less than 1 in XOutputDev (this speeds up
+ rendering a little bit when there are lots of tiny curves).
+Moved the font subset character name guessing from GfxFont to
+ XOutputDev and TextOutputDev - now these files print correctly.
+Cast argument to XFree() to XPointer; add XPointer definition where
+ necessary (portability fixes).
+Various minor VMS fixes.
+Changes to configure script and Makefiles:
+ - Print a warning if X is missing.
+ - Use C++ when checking select() argument type (HP-UX).
+ - Use 0 instead of NULL when checking select().
+ - Default to gcc instead of c++.
+ - Get rid of AC_C_INLINE -- this is meant for C, not C++.
+ - Changed -USE_GZIP to -DUSE_GZIP.
+ - Added ability to compile ouside of the source tree.
+ - Added .cc.o rule to {goo,ltk,xpdf}/Makefile.in.
+ - Added @LIBS@ to XLIBS in xpdf/Makefile.in.
+ - In top-level Makefile.in: added '-' to clean commands; added
+ distclean rule.
+ - Create install directories.
+ - Use INSTALL_DATA (instead of INSTALL) for man pages.
+ - Changed xpdf-ltk.h rule to avoid leaving an empty file when
+ ltkbuild fails.
+ - Change things so that by default, ltkbuild is not built and
+ xpdf-ltk.h is not rebuilt.
+ - Use AM_PROG_CC_STDC to add compiler flags for ANSI C.
+ - Modify autoconf's builtin macros to check for xlC.
+ - Use Steve Robbins' smr_CHECK_LIB to test for pixmap library (Xpm)
+ -- this should fix the problems on systems that have the library
+ but not the include file.
+ - Added better test for sys/select.h, sys/bsdtypes.h, strings.h,
+ bstring.h.
+ - New VMS make scripts from Martin P.J. Zinser.
+ - Moved dependences into Makefile.in -- this gets rid of problems
+ with 'cc -MM' (which is gcc-specific) and 'include Makefile.dep'
+ (which isn't supported by all make implementations). Also changed
+ all non-system include files to '#include "..."' (from '<...>').
+Tweaked the TextOutputDev heuristics slightly.
+Modify Gfx to use a stack of resources -- this is necessary for Form
+ XObjects, which can define their own local resources; also modified
+ PSOutputDev to dump fonts used by forms.
+Look for excessively large MediaBox (compared to CropBox) and shrink
+ it to CropBox.
+Minor fix to scrolling when dragging a selection.
+Various patches for pdftex and Win32 support.
+Deal with Separation colorspaces by using their alternate colorspace
+ entry.
+Added PBMOutputDev for pdftopbm application.
+Added ImageOutputDev for pdfimages application.
+Separated XOutputDev into LTKOutputDev + XOutputDev.
+Added support for 1-D and mixed 1-D/2-D (Group 3) decoding to
+ CCITTDecode filter.
+Added resetImage(), getImagePixel(), and skipImageLine() to Stream
+ class; used these in XOutputDev, PSOutputDev, and ImageOutputDev.
+Implemented predictor for LZW and Flate filters.
+In pdfImM1 in PSOutputDev prolog: div should be idiv.
+Changed output from printUsage() function in parseargs to look nicer.
+
+0.90 (99-aug-02)
+----------------
+Added Type 1/1C font rendering, using t1lib.
+Added "backward" and "forward" buttons.
+Added fit-page and fit-page-width zoom factors; replaced zoom-in and
+ zoom-out buttons with a zoom popup menu.
+Type 1C fonts are converted to Type 1 and embedded in PostScript.
+Support vertical Japanese text.
+Added Japanese text support (EUC-JP) to pdftotext.
+Bumped PDF version to 1.3. Added stub functions for ri and sh
+ operators. (But there are still some missing 1.3 features.)
+Added -raw option to pdftotext.
+Minor changes to allow compiling under MS Visual C++ 5.0.
+Top-level makefile: changed 'mkdir -p' to '-mkdir -p'.
+Configure script: added X_CFLAGS to smr_CHECK_LIB(Xpm).
+Added Xpm_CFLAGS to xpdf/Makefile.in (this is needed to get the -I for
+ the xpm includes).
+Rewrote code that handles font encodings; added support for Type 1C
+ fonts.
+In the setpagedevice dictionary in PostScript output - added a
+ /Policies entry which tells the PS interpreter to scale the page to
+ fit the available paper.
+Changed PageUp behavior slightly: move to bottom (instead of top) of
+ previous page.
+TextPage used character's dx (width + char space) instead of just its
+ width.
+Read base URI from document Catalog (for URI-type links).
+Minor change to configure script to avoid using 'unset'.
+Fixed bugs in CropBox inheritance.
+Fixed a bug in resource stack handling for form objects.
+Display forms even if they have a missing/incorrect FormType.
+Fixed a bug in stream predictors -- the predictor parameters (width,
+ comps, bits) don't need to match the actual image parameters.
+ Completely rearranged the predictor code.
+Fixed PostScript output to correctly handle stream predictors.
+Don't segfault on empty (zero-page) documents.
+Added the xpdf.viKeys feature.
+Added the ffi and ffl ligatures to XOutputDev and TextOutputDev.
+Pdftotext and pdfimages now check okToCopy().
+Added a '-q' flag to all programs (except pdfinfo) to suppress
+ messages and errors.
+Deal with DeviceN colorspaces by using their alternate colorspace
+ entry.
+Change PostScript output so setpagedevice is only called once, at the
+ very beginning of the document (to avoid problems on duplex
+ printers).
+Changes to configure script and makefiles for DOS/DJGPP.
+FontEncoding::getCharCode() looked for (code>0) instead of (code>=0).
+Added keypad arrow keys, etc. to xpdf.
+Minor changes to gfile.{h,cpp} (<windows.h>) to compile under VC++.
+Fixed CCITTFaxStream to correctly handle all parameters.
+Modifications to gfile.{h,cc} for Acorn.
+Some minor changes for OS/2.
+Added 'SHELL = /bin/sh' to Makefiles.
+Compare file version to pdfVersionNum+0.0001 to avoid floating point
+ precision problems.
+Added LDFLAGS to Makefiles.
+Removed strip entirely from configure and Makefiles.
+Fixed a bug in choosing the correct DCTStream color transform.
+
+0.91 (2000-aug-14)
+------------------
+Added TrueType font rendering, using FreeType.
+Support for Chinese fonts (Type 0 fonts using the Adobe-GB1-2
+ character collection).
+Decryption code is included with the main distribution (now that the
+ US export regulations are a little bit less irrational).
+Added (very basic) support for generating PostScript with Japanese
+ fonts -- only tested with ghostscript so far.
+Added support for generating EPS files (pdftops -eps).
+Much-improved image filtering in xpdf (for downsampling and for
+ transforms other than 0/90/180/270-degree rotations).
+Implemented a basic full-screen (presentation) mode (xpdf
+ -fullscreen). (There is currently no way to switch between window
+ and full-screen modes on the fly -- this will be fixed in a later
+ release.)
+Added "reload" menu item.
+Do a better job with anti-aliased Type 1 fonts on non-white
+ backgrounds.
+Handle Lab color spaces.
+Handle non-null user passwords.
+Avoid security hole with tmpnam()/fopen() -- added openTempFile() in
+ goo/gfile.cc. [Thanks to Joseph S. Myers for pointing this out.]
+Filter out quote marks (' and ") in URLs before running urlCommand to
+ avoid a potential security hole. [Thanks to Frank Doepper for
+ pointing this out.]
+Fixed TrueColor detection to look at the complete list of available
+ visuals, not just the default visual.
+In gfile.h, changed NAMLEN(dirent) macro to NAMLEN(d).
+Removed copyright character from start-up banners.
+In the open and save dialogs, if the open/save button is pressed with
+ no file name, the dialog is not canceled.
+Added Xpm_CFLAGS to ltk/Makefile.
+XOutputDev::updateLineAttrs was using dashLength before it was
+ defined.
+In top-level Makefile.in, use INSTALL_PROGRAM instead of INSTALL.
+In man page, recommend -q instead of -err in .mailcap.
+Changes for GNOME / Bonobo support:
+ - Separated Stream classes into BaseStream and FilterStream trees.
+ - Got rid of all FileStream-specific stuff.
+ - Added a PDFDoc constructor that takes a BaseStream* instead of a
+ file name.
+Allow newlines inside strings (Photoshop does this).
+Don't require whitespace between tokens in consecutive content
+ streams (for pages that specify an array of streams).
+Look at MissingWidth when constructing font character widths array.
+Fixed a bug that caused incorrect PostScript output for images that
+ use 8-bit indexed color spaces with < 256 colors in the palette.
+Handle case where embedded font file is bad (this was seg faulting).
+Minor changes for Windows/pdftex.
+Work around a bug in PDF files from the IBM patent server.
+Fixed bugs in PostScript form generation: use pdfStartPage instead of
+ pdfSetup; problem with inline images.
+Minor bug fix in FlateStream::loadFixedCodes().
+Added %%DocumentMedia and %%PageMedia comments to the PostScript so
+ that gsview (a Windows frontend for ghostscript) gets the right
+ paper size.
+Draw AcroForm fields that have appearance annotations.
+Bounds check gray, CMYK, and RGB values (in GfxColor).
+Moved the link border drawing code into Page (from PDFDoc).
+Minor modifications for pdftohtml.
+PSOutputDev: use the Type 3 font scaling kludge from XOutputDev.
+Separation color spaces were handled incorrectly in images.
+Fixed a bug with form bounding boxes.
+Modified the t1lib support -- replace libt1x code with my own code.
+ Type 1 and TrueType fonts are now handled similarly, and clipping
+ works on Type 1 fonts.
+Don't print copyright banner (xpdf); add -v switch to get copyright
+ and version info (all apps); get rid of -err switch (xpdf).
+Automatically reload the PDF file if it has been changed, i.e., if the
+ modification time is different.
+Fixed a memory (malloc size) bug in CCITTFaxStream.
+Fixed two bugs in FontEncoding::hash() -- handle zero-length character
+ names (which were found in a (buggy?) PDF file), and handle
+ character names with high-bit-set characters (use unsigned ints).
+Added PDFDoc::isLinearized() and corresponding code in pdfinfo.cc.
+Handle files with an incorrect page count in the Pages dictionary
+ (FOP, from the Apache project produces a page count of 0).
+Handle TrueType equivalents to the Base14 fonts (Arial, TimesNewRoman,
+ CourierNew) -- Adobe's tools use these names without embedding the
+ fonts.
+Tweaked the Type 3 font sizing kludge.
+Changed pdfimages (ImageOutputDev) so it doesn't output JPEG files for
+ 4-component color spaces, since these seem to confuse most image
+ viewers.
+Added support for generating OPI comments (pdftops -opi).
+In XOutputDev::drawImage() and drawImageMask(), check for images that
+ are completely off-page.
+Use the provided alternate or a default (DeviceGray/RGB/CMYK) color
+ space for ICCBased color spaces.
+Incorporated MacOS-specific code from Leonard Rosenthol.
+Configure script switches to C++ for the strings.h/bstring.h test.
+Gfx::opRestore() calls clearPath() to handle (apparently) buggy PDF
+ files produced by FreeHand.
+The /Type field in most dictionaries is optional (PDF 1.3 change).
+Move printCommands variable definition into Gfx.cc.
+If page is smaller than paper, center the PostScript output.
+Fix a minor bug in the SELECT_TAKES_INT detection in the configure
+ script.
+TextOutputDev filters out control characters.
+Changed enough occurrences of 'char *' to 'const char *' to keep gcc
+ 2.95 from barfing.
+Support for Latin-2 and Latin-5 in pdftotext (however, this will only
+ work if the PDF file contains correct font encodings, which seems to
+ be rare).
+TextOutputDev converts "eightoldstyle" to "eight", etc.
+Don't use the return value from sprintf() -- most systems return the
+ length, but some return the string.
+Minor fixes for SunOS 4.
+Configure script looks for both select() and fd_set in sys/select.h.
+Configure script checks for gethostbyname() in -lbsd (for LynxOS).
+Fix missing closepath bug in PostScript output.
+Change PostScript portrait/landscape mode selection so it only uses
+ landscape if the page width is greater than the paper width.
+Tweaked the VMS code in makePathAbsolute().
+
+0.91a (2000-oct-11)
+-------------------
+Implemented separable CMYK PostScript output (the -level1sep switch to
+ pdftops).
+Implemented Pattern color spaces with tiling patterns (polygon fills
+ only).
+Implemented Stamp annotations.
+Implemented Named link actions.
+Fixed a really dumb bug in the TrueColor code in SFont (which affects
+ both Type 1 and TrueType font rendering on 16-bit displays).
+Rewrote the GfxColorSpace / GfxColor code.
+Switched from djgppcfg to dj_make.bat (from Michael Richmond).
+Bug in the Type 1 encoding parser -- couldn't handle lines of the form
+ 'dup NNN/name put' (with no space between the code and the name).
+Fixed the mkstemp() test in configure.in -- switched from
+ AC_TRY_COMPILE to AC_TRY_LINK and added <unistd.h>.
+Added DESTDIR to top-level Makefile.in.
+Fixed an incorrect OPI comment in PSOutputDev.
+Minor tweak to the CCITTFax code to avoid writing past the end of an
+ array on an invalid data stream.
+Xpdf crashed if the user selected 'reload' when no document was
+ loaded.
+Look for character names of the form "xx" (two hex digits with no
+ leading alphabetic char) and 'cNNN' (decimal digits with a leading
+ alphabetic char that happens to be a hex digit).
+FlateStream didn't correctly handle zero-length streams.
+Xref reconstruction didn't handle the case where the opening "<<"
+ immediately followed "trailer" with no intervening whitespace.
+Fix the %%DocumentSuppliedResources comment in EPS output.
+Scale annotations to fit their rectangles.
+Added Stream::close() to handle cases (e.g., patterns) where a Stream
+ object is used multiple times before it is deleted.
+Added the topLevel arg to Gfx::go() so it doesn't call out->dump() for
+ every pattern element (and form).
+Rearranged the GfxResources class.
+Clean up white space handling in Lexer.
+Make the dpi parameter to PDFDoc::displayPage etc. a double - this
+ avoids margin gaps with fit-page and fit-width.
+Fix a rounding problem in xpdf.cc that was causing the window to
+ sometimes be one pixel too small.
+Fixed a minor bug in dealing with Base-14 TrueType font names.
+Fixed Lab -> RGB color space conversion.
+Added support for opacity values (from PDF 1.4) to GfxState and
+ OutputDev. [Thanks to Leonard Rosenthol.]
+Implemented type 2 functions; rearranged the Function class
+ hierarchy.
+
+0.91b (2000-oct-29)
+-------------------
+Print a warning about Type 3 fonts (XOutputDev, PSOutputDev).
+Added the scroll lock behavior to 'n' and 'p' keys in xpdf.
+Change FileStream buffer size to a #define'd constant.
+Renamed Pattern to GfxPattern to avoid clashes with Windows and MacOS
+ types.
+Added CNS (Big5) Chinese font support (CHINESE_CNS_SUPPORT); renamed
+ CHINESE_SUPPORT to CHINESE_GB_SUPPORT.
+
+0.91c (2000-nov-19)
+-------------------
+Fix an endianness problem in the Type 1 font code which resulted in an
+ incorrect display with "-t1lib plain" on big-endian systems.
+CCITTFax stream decoder will skip over extra zero bits at end of line,
+ even if EncodedByteAlign flag wasn't set.
+Added Big5 support to pdftotext (with CHINESE_CNS_SUPPORT enabled).
+Fixed a typo in the CNS/Big5 encoding translation table.
+Change the form code in PSOutputDev to store images in arrays of
+ strings.
+The xref reconstruction (for damaged files) now also looks for
+ 'endstream' tags, and the parser uses this information when setting
+ up stream objects.
+In pdfinfo, convert Unicode chars in the 00xx range into 8-bit chars;
+ print a warning if there are any other Unicode chars.
+
+0.92 (2000-dec-03)
+------------------
+Fixed %%BeginResource comment (for xpdf procset) in PostScript
+ output.
+Added "-title" switch and "xpdf.title" resource to set the window
+ title.
+Check for <freetype.h> in addition to <freetype/freetype.h>.
+Upgraded the configure script to smr_macros 0.2.4 - this should fix a
+ bug where configure wasn't correctly finding t1lib.
+
+0.92a (2000-dec-17)
+-------------------
+Added 'extern "C" { ... }' in various places for ANSI C++ compliance.
+Tweaked the code that figures out DPI for fit-to-page and fit-to-width
+ modes.
+Fixed the image transformation code in XOutputDev -- no more missing
+ lines.
+Implemented color key image masking in XOutputDev.
+
+0.92b (2001-jan-07)
+-------------------
+Fixed a bug in the error-checking code in the Separation/DeviceN color
+ space parsing functions. [Thanks to Lidia Mirkin.]
+Added wheel mouse support (mouse buttons 4 and 5). [Thanks to
+ Thorsten Schreiner.]
+Added preliminary support for FreeType 2 (disabled by default).
+
+0.92c (2001-jun-04)
+-------------------
+Fixed a bug in the new image transformation code.
+Look for character names of the form "<letter><digit><digit>", instead
+ of looking for names beginning with a few specific letters.
+T1FontFile::T1FontFile wasn't initializing vars, and ~T1FontFile
+ wasn't checking before calling T1_DeleteFont -- this caused crashes
+ if it tried to open a nonexistent font file.
+Catalog::Catalog didn't set baseURI to NULL early enough.
+Tweak the check for strings.h in the configure script.
+Yet another fix for the image rotation code in XOutputDev --
+ off-by-one problem when upsampling.
+Handle Type 1/1C encodings when using FreeType 2.
+Allow FreeType2 to render user-supplied Type 1 base fonts.
+Opening a new file from full-screen mode tried to scroll.
+Fixed a bug in GfxFont constructor (missing check for NULL base font
+ name).
+Don't crash if a Type 1 font's FontBBox is non-integer.
+Pdfinfo prints page size.
+Tweak for the alpha hack in T1Font/TTFont: sample the middle pixel
+ instead of the top-left pixel.
+Automatically activate the text input widget in the find window.
+Changed a Japanese char code mapping in XOutputDev and TextOutputDev:
+ period was being incorrectly mapped to small circle (end-of-sentence
+ character).
+Add the 0/+/-/z/w key bindings to control the zoom setting.
+Fixed ImageOutputDev (pdfimages) to correctly handle inline image
+ masks.
+Extract ascent/descent info from font descriptor.
+
+0.92d (2001-jun-26)
+-------------------
+Embed TrueType fonts in PostScript output. (Added a "-noembtt" flag
+ to pdftops.)
+Extract encoding from TrueType fonts.
+Moved Function classes to a separate file (Function.h/cc).
+Implemented multi-dimensional sampled Functions.
+Implemented Type 4 (PostScript calculator) Functions.
+For Type 0 fonts, FontDescriptor is in descendant font, not parent.
+ [Thanks to Lidia Mirkin.]
+Added the "-htmlmeta" option to pdftotext.
+In TextOutputDev, when computing the number of blank lines to insert,
+ do a sanity check on the result.
+If both FlateDecode and some other filter (e.g., DCTDecode) were
+ applied to an image stream, getPSFilter() crashed instead of just
+ returning NULL.
+Handle the /Identity function.
+
+0.92e (2001-aug-23)
+-------------------
+Widths in font dict should override built-in font widths.
+Changed "rotate left/right" menu items to "rotate
+ clockwise/counterclockwise".
+The link parsing code choked if the Border array was incorrect (too
+ short).
+Modified PSOutputDev to output CMYK for fill/stroke colors.
+
+0.93 (2001-oct-25)
+------------------
+Implement PDF 1.4 (128-bit) decryption.
+Bump supported PDF version number to 1.4.
+Text output for Simplified Chinese. [Thanks to Cheung Siu Fai.]
+Read an app-defaults file for Xpdf.
+Read a system-wide config file (<prefix>/etc/xpdfrc) if ~/.xpdfrc
+ doesn't exist.
+Accept and verify owner password; if correct, allow all actions.
+Added a "-level2sep" option to pdftops to generate Level 2 separable
+ PostScript. The PostScript separation convention operators are used
+ to handle custom (spot) colors. [Thanks to Thomas Freitag for help
+ on this.]
+Add support for FreeType 2 to the configure script. Warning: this
+ requires FT 2.0.5 or newer.
+Fixed the bounding rectangle overlap test in the disconnected subpath
+ fill hack in XOutputDev.
+Stupid typo in font name table in PSOutputDev.
+Changing the zoom setting with a keyboard shortcut didn't update the
+ displayed setting.
+Modified the mouse wheel support and added the second wheel (mouse
+ buttons 6 and 7). [Thanks to Michal Pasternak.]
+Character and word spacing is affected by horizontal scaling (display
+ and PS output). [Thanks to Eddy Ng.]
+Rotation specified by the text matrix, character spacing, and
+ horizontal scaling interacted incorrectly (display and PS output).
+Some broken Type 1/1C fonts have a zero BBox -- kludge around this by
+ assuming a largeish BBox.
+Handle PDF files with an incorrect (too small) xref table size.
+Allow "-?" and "--help" as aliases for "-h" (all apps).
+Correctly handle unescaped parens in strings in Lexer.
+Fixed a bug in LTK where a menu got posted multiple times if you right
+ clicked while a page was being rendered.
+Removed a comma inside a string in configure.in.
+Kludge around broken PDF files that use char 32 but encode it as
+ .notdef instead of space.
+Clean up various compiler warnings: use constructor args like "fooA"
+ if there is a field named "foo". Everything now compiles cleanly
+ under gcc 2.91.66, 2.95.2, and 3.0.1.
+Page objects now read all of the page rectangles (MediaBox, CropBox,
+ BleedBox, TrimBox, ArtBox), as requested by the pdfTeX folks.
+ Added a new PDFRectangle struct to hold these.
+Use XOutputDev's Type 3 font size hack in TextOutputDev too, so it
+ does a little better job of extracting text in Type 3 fonts.
+Modify pdfimages to write one-bit images as PBM files.
+Work around a bug in cygwin's implementation of fseek.
+
+0.93a (2001-nov-21)
+-------------------
+Implemented the sh (shaded fill) operator for the axial shading type.
+Minor fixes to avoid compiler warnings.
+Cleaned up global variables -- moved many into instance vars and
+ function args.
+Minor fixes for OS/2.
+Fix the system config file path for VMS.
+Fix an uninitialized var in XOutputDev that caused crashes on Alphas.
+Don't incrementally update the display in full-screen mode.
+For Type 1/1C fonts, use the FontBBox from the PDF FontDescriptor
+ (instead of the one in the font file) if present -- this avoids
+ problems with fonts that have non-standard FontMatrixes.
+Add the Euro character to WinAnsiEncoding.
+Track the bounding box of the clip region to make rendering patterns
+ more efficient.
+Fix openTempFile() for Win32.
+
+0.93b (2001-dec-11)
+-------------------
+Added a duplex option to PSOutputDev and a -duplex switch to pdftops.
+Added XRef::PDFgetDocInfoNF() for pdftex project.
+Updated the VMS build script.
+
+0.93c (2001-dec-12)
+-------------------
+Completely rewrote the code that handles font encodings:
+ - everything is Unicode-based
+ - 16-bit fonts are handled much more cleanly
+ - text output encoding can be set more flexibly
+New .xpdfrc config files.
+
+1.00 (2002-feb-01)
+------------------
+More work on the font encoding rewrite:
+ - use the ToUnicode font dict entry
+ - pdfinfo and pdftotext (with '-htmlmeta') convert info strings to
+ the selected text encoding
+Added key bindings for forward ('v') and backward ('b').
+Added the pdffonts program which lists the fonts used in a PDF file.
+Fixed several problems in the TrueType font embedding code (for
+ PostScript output).
+Accept named destination on command line.
+Added several new items to pdfinfo: file size, PDF version, tagged
+ (yes or no), XML metadata (with the -meta option).
+Pdftops didn't get the portrait/landscape setting correct for PDF
+ files with rotated pages.
+The TrueTypeFontFile class (including the Type 42 converter) now
+ understands cmap format 6.
+Improved the "about" window -- mention the GPL, add a list of key
+ bindings.
+Added Zcaron and zcaron characters to WinAnsiEncoding.
+The '0' keyboard shortcut didn't update the zoom popup menu.
+Handle the complete list of alternate names for the Base14 fonts.
+Fixed substitute font scaling in XOutputDev - scale only the width,
+ not the height.
+Implemented stitching (type 3) functions.
+Handle the case of moveto/closepath/clip, which defines an empty
+ clipping region.
+Move dependences into separate Makefile.dep files; get rid of the
+ distdepend target.
+Move all of the configure-script-generated -D options out of the
+ Makefiles and into a top-level .h file (aconf.h).
+Cleaned up the FreeType 1/2 detection code in the configure script.
+Pdfinfo prints dates in a more readable format.
+Fixed a bug in the Paeth image predictor.
+Handle annotations with multiple states.
+Another workaround for buggy X servers: clip points that are way out
+ of bounds.
+Added libpaper support (for Debian).
+Generate PostScript DSC resource comments for PS (not just EPS)
+ files.
+The save and restore (q/Q) operators shouldn't save/restore the path.
+Performance optimization: disable pattern drawing in TextOutputDev.
+
+1.00a (2002-feb-25)
+-------------------
+Added an optimized special case for one-bit images in XOutputDev.
+Implemented CID TrueType font embedding; added a psEmbedCIDTrueType
+ option.
+The initialZoom X resource was broken.
+The reverse MacRoman encoding should return 32 for "space" (not 202,
+ which is an alternate encoding).
+Tweaks to the FreeType 2 support: only disable hinting if the bytecode
+ interpreter is disabled (i.e., disable autohinting but not bytecode
+ hinting); add some padding to the glyph cache for CJK fonts.
+Added level3 and level3Sep options for the psLevel setting and
+ corresponding -level3 and -level3Sep options to pdftops.
+Added a -level2 option to pdftops for consistency.
+Avoid a divide by zero in pdftotext. [Thanks to William Bader.]
+Added a Greek language support package. [Thanks to Alexandros
+ Diamantidis and Maria Adaloglou.]
+Don't bother trying to extract a "builtin" encoding from a TrueType
+ font.
+Accept either a page number or a page reference in a link
+ destination.
+Update the fontFixedWidth flag in GfxFont after reading the char
+ widths (used by the Acorn RiscOS port).
+Removed yet another (illegal but not caught by gcc) class specified
+ from a .h file.
+Avoid using snprintf - it's not available everywhere.
+Improved the CMYK->RGB transform.
+Use mkstemps where available.
+
+1.01 (2002-may-20)
+------------------
+Implemented Type 3 fonts.
+Implemented PostScript CID font embedding; added a
+ psEmbedCIDPostScriptFonts option.
+Implemented PostScript 16-bit font substitution; added psNamedFont16
+ and psFont16 options.
+Moved the initialZoom setting from X resources to the xpdfrc file.
+Implemented the radial shading type in the sh (shaded fill) operator.
+ [Thanks to Mike Sweet.]
+Added an 'include' command to the xpdfrc format.
+Added the displayNamedCIDFontX option so different fonts can be used
+ within one character collection.
+Added a simple reverse video mode (-rv switch, xpdf.reverseVideo
+ resource).
+Implemented stroked text in XOutputDev (with t1lib and FreeType2).
+ [Thanks to Leonard Rosenthol.]
+Implemented stroked text in PSOutputDev.
+Added a built-in Unicode map for UCS-2.
+New key binding in xpdf: 'g' activates the page number text field.
+PSOutputDev will now embed external TrueType fonts in addition to
+ external Type 1 fonts.
+The psEmbedType1Fonts and psEmbedTrueTypeFonts options were missing
+ the "Fonts" suffix.
+Documentation in xpdf.1 for -freetype option was wrong.
+Added the Big5ascii Unicode map to the Chinese-traditional support
+ package (maps 7-bit ASCII straight through). [Thanks to Lawrence
+ Lai.]
+Modified the EUC-CN and EUC-JP encodings to pass 7-bit ASCII straight
+ through. [Thanks to Lawrence Lai.]
+Avoid a divide by zero in XOutputDev. [Thanks to Simon Burge.]
+Remove old code in openTempFile that removed an extension from the
+ name returned by tmpnam.
+Tweak the scrolling behavior when switching pages. [Thanks to Case
+ Jones.]
+In the code that guesses character names (for font subsets), also
+ handle names of the form 'ABnnn'. [Thanks to Colin Granville.]
+Fix the transform code for annotations.
+Improved the CMap file parser to handle more general PostScript
+ lexical conventions.
+Added '-enc' option to pdfinfo.
+Added the small caps and oldstyle numbers from Adobe's Unicode
+ corporate use area to the Latin1 and ASCII7 Unicode maps.
+The code in TextOutputDev that guesses Type 3 font size could generate
+ a zero size, which resulted in div-by-zero errors.
+Various tools (including Adobe's) occasionally embed Type 1 fonts but
+ label them Type 1C - so check for a '%!' at the start.
+Some tools embed Type 1C fonts with an extra whitespace char at the
+ beginning - just skip over it.
+Fixed a typo in the Simplified Chinese add-to-xpdfrc file.
+Updates to dj_make.bat and the djgpp build instructions.
+Added a Turkish language support package.
+Updated VMS build scripts. [Thanks to Martin Zinser.]
+Modify the incremental display update code to redraw less often if
+ most of the commands are vector graphics, as opposed to text and
+ images.
+Tweak the Type 1 font bbox code to look at the bboxes in both the PDF
+ font object and the embedded font file.
+Fixed the ETenms-B5-H CMap file (for traditional Chinese) to map the
+ Latin characters to their proportional versions.
+Added an optional displayCIDFontX entry for one of the Arphic TrueType
+ fonts in the traditional Chinese 'add-to-xpdfrc' file.
+Remove leading '-' on include statements in Makefiles.
+Added psASCIIHex parameter.
+Added the GBK Unicode map to the simplified Chinese language pack.
+Pdftotext now opens the text file in binary mode to avoid Microsoft's
+ annoying automatic end-of-line translation stuff.
+Added an executeCommand function in goo/gfile.cc. [Thanks to Mikhail
+ Kruk.]
+The %ALDImagePosition OPI comment was wrong if the page was scaled to
+ a different paper size.
+The OPI code was saving the default transform matrix before calling
+ setpagedevice, which can change the matrix.
+Fixed a crash when an inline image dictionary contains garbage.
+Upgraded to autoconf 2.53.
+Use unsigned int file offsets, to allow access to PDF files in the 2-4
+ GB size range; use fseek64/ftell64 if available.
+Fixed two floating point exception cases that came up with broken PDF
+ files.
+Avoid a crash when printing an error message regarding an unnamed
+ font.
+Default link border width should be 1. [Thanks to Michael Pfeiffer.]
+Minor tweak to build with FreeType 2.1.0.
+Handle "weird" characters in PostScript font names.
+PSOutputDev now handles PostScript XObjects.
+Added several more page attributes for the pdftex project.
+Transferred the copyright to Glyph & Cog, LLC.
+
+2.00 (2002-nov-04)
+------------------
+Switched to the Motif toolkit.
+Support multiple open documents (in separate windows).
+Added document outlines to the viewer.
+Modified the text extraction (placement) algorithm.
+Implemented the JBIG2 decoder.
+Added a Latin2 language support package.
+Added support for movie annotations.
+Switched back to native LZW decompression code.
+Text extraction from Type 3 fonts was (partly) broken.
+The owner password checking code was missing a step in the case of
+ 128-bit encryption.
+Added the 'printCommands' option to the xpdfrc file.
+Added key binding for '?' to bring up the about/help dialog.
+In TextOutputDev, ignore any text that's outside the page bounding
+ box.
+Text extraction throws away "tiny" characters after the first 20000
+ per page, to avoid really slow runtimes with PDF files that use
+ special fonts to do shading or cross-hatching; added the
+ 'textKeepTinyChars' option to disable this behavior.
+Text extraction discards duplicated text (fake boldface, shadow
+ effects).
+Added ctrl-F as a key binding for find.
+Added a "find next" function, bound to ctrl-G.
+Added ctrl-P as a key binding for print.
+Modified the DCT decoder to handle progressive and non-interleaved
+ JPEG streams.
+Added key bindings for ctrl-Home and ctrl-End.
+Allow the initialZoom setting to be made in either the xpdfrc file or
+ as an X resource.
+Added a Hebrew language support package. [Thanks to Roy Arav.]
+The "make distclean" target now creates (empty) Makefile.dep files in
+ the three subdirectories.
+Initialize XRef::ownerPasswordOk.
+Correctly handle stroking of Type 3 fonts in PSOutputDev.
+Generate correct PostScript for fonts with "weird" character names
+ (e.g., "(").
+Generate correct PostScript for images using Indexed color spaces with
+ DeviceN base color spaces.
+Added lowercase Roman numerals to ISO-2022-CN.unicodeMap (simplified
+ Chinese support package).
+Tweak the image scaling code to better handle flipped (top-bottom
+ and/or left-right) images.
+Generate correct PostScript code for inline images and images in Type
+ 3 fonts which are too large for a single PS string.
+Correctly handle indexed color spaces whose base color spaces have
+ component ranges other than [0,1].
+Optimized the DCT decoder.
+Fixed mistakes in the list of key bindings in the about/help dialog.
+Optimized the Flate decoder.
+Add literal names for punctuation and digits to the Unicode name
+ table.
+Cygwin's popen wants mode "r", not "rb".
+Fixed a bug in the Type 4 function parser (the "if" operator wasn't
+ parsed correctly).
+Fix a bug in PS output for TrueType fonts with no PDF encoding.
+Make the bbox size in FTFont more liberal (to avoid problems with
+ fonts that have incorrect bboxes).
+Reverse the colors in PBM files generated by pdfimages, so the common
+ case (an image mask filled with black) comes out correct.
+Add fseeko/ftello support which is basically identical to
+ fseek64/ftell64. [Thanks to Nassib Nassar.]
+Modified column assignment in text extractor to account for characters
+ that convert to multiple characters in the output encoding.
+Fix TrueType fonts which have an incorrect cmap table length.
+Work around a pragma bug in the version of gcc that ships with MacOS X
+ 10.2. [Thanks to Frank Siegert and Andrew Stone.]
+Fix a problem that was causing an infinite loop when a damaged content
+ stream contains an 'ID' command inside a dictionary.
+Handle the case where systempapername() returns NULL (libpaper
+ support).
+Handle fonts which are defined directly in the font resource
+ dictionary rather than as separate objects.
+Track process colors in Level 1 separable PostScript.
+Pdfinfo now checks the return value from mktime to avoid seg faults in
+ flakey strftime implementations.
+If duplex is not enabled in PostScript output, leave the duplex
+ setting alone, allowing the spooler to insert its own setting.
+Added three missing fclose calls.
+Change the default encoding for TrueType fonts (used when the PDF file
+ doesn't specify an encoding) from MacRomanEncoding to
+ WinAnsiEncoding.
+Move X_CFLAGS to the end of the list in CXXFLAGS (in Makefile.in) to
+ avoid some of the FreeType2 include path problems.
+Fixed an obscure bug in the LZW decoder. [Thanks to Martin
+ Schroeder.]
+Fixed a bug in decryption when using the newer (PDF 1.4) algorithm
+ with shorter-than-128-bit keys.
+Minor optimization for image data streams: the ImageStream class can
+ return an entire buffered line.
+
+2.01 (2002-dec-05)
+------------------
+Redesigned the text extraction process:
+ - process the text into "reading order"
+ - added a "-layout" flag to pdftotext to switch back to the old
+ style, where physical layout is maintained
+ - use of the "-raw" flag is no longer recommended
+Added the -reload option for xpdf (in remote mode).
+Added support for external CID fonts; added the displayCIDFontT1 and
+ displayNamedCIDFontT1 commands to the xpdfrc file.
+Handle the case of moveto/newpath/clip, which defines an empty
+ clipping region (just like moveto/closepath/clip).
+Accept XYZ link destinations with missing array elements.
+Fix some problems with state save/restore triggered by Type 3 fonts
+ that reference other fonts.
+Accept bogus font names based on "Symbol": Symbol,{Bold,Italic,
+ BoldItalic}.
+Fixed color and font resource names in the xpdf man page.
+Was using delete instead of gfree in OutlineItem::~OutlineItem.
+Set the busy cursor in the find dialog while searching.
+Map variants of the copyright, trademark, and registered trademark
+ symbols to the proper Unicode codes, not to Adobe's corporate use
+ area codes.
+Fixed a floating point exception bug in TextOutputDev (check for a
+ too-small denominator).
+Fixed a typo in TextOutputDev, in the code that generating blank lines
+ to add vertical whitespace.
+Config files whose last line didn't end with a LF (or CR+LF) weren't
+ being handled correctly.
+The code that handled CIDToGIDMaps in Type 2 CIDFonts was broken.
+Check the per-glyph bounding box in Type 3 fonts, and don't try to
+ cache glyphs with bogus bboxes.
+Allow ToUnicode CMaps to use fewer than four hex digits in the Unicode
+ char indexes.
+Added multithreading protection to the GlobalParams class.
+Fixed a bug in end-of-stream detection with the TIFF predictor.
+Added some characters to MacRomanEncoding to match up with Apple's
+ definition.
+
+2.02 (2003-mar-24)
+------------------
+Rewrote the text extractor code that assembles words into lines to
+ better handle vertically overlapping lines.
+Add the "match" option for paper size (in PostScript output).
+Added support for external 16-bit TrueType fonts; added the
+ displayCIDFontTT and displayNamedCIDFontTT commands to the xpdfrc
+ file.
+Added an Arabic language support package.
+Added the Windows-1255 encoding to the Hebrew language package.
+A missing NULL check was causing a crash when closing the file in a
+ single window (which clears out the window, but leaves it open).
+Deal with TrueType fonts whose glyph data is out of order - this
+ affected both FreeType rasterization and PostScript generation.
+Munge font names in PSOutputDev to avoid names that are problematic
+ for ghostscript because they start with an out-of-limits number
+ (e.g., 1e999foo).
+Modify the TrueType font encoding deciphering algorithm in yet another
+ attempt to match up with Acrobat's behavior.
+Bounds check the indexHigh value in indexed color spaces.
+The text extractor no longer bothers trying to get an average
+ character width for Type 3 fonts, since it generally doesn't work
+ very well (because Type 3 metrics are unreliable).
+Don't crash if the user hits ctrl-G ("find again") before doing a
+ find.
+Set the button pixmap foreground color correctly.
+Handle text drawn backward on 180 degree rotated pages.
+Added a magic call to XtUngrabButton after calling XmCreatePopupMenu
+ which appears to prevent some very odd problems (idea taken from the
+ DDD source code).
+Fix the MacOS X fix (needed to include <AvailabilityMacros.h>).
+Fixed a bunch of Motif 1.x / X11R5 incompatibilities. [Thanks to
+ William Bader and Albert Chin-A-Young.]
+Fixed various bugs in previously untested code in the JBIG2 decoder.
+Modify the XPDFCore destructor to avoid a bogus warning message from
+ OpenMotif 2.2.
+Modified the Type 1C font parser to do proper bounds checking.
+Fixed the bounds checking in the TrueType font parser.
+Text extractor shouldn't do block merging in physical layout mode.
+Fixed a problem in PSOutputDev in level2sep mode with images in a
+ Separation color space and with a non-default Decode array.
+Text extraction with "-raw" was concatenating lines from the bottom of
+ one column and the top of the next.
+Handle Type 1C subroutines in the font converters.
+Correctly handle progressive JPEG images whose scans are slightly
+ different sizes (e.g., the Y scan rounds up to a multiple of 8
+ pixels and the Cb/Cr scans round up to 16 pixels).
+Avoid a potential divide-by-zero problem in TextOutputDev.
+Modified the T1Font and FTFont modules to correctly handle glyphs that
+ are larger than the font's claimed bounding box.
+Tweak dupMaxDeltaX parameter in TextOutputDev to avoid triggering on
+ double characters.
+Improved detection in pdfinfo for ISO paper sizes. [Thanks to Hartmut
+ Henkel.]
+Xpdf wasn't responding to the TARGETS atom, which prevented pasting
+ the selection into various applications. [Thanks to Phillip Ezolt.]
+Handle XObjects with recursive references in their Resources
+ dictionaries (in PSOutputDev).
+Change PSOutputDev to deal with invalid PDF files that use
+ non-embedded TrueType fonts with no encoding.
+Check for undersized Widths arrays in fonts.
+Add bounds checking code to Array class.
+Updated VMS build scripts. [Thanks to Martin Zinser.]
+Tweak the TrueType font handling code (again):
+ - char codes in symbolic fonts may or may not be offset by 0xf000
+ - discard empty tables because they sometimes confuse FreeType
+Fixed bounds checking in the Flate decoder.
+Removed a bogus error message for exponential functions without
+ explicit C0/C1 values. [Thanks to Hartmut Henkel.]
+Handle the other Unicode cmap type (platform=0) in TrueType fonts.
+Added support for the SGI Motif horizontal paned window widget.
+ [Thanks to Felix Ritter.]
+Ignore extra elements in link destination arrays.
+Accept external Type 1 font files with a suffix of ".ps" or no suffix
+ at all.
+Add a bounds check in the DCT decoder.
+Added instructions for building xpdf.exe under cygwin/XFree86.
+Tweaked the word separation parameter for raw-mode text extraction.
+
+2.03 (2003-oct-10)
+------------------
+Rewrote the text extractor to:
+ - do a better job with rotated text;
+ - handle right-to-left scripts;
+ - be faster.
+Changed the zoom setting to use a percentage (relative to 72 dpi)
+ instead of a zoom "factor".
+If the PDF file has an outline, open the outline pane initially.
+Added -f and -l options to pdfinfo; print multiple page sizes.
+The HAVE_XTAPPSETEXITFLAG test in XPDFApp.cc was backwards.
+The BitsPerComponent entry is optional in image mask objects.
+Render any annotation with an appearance stream, instead of just
+ Widget and Stamp annotations.
+Fix a bug in the TrueType font checker: the test for an unsorted
+ 'loca' table was wrong.
+Modify the TrueType cmap selection algorithm yet again to try to match
+ Adobe's behavior.
+Changed sqrt(2) to sqrt(2.0) in pdfinfo.cc to make various compilers
+ happy.
+Fixed a deadlock problem (when MULTITHREADING is set); cleaned up some
+ other problems with the locking code.
+Fixed a bug in the interpolation code for type 0 (sampled) functions.
+Implemented type 1 (function-based) shaded fills.
+Fixed some stupid bugs in the JBIG2 decoder (introduced with the
+ previous optimization work).
+Fixed a typo in the code that parses vertical font metrics for CID
+ fonts that was causing a seg fault.
+Fixed a couple of bugs that were causing seg faults with badly damaged
+ PDF files.
+Limit the number of nested Forms to avoid infinite recursion (in buggy
+ PDF files).
+Add a special case for rectangular clip regions - make sure these
+ don't drop pixels on the right and bottom edges.
+Tell FreeType not to use glyph bitmaps when in anti-aliased mode.
+Read all of the border style info for links.
+All of the shaded fill types now do at least one bisection to avoid
+ problems when the colors at the endpoints of the domain are the
+ same.
+If the Length2 parameter for an embedded Type 1 font was incorrect
+ (too small), pdftops was losing font data.
+Deal with (broken) DCT streams that use the same component ID number
+ for different components.
+The MediaBox page attribute was not being inherited correctly.
+Fixed a bug in the Type 1C font converter related to local
+ subroutines.
+The Type 1C -> Type 1 font converter was allocating the font dictionary
+ one slot too small.
+Added a missing private dictionary entry to Type 1 fonts generated by
+ the Type 1C converter. [Thanks to Michael Shell.]
+Fixed bugs in the tiling pattern fill code.
+Try the TrueType 0xf000 char code offset hack for the MacRoman
+ encoding too (in addition to MS Symbol).
+Update the font metrics info for the Base 14 fonts to include the Euro
+ character.
+SECURITY HOLE: Escape various characters in URLs before running a web
+ browser (or movie viewer). [Fixed in 2.02p11]
+SECURITY HOLE: In the dialog used to verify "launch" links, provide a
+ scrolling view if the command to be run is excessively long. [Fixed
+ in 2.02p11]
+Added an option to disable insertion of page breaks (form feed
+ characters) in extracted text (pdftotext -nopgbrk; xpdfrc
+ "textPageBreaks" option).
+Check for 8-bit fonts that specify an out-of-range FirstChar or
+ LastChar.
+Correctly handle an obsolete Type 2 charstring op (in the Type
+ 1C-to-Type 1 font converter). [Thanks to Helge Blischke.]
+Use the font encoding info to fill in holes in the ToUnicode map.
+Added character names for Bulgarian (in the Cyrillic support pacakage)
+ and Greek.
+Handle clipping to text in xpdf and pdftops.
+Fix color space detection in DCT decoder. [Thanks to Dwight Kelly.]
+Added the "unicodeToUnicode" xpdfrc option, intended (initially) for
+ Arabic support.
+Handle the case in PSOutputDev where two font objects refer to the
+ same embedded TrueType font, but with different encodings. [Thanks
+ to Frank Siegert.]
+Kill any pre-existing path before drawing a form (or annotation).
+Save state before rendering page content; restore state afterward.
+Fix Stream::reset/close to work correctly with encoder streams; fix
+ PSOutputDev to use Stream::close consistently.
+Fix a seg fault when hitting the 'back' button after closing a file.
+GfxState::getStrokeGray was returning the fill gray value (this only
+ affected Level 1 PS output).
+Change PSOutputDev to reuse dictionaries in Level 1 mode (since Level
+ 1 PS interpreters don't do garbage collection). [Thanks to Frank
+ Siegert.]
+PSOutputDev was generating incorrect translations for landscape-mode
+ pages.
+Implemented shading pattern color spaces.
+PSOutputDev wasn't correctly handling Type 3 fonts which used image
+ resources (as opposed to inline images). [Thanks to Frank Siegert.]
+The fix from 1.00 which clipped out-of-bounds points was a bit too
+ aggressive.
+Do proper Floyd-Steinberg dithering in XOutputDev.
+Don't automatically check for a null owner password (to match Adobe's
+ behavior).
+Allow the FlateDecode filter in Level 3 PostScript output.
+Fixed small bugs in the Type 1C -> Type 1 converter and Type 1C ->
+ Type 0 converter. [Thanks to Tom Kacvinsky.]
+Work around another weird Motif problem with the right button menu
+ (which was sometimes causing the menu to not be displayed).
+Make the code that handles fonts defined directly in the resource dict
+ more robust.
+Add a brief description of the outline pane to the xpdf man page.
+Ignore extra operands to content stream operators.
+Fixed a bug in the CCITTFax decoder.
+Allow the Count entry in a Pages dictionary to be a real number
+ (because some PDF generators actually do this).
+Shading pattern fills weren't being clipped correctly.
+Incorrect shallow copies in GfxRadialShading and StitchingFunction.
+The StitchingFunction destructor wasn't checking for funcs being
+ NULL.
+Change the TrueType code-to-GID mapping code so it looks at the
+ TrueType 'post' table.
+Set the print command in the print dialog once at startup, don't
+ change it each time a file is (re)loaded.
+Generate the %%BoundingBox comment in regular PostScript files (not
+ just EPS files).
+Fixed a bug in the Unicode CMap parser.
+
+3.00 (2004-jan-22)
+------------------
+New PDF rasterizer ("Splash").
+Added support for PDF 1.5:
+ - JPX (JPEG 2000) decoder
+ - XRef streams
+ - object streams
+ - DeviceN color spaces with up to 32 components
+ - Added new CMaps to the CJK language support packages
+Replaced pdftopbm with pdftoppm (which can generate PBM, PGM, and PPM
+ files).
+Reorganized the font file parser code into a new library ("Fofi").
+Removed support for FreeType 1.x.
+Removed support for X server fonts - Xpdf (and pdftoppm) will now
+ search for the URW fonts (from ghostscript).
+Changed the "-t1lib" and "-freetype" switches; replaced the
+ "t1libControl" and "freetypeControl" config file options with
+ "enableT1lib", "enableFreeType", and "antialias".
+Added the "-box" option to pdfinfo.
+Added imageable area support to PSOutputDev (for CUPS); added the
+ "psImageableArea" config file option.
+Added the "-nocrop", "-expand", "-noshrink", and "-nocenter" switches
+ to pdftops; added the "psCrop", "psExpandSmaller", "psShrinkLarger",
+ and "psCenter" config file options.
+Dictionary size was in PostScript code generated for Type 3 fonts.
+The PS code generated for images in Type 3 characters was broken.
+Tweaked the text extractor.
+Accept xref entries that are one byte too short (matching Adobe's
+ behavior).
+Change things so "xpdf -h" and "xpdf -v" work if DISPLAY isn't set.
+Fix a problem in the damaged file repair code that handles the trailer
+ dictionary.
+Use the "Last" entries in "Outlines" objects - this avoids a problem
+ with PDF files generated by buggy software that, e.g., sets the last
+ item's Next pointer to point to itself.
+PSOutputDev was not handling DeviceN color spaces correctly in Level 2
+ images.
+Fixed a stupid little bug that broke PS output for JBIG2 images.
+Work around a Lesstif bug: set up an extra callback so hitting <Enter>
+ in the find dialog performs a search. [Thanks to Elliott Hughes.]
+Pdftops was crashing on zero page PDF files.
+Add an AC_PREREQ call to configure.in.
+Change the 'find' dialog so the text entry box resizes with the
+ dialog.
+Skip extraneous zero bits at the start of a CCITTFax stream.
+The PostScript text clipping operator was missing a 'newpath'.
+ [Thanks to Frank Siegert.]
+Fix a bug in tiling patterns with bboxes that don't start at (0,0).
+Fix a bug in Type 3 font handling with rotated text.
+The tiled pattern fill code was destroying the current path, which
+ broke the fill+stroke operators when the fill color space was a
+ tiled pattern.
+ICCBased color spaces don't always set their Ranges values correctly,
+ so just use the values from the alternate color space.
+Modified GHash to accept int or void* - this avoids some conversion
+ warnings.
+Check for missing Type 3 CharProcs - avoid a segfault.
+Pdffonts now marks all Type 3 fonts as embedded.
+Outline entries with no Title string weren't being handled correctly,
+ resulting in segfaults.
+PSOutputDev now forces the text horizontal scale factor to be non-zero
+ to avoid singular font matrices in the PS code.
+Tweaked the error recovery in the CCITTFax decoder.
+The LZW/Flate predictor should treat any Predictor value (in the
+ stream dictionary) >= 10 identically.
+PSOutputDev and pdffonts check for NULL font objects (which can
+ happen, e.g., because of missing CMap files).
+Swap the left and right mouse wheel button numbers.
+EPS output ("pdftops -eps") now uses the CropBox instead of the
+ MediaBox as the EPS bounding box.
+
+3.01 (2005-aug-17)
+------------------
+Added the continuous view mode, including the '-cont' switch and the
+ 'continuousView' config file option.
+At high zoom levels, don't rasterize the entire page - this avoids
+ problems running out of memory.
+Added "search backward" and "match case" options to the find dialog.
+Support explicitly masked images and soft masked images.
+Add support to DCTStream for 16-bit quant tables.
+Don't segfault if the user clicks on an outline entry with a broken
+ destination.
+Changed the makefiles and configure script to skip building pdftoppm
+ (in addition to xpdf) if X, Motif, or FreeType is not found; changed
+ the error message in the configure script to match.
+Move an inline function in JArithmeticDecoder.cc to avoid compiler
+ errors.
+Fixed a bug in the rasterizer that was sometimes causing infinite
+ loops with round line caps on vertical lines.
+Various rasterizer optimizations.
+Look for intermediate resize events - try to avoid lagging when the
+ user is doing an opaque resize.
+The FormType key in Form XObjects is optional.
+Handle external 16-bit TrueType fonts correctly, using the Unicode
+ cmap.
+Add class declarations to TextOutputDev.h to work with stricter C++
+ compilers.
+Support FreeType's weird include file stuff (ft2build.h, etc.).
+Fixed a bug handling empty paths.
+Fixed a text positioning problem in PostScript output.
+Handle TrueType collections in FoFiTrueType.cc.
+FoFiTrueType constructor was reporting a failure if the post table was
+ bad - this should be non-fatal.
+Type 1 font parser was missing a NULL test.
+Mask chars passed to isdigit in goo/parseargs.c to avoid problems with
+ signed chars.
+Added more error checking to the CCITTFax decoder.
+Fixed a bug (computing the MCU size) in the DCT decoder.
+Change a test in the Splash stroke code to avoid x86 floating point
+ weirdness.
+Reorganized the decryption code to allow security handler plugins;
+ removed the NO_DECRYPTION #ifdefs.
+Added a plugin interface, initially just for security handlers.
+Support color key masked images and explicitly masked images in PS
+ output (Level 2 only).
+When checking for aliases of the Base 14 fonts, ignore spaces in the
+ specified font name.
+Handle encrypted PDF files that are missing the file ID string.
+Handle tiling patterns more efficiently in the PostScript output.
+Rewrote the code that handles color spaces in PostScript output.
+Fixed a bug in the Type 1C font parser - zero-length indexes (and
+ zero-length names) weren't handled correctly.
+Handle shaded fills more efficiently in the PostScript output.
+Implement the remaining shading types (4-7).
+Rearranged the Splash color modes.
+Add the EarlyChange parameter to LZWStream when generating PostScript.
+Check for zero values in line dash arrays in PSOutputDev.
+Fixed an uninitialized variable in JArithmeticDecoder which was
+ causing crashes.
+Treat unknown CMap names as identity mappings (to match Adobe's
+ behavior).
+Fixed bugs in the XRef parser related to XRef streams in updated
+ files.
+Added a missing call to FT_Done_Glyph which was causing a memory leak.
+ [Thanks to Dave Formanek.]
+Fixed a bug in text copying that was causing the last word to be
+ dropped on some pages.
+Tweaked the image width/height computation in Splash::drawImage and
+ Splash::fillImageMask to make striped images work better.
+Ignore minus signs in the middle of numbers (to match Adobe's
+ behavior).
+Missing '%s' in format strings for dates in pdftotext '-htmlmeta'
+ mode.
+Change the TrueType code-to-GID mapping code so it looks at the
+ standard name-to-Unicode mapping before the ToUnicode mapping
+ defined in the font object.
+Added a matteColor setting (command line option and X resource).
+Tweaked the CMYK->RGB transform.
+Fix some problems in tracking the character position (to match up with
+ Adobe's highlight file format).
+Handle moveto/closepath/stroke correctly.
+Check for singular text matrices and font size of zero in PSOutputDev.
+Clip PS output to the size of the page (avoiding any gibberish that
+ lies outside the MediaBox, in the case where the MediaBox is smaller
+ than the paper).
+If the line dash element in an annotation's Border array is of an
+ invalid type (i.e., not an array), don't draw the link at all (this
+ matches Adobe's behavior).
+Don't remap small caps and oldstyle glyphs in the name-to-Unicode
+ table - it messes up TrueType font encodings.
+Pdftoppm wasn't setting the paper color correctly in mono and gray
+ modes (this only showed up on big-endian machines).
+Missing NULL check was causing crashes when attempting to read non-PDF
+ files that happened to contain the string '%PDF'.
+Fixed a problem in the text extractor that was breaking up words.
+Handle vertical text (CJK fonts) in PS output with TrueType fonts that
+ are missing the vertical metrics tables.
+Handle the case where a font object and the corresponding embedded
+ font are different types.
+Handle basic crypt filter functionality.
+Added more value checking in the XRef parser, to avoid potential
+ security problems.
+Updated the CJK language support packages: replaced the
+ displayCIDFontX references with displayCIDFontTT; added pointers to
+ free TrueType fonts.
+Added a missing error message when SplashOutputDev can't parse an
+ embedded TrueType font file.
+PDFCore and TextOutputDev now correctly handle searching for Unicode
+ strings, including real Unicode case-folding.
+Throw away tiling pattern fills that are completely outside the clip
+ region.
+The JPEG 2000 inverse reversible multiple component transform code was
+ wrong.
+Fixed some bugs in shading pattern fills: clipping was wrong, and
+ background color was not implemented.
+Added tool tips for the toolbar buttons.
+Decrease the max depth of recursive patch mesh filling if the pattern
+ has a large number of patches.
+Highlight the find text whenever the find dialog is mapped.
+Handle page boundary boxes with reversed coordinates.
+Fixed a bug in the text extractor code that handles duplicated text.
+Optimization work on SampledFunction::transform().
+Use the CropBox instead of the MediaBox as the display region.
+Dither for PseudoColor (8-bit) displays.
+Fix a bug in DCTStream that was causing an infinite loop with
+ corrupted DCT image data.
+Fix a bug in the ToUnicode CMap parser.
+Fix a bug in the text extractor - negative font sizes weren't being
+ handled correctly.
+Fix a bug in the text extractor - in certain cases, out-of-bounds text
+ could cause crashes (generally only in damaged PDF files).
+Fix a read-past-end-of-array bug in the JBIG2 decoder.
+Fix a case where pdftops was generating lines longer than 255 chars.
+Optimize redraws - don't regenerate the XImage every time redrawRect
+ is called.
+The ASCII85 decoder wasn't skipping whitespace properly.
+Optimize text extraction: skip (non-inline) image setup entirely.
+Added initial transparency support (stroke/fill alpha and blend mode).
+Added support for the overprint setting in PostScript output.
+Fixed various buffer overflow bugs.
+Handle negative font sizes and horizontal scaling correctly - this
+ affected PSOutputDev for all text operators, as well as the TJ
+ operator for all OutputDevs.
+Fixed a buffer overflow in the CCITTFax decoder.
+Fixed an out-of-order entry in the list of font name aliases.
+Fixed a backward loop in the PostScriptFunction code.
+Treat a zero-length base URI the same way as a nonexistent base URI.
+Add a divide-by-zero check in TextOutputDev (the problem was happening
+ in cases of mixed horizontal and vertical text).
+PSOutputDev wasn't rounding the page bounding box coordinates
+ correctly.
+Support the SOF1 marker in DCT (JPEG) image streams.
+Minor changes to GlobalParams.h and JPXStream.h because some compilers
+ don't like anonymous structs inside anonymous unions.
+Xpdf now complains about a negative page number.
+Changed GString::cmp and GString::cmpN to correctly handle '\0' chars
+ in the middle of strings.
+Fixed the radial shading code; corrected the handling of the 'extend'
+ parameters.
+Added the gmallocn and greallocn functions.
+Fixed a bug in the TIFF image component predictor which shows up with
+ components that are not 1 or 8 bits wide.
+Optimized FlateStream::loadFixedCodes().
+For non-embedded Base-14 fonts, don't use the ascent/descent/bbox
+ values from the FontDescriptor - various PDF generators get them
+ wrong.
+Fixed a bug in the text extractor - words on the same line (especially
+ in tables) were being split vertically onto multiple lines.
+Automatically select the correct radio button ("print with command"
+ vs. "print to file") in the print dialog.
+Don't create the "open" and "save as" dialogs until needed - this
+ avoids stat-ing every file in the directory at startup.
+Changed the Big5 and Big5ascii encodings (in the traditional Chinese
+ language support package) to include characters from the Unicode
+ database (which aren't mentioned in the Adobe character collection
+ documentation).
+Added the '-pagecrop' switch to pdftops.
+Tweaked the RGB->gray and CMYK->gray conversion functions to match the
+ PDF spec.
+The JPEG 2000 decoder wasn't correctly handling codeblocks split
+ across multiple packets/layers.
+Fixed a typecast that caused compile errors on 64-bit systems.
+The CMap parser wasn't handling the 'cidchar' construct.
+Handle the case in PSOutputDev where two font objects refer to the
+ same embedded 16-bit TrueType font, but with different CIDToGIDMaps.
+Changed the configure script to report more accurate warnings when
+ it can't find X / Motif / FreeType.
+Encryption with revision=2 always uses a 40-bit key, regardless of the
+ specified Length value.
+Yet another minor change to the TrueType font encoding deciphering
+ algorithm.
+Don't completely invalidate the Catalog if one (or more) of the page
+ objects are bogus -- just skip over those pages.
+Removed the workaround in pdftops for too-small Length2 values in Type
+ 1 fonts -- it was causing problems on various PostScript printers.
+Started adding error checking to the JBIG2 decoder (this is nowhere
+ near complete yet).
+Extended the "unicodeToUnicode" config option to also apply to CID
+ fonts.
+Added the narrow Latin characters to the Adobe-Korea1.cidToUnicode
+ file in the Korean language support package.
+Fixed the code that handles page rotation in PSOutputDev.
+When converting a Type 1C glyph to a Type 1 glyph, insert closepath
+ operators as appropriate.
+Check for a sane 'loca' table in TrueType fonts (FoFiTrueType::parse).
+Fix PSOutputDev to correctly handle the case of an empty name in a
+ font encoding.
+
+3.02 (2007-feb-27)
+------------------
+Added anti-aliasing for vector graphics; added the vectorAntialias
+ xpdfrc option; added the "-aaVector" switch to xpdf and pdftoppm.
+Implemented stroke adjustment (always enabled by default, ignoring the
+ SA parameter, to match Adobe's behavior), and added the strokeAdjust
+ xpdfrc command.
+Support PDF 1.6 and PDF 1.7.
+Added support for AES decryption.
+Added support for OpenType fonts (only tested with 8-bit CFF data so
+ far).
+Added user-configurable key/mouse bindings - the bind/unbind xpdfrc
+ commands.
+Cleaned up the full-screen mode code and added the ability to toggle
+ it on the fly (the default key binding is alt-f).
+Pdfimages with the -j option now writes JPEG files for 1-component
+ (grayscale) DCT images, in addition to 3-component (RGB) images.
+Fixed bugs in handling sampled (type 0) functions with 32-bit
+ samples.
+Fixed some things to support DeviceN color spaces with up to 32
+ colorants.
+Pdftops now constructs the %%Creator and %%Title DSC comments from the
+ relevant information in the PDF Info dictionary.
+Tweak the TrueType font encoding deciphering algorithm.
+Added the "mapUnkownCharNames" xpdfrc option.
+Fix a bug (that only showed up with certain window managers) in the
+ intermediate resize event optimization. [Thanks to Michael Rogers.]
+Check for a broken/missing embedded font (this was causing xpdf to
+ crash).
+Added support for transfer functions in PostScript output.
+Be a bit more tolerant of Link destinations that contain null values
+ for positioning parameters.
+Use ordered dot dithering instead of clustered dot dithering at
+ resolutions below 300 dpi (for monochrome output).
+Fixed security holes (bounds checking issues) in several places.
+Don't bother creating a SplashFont (allocating memory) for fonts that
+ are only used for hidden text - this avoids problems with fonts of
+ unreasonably large sizes.
+Clipping in TextOutputDev was off for characters on the left edge of
+ the page.
+The scn and SCN operators weren't correctly handling colors with more
+ than four components.
+FoFiType1::writeEncoded wasn't always correctly finding the end of the
+ encoding.
+Use the ColorTransform parameter in the DCTDecode stream dictionary.
+Type 3 fonts are allowed to have a bbox of [0 0 0 0], which means
+ "unspecified" -- don't issue error messages in that case.
+Perform the transform (to device space) in Splash instead of in
+ SplashOutputDev -- this is needed to correctly handle round joins
+ and caps on stroked paths.
+PSOutputDev now rasterizes any pages that use transparency.
+Limit the crop, bleed, trim, and art boxes to the edges of the media
+ box (per the PDF spec).
+Change GString to increase the allocation increment by powers of two.
+Handle whitespace in hex strings in CMap files/streams.
+Use strings instead of names for separation colorant names in
+ PSOutputDev.
+For explicitly masked images where the mask is higher resolution than
+ the image, use the soft mask code.
+Avoid problems with very large x-steps in the PostScript output for
+ tiling pattern fills.
+Avoid a divide-by-zero in stitching functions which have a subfunction
+ with empty bounds.
+Honor the "Hidden", "NoView", and "Print" flags on annotations.
+Rewrote the pixel rendering code in Splash to use a single set of
+ pixel pipeline functions.
+Added support for transparency groups and soft masks.
+Fixed the transparency blend functions to match the addendum published
+ by Adobe.
+Changed Splash/SplashBitmap to store alpha in a separate plane.
+Setting the color space now selects the correct default color for that
+ color space.
+Remove the mutex lock from GlobalParams::getErrQuiet() to avoid a
+ deadlock when parseCIDToUnicode() or parseUnicodeToUnicode() calls
+ it from inside a locked section.
+Added error checking (on the argument count) in the sc/SC/scn/SCN
+ operators.
+Skip over notdef glyphs in TrueType fonts (which sometimes get drawn
+ as little boxes), to match Adobe's behavior.
+Painting operations in a Separation color space with the "None"
+ colorant or a DeviceN color space with all colorants set to "None"
+ never mark the page.
+Fixed an obscure bug in the JPX decoder - it wasn't reading the extra
+ stuffing byte in the case where the last byte of a packet header was
+ 0xff.
+Change the TrueType font parser (FoFiTrueType) to change the glyph
+ count rather than report an error if the 'loca' table is too small.
+Fixed a couple of bugs in the JBIG2 decoder.
+Added stochastic clustered dot dithering.
+Added the screenType, screenSize, screenDotRadius, screenGamma,
+ screenBlackThreshold, and screenWhiteThreshold xpdfrc settings.
+PSOutputDev now correctly handles invalid Type 3 charprocs which don't
+ start with a d0 or d1 operator
+FreeType 2.2.x support - get rid of the FT_INTERNAL_OBJECTS_H include,
+ and add some 'const' declarations.
+Handle PDFDocEncoding in Info dictionary strings.
+Tweak the xref repair code - ignore whitespace at the start of lines
+ when looking for objects.
+Added the "-exec" switch to xpdf.
+Removed the xpdf.viKeys X resource.
+Changed the color key / explicit masked image code in PSOutputDev to
+ generate better PS code, including a Level 3 option.
+Tweaked the DEBUG_MEM code for performance.
+Move the JBIG2 global stream reading code into reset() instead of the
+ constructor - this way, pdftotext doesn't end up reading the global
+ stream.
+Added the "-preload" option to pdftops and the psPreload xpdfrc
+ command.
+Added the "zoom to selection" command (on the popup menu).
+Fix a bug (in xpdf/pdftoppm/pdftops) with tiling patterns whose bbox
+ size is different from their xStep/yStep.
+Implemented stroke with pattern color spaces.
+Following a link to a page whose CropBox was different from the
+ MediaBox was resulting in an incorrect scroll position.
+Parse truncated date strings from the Info dictionary correctly.
+Change FoFiType1 to handle Type 1 fonts with two /Encoding keys.
+Extend the PSOutputDev shaded fill code to handle DeviceCMYK shaded
+ fills in level2sep and level3sep modes.
+Detect infinite loops in the Page tree.
+Optimized the ASCII85Encoder code.
+Tweaked the text extractor to do a better job of lining up rows of
+ text.
+Leave images compressed (or re-compress them with RLE) in PostScript
+ output when setting up images for forms and Type 3 fonts (or with
+ -preload).
+Extend FoFiType1 to handle Type 1 fonts with octal character codes in
+ their encodings.
+Use a custom string formatter to avoid problems with locale-based decimal
+ formatting (commas instead of periods) in PS output.
+Allow comments in PostScript-type functions.
+Change the TrueType font parser (FoFiTrueType) to delete glyf table
+ entries that are too short.
+
+3.03 (2011-aug-15)
+------------------
+Added the "fixed pitch" text extraction mode.
+Modified "pdftops -paper match" to handle PDF files with
+ different-sized pages, i.e., it will now select the matching paper
+ size on a page-by-page basis.
+Add ability for pdftoppm to write to stdout.
+Added the pdfdetach tool.
+Implemented 256-bit AES decryption.
+Commented out the t1lib section in the configure script -- t1lib has
+ some potential security holes, and hasn't been updated in years.
+Redesigned the font configuration xpdfrc commands: removed the
+ displayFontT1, displayFontTT, displayNamedCIDFontT1,
+ displayCIDFontT1, displayNamedCIDFontTT, displayCIDFontTT, psFont,
+ psNamedFont16, and psFont16 commands; added the fontFile,
+ fontFileCC, psResidentFont, psResidentFont16, and psResidentFontCC
+ commands.
+Switched from GPLv2 to dual v2/v3 licensing.
+Performance: cache tiling patterns.
+Implemented text fills with pattern color spaces.
+Rewrote the image and image mask rendering code to be more accurate
+ and faster.
+Fixed a bug in PDFCore that could sometimes cause crashes at high zoom
+ levels.
+Implemented embedded CMap streams.
+Added the 'setSelection' command.
+Added the 'rotateCCW' and 'rotateCW' commands.
+Added the 'psFontPassthrough' xpdfrc command.
+Added the 'launchCommand' xpdfrc command.
+Implemented alpha-type soft masks.
+Added "Form: AcroForm|XFA|none" to pdfinfo output.
+Added support for image masks filled with pattern color spaces.
+Text search wasn't finding all occurrences of a string on rotated pages
+ (i.e., pages where the primary rotation, as displayed, was not
+ horizontal).
+The text extractor now uses "ActualText" spans if they are present.
+Modified PSOutputDev so it always check for transparency; if Splash is
+ not available, it now prints a warning.
+Handle the blending color space for soft masks.
+Added the disableFreeTypeHinting xpdfrc option.
+Added the psAlwaysRasterize xpdfrc option.
+Added support for transfer functions in the rasterizer.
+Optimized the JPEG 2000 decoder to use less memory.
+Do fill adjustment (similar to stroke adjustment) on simple
+ rectangular fills.
+Added the antialiasPrinting xpdfrc setting.
+Added '%i', '%j', and '%k' (mouse pointer page and position) to the
+ available options for the 'run' command.
+Links with the underlined border style were being drawn with the lines
+ over, instead of under, the text.
+Add #include <aconf.h> to XPDFTree.cc (to avoid problems with certain
+ compilers).
+Change XRef::fetch() to avoid infinite loops caused by odd damage to
+ the xref table (e.g., where a stream object's "Length" value is an
+ indirect reference that points to another stream object).
+Minor fix in GString.cc to deal with an error in newer C++ compilers
+ (pow() can take int or double args).
+Handle embedded fonts which are declared with the wrong font type,
+ including 8-bit fonts declared as CID fonts and vice versa; this
+ was causing various problems, including crashes and invalid
+ PostScript output.
+In text extractor, don't drop horizontally overlapping words onto a
+ separate line.
+The numbers in the operand to the TJ operator should be multiplied by
+ the current horizontal scaling parameter.
+Fixed a bug in the Type 1C-to-Type 1 font converter -- need to escape
+ strings in the font dictionary.
+The zero-font-size check in PSOutputDev.cc was broken.
+Fixes for the form field appearance regeneration code: handle Unicode
+ strings (by downconverting to Latin1); check for "True" in addition
+ to "Yes" as a button value.
+Modify XPDFTree to limit the widget height to 32767 pixels -- this
+ avoids crashes with very large outlines.
+Modify FoFiType1 to handle PFB headers in Type 1 font files.
+Allow image mask decode arrays to be [1.0 0.0] in addition to [1 0].
+Tweak the form field appearance regeneration code.
+PSOutputDev now sets up resources for DR dictionaries in forms (in
+ case the form field appearances are regenerated).
+For TrueType fonts which are marked symbolic, the cmaps should be
+ ignored.
+Change the handling of numeric characters in Unicode text output --
+ they are now treated as left-to-right, which isn't strictly correct,
+ but does result in correct visual formatting.
+Modify FoFiTrueType to handle bogus loca table entries where the
+ offset is past the end of the glyf table.
+Fixed shading pattern fills to do clipping and background fills
+ correctly.
+Change the code that reads the page tree to be more flexible with
+ regard to improperly constructed trees.
+Changed the PostScript header comment from "Produced by xpdf/pdftops
+ x.yy" to "XpdfVersion: x.yy" to make it (mostly) DSC-compliant.
+Fixed PSOutputDev to handle page rotation correctly where the PDF page
+ is rotated 90 or 270 degrees and the page width (before rotation) is
+ greater than its height (and vice versa for 0 or 180 degrees).
+Unbalanced save/restores inside form XObjects (which can be happen in
+ damaged or incorrectly constructed PDF files) could cause crashes.
+The CCITTFax decoder could go into an infinite loop on certain types
+ of corrupt input.
+Added the "drawAnnotations" xpdfrc command.
+Added the "psUncompressPreloadedImages" xpdfrc command.
+Escape newlines and other non-printable characters in the custom color
+ DSC comments in PostScript output.
+Added the tilingPatternFill and *ShadedFill functions to
+ PreScanOutputDev to speed it up.
+Too many elements in an image's Decode array should not be a fatal
+ error.
+Fixed a buffer overflow security hole in StreamPredictor.
+Empty pages (zero-length content streams and null contents) were
+ causing crashes in continuous view mode.
+Handle line dash arrays that start with a zero element correctly.
+PreScanOutputDev was not correctly detecting all transparency - in
+ some places, it was looking only at the blending mode, and not at
+ the opacity setting.
+Force halftone screen size to be a power of 2. This allows optimizing
+ the halftoning code.
+Fixed a bug in the JBIG2 MMR decoder (and also in the CCITTFax
+ decoder) that was causing array references with negative indexes.
+Fixed a bug in the transparency code that was causing memory overruns.
+Fixed a 64-bit bug in the ASCII85 encoder.
+The focusToPageNum was crashing in full-screen mode - it should simply
+ do nothing.
+Added '%p' (current page number) to the available options for the 'run'
+ command.
+Tweak the behavior with PDF files that have pages of different widths
+ in continuous mode: scroll horizontally to avoid blank space on the
+ left side (when changing pages via entering a page number or
+ clicking on a link).
+A closepath followed by a lineto should create a new subpath for the
+ lineto.
+Fixed a buffer overflow in the CCITTFax decoder.
+Adobe Acrobat appears to ignore the flatness setting when rasterizing
+ curves, so Xpdf now does the same. (Oddly, Acrobat passes the
+ flatness setting through to PostScript output, which ends up making
+ the PS file look different from the PDF file - so Xpdf continues to
+ pass flatness through to PS files, too.)
+Pdfimages now ignores tiling pattern fills (for performance reasons).
+Fixed a bug in PDFCore that could sometimes cause crashes at high zoom
+ levels.
+Use std::sort (with functors) in place of qsort (if available) - this
+ can be significantly faster.
+Hitting "close" while Xpdf is in full-screen mode (with only one file
+ open) was crashing.
+Tweak the TrueType font encoding deciphering algorithm.
+Rewrote the CCITTFax decoder inner loop - this fixes a security hole.
+Fixed two security holes (missing bounds checks) in the DCT decoder.
+Do the correct zooming for "Fit" and "FitR" destinations.
+Implement the rotation value in the form field appearance regeneration
+ code.
+When PSOutputDev rasterizes a page (because it contains transparency),
+ the image is broken into stripes if it is above a size threshold.
+Don't clip the other page boxes to the MediaBox at the intermediate
+ (Pages) nodes; only do it at the leaf (Page) nodes - the other boxes
+ can be specified before the MediaBox is specified.
+Split several special cases off from Splash::pipeRun, for performance.
+Add a sanity check for excessively large font sizes (which caused
+ problems because Xpdf tried to allocate memory for a font cache).
+Fixed a bug in the GfxCIDFont constructor involving reading the
+ vertical metrics.
+Rewrote the code that handles annotation transforms - it was not
+ handling non-rectangular transforms correctly.
+Tweak the Type 3 bbox code to allow some slack on the left/bottom
+ edges, as well as the top/right edges.
+Fixed a bug that was causing problems rendering Type 3 fonts to 1-bit
+ monochrome output.
+Handle the case where AES padding is invalid.
+Changed XRef::getNumObjects to return the number of used entries,
+ instead of the same value as returned by XRef::getSize().
+Ignore bogus entries in the TrueType table directory instead of
+ immediately giving up on the font.
+Fixed a bug in the radial shading code that could cause divide-by-zero
+ errors.
+Tweaked the TrueType font fixup code to deal with an extra zero entry
+ at the end of the loca table.
+Increased font cache sizes to improve performance.
+Tweaked the TrueType notdef kludge to skip the notdef glyph only if it
+ was caused by a character for which a Unicode/MacRoman mapping could
+ not be found.
+Added another font size sanity check, this time for Type 3 glyphs.
+Added initial support for optional content (layers) - no GUI yet.
+For CID fonts that specify the 'Adobe-Identity' or 'Adobe-UCS'
+ collection, use an identity mapping for char code-to-Unicode
+ conversion.
+Updated the error function to take a category argument, and to use
+ GString::format instead of printf; added an error callback.
+The PDF spec claims that names are limited to 127 chars, but Distiller
+ 8 will produce longer names, and Acrobat 8 will accept longer names
+ -- Xpdf will now handle them, too.
+Change the Catalog code so it doesn't load the entire page tree at
+ startup (this only helps the command line tools - the viewer scans
+ all of the pages at startup).
+Clip opacity values to the range [0,1].
+Handle glyph names of the form 'unixxxx' (similar to Ann, Axx, etc.).
+Resolution of rasterized pages in PostScript output was not being
+ computed correctly (resulting in overly large images).
+Extend the mapUnknownCharNames config command to cover CID fonts.
+Zero-length segments in the middle of stroked paths were not being
+ handled correctly -- they should be completely ignored, except for
+ the special case of a zero-length path with round line caps.
+Various optimizations to the Splash rasterizer.
+Allow "Identity" and "Default" as the transfer function in soft masks.
+Tweaked the ToUnicode CMap parser to allow <00xx> char codes for 8-bit
+ fonts.
+TextPage::clear() was not clearing the lists of underlines and links.
+Changed the CCITTFax decoder to correctly handle the interaction
+ between the EndOfLine and EncodedByteAlign parameters.
+Fixed a bug where xpdf wouldn't go to a destination specified on the
+ command line, if continuous mode was enabled
+ (xpdf -cont file.pdf +foo).
+Fixed a bug in the FreeType interface code which was causing incorrect
+ positioning/sizing of characters.
+Tweaked the FreeType interface code - use 'light' hinting with Type 1
+ fonts (because it generally looks better).
+Tweak the Windows font searching code to handle "Black" fonts.
+Fixed a bug in the PostScript-type function parser -- real numbers
+ that start with a decimal point weren't being handled correctly.
+Changed the way filled-and-stroked text is handled -- use Splash to do
+ both the fill and the stroke (rather than using the font ending to
+ do the fill and Splash to do the stroke); also turn off stroke
+ adjustment when drawing stroked text.
+Ignore generation numbers on compressed objects (to match Adobe's
+ behavior).
+Changed the PostScript PageSize policy from 3 to 6 (choose next
+ largest paper size, don't rescale).
+Check that the mask values for color key masked images are in range --
+ both Ghostscript and Distiller choke on the PostScript if invalid
+ mask colors are specified.
+Fixed a bug in generic region decoding in the JBIG2 decoder.
+Fixed the lexer to handle large real numbers correctly.
+Pdftops wasn't correctly handling tiling patterns that use both fill
+ and stroke operators.
+Report an error if the Size array in a sampled function includes any
+ zeros.
+The PostScriptFunction.codeString field wasn't being initialized
+ correctly.
+Invalid object streams were not being handled correctly.
+Check for loops in xref tables.
+Handle the case where a content stream ends after the 'ID' operator
+ which starts inline image data.
+Check for invalid object streams (i.e., an object stream can't be
+ inside another object stream.
+Add a recursion limit to the object parser - this avoids stack
+ overflows with various sorts of damaged PDF files.
+Handle various parameter settings in the extended graphics state
+ dictionary.
+An invalid document outline (missing fields) could cause a crash.
+Added an overprint preview mode (for CMYK output only).
+Correctly handle FitH/BH/V/BV link destinations that contain null
+ values for positioning parameters.
+If the PDF file doesn't define a BaseURI, set one based on the
+ location of the PDF file -- this allows relative links to be handled
+ correctly.
+Use ResusableStreamDecode when generating Level 3 PostScript for an
+ explicitly masked image.
+Tweak the Type 1 font parser to handle encodings with multiple
+ characters on one line.
+Invert subtractive color components before passing them to the
+ blending function.
+Fix an invalid array access in SplashOutputDev::setSoftMask() in CMYK
+ mode.
+A PS interpreter may attempt to read past the end of a preloaded
+ image, so we need to check for that.
+Fixed several overflow/uninit bugs in JBIG2Stream.
+Fix the CCITTFax decoder to correctly find end-of-file (RTC/EOFB)
+ markers when the EndOfLine parameter is false.
+Don't limit the startxref offset to 10 digits - some PDF generators
+ use extra leading zeros.
+Use the "DV" (default value) field in text annotations if the "V"
+ (value) field is missing.
+Increase the number of digits printed for floating point numbers in
+ PostScript output -- it was running into numerical accuracy problems
+ on large pages.
+Fixed integer overflow bugs in Catalog.cc and GfxFont.cc.
+Zero-length tables in TrueType fonts should be treated as missing.
+ToUnicode CMaps map char codes to Unicode; .cidToUnicode files map
+ CIDs to Unicode -- ToUnicodeCMaps were being handled incorrectly.
+Added the "psRasterResolution" and "psRasterMono" xpdfrc commands.
+Added code to FoFiTrueType to check for entries in the table directory
+ with bogus tags -- this handles the case where the number of tables
+ given in the header is too high.
+Negative shift values in the PostScript bitshift operator were being
+ handled incorrectly.
+GfxICCBasedColorSpace was not correctly bounds-checking the number of
+ components.
+Check SampledFunction input values for NaNs.
+Fix a divide-by-zero when the page width or height is zero.
+Fix a bug positioning text in PostScript output - if the last char in
+ a string has an incorrect width in the PDF font object, that messes
+ up the total string width, so we have to position individual chars.
+In PostScript output, if CID font substitution fails, drop all text in
+ that font.
+Handle PDF files that set the stream/string decryption filters to
+ Identity (i.e., no encryption).
+Avoid passing a zero font size to FreeType.
+Tweak raw mode in the text extractor to handle words on the same line
+ drawn in the wrong order.
+Pdftops was generating a singular transform matrix for annotations
+ whose bounding boxes had zero width or height.
+Handle embedded OpenType CFF fonts with CIDToGIDMaps.
+Remove the old kludge from PSOutputDev that was converting char 32
+ from ".notdef" to "space".
+Allow CCITTFax images to be more than 32k pixels wide.
+Modified the CMap parser to handle usecmap with Identity-H/V.
+Added some parameter checking in the JPX decoder.
+Added checks for infinite loops in PDF objects - for color spaces,
+ functions, optional content, and outline items.
+Add support for mouse button bindings up to button 32 (old limit was
+ 7).
+Fixed a bug in the decryption code for revision 3 with keyLength < 16
+ -- the owner password was not being handled correctly. [Thanks to
+ Matthias Franz.]
+Optimize SampledFunction: pull index computation code out of the
+ transform function; cache the last transform.
+Tweaked the font naming algorithm in PSOutputDev.
+Treat mirrored (as opposed to rotated) text the same as upright text
+ in pdftotext.
+Fixed buffer overflows in Splash and SplashBitmap.
+Check for bogus character codes (e.g., <ffffffff>) in ToUnicode CMaps.
+The radial shading code (in both Gfx.cc and PSOutputDev.cc) was not
+ computing the s bounds properly.
+Drop empty subpaths in clip and fill (but not stroke) operations -
+ this can significantly speed up clip performance in the weird case
+ where a PDF file does "<x> <y> <w> <h> re <x> <y> m h W n".
+Added code to FoFiTrueType to check for an invalid loca format field
+ in the head table.
+The axial shading code (in Gfx.cc, but not PSOutputDev.cc) was not
+ computing the incremental polygon vertices correctly.
+Set the character width in TextOutputDev to something sensible for
+ vertical fonts.
+Added basic support to the text extractor for vertical writing mode.
+The non-interactive tools (pdftotext, pdftops) now free Page objects
+ after using them, avoiding performance problems with pages that have
+ huge resource dictionaries.
+Check for line dash arrays like [0], and draw nothing at all (to match
+ Acrobat's behavior).
+Add a sanity check for the ascent/descent values in FontDescriptors.
+Single-point paths with a line dash were causing a crash.
+Correctly handle Level 3 PostScript output with masked images inside
+ patterns.
+Tweaked the xref repair code so that it runs if the catalog is messed
+ up (in addition to running if the xref table is damaged).
+If Indexed color space tables (streams or strings) are too small,
+ reduce the max index instead of throwing away the color space.
+Change the CMap parser to allocate memory only when it sees a mapping,
+ not when it sees a 'codespacerange' declaration -- this avoids
+ allocating huge amounts of memory for CMaps with large, unused
+ codespaceranges.
+In monochrome mode, treat lines with width <= 1 as hairlines (to match
+ Acrobat's behavior).
+Cache the last transform for PostScript-type functions.
+Added the "-rawdates" option to pdfinfo.
+Optimized ImageStream::getLine().
+Fixed the Hue, Saturation, Color, and Luminosity blend functions to
+ match Adobe's spec.
+Fixed the non-isolated group compositing computation.
+Skip extraneous unused data at the end of JBIG2 segments.
+Change the algorithm that stroke/fill adjustment uses so that the
+ edges of adjacent strokes/fills line up.
+Do stroke adjustment on end caps when cap style is butt or projecting.
+Fixed a security hole: Gfx.parser was not being initialized to NULL.
+Fixed a security hole: integer bounds check in the Type 1 encoding
+ parser in FoFiType1.cc.
+If an embedded font object is invalid or non-existent, do font
+ substitution (same as if there were no embedded font).
+TextOutputDev was reusing an old font in the case where the font
+ changed but the font size and character positioning stayed the same.
+When starting a transparency group, copy the fill/stroke colors from
+ the graphics state.
+Tweaked the fixed-point code.
+When a TrueType font is declared resident (with a psFont command),
+ don't munge the encoding.
+Look for URIs starting with "www." and treat them as absolute "http:"
+ URIs, not as relative URIs (to match Adobe's behavior).
+Added code to FoFiTrueType to check for a zero-entry cmap table.
+Tweaked the font substitution code to do a better job of scaling the
+ substituted font.
+Require at least two splits in the axial shading color bisection.
+Optimized JBIG2Stream::readGenericBitmap().
+JPXStream wasn't correctly handling row padding for images with fewer
+ than 8 bits per component.
+Optimized the ToUnicode CMap parser.
+Added a "whole words only" option to text searches.
+Check for valid component parameters in the DCT decoder.
+Implement embedding of external 16-bit fonts (without subsetting) in
+ PostScript output.
+Added the minLineWidth xpdfrc command.
+Added warning messages for font substitutions.
+
+3.04 (2014-may-28)
+------------------
+New text extractor.
+Added the pdftohtml tool.
+Added the pdftopng tool.
+New trapezoid-based rasterizer core (for performance).
+Generate appearance streams for Line, PolyLine, and Polygon
+ annotations.
+Added the closeWindowOrQuit command, and changed the default binding
+ for ctrl-W from closeWindow to closeWindowOrQuit.
+Implemented the new AES-256 mode (R=6, Acrobat X).
+Add an object cache.
+Added a small cache for object streams.
+Modify PSOutputDev to use LZW compression instead of RLE, with a
+ fallback to RLE if the "psLZW no" setting is given.
+Pdfinfo now prints page rotation info.
+Modified ImageOutputDev, used by pdfimages, to output the masks and
+ soft masks used when drawing images.
+Remove non-printable characters from error output, just in case they
+ might cause problems for the terminal program.
+Added initial support for Code3of9 bar codes in XFA forms.
+Added the mapExtTrueTypeFontsViaUnicode xpdfrc command.
+Apply stroke adjustment to rectangular images and clipping regions (in
+ addition to strokes and fills).
+Decode JPEG 2000 images at less than full resolution if the full res
+ image isn't needed (i.e., if the raw image is higher resolution than
+ the output).
+Implemented knockout groups.
+Removed t1lib support.
+Added support for images with 16-bit components.
+Rewrote the Dict class to use a hash table; as a side effect, this
+ handles dictionaries with multiple definitions for a key, which are
+ in violation of the spec, but Acrobat appears to handle.
+The transformed line width computation -- used to implement the
+ minLineWidth setting, and the hairline threshold in monochrome mode --
+ was incorrect.
+Pdftops was not correctly handling the case where it couldn't find
+ a 16-bit font -- this led to crashes and/or invalid PostScript.
+A bug in FlateStream::getBlock() was causing problems with narrow
+ images.
+Use the correct _WIN32 define instead of WIN32.
+Use copy-on-write for the clip path in SplashState (when doing gsave),
+ for performance.
+Added a Solaris-specific entry to the ghostscript font search path.
+SplashState was initializing line width to 0 instead of 1.
+Abort processing on a content stream after getting 500 errors
+ (undefined operator, wrong number of args) -- this avoids very long
+ processing time for malicious PDF files using bogus RLE encoded
+ content streams.
+Added the psUseCropBoxAsPage xpdfrc option; "pdftops -pagecrop" now
+ sets psUseCropBoxAsPage; "pdftops -pagecrop -paper match" now uses
+ the CropBox as the page size.
+Re-architected the AcroForm support code into a separate AcroForm
+ module.
+Fixed the handling of overprinting/transparency interaction, using
+ the CompatibleOverprint blend mode.
+The TIFF predictor code for the 1-bit-per-pixel case was broken.
+For triangle and patch mesh shadings (types 4-7) with color functions,
+ interpolate the function parameter not the color.
+Check the fontFile/fontDir commands before (instead of after) doing
+ Base-14 substitution in PS output.
+Correctly handle non-embedded TrueType fonts that have an Identity
+ ToUnicode mapping (display and PS output were failing).
+Added support for XFA form rendering, including an "enableXFA" xpdfrc
+ setting.
+Handle PFB Type 1 fonts when generating PostScript output.
+Unwind any extraneous saved graphics state at the end of the page
+ (before drawing annotations).
+Added some integer overflow checks in the GString class.
+Handle 16-bit components in JPEG 2000 images.
+ActualText spans can end without a valid font, in which case
+ TextPage::beginWord was crashing.
+The Domain entry in function shadings wasn't being parsed correctly.
+Fixed a bug in the JPEG decoder - successive approximation
+ (progressive mode) coefficients weren't being handled correctly.
+Added a better infinite loop test to the xref parser.
+When generating PostScript, merge reused TrueType fonts (if their
+ code-to-GID mappings are the same).
+Tweak the Gouraud triangle shaded fill code to end the recursive
+ splitting if the triangles get sufficiently small.
+Do bilinear interpolation when upsampling images.
+When skipping extraneous image data from an inline image, look for
+ EI<whitespace> instead of just EI.
+When writing to stdout on Windows, pdftoppm now sets the file mode to
+ binary. [Thanks to Robert Frunzke.]
+Accept strings as well as names for the BaseFont entry in font
+ objects.
+Removed the TEXTOUT_WORD_LIST config option (with the new text
+ extractor, this is always enabled).
+Fixed a bug in the JBIG2 decoder (the TPGD context for template #3 in
+ readGenericBitmap was incorrect).
+Rewrote the PostScriptFunction code for performance.
+Handle 8-bit OpenType CFF fonts that are missing required tables in
+ the OpenType wrapper.
+Handle tiling patterns with reversed coordinates in their bounding
+ boxes.
+Added support for 64-bit file offsets, i.e., PDF files larger than
+ 2GB.
+Optimize the code that rasterizes pattern-filled image masks.
+Added support for Mac OS X system fonts (Base-14 only).
+The backdrop color in luminosity-type soft mask groups was not being
+ handled correctly.
+Modified behavior of "pdftops -paper match -duplex ..." - it will now
+ duplex consecutive same-sized pages.
+Tweak the handling of degenerate fills ('moveto lineto fill') to
+ match Adobe.
+Don't honor the OPM=1 setting with ICCBased CMYK color spaces.
+Whole-word searches were treating certain punctuation (Unicode number
+ separators and terminators) as part of the word, e.g., searching for
+ "foo" would not match "foo,".
+Use the TextString class everywhere it makes sense.
+Removed the unnecessary segment sort in Splash (performance
+ optimization).
+Handle hyperlinks that use Widget-type annotations.
+Fix up the integer overflow checks to avoid issues with clever
+ compilers. [Thanks to Nickolai Zeldovich.]
+Correctly handle streams with missing Length entries in damaged PDF
+ files.
+Added a compile-time option (LOAD_FONTS_FROM_MEM) to load fonts from
+ memory rather than temporary files on disk.
+Added the psRasterSliceSize xpdfrc option.
+Fixed a case in the JPEG 2000 arithmetic decoder where extra data is
+ present in packet i, and needs to be saved for use in packet i+1.
+Fixed a bug in the JPEG 2000 decoder related to images with fewer than
+ 8 bits per component.
+Handle the case in PSOutputDev where slice size overflows a 32-bit
+ integer.
+Add (partial) support for TrueType cmap format 2.
+Always pass FT_LOAD_NO_BITMAP to FreeType -- bitmaps apparently fail
+ with rotated characters.
+Support fonts specified in ExtGState dictionaries.
+Annotations with empty Border arrays should not draw a border.
+Fix the CMap parser to handle large CID ranges.
+Check for Type 3 CharProcs that call q or Q before the d0/d1 operator,
+ and treat them as uncacheable.
+Invert the selection color when starting in reverse video mode.
+Device{Gray,RGB,CMYK} cannot be mapped via a resource dict.
+Changed the PS output for masked images (explicit and color key
+ masking): use a plain old clip path instead of rectclip to avoid
+ array overflows.
+Check the StemSnapH/V arrays when converting Type 1C fonts to Type 1 -
+ if there are any duplicate or out-of-order values, skip that
+ StemSnapH/V array.
+Added the psMinLineWidth xpdfrc setting.
+Fix an obscure issue in converting TrueType fonts to Type 42, related
+ to empty glyph descriptions (12 zero bytes).
+Pdftops now reports an error if there were any I/O errors writing to
+ the PS output file.
+Fix vertical text (CJK fonts) in PS output -- offset the character
+ origin correctly.
+Increased the number of digits used by pdfimages for the image number
+ from three to four.
+Handle right-to-left (e.g., Arabic) ligatures correctly in the text
+ extractor.
+Added the -loc and -locPS options to pdffonts.
+Extend the object parser recursion limit to cover Stream::addFilters()
+ / Stream::makeFilters() - to avoid another possibility of stack
+ overflow.
+Disable FreeType autohinting, because it can fail badly with font
+ subsets that use invalid glyph names -- except in the case of Type 1
+ fonts, which look much better with light autohinting.
+Modified the rasterizer pipeline functions to process a scan line at a
+ time (for performance).
+Removed VMS build support (it hasn't been updated in ages).
+Removed pdftotext's '-htmlmeta' option (use pdftohtml instead).
+PSOutputDev's font/form setup code, and pdffonts, were not scanning
+ soft mask groups in ExtGState dictionaries.
+Invalid DCT input (e.g., from a damaged PDF file) could overflow the
+ dctClip array.
+When upsampling an image mask or image with a large resulting image
+ size, do it in stream mode instead of prescaling the whole image
+ (to avoid running out of memory).
+Added infinite loop detection to pdffonts.
+
+4.00 (2017-aug-10)
+------------------
+Complete rewrite of the xpdf GUI, using Qt instead of Motif.
+Multithreaded rasterization in the viewer - pages are now rasterized
+ in a separate thread so that scrolling and other UI activity is not
+ blocked.
+Added a linear text selection mode.
+Limit transparency groups to the clip rectangle (performance
+ optimization).
+Optimized the SplashScreen code, used in 1-bit monochrome mode.
+Added setmode calls to pdftopng, when writing to stdout on Windows.
+ [Thanks to Robert Schroll.]
+Regenerate the appearance stream for an AcroForm field if there is
+ no appearance stream, even if NeedAppearances isn't set.
+When regenerating AcroForm field appearance streams, use a default
+ font (Helvetica) for fields that don't have a valid font.
+When the line width is increased by the minLineWidth setting, force
+ the line join mode to "bevel" to avoid "whiskers" at sharp corners.
+Change the pdftoppm/pdftopng resolution (-r) argument from an integer
+ to floating point.
+Use the FontDescriptor 'CapHeight' value in place of 'Ascent' if it's
+ available.
+OC (optional content) entries in image XObjects were being ignored.
+Added support for preblended soft-masked images.
+Added optional support for using libjpeg to decode DCT (JPEG)
+ streams.
+Transparency groups weren't being composited correctly in mono1 mode.
+Switched to a different IDCT transform in the DCT (JPEG) decoder, to
+ get better accuracy; the new transform is also a bit faster.
+Modified the polygon scan converter to avoid O(n^2) performance, which
+ can get really bad with paths that have extremely large numbers of
+ segments.
+Added the maxTileWidth, maxTileHeight, tileCacheSize, and
+ workerThreads xpdfrc settings.
+Modified PSOutputDev so it doesn't output resources (fonts, etc.) for
+ pages that are rasterized (because they use transparency).
+Added the -alpha flag to pdftopng.
+Handle TrueType fonts with out-of-bounds loca entries.
+Optimize consectutive "q" (gsave) operations in PostScript output.
+Various improvements to the XFA rendering code.
+Added the -nodiag flag to pdftotext.
+Switched to cmake instead of autoconf.
+Look for Widget-type annotations that aren't attached to the
+ AcroForm, and add them to the AcroForm.
+Added the "-z" option to pdftohtml.
+The JPEG 2000 decoder now treats invalid boxes after the image
+ codestream as non-fatal errors.
+Improved the handling of drop caps in pdftohtml.
+Added the "psNeverRasterize" setting.
+Pdftohtml now converts invisible PDF text to transparent HTML text.
+Check for zero-width/height bitmaps in the JBIG2 decoder -- these can
+ happen in corrupted JBIG2 streams.
+Pdfimages was inverting 1-bit monochrome images.
+Added CCITTFaxStream::getBlock() to speed up the CCITTFax decoder.
+Added resolution info to PNG files generated by pdftopng.
+The DCT decoder now ignores non-Adobe APP14 markers (rather than
+ generating an error).
+Regenerate appearance streams for FreeText annotations.
+The TextString class now handles UTF-16LE in addition to UTF-16BE.
+ (UTF-16LE isn't allowed by the PDF spec, but I've seen it used.)
+Added the simple one-column text extraction mode (pdftotext -simple).
+Added a -cmyk option to pdftoppm to write CMYK PAM files.
+Modified pdfinfo to output "static XFA" or "dynamic XFA", rather than
+ just "XFA".
+Added the "drawFormFields" xpdfrc command.
+Various performance optimizations in the rasterizer.
+Fixed the tiling pattern code to avoid stripes between pattern cells,
+ and to honor the TilingType flag.
+Always split axial shadings into 256 slices.
+Handle the case where an optional content block is left open at the
+ end of a page content stream.
+Accept code-to-CID-type CMaps as ToUnicode CMaps (to work around buggy
+ PDF generators).
+Unicode-to-unicode maps weren't working correctly with fonts that have
+ an "Identity" encoding.
+Modify the lexer to interpret "--123.4" as -123.4, "--123" as 0, and
+ "123-45" as "123" to match Adobe's behavior.
+The text extractor now reverses the order of side-by-side columns for
+ right-to-left scripts.
+Worked on right-to-left script support in pdftohtml (still not
+ complete).
+Switched the default display mode to continuous (from single page).
+Added the "-bom" switch to pdftotext.
+Share font objects when multiple font tags point to the same object.
+The transfer function goes before alpha blending in the rasterizer
+ pipeline.
+Added the "-allinvisible" switch to pdftohtml.
+Added overprint mode (OPM) support in Level 3 PostScript output.
+Added support for DeviceN color spaces in Level 3 PostScript output.
+Added the "-userunit" option to pdftops.
+Added the "-raw" and "-list" options to pdfimages.
+Pdfimages now writes PGM files (instead of PPM files) for DeviceGray
+ and CalGray images.
+Added grayscale PostScript output -- added the '-level2gray' and
+ '-level3gray' switches to pdftops.
+Fix up Type 1 fonts when embedding in PostScript.
+Added the "problematic" column to pdffonts output.
+Generate an appearance stream for signature fields in AcroForms.
+Correctly handle line dash patterns with zero-length segments when the
+ line cap is butt or project.
+Added the "strokeAdjust cad" xpdfrc option; fixed some issues with
+ stroke adjustment and projecting line caps.
+Added support for Code128B bar codes in XFA forms.
+Look at both the ON and OFF arrays in the default OCCD (optional
+ content config dict), to work around certain broken PDF files.
+Added support for XFA 'numericEdit' fields.
+Added support for 'picture' formatting in XFA forms.
+Added mouseClickN events (in addition to mousePressN and
+ mouseReleaseN).
+External CID OpenType CFF fonts should map through Unicode (similarly
+ to external CID TrueType fonts).
+Handle axial and radial shadings in SplashOutputDev, in device space.
+Use the PDF 2.0 inline image length field.
+Handle duplicate embedded Type 1 font names in PostScript output.
+Handle the case of a stroked closed path with a dash pattern -- if the
+ dash pattern is "on" at both the start and end of a subpath, it
+ should be joined.
+If the line dash phase is negative, add a multiple of 2x the total
+ dash length.
+Indexed color space indexes should be clipped to [0,hival].
+Fix the handling of the text render mode with Type 3 fonts, in the
+ rasterizer and in PostScript output.
+CID font metrics shouldn't be sorted - the PDF 2.0 spec says that, in
+ the case of duplicate entries, the first entry should be used.
+PSOutputDev now converts tiling patterns to PostScript tiling patterns
+ (in Level 2/3).
+Fixed a security hole in SecurityHandler.cc (uninitialized variables).
+ This vulnerability was discovered by Kushal Shah of Fortinet's
+ FortiGuard Labs.
+Fixed a security hole in Function.cc (write past end of array).
+Fixed a security hole with the use of d0/d1 operators outside of a
+ Type3 CharProc [CVE-2016-9027].
+
+4.01 (2019-feb-18)
+------------------
+Added remote server mode back into xpdf.
+Add support for Unicode file names for the command line tools on
+ Windows.
+Added the tabStateFile setting, the saveTabState/loadTabState
+ commands, and the "-tabstate" switch to xpdf. [Thanks to Christian
+ Barthel for the suggestion.]
+Added the defaultPrinter xpdfrc setting.
+Removed the psFile xpdfrc option (should have been removed in the 4.00
+ release).
+Tweaked the TrueType encoding/cmap code again, to get closer to the
+ PDF 2.0 spec, and to fix a problem (difference between Xpdf and
+ Adobe) with a specific PDF file.
+Optimized transparency group rasterization: only composite the part of
+ the group bitmap that was modified.
+If vector antialiasing is disabled, use the narrow stroke code for
+ lines less than one pixel wide.
+Do not map through Unicode for non-embedded CID TrueType fonts with
+ encoding = Identity-H and char collection = Adobe-Identity -- this
+ matches Adobe's behavior on a somewhat common case.
+The CCITTFax decoder now aborts after 1000 error messages, avoiding
+ problems with huge data expansion for badly corrupted CCITTFax
+ streams.
+The xref loop detection code was only looking at xref tables, and not
+ xref streams. (CVE-2018-7174) [Thanks to skysider for the bug
+ report.]
+The JPX decoder wasn't checking to make sure the number of components
+ is non-zero. (CVE-2018-7175) [Thanks to skysider for the bug
+ report.]
+Modify the lexer to accept leading '+' signs on numbers.
+Pdftohtml wasn't setting the background image width/height attributes
+ correctly for rotated pages.
+Ignore color-setting operators in cached Type 3 characters.
+Support color-key masking in Level3Gray PS output with preload.
+Xpdf was crashing on zero-page PDF files.
+Added the unicodeRemapping xpdfrc option.
+Change the cursor when the mouse is over text (in linear selection
+ mode).
+Support external OpenType CFF fonts for PostScript output.
+Handle choice-type AcroForm fields that have separate display values
+ and export values.
+Increased the supported PDF version from 1.7 to 2.0. (This isn't a
+ change in functionality. The code was already in place -- I just
+ forgot to bump the PDF version number.)
+Added the dropFont xpdfrc option.
+Added support for PDF417 barcodes in XFA forms.
+Modified pdfinfo to look at both the Info dict and the XML metadata.
+Check for invalid line cap/join values. [Thanks to
+ fish@360TeamSeri0us for the bug report.]
+Modified the object stream cache to hold onto more object streams, if
+ they're being used.
+Don't look at the "DV" (default value) key in AcroForm fields -- that
+ should only be used when a form is explicitly reset.
+Accept 8-byte values in xref streams.
+Two DCTStream bugs: don't allow SOF headers between progressive scans;
+ check for invalid Huffman table indexes. [Thanks to
+ fish@360TeamSeri0us for the bug reports.]
+Check for uses of the scn/SCN operators with no arguments. [Thanks to
+ fish@360TeamSeri0us for the bug report.]
+Correctly handle indexed color spaces with empty lookup tables.
+ [Thanks to fish@360TeamSeri0us for the bug report.]
+Support large bitmaps (>4GB) on 64-bit systems.
+Soft masks are always isolated.
+When "undoing" preblended image/softmask data, clip the resulting
+ color values to avoid problems with incorrect data.
+Set the default text encoding to UCS-2 in Xpdf, so that copying to the
+ clipboard works as expected.
+Added a sanity check for JBIG2 symbol height. (CVE-2018-7173)
+ [Reported by skysider.]
+Check for uninitialized value in JPXStream::fillReadBuf.
+ (CVE-2018-7452) [Thanks to skysider for the bug report.]
+Don't try to load an XFAForm if the PDF file has zero pages.
+ (CVE-2018-7454) [Thanks to skysider for the bug report.]
+Check for invalid line cap/join values. (CVE-2018-16368) [Thanks to
+ fish@360TeamSeri0us for the bug report.]
+If the page count is greater than 50k, rescan the page tree and count
+ the pages. This prevents long load times where various tools try to
+ read pages 1 through n. (CVE-2018-18651) [Thanks to krace for the
+ bug report.]
+Handle a null font name in PSOutputDev::setupEmbeddedType1Font.
+ [Thanks to r4xis for the bug report.]
+Check for invalid quant table indexes in the DCT decoder. [Thanks to
+ r4xis for the bug report.]
+
+4.01.01 (2019-mar-14)
+---------------------
+The PDFDoc(BaseStream) initializer wasn't working correctly.
+Fixed a missing array bounds check in PSOutputDev. [Thanks to
+ Loginsoft for the bug report.]
+If the "U" string used for RC4 decryption is short, Adobe apparently
+ zero-pads it, so Xpdf now does the same.
+Pdffonts now checks more carefully for loops between objects.
+Fixed a problem parsing large real numbers. [Thanks to Loginsoft for
+ the bug report.]
+
+4.02 (2019-sep-25)
+------------------
+Pdftohtml now extracts embedded fonts (TrueType and CFF only).
+Added the margin settings (-marginl -marginr -margint -marginb) to
+ pdftotext.
+Various user interface tweaks:
+ - added a toolbar button to toggle (show/hide) the sidebar
+ - added view menu items to toggle (show/hide) the sidebar and
+ toolbar
+ - added the 'showToolbar', 'hideToolbar', 'toggleToolbar',
+ 'expandSidebar', and 'shrinkSidebar' commands
+ - added the 'initialDisplayMode', 'initialToolbarState', and
+ 'initialSelectMode' xpdfrc settings
+ - rearranged the xpdf toolbar
+Implemented drag-and-drop, so that PDF files can be drag-and-dropped
+ onto an already-open xpdf window.
+Added the option to display page labels, rather than page numbers.
+Implemented the missing 'openInNewWin' command.
+Added the 'openFileIn', 'openFileAtDestIn', 'openFileAtPageIn', and
+ 'openIn' commands; removed the 'openInNewWin' command.
+Added the '-open' switch to xpdf.
+Added the reverseVideoInvertImages setting.
+Page-up and page-down now "snap" to the nearest page, if it's within a
+ few pixels. This avoids annoying behavior when the window is a tiny
+ bit too short or too tall for a page.
+Properly handle overprint in non-isolated transparency groups.
+Missing null check in Gfx::opSetExtGState(). [Thanks to
+ pwd@360TeamSeri0us for the bug report.]
+The DCT decoder doesn't handle a sampling factor of 3 -- check for
+ this and report an error. [Thanks for Agostino Sarubbo of Gentoo
+ for the bug report.]
+Check for images with a Pattern color space, and report an error.
+ [Thanks to TeamSeri0us for the bug report.]
+Check that the Width, Height, and BitsPerComponent are valid in image
+ soft masks. [Thanks to TeamSeri0us for the bug report.]
+Check for zero page width/height in PSOutputDev. [Thanks to
+ TeamSeri0us for the bug report.]
+Check for divide-by-zero in PostScript functions. [Thanks to
+ TeamSeri0us for the bug report.]
+Properly handle overprint in shading pattern strokes.
+The "save image" feature in Xpdf wasn't getting the user-specified
+ page number correctly.
+PostScript doesn't support progressive or non-interleaved DCT (JPEG)
+ streams, so check for those and re-encode them in PS output.
+Splash now caches the most recent scaled image, in case it is
+ immediately reused -- this results in a significant speedup in
+ certain cases.
+Fixed a problem with parsing the TrueType loca table. [Thanks to
+ Pangu Lab for the bug report.]
+Fixed a problem with int overflow on image bounds. [Thanks to
+ Pangu Lab for the bug report.]
+Fixed a problem with TrueType font parsing where there is gibberish in
+ the TrueType table directory. [Thanks to Pangu Lab for the bug
+ report.]
+Fixed a problem with JPX image resolution reduction. [Thanks to Pangu
+ Lab for the bug report.]
+Fixed a problem with non-isolated transparency groups in 1-bit
+ monochrome mode. [Thanks to Pangu Lab for the bug report.]
+Fixed various bugs in FoFi. [Thanks to Pangu Lab for the bug
+ reports.]
+Added a missing bounds check to Annot::setFillColor(). [Thanks to
+ Pangu Lab for the bug report.]
+Added a check on the DCT quant table selector. [Thanks to Pangu Lab
+ for the bug report.]
+Fixed a problem with the Type 3 font cache running out of entries.
+ [Thanks to Pangu Lab for the bug report.]
+Fixed an integer overflow bug in SampledFunction. [Thanks to Pangu
+ Lab for the bug report.]
+Fixed an integer overflow bug in the tiling pattern size. [Thanks to
+ Martin Muskens at Ergosoft for the bug report.]
+Fixed a read-past-end-of-buffer in the Type 1 font parser. [Thanks to
+ Pangu Lab for the bug report.]
+Fixed an int overflow bug in the JBIG2 decoder. [Thanks to
+ TeamSeri0us for the bug report.]
+Added a missing bounds check to GfxPatchMeshShading::parse(). [Thanks
+ to TeamSeri0us for the bug report.]
+JPEG 2000 tile indexes were being computed incorrectly. [Thanks to
+ TeamSeri0us for the bug report.]
+Large sample separation values in a JPX stream were resulting in
+ zero-width/height tiles, which caused problems. [Thanks to Pangu
+ Lab for the bug report.]
+The XFA parser now looks for "ancestor matches" when searching for
+ data to fill a form field.
+Fixed an uninitialized variable in BuiltinFontWidths::getWidth().
+ [Thanks to Martin Muskens at Ergosoft for the bug report.]
+If there are no popupMenuCmd instances, construct a popup menu with
+ basic instructions pointing to 'popupMenuCmd'.
+Ignore color operators in uncolored tiling patterns. [Thanks to
+ Martin Muskens at Ergosoft for the bug report.]
+Pdftotext raw mode output looks for space characters.
+Increased the width of the font name column in the pdffonts output.
+Function objects weren't checking their input/output counts properly.
+ [Thanks to Pangu Lab for the bug report.]
+TextPage::findGaps() wasn't checking the x/y min/max values for int
+ overflow. [Thanks to Taolaw for the bug report.]
+
+4.03 (2021-jan-28)
+------------------
+Implemented selection extension via shift-click, and word/line
+ selection via double/triple click.
+Added default bindings for ctrl-mousewheel-up/down to zoom in/out.
+Added the "-nofonts" option to pdftohtml.
+Added the "simple2" mode to pdftotext.
+Added the "-rot" flag to xpdf, pdftoppm, and pdftopng.
+Added the "-listencodings" flag to pdftotext.
+Added the 'copyLinkTarget' command.
+Added the 'selectionColor' xpdfrc setting.
+Added the 'initialSidebarWidth' xpdfrc setting.
+Added support for @"..." strings in xpdfrc files. This includes using
+ '%' as an escape character, and also the '${DATADIR}' variable.
+Added a help menu item that shows all of the key bindings.
+Reorganized the gradient shading rasterization code to avoid
+ transparency artifacts between triangles/patches.
+Use interpolation rather than subdivision to rasterize Gouraud
+ triangle shadings.
+Allow escaping (via the \x01 character) in command args, so that "xpdf
+ -open foo(123).pdf" works correctly.
+Extended the damaged file repair code to handle PDF files that use
+ xref streams and object streams.
+Modified pdfinfo to print the encryption algorithm used (if any).
+Handle Windows shortcut (.lnk) files in Xpdf and in the command line
+ tools.
+Display an error dialog when trying to copy text from a protected
+ file.
+Updated all four of the CJK language support packages with the latest
+ Adobe data.
+Modified pdftohtml to draw 'invisible' text over non-horizontal words.
+Catalog.pageLabels wasn't being properly initialized to NULL. [Thanks
+ to Dhiraj for the bug report.]
+Added a sanity check for JBIG2 symbol width. [Reported by Marc
+ Schoenefeld.]
+Fixed a bug in the fontconfig calls that was causing Xpdf to crash.
+The Type 3 font cache code wasn't correctly handling the case where a
+ Type 3 char refers to another char in the same T3 font. [Thanks to
+ Pangu Lab for the bug report.]
+Xpdf was crashing if 'view page labels' was enabled without any
+ document open. [Thanks to TeamSeri0us for the bug report.]
+The Type 1C-to-Type 1 font converter wasn't checking for
+ divide-by-zero with rational numbers. [Thanks to TeamSeri0us for
+ the bug report.]
+Fixed a bug in the TrueType font parser - zero-length loca tables
+ weren't handled correctly. [Thanks to TeamSeri0us for the bug
+ report.]
+Fixed an integer overflow bug in the transparency group setup code.
+ [Thanks to TeamSeri0us for the bug report.]
+Pdfinfo with the "-box" option was crashing on zero-page PDF files.
+ [Thanks to TeamSeri0us for the bug report.]
+The code that caches scaled images wasn't checking the rendering
+ intent. [Thanks to Martin Muskens at Ergosoft for the bug report.]
+The JBIG2 decoder now checks for gibberish values in various segment
+ headers, but keeps any data decoded prior to that.
+Fixed two bugs in the FoFi code that handles CFF fonts. [Thanks to
+ dsmic for the bug report.]
+Redesigned the image scaling code, for performance.
+Cleaned up the code that sanity-checks font sizes to avoid trying to
+ allocate too much memory for the font cache.
+Implemented precincts in the JPEG 2000 decoder.
+The page-up/down snapping code was calling TileMap::getPageTopY() with
+ invalid page numbers. [Thanks to dfandrich for the bug report.]
+Added missing error-checking when parsing an annotation appearance
+ stream's bbox.
+Handled UTF-16 sequences in ToUnicode maps.
+Rewrote the code that draws static XFA forms: combined it with the
+ AcroForm code, to match Adobe's behavior. Removed the enableXFA
+ xpdfrc setting.
+Check for indirect references in content streams and report an error.
+Doing overprint preview in tiling patterns requires tracking the
+ overprint mask at each pixel.
+Check for "decompression bombs" in Flate and LZW streams.
+The nextPageNoScroll and prevPageNoScroll commands weren't working
+ correctly in continuous mode.
+Disable stroke adjustment when drawing Type 3 characters.
+The "xpdf -open" flag now constructs an absolute path, so it's not
+ dependent on the current directory when xpdf was started.
+Check for infinite loops in Type 1C charstring subroutines. [Thanks
+ to blbi for the bug report.]
+Fixed an incomplete test for headless CFF files. [Thanks to Chengbin
+ for the bug report.]
+Tweaked the code that computes segment slope in SplashXPath.cc to
+ avoid problems with extremely small coordinate values. [Thanks to
+ Chengbin for the bug report.]
+Check for an invalid segment length in PSOutputDev's PFB parse.
+ [Thanks to Chengbin for the bug report.]
+Check for JPEG 2000 segments that are only allowed in the first
+ tile-part of a tile. [Thanks to Chengbin for the bug report.]
+Check for invalid AcroForm ListBox field top index. [Thanks to
+ Chengbin for the bug report.]
+Check for invalid mesh shading parameters. [Thanks to Chengbin for
+ the bug report.]
+
+4.04 (2022-apr-18)
+------------------
+When closing a file, save the current page number in ~/.xpdf.pages,
+ and restore it next time the file is opened. This can be disabled
+ with "savePageNumbers no" in your xpdfrc file.
+Allow the tab list to be reordered, using drag-and-drop.
+Added a document information dialog, with metadata and fonts, to xpdf.
+Pdftohtml now generates HTML links for URI links anchored on text.
+Added the useTrueTypeUnicodeMapping xpdfrc setting.
+Added the 'enableXFA' xpdfrc setting back: if set to 'no', xpdf will
+ not read an XFA form, meaning all form info comes from the AcroForm.
+Add support for long paths on Windows 10.
+Added the "-formfields" option to pdftohtml.
+Added the "-embedbackground" and "-embedfonts" options to pdftohtml.
+Added the "-vstretch" option to pdftohtml.
+Added the "-verbose" flag to pdfimages, pdftohtml, pdftopng, pdftoppm,
+ pdftops, and pdftotext.
+Added the showAttachmentsPane, showLayersPane, and showOutlinePane
+ commands.
+Added the 'openFile2' command to xpdf.
+Added the showMenuBar, hideMenuBar, and toggleMenuBar commands to
+ xpdf.
+Rearrange file names in the tab list to "foo.pdf [/full/path/]", to
+ improve the usability of the (narrow) tab list.
+Added the 'imageMaskAntialias' xpdfrc setting.
+Added the '-table' switch to pdftohtml.
+Fixed a couple of progression order bugs in the JPEG 2000 decoder.
+ [Thanks to shellway for the bug reports.]
+Fixed a problem with subsampled pixel index computations in the JPEG
+ 2000 decoder. [Thanks to shellway for the bug report.]
+Fixed a couple of memory leaks triggered by fuzzed PDF files. [Thanks
+ to shellway for the bug report.]
+Changed pdftohtml to generate spans with 'class=' instead of 'id=', so
+ there aren't duplicate ids. Also removed the unused id in the
+ background img element.
+Optimized SplashOutputDev::drawTilingPattern for the case where the
+ tile is much larger than the area being drawn (i.e., the clipping
+ bbox). In this case, we can render just the needed portion of the
+ tile.
+Added a missing zero check for precinct size in the JPEG 2000 decoder.
+ [Thanks to shellway for the bug report.]
+Added a missing null check in the XFA form scanner. [Thanks to Taolaw
+ for the bug report.]
+Deal with xref streams that include a free entry with gen=0xffffffff.
+Fixed a problematic corner case in looking up XObject resources.
+ [Thanks to shellway for the bug report.]
+The unicodeRemapping config command wasn't correctly handling unsorted
+ remapping files.
+Improved handling of RTL text in the text extractor.
+Extended the saveTabState/loadTabState commands to save/restore
+ display mode, zoom, rotation, and scroll position for each tab.
+Added support for Qt6.
+Added a missing bounds check on stream DecodeParms arrays. [Thanks to
+ minipython for the bug report.]
+Fixed an integer overflow check in XRef::readXRefTable. [Thanks to
+ yangshufan for the bug report.]
+The builtin Latin1 encoding was mapping 'endash' instead of
+ 'softhyphen' to 0xad. [Thanks to Jach Fong for the bug report.]
+Fixed a bug in PSOutputDev::checkPageSlice() when built without
+ SPLASH_CMYK. [Thanks to irfanariq for the bug report.]
+Added missing array length and type checks in Gfx::doForm(). [Thanks
+ to shaohua for the bug report.]
+Fixed an integer overflow security hole in the JBIG2 decoder.
+Substitute Helvetica for undefined fonts and bad font objects.
+Added an integer overflow check in JPXStream. (JPXStream issue)
+ [Thanks to Shin Ando @ Ricera Security for the bug report.]
+The DCT (JPEG) decoder was allowing the 'interleaved' flag to be
+ changed after the first scan of the image. (CVE-2022-24106) [Thanks
+ to Shin Ando @ Ricera Security for the bug report.]
diff --git a/CMakeCache.txt b/CMakeCache.txt
new file mode 100644
index 0000000..ecc88f8
--- /dev/null
+++ b/CMakeCache.txt
@@ -0,0 +1,608 @@
+# This is the CMakeCache file.
+# For build in directory: /home/calvin/src/xpdf-4.04
+# It was generated by CMake: /usr/bin/cmake
+# You can edit this file to change values found and used by cmake.
+# If you do not want to change any of the values, simply exit the editor.
+# If you do want to change a value, simply edit, save, and exit the editor.
+# The syntax for the file is as follows:
+# KEY:TYPE=VALUE
+# KEY is the name of a variable in the cache.
+# TYPE is a hint to GUIs for the type of VALUE, DO NOT EDIT TYPE!.
+# VALUE is the current value for the KEY.
+
+########################
+# EXTERNAL cache entries
+########################
+
+//use A4 (instead of Letter) paper size by default for PostScript
+// output
+A4_PAPER:BOOL=OFF
+
+//Path to a program.
+CMAKE_ADDR2LINE:FILEPATH=/usr/bin/addr2line
+
+//Path to a program.
+CMAKE_AR:FILEPATH=/usr/bin/ar
+
+//Choose build mode - options are: None Debug Release RelWithDebInfo
+// MinSizeRel Profiling
+CMAKE_BUILD_TYPE:STRING=
+
+//Enable/Disable color output during build.
+CMAKE_COLOR_MAKEFILE:BOOL=ON
+
+//CXX compiler
+CMAKE_CXX_COMPILER:FILEPATH=/usr/bin/c++
+
+//A wrapper around 'ar' adding the appropriate '--plugin' option
+// for the GCC compiler
+CMAKE_CXX_COMPILER_AR:FILEPATH=/usr/bin/gcc-ar-10
+
+//A wrapper around 'ranlib' adding the appropriate '--plugin' option
+// for the GCC compiler
+CMAKE_CXX_COMPILER_RANLIB:FILEPATH=/usr/bin/gcc-ranlib-10
+
+//Flags used by the CXX compiler during all build types.
+CMAKE_CXX_FLAGS:STRING=
+
+//Flags used by the CXX compiler during DEBUG builds.
+CMAKE_CXX_FLAGS_DEBUG:STRING=-g
+
+//Flags used by the CXX compiler during MINSIZEREL builds.
+CMAKE_CXX_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG
+
+//C++ compiler flags for profiling mode
+CMAKE_CXX_FLAGS_PROFILING:STRING=-g -pg -O -Wall
+
+//Flags used by the CXX compiler during RELEASE builds.
+CMAKE_CXX_FLAGS_RELEASE:STRING=-O3 -DNDEBUG
+
+//Flags used by the CXX compiler during RELWITHDEBINFO builds.
+CMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG
+
+//C compiler
+CMAKE_C_COMPILER:FILEPATH=/usr/bin/cc
+
+//A wrapper around 'ar' adding the appropriate '--plugin' option
+// for the GCC compiler
+CMAKE_C_COMPILER_AR:FILEPATH=/usr/bin/gcc-ar-10
+
+//A wrapper around 'ranlib' adding the appropriate '--plugin' option
+// for the GCC compiler
+CMAKE_C_COMPILER_RANLIB:FILEPATH=/usr/bin/gcc-ranlib-10
+
+//Flags used by the C compiler during all build types.
+CMAKE_C_FLAGS:STRING=
+
+//Flags used by the C compiler during DEBUG builds.
+CMAKE_C_FLAGS_DEBUG:STRING=-g
+
+//Flags used by the C compiler during MINSIZEREL builds.
+CMAKE_C_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG
+
+//C compiler flags for profiling mode
+CMAKE_C_FLAGS_PROFILING:STRING=-g -pg -O -Wall
+
+//Flags used by the C compiler during RELEASE builds.
+CMAKE_C_FLAGS_RELEASE:STRING=-O3 -DNDEBUG
+
+//Flags used by the C compiler during RELWITHDEBINFO builds.
+CMAKE_C_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG
+
+//Path to a program.
+CMAKE_DLLTOOL:FILEPATH=CMAKE_DLLTOOL-NOTFOUND
+
+//Flags used by the linker during all build types.
+CMAKE_EXE_LINKER_FLAGS:STRING=
+
+//Flags used by the linker during DEBUG builds.
+CMAKE_EXE_LINKER_FLAGS_DEBUG:STRING=
+
+//Flags used by the linker during MINSIZEREL builds.
+CMAKE_EXE_LINKER_FLAGS_MINSIZEREL:STRING=
+
+//linker flags for profiling mode
+CMAKE_EXE_LINKER_FLAGS_PROFILING:STRING=-g -pg -O -Wall
+
+//Flags used by the linker during RELEASE builds.
+CMAKE_EXE_LINKER_FLAGS_RELEASE:STRING=
+
+//Flags used by the linker during RELWITHDEBINFO builds.
+CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO:STRING=
+
+//Enable/Disable output of compile commands during generation.
+CMAKE_EXPORT_COMPILE_COMMANDS:BOOL=
+
+//User executables (bin)
+CMAKE_INSTALL_BINDIR:PATH=bin
+
+//Read-only architecture-independent data (DATAROOTDIR)
+CMAKE_INSTALL_DATADIR:PATH=
+
+//Read-only architecture-independent data root (share)
+CMAKE_INSTALL_DATAROOTDIR:PATH=share
+
+//Documentation root (DATAROOTDIR/doc/PROJECT_NAME)
+CMAKE_INSTALL_DOCDIR:PATH=
+
+//C header files (include)
+CMAKE_INSTALL_INCLUDEDIR:PATH=include
+
+//Info documentation (DATAROOTDIR/info)
+CMAKE_INSTALL_INFODIR:PATH=
+
+//Object code libraries (lib)
+CMAKE_INSTALL_LIBDIR:PATH=lib
+
+//Program executables (libexec)
+CMAKE_INSTALL_LIBEXECDIR:PATH=libexec
+
+//Locale-dependent data (DATAROOTDIR/locale)
+CMAKE_INSTALL_LOCALEDIR:PATH=
+
+//Modifiable single-machine data (var)
+CMAKE_INSTALL_LOCALSTATEDIR:PATH=var
+
+//Man documentation (DATAROOTDIR/man)
+CMAKE_INSTALL_MANDIR:PATH=
+
+//C header files for non-gcc (/usr/include)
+CMAKE_INSTALL_OLDINCLUDEDIR:PATH=/usr/include
+
+//Install path prefix, prepended onto install directories.
+CMAKE_INSTALL_PREFIX:PATH=/usr/local
+
+//Run-time variable data (LOCALSTATEDIR/run)
+CMAKE_INSTALL_RUNSTATEDIR:PATH=
+
+//System admin executables (sbin)
+CMAKE_INSTALL_SBINDIR:PATH=sbin
+
+//Modifiable architecture-independent data (com)
+CMAKE_INSTALL_SHAREDSTATEDIR:PATH=com
+
+//Read-only single-machine data (etc)
+CMAKE_INSTALL_SYSCONFDIR:PATH=etc
+
+//Path to a program.
+CMAKE_LINKER:FILEPATH=/usr/bin/ld
+
+//Path to a program.
+CMAKE_MAKE_PROGRAM:FILEPATH=/usr/bin/gmake
+
+//Flags used by the linker during the creation of modules during
+// all build types.
+CMAKE_MODULE_LINKER_FLAGS:STRING=
+
+//Flags used by the linker during the creation of modules during
+// DEBUG builds.
+CMAKE_MODULE_LINKER_FLAGS_DEBUG:STRING=
+
+//Flags used by the linker during the creation of modules during
+// MINSIZEREL builds.
+CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL:STRING=
+
+//Flags used by the linker during the creation of modules during
+// RELEASE builds.
+CMAKE_MODULE_LINKER_FLAGS_RELEASE:STRING=
+
+//Flags used by the linker during the creation of modules during
+// RELWITHDEBINFO builds.
+CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO:STRING=
+
+//Path to a program.
+CMAKE_NM:FILEPATH=/usr/bin/nm
+
+//Path to a program.
+CMAKE_OBJCOPY:FILEPATH=/usr/bin/objcopy
+
+//Path to a program.
+CMAKE_OBJDUMP:FILEPATH=/usr/bin/objdump
+
+//Value Computed by CMake
+CMAKE_PROJECT_DESCRIPTION:STATIC=
+
+//Value Computed by CMake
+CMAKE_PROJECT_HOMEPAGE_URL:STATIC=
+
+//Value Computed by CMake
+CMAKE_PROJECT_NAME:STATIC=xpdf
+
+//Path to a program.
+CMAKE_RANLIB:FILEPATH=/usr/bin/ranlib
+
+//Path to a program.
+CMAKE_READELF:FILEPATH=/usr/bin/readelf
+
+//Flags used by the linker during the creation of shared libraries
+// during all build types.
+CMAKE_SHARED_LINKER_FLAGS:STRING=
+
+//Flags used by the linker during the creation of shared libraries
+// during DEBUG builds.
+CMAKE_SHARED_LINKER_FLAGS_DEBUG:STRING=
+
+//Flags used by the linker during the creation of shared libraries
+// during MINSIZEREL builds.
+CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL:STRING=
+
+//shared linker flags for profiling mode
+CMAKE_SHARED_LINKER_FLAGS_PROFILING:STRING=-g -pg -O -Wall
+
+//Flags used by the linker during the creation of shared libraries
+// during RELEASE builds.
+CMAKE_SHARED_LINKER_FLAGS_RELEASE:STRING=
+
+//Flags used by the linker during the creation of shared libraries
+// during RELWITHDEBINFO builds.
+CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO:STRING=
+
+//If set, runtime paths are not added when installing shared libraries,
+// but are added when building.
+CMAKE_SKIP_INSTALL_RPATH:BOOL=NO
+
+//If set, runtime paths are not added when using shared libraries.
+CMAKE_SKIP_RPATH:BOOL=NO
+
+//Flags used by the linker during the creation of static libraries
+// during all build types.
+CMAKE_STATIC_LINKER_FLAGS:STRING=
+
+//Flags used by the linker during the creation of static libraries
+// during DEBUG builds.
+CMAKE_STATIC_LINKER_FLAGS_DEBUG:STRING=
+
+//Flags used by the linker during the creation of static libraries
+// during MINSIZEREL builds.
+CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL:STRING=
+
+//Flags used by the linker during the creation of static libraries
+// during RELEASE builds.
+CMAKE_STATIC_LINKER_FLAGS_RELEASE:STRING=
+
+//Flags used by the linker during the creation of static libraries
+// during RELWITHDEBINFO builds.
+CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO:STRING=
+
+//Path to a program.
+CMAKE_STRIP:FILEPATH=/usr/bin/strip
+
+//If this value is on, makefiles will be generated without the
+// .SILENT directive, and all commands will be echoed to the console
+// during the make. This is useful for debugging only. With Visual
+// Studio IDE projects all commands are done without /nologo.
+CMAKE_VERBOSE_MAKEFILE:BOOL=FALSE
+
+//Path to a file.
+CUPS_INCLUDE_DIR:PATH=/usr/include
+
+//Path to a library.
+CUPS_LIBRARIES:FILEPATH=/usr/lib/x86_64-linux-gnu/libcups.so
+
+//Path to a library.
+FONTCONFIG_LIBRARY:FILEPATH=/usr/lib/x86_64-linux-gnu/libfontconfig.so
+
+//Path to a file.
+FREETYPE_INCLUDE_DIR_freetype:PATH=FREETYPE_INCLUDE_DIR_freetype-NOTFOUND
+
+//Path to a file.
+FREETYPE_INCLUDE_DIR_freetype_freetype:PATH=/usr/include/freetype2
+
+//Path to a file.
+FREETYPE_INCLUDE_DIR_ft2build:PATH=/usr/include/freetype2
+
+//Path to a library.
+FREETYPE_LIBRARY:FILEPATH=/usr/lib/x86_64-linux-gnu/libfreetype.so
+
+//include support for multithreading
+MULTITHREADED:BOOL=ON
+
+//disable support for libfontconfig
+NO_FONTCONFIG:BOOL=OFF
+
+//do not allow text selection
+NO_TEXT_SELECT:BOOL=OFF
+
+//include support for OPI comments
+OPI_SUPPORT:BOOL=OFF
+
+//Path to a library.
+PAPER_LIBRARY:FILEPATH=PAPER_LIBRARY-NOTFOUND
+
+//Path to a library.
+PNG_LIBRARY_DEBUG:FILEPATH=PNG_LIBRARY_DEBUG-NOTFOUND
+
+//Path to a library.
+PNG_LIBRARY_RELEASE:FILEPATH=/usr/lib/x86_64-linux-gnu/libpng.so
+
+//Path to a file.
+PNG_PNG_INCLUDE_DIR:PATH=/usr/include
+
+//The directory containing a CMake configuration file for Qt5Core.
+Qt5Core_DIR:PATH=/usr/lib/x86_64-linux-gnu/cmake/Qt5Core
+
+//The directory containing a CMake configuration file for Qt5Gui.
+Qt5Gui_DIR:PATH=/usr/lib/x86_64-linux-gnu/cmake/Qt5Gui
+
+//The directory containing a CMake configuration file for Qt5Network.
+Qt5Network_DIR:PATH=/usr/lib/x86_64-linux-gnu/cmake/Qt5Network
+
+//The directory containing a CMake configuration file for Qt5PrintSupport.
+Qt5PrintSupport_DIR:PATH=/usr/lib/x86_64-linux-gnu/cmake/Qt5PrintSupport
+
+//The directory containing a CMake configuration file for Qt5Widgets.
+Qt5Widgets_DIR:PATH=/usr/lib/x86_64-linux-gnu/cmake/Qt5Widgets
+
+//The directory containing a CMake configuration file for Qt6Widgets.
+Qt6Widgets_DIR:PATH=Qt6Widgets_DIR-NOTFOUND
+
+//include support for CMYK rasterization
+SPLASH_CMYK:BOOL=OFF
+
+//full path for system-wide xpdfrc file
+SYSTEM_XPDFRC:BOOL=OFF
+
+//use C++ exceptions
+USE_EXCEPTIONS:BOOL=ON
+
+//use fixed point (instead of floating point) arithmetic
+USE_FIXEDPOINT:BOOL=OFF
+
+//directory to use for the DATADIR xpdfrc variable
+XPDFRC_DATADIR:BOOL=OFF
+
+//include printing support in XpdfWidget
+XPDFWIDGET_PRINTING:BOOL=ON
+
+//Path to a file.
+ZLIB_INCLUDE_DIR:PATH=/usr/include
+
+//Path to a library.
+ZLIB_LIBRARY_DEBUG:FILEPATH=ZLIB_LIBRARY_DEBUG-NOTFOUND
+
+//Path to a library.
+ZLIB_LIBRARY_RELEASE:FILEPATH=/usr/lib/x86_64-linux-gnu/libz.so
+
+//Value Computed by CMake
+xpdf_BINARY_DIR:STATIC=/home/calvin/src/xpdf-4.04
+
+//Value Computed by CMake
+xpdf_SOURCE_DIR:STATIC=/home/calvin/src/xpdf-4.04
+
+
+########################
+# INTERNAL cache entries
+########################
+
+//ADVANCED property for variable: CMAKE_ADDR2LINE
+CMAKE_ADDR2LINE-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_AR
+CMAKE_AR-ADVANCED:INTERNAL=1
+//This is the directory where this CMakeCache.txt was created
+CMAKE_CACHEFILE_DIR:INTERNAL=/home/calvin/src/xpdf-4.04
+//Major version of cmake used to create the current loaded cache
+CMAKE_CACHE_MAJOR_VERSION:INTERNAL=3
+//Minor version of cmake used to create the current loaded cache
+CMAKE_CACHE_MINOR_VERSION:INTERNAL=18
+//Patch version of cmake used to create the current loaded cache
+CMAKE_CACHE_PATCH_VERSION:INTERNAL=4
+//ADVANCED property for variable: CMAKE_COLOR_MAKEFILE
+CMAKE_COLOR_MAKEFILE-ADVANCED:INTERNAL=1
+//Path to CMake executable.
+CMAKE_COMMAND:INTERNAL=/usr/bin/cmake
+//Path to cpack program executable.
+CMAKE_CPACK_COMMAND:INTERNAL=/usr/bin/cpack
+//Path to ctest program executable.
+CMAKE_CTEST_COMMAND:INTERNAL=/usr/bin/ctest
+//ADVANCED property for variable: CMAKE_CXX_COMPILER
+CMAKE_CXX_COMPILER-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_CXX_COMPILER_AR
+CMAKE_CXX_COMPILER_AR-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_CXX_COMPILER_RANLIB
+CMAKE_CXX_COMPILER_RANLIB-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_CXX_FLAGS
+CMAKE_CXX_FLAGS-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_CXX_FLAGS_DEBUG
+CMAKE_CXX_FLAGS_DEBUG-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_CXX_FLAGS_MINSIZEREL
+CMAKE_CXX_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_CXX_FLAGS_PROFILING
+CMAKE_CXX_FLAGS_PROFILING-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELEASE
+CMAKE_CXX_FLAGS_RELEASE-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELWITHDEBINFO
+CMAKE_CXX_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_C_COMPILER
+CMAKE_C_COMPILER-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_C_COMPILER_AR
+CMAKE_C_COMPILER_AR-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_C_COMPILER_RANLIB
+CMAKE_C_COMPILER_RANLIB-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_C_FLAGS
+CMAKE_C_FLAGS-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_C_FLAGS_DEBUG
+CMAKE_C_FLAGS_DEBUG-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_C_FLAGS_MINSIZEREL
+CMAKE_C_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_C_FLAGS_PROFILING
+CMAKE_C_FLAGS_PROFILING-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_C_FLAGS_RELEASE
+CMAKE_C_FLAGS_RELEASE-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_C_FLAGS_RELWITHDEBINFO
+CMAKE_C_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_DLLTOOL
+CMAKE_DLLTOOL-ADVANCED:INTERNAL=1
+//Executable file format
+CMAKE_EXECUTABLE_FORMAT:INTERNAL=ELF
+//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS
+CMAKE_EXE_LINKER_FLAGS-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_DEBUG
+CMAKE_EXE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_MINSIZEREL
+CMAKE_EXE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_PROFILING
+CMAKE_EXE_LINKER_FLAGS_PROFILING-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELEASE
+CMAKE_EXE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO
+CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_EXPORT_COMPILE_COMMANDS
+CMAKE_EXPORT_COMPILE_COMMANDS-ADVANCED:INTERNAL=1
+//Name of external makefile project generator.
+CMAKE_EXTRA_GENERATOR:INTERNAL=
+//Name of generator.
+CMAKE_GENERATOR:INTERNAL=Unix Makefiles
+//Generator instance identifier.
+CMAKE_GENERATOR_INSTANCE:INTERNAL=
+//Name of generator platform.
+CMAKE_GENERATOR_PLATFORM:INTERNAL=
+//Name of generator toolset.
+CMAKE_GENERATOR_TOOLSET:INTERNAL=
+//Test CMAKE_HAVE_LIBC_PTHREAD
+CMAKE_HAVE_LIBC_PTHREAD:INTERNAL=
+//Have library pthreads
+CMAKE_HAVE_PTHREADS_CREATE:INTERNAL=
+//Have library pthread
+CMAKE_HAVE_PTHREAD_CREATE:INTERNAL=1
+//Have include pthread.h
+CMAKE_HAVE_PTHREAD_H:INTERNAL=1
+//Source directory with the top level CMakeLists.txt file for this
+// project
+CMAKE_HOME_DIRECTORY:INTERNAL=/home/calvin/src/xpdf-4.04
+//ADVANCED property for variable: CMAKE_INSTALL_BINDIR
+CMAKE_INSTALL_BINDIR-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_INSTALL_DATADIR
+CMAKE_INSTALL_DATADIR-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_INSTALL_DATAROOTDIR
+CMAKE_INSTALL_DATAROOTDIR-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_INSTALL_DOCDIR
+CMAKE_INSTALL_DOCDIR-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_INSTALL_INCLUDEDIR
+CMAKE_INSTALL_INCLUDEDIR-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_INSTALL_INFODIR
+CMAKE_INSTALL_INFODIR-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_INSTALL_LIBDIR
+CMAKE_INSTALL_LIBDIR-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_INSTALL_LIBEXECDIR
+CMAKE_INSTALL_LIBEXECDIR-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_INSTALL_LOCALEDIR
+CMAKE_INSTALL_LOCALEDIR-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_INSTALL_LOCALSTATEDIR
+CMAKE_INSTALL_LOCALSTATEDIR-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_INSTALL_MANDIR
+CMAKE_INSTALL_MANDIR-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_INSTALL_OLDINCLUDEDIR
+CMAKE_INSTALL_OLDINCLUDEDIR-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_INSTALL_RUNSTATEDIR
+CMAKE_INSTALL_RUNSTATEDIR-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_INSTALL_SBINDIR
+CMAKE_INSTALL_SBINDIR-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_INSTALL_SHAREDSTATEDIR
+CMAKE_INSTALL_SHAREDSTATEDIR-ADVANCED:INTERNAL=1
+//Install .so files without execute permission.
+CMAKE_INSTALL_SO_NO_EXE:INTERNAL=1
+//ADVANCED property for variable: CMAKE_INSTALL_SYSCONFDIR
+CMAKE_INSTALL_SYSCONFDIR-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_LINKER
+CMAKE_LINKER-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_MAKE_PROGRAM
+CMAKE_MAKE_PROGRAM-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS
+CMAKE_MODULE_LINKER_FLAGS-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_DEBUG
+CMAKE_MODULE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL
+CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELEASE
+CMAKE_MODULE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO
+CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_NM
+CMAKE_NM-ADVANCED:INTERNAL=1
+//number of local generators
+CMAKE_NUMBER_OF_MAKEFILES:INTERNAL=6
+//ADVANCED property for variable: CMAKE_OBJCOPY
+CMAKE_OBJCOPY-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_OBJDUMP
+CMAKE_OBJDUMP-ADVANCED:INTERNAL=1
+//Platform information initialized
+CMAKE_PLATFORM_INFO_INITIALIZED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_RANLIB
+CMAKE_RANLIB-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_READELF
+CMAKE_READELF-ADVANCED:INTERNAL=1
+//Path to CMake installation.
+CMAKE_ROOT:INTERNAL=/usr/share/cmake-3.18
+//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS
+CMAKE_SHARED_LINKER_FLAGS-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_DEBUG
+CMAKE_SHARED_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL
+CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_PROFILING
+CMAKE_SHARED_LINKER_FLAGS_PROFILING-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELEASE
+CMAKE_SHARED_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO
+CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_SKIP_INSTALL_RPATH
+CMAKE_SKIP_INSTALL_RPATH-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_SKIP_RPATH
+CMAKE_SKIP_RPATH-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS
+CMAKE_STATIC_LINKER_FLAGS-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_DEBUG
+CMAKE_STATIC_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL
+CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELEASE
+CMAKE_STATIC_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO
+CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_STRIP
+CMAKE_STRIP-ADVANCED:INTERNAL=1
+//uname command
+CMAKE_UNAME:INTERNAL=/usr/bin/uname
+//ADVANCED property for variable: CMAKE_VERBOSE_MAKEFILE
+CMAKE_VERBOSE_MAKEFILE-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CUPS_INCLUDE_DIR
+CUPS_INCLUDE_DIR-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CUPS_LIBRARIES
+CUPS_LIBRARIES-ADVANCED:INTERNAL=1
+//Details about finding Cups
+FIND_PACKAGE_MESSAGE_DETAILS_Cups:INTERNAL=[/usr/lib/x86_64-linux-gnu/libcups.so][/usr/include][v2.3.3()]
+//Details about finding PNG
+FIND_PACKAGE_MESSAGE_DETAILS_PNG:INTERNAL=[/usr/lib/x86_64-linux-gnu/libpng.so][/usr/include][v1.6.37()]
+//Details about finding Threads
+FIND_PACKAGE_MESSAGE_DETAILS_Threads:INTERNAL=[TRUE][v()]
+//Details about finding ZLIB
+FIND_PACKAGE_MESSAGE_DETAILS_ZLIB:INTERNAL=[/usr/lib/x86_64-linux-gnu/libz.so][/usr/include][v1.2.11()]
+//Have function fseek64
+HAVE_FSEEK64:INTERNAL=
+//Have function _fseeki64
+HAVE_FSEEKI64:INTERNAL=
+//Have function fseeko
+HAVE_FSEEKO:INTERNAL=1
+//Have function mkstemp
+HAVE_MKSTEMP:INTERNAL=1
+//Have function mkstemps
+HAVE_MKSTEMPS:INTERNAL=1
+//Have function popen
+HAVE_POPEN:INTERNAL=1
+//Test HAVE_STD_SORT
+HAVE_STD_SORT:INTERNAL=1
+//ADVANCED property for variable: PNG_LIBRARY_DEBUG
+PNG_LIBRARY_DEBUG-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: PNG_LIBRARY_RELEASE
+PNG_LIBRARY_RELEASE-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: PNG_PNG_INCLUDE_DIR
+PNG_PNG_INCLUDE_DIR-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: ZLIB_INCLUDE_DIR
+ZLIB_INCLUDE_DIR-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: ZLIB_LIBRARY_DEBUG
+ZLIB_LIBRARY_DEBUG-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: ZLIB_LIBRARY_RELEASE
+ZLIB_LIBRARY_RELEASE-ADVANCED:INTERNAL=1
+//CMAKE_INSTALL_PREFIX during last run
+_GNUInstallDirs_LAST_CMAKE_INSTALL_PREFIX:INTERNAL=/usr/local
+
diff --git a/CMakeFiles/3.18.4/CMakeCCompiler.cmake b/CMakeFiles/3.18.4/CMakeCCompiler.cmake
new file mode 100644
index 0000000..e033eb1
--- /dev/null
+++ b/CMakeFiles/3.18.4/CMakeCCompiler.cmake
@@ -0,0 +1,77 @@
+set(CMAKE_C_COMPILER "/usr/bin/cc")
+set(CMAKE_C_COMPILER_ARG1 "")
+set(CMAKE_C_COMPILER_ID "GNU")
+set(CMAKE_C_COMPILER_VERSION "10.2.1")
+set(CMAKE_C_COMPILER_VERSION_INTERNAL "")
+set(CMAKE_C_COMPILER_WRAPPER "")
+set(CMAKE_C_STANDARD_COMPUTED_DEFAULT "11")
+set(CMAKE_C_COMPILE_FEATURES "c_std_90;c_function_prototypes;c_std_99;c_restrict;c_variadic_macros;c_std_11;c_static_assert")
+set(CMAKE_C90_COMPILE_FEATURES "c_std_90;c_function_prototypes")
+set(CMAKE_C99_COMPILE_FEATURES "c_std_99;c_restrict;c_variadic_macros")
+set(CMAKE_C11_COMPILE_FEATURES "c_std_11;c_static_assert")
+
+set(CMAKE_C_PLATFORM_ID "Linux")
+set(CMAKE_C_SIMULATE_ID "")
+set(CMAKE_C_COMPILER_FRONTEND_VARIANT "")
+set(CMAKE_C_SIMULATE_VERSION "")
+
+
+
+
+set(CMAKE_AR "/usr/bin/ar")
+set(CMAKE_C_COMPILER_AR "/usr/bin/gcc-ar-10")
+set(CMAKE_RANLIB "/usr/bin/ranlib")
+set(CMAKE_C_COMPILER_RANLIB "/usr/bin/gcc-ranlib-10")
+set(CMAKE_LINKER "/usr/bin/ld")
+set(CMAKE_MT "")
+set(CMAKE_COMPILER_IS_GNUCC 1)
+set(CMAKE_C_COMPILER_LOADED 1)
+set(CMAKE_C_COMPILER_WORKS TRUE)
+set(CMAKE_C_ABI_COMPILED TRUE)
+set(CMAKE_COMPILER_IS_MINGW )
+set(CMAKE_COMPILER_IS_CYGWIN )
+if(CMAKE_COMPILER_IS_CYGWIN)
+ set(CYGWIN 1)
+ set(UNIX 1)
+endif()
+
+set(CMAKE_C_COMPILER_ENV_VAR "CC")
+
+if(CMAKE_COMPILER_IS_MINGW)
+ set(MINGW 1)
+endif()
+set(CMAKE_C_COMPILER_ID_RUN 1)
+set(CMAKE_C_SOURCE_FILE_EXTENSIONS c;m)
+set(CMAKE_C_IGNORE_EXTENSIONS h;H;o;O;obj;OBJ;def;DEF;rc;RC)
+set(CMAKE_C_LINKER_PREFERENCE 10)
+
+# Save compiler ABI information.
+set(CMAKE_C_SIZEOF_DATA_PTR "8")
+set(CMAKE_C_COMPILER_ABI "ELF")
+set(CMAKE_C_LIBRARY_ARCHITECTURE "x86_64-linux-gnu")
+
+if(CMAKE_C_SIZEOF_DATA_PTR)
+ set(CMAKE_SIZEOF_VOID_P "${CMAKE_C_SIZEOF_DATA_PTR}")
+endif()
+
+if(CMAKE_C_COMPILER_ABI)
+ set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_C_COMPILER_ABI}")
+endif()
+
+if(CMAKE_C_LIBRARY_ARCHITECTURE)
+ set(CMAKE_LIBRARY_ARCHITECTURE "x86_64-linux-gnu")
+endif()
+
+set(CMAKE_C_CL_SHOWINCLUDES_PREFIX "")
+if(CMAKE_C_CL_SHOWINCLUDES_PREFIX)
+ set(CMAKE_CL_SHOWINCLUDES_PREFIX "${CMAKE_C_CL_SHOWINCLUDES_PREFIX}")
+endif()
+
+
+
+
+
+set(CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES "/usr/lib/gcc/x86_64-linux-gnu/10/include;/usr/local/include;/usr/include/x86_64-linux-gnu;/usr/include")
+set(CMAKE_C_IMPLICIT_LINK_LIBRARIES "gcc;gcc_s;c;gcc;gcc_s")
+set(CMAKE_C_IMPLICIT_LINK_DIRECTORIES "/usr/lib/gcc/x86_64-linux-gnu/10;/usr/lib/x86_64-linux-gnu;/usr/lib;/lib/x86_64-linux-gnu;/lib")
+set(CMAKE_C_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "")
diff --git a/CMakeFiles/3.18.4/CMakeCXXCompiler.cmake b/CMakeFiles/3.18.4/CMakeCXXCompiler.cmake
new file mode 100644
index 0000000..7d1c1cf
--- /dev/null
+++ b/CMakeFiles/3.18.4/CMakeCXXCompiler.cmake
@@ -0,0 +1,89 @@
+set(CMAKE_CXX_COMPILER "/usr/bin/c++")
+set(CMAKE_CXX_COMPILER_ARG1 "")
+set(CMAKE_CXX_COMPILER_ID "GNU")
+set(CMAKE_CXX_COMPILER_VERSION "10.2.1")
+set(CMAKE_CXX_COMPILER_VERSION_INTERNAL "")
+set(CMAKE_CXX_COMPILER_WRAPPER "")
+set(CMAKE_CXX_STANDARD_COMPUTED_DEFAULT "14")
+set(CMAKE_CXX_COMPILE_FEATURES "cxx_std_98;cxx_template_template_parameters;cxx_std_11;cxx_alias_templates;cxx_alignas;cxx_alignof;cxx_attributes;cxx_auto_type;cxx_constexpr;cxx_decltype;cxx_decltype_incomplete_return_types;cxx_default_function_template_args;cxx_defaulted_functions;cxx_defaulted_move_initializers;cxx_delegating_constructors;cxx_deleted_functions;cxx_enum_forward_declarations;cxx_explicit_conversions;cxx_extended_friend_declarations;cxx_extern_templates;cxx_final;cxx_func_identifier;cxx_generalized_initializers;cxx_inheriting_constructors;cxx_inline_namespaces;cxx_lambdas;cxx_local_type_template_args;cxx_long_long_type;cxx_noexcept;cxx_nonstatic_member_init;cxx_nullptr;cxx_override;cxx_range_for;cxx_raw_string_literals;cxx_reference_qualified_functions;cxx_right_angle_brackets;cxx_rvalue_references;cxx_sizeof_member;cxx_static_assert;cxx_strong_enums;cxx_thread_local;cxx_trailing_return_types;cxx_unicode_literals;cxx_uniform_initialization;cxx_unrestricted_unions;cxx_user_literals;cxx_variadic_macros;cxx_variadic_templates;cxx_std_14;cxx_aggregate_default_initializers;cxx_attribute_deprecated;cxx_binary_literals;cxx_contextual_conversions;cxx_decltype_auto;cxx_digit_separators;cxx_generic_lambdas;cxx_lambda_init_captures;cxx_relaxed_constexpr;cxx_return_type_deduction;cxx_variable_templates;cxx_std_17;cxx_std_20")
+set(CMAKE_CXX98_COMPILE_FEATURES "cxx_std_98;cxx_template_template_parameters")
+set(CMAKE_CXX11_COMPILE_FEATURES "cxx_std_11;cxx_alias_templates;cxx_alignas;cxx_alignof;cxx_attributes;cxx_auto_type;cxx_constexpr;cxx_decltype;cxx_decltype_incomplete_return_types;cxx_default_function_template_args;cxx_defaulted_functions;cxx_defaulted_move_initializers;cxx_delegating_constructors;cxx_deleted_functions;cxx_enum_forward_declarations;cxx_explicit_conversions;cxx_extended_friend_declarations;cxx_extern_templates;cxx_final;cxx_func_identifier;cxx_generalized_initializers;cxx_inheriting_constructors;cxx_inline_namespaces;cxx_lambdas;cxx_local_type_template_args;cxx_long_long_type;cxx_noexcept;cxx_nonstatic_member_init;cxx_nullptr;cxx_override;cxx_range_for;cxx_raw_string_literals;cxx_reference_qualified_functions;cxx_right_angle_brackets;cxx_rvalue_references;cxx_sizeof_member;cxx_static_assert;cxx_strong_enums;cxx_thread_local;cxx_trailing_return_types;cxx_unicode_literals;cxx_uniform_initialization;cxx_unrestricted_unions;cxx_user_literals;cxx_variadic_macros;cxx_variadic_templates")
+set(CMAKE_CXX14_COMPILE_FEATURES "cxx_std_14;cxx_aggregate_default_initializers;cxx_attribute_deprecated;cxx_binary_literals;cxx_contextual_conversions;cxx_decltype_auto;cxx_digit_separators;cxx_generic_lambdas;cxx_lambda_init_captures;cxx_relaxed_constexpr;cxx_return_type_deduction;cxx_variable_templates")
+set(CMAKE_CXX17_COMPILE_FEATURES "cxx_std_17")
+set(CMAKE_CXX20_COMPILE_FEATURES "cxx_std_20")
+
+set(CMAKE_CXX_PLATFORM_ID "Linux")
+set(CMAKE_CXX_SIMULATE_ID "")
+set(CMAKE_CXX_COMPILER_FRONTEND_VARIANT "")
+set(CMAKE_CXX_SIMULATE_VERSION "")
+
+
+
+
+set(CMAKE_AR "/usr/bin/ar")
+set(CMAKE_CXX_COMPILER_AR "/usr/bin/gcc-ar-10")
+set(CMAKE_RANLIB "/usr/bin/ranlib")
+set(CMAKE_CXX_COMPILER_RANLIB "/usr/bin/gcc-ranlib-10")
+set(CMAKE_LINKER "/usr/bin/ld")
+set(CMAKE_MT "")
+set(CMAKE_COMPILER_IS_GNUCXX 1)
+set(CMAKE_CXX_COMPILER_LOADED 1)
+set(CMAKE_CXX_COMPILER_WORKS TRUE)
+set(CMAKE_CXX_ABI_COMPILED TRUE)
+set(CMAKE_COMPILER_IS_MINGW )
+set(CMAKE_COMPILER_IS_CYGWIN )
+if(CMAKE_COMPILER_IS_CYGWIN)
+ set(CYGWIN 1)
+ set(UNIX 1)
+endif()
+
+set(CMAKE_CXX_COMPILER_ENV_VAR "CXX")
+
+if(CMAKE_COMPILER_IS_MINGW)
+ set(MINGW 1)
+endif()
+set(CMAKE_CXX_COMPILER_ID_RUN 1)
+set(CMAKE_CXX_SOURCE_FILE_EXTENSIONS C;M;c++;cc;cpp;cxx;m;mm;CPP)
+set(CMAKE_CXX_IGNORE_EXTENSIONS inl;h;hpp;HPP;H;o;O;obj;OBJ;def;DEF;rc;RC)
+
+foreach (lang C OBJC OBJCXX)
+ if (CMAKE_${lang}_COMPILER_ID_RUN)
+ foreach(extension IN LISTS CMAKE_${lang}_SOURCE_FILE_EXTENSIONS)
+ list(REMOVE_ITEM CMAKE_CXX_SOURCE_FILE_EXTENSIONS ${extension})
+ endforeach()
+ endif()
+endforeach()
+
+set(CMAKE_CXX_LINKER_PREFERENCE 30)
+set(CMAKE_CXX_LINKER_PREFERENCE_PROPAGATES 1)
+
+# Save compiler ABI information.
+set(CMAKE_CXX_SIZEOF_DATA_PTR "8")
+set(CMAKE_CXX_COMPILER_ABI "ELF")
+set(CMAKE_CXX_LIBRARY_ARCHITECTURE "x86_64-linux-gnu")
+
+if(CMAKE_CXX_SIZEOF_DATA_PTR)
+ set(CMAKE_SIZEOF_VOID_P "${CMAKE_CXX_SIZEOF_DATA_PTR}")
+endif()
+
+if(CMAKE_CXX_COMPILER_ABI)
+ set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_CXX_COMPILER_ABI}")
+endif()
+
+if(CMAKE_CXX_LIBRARY_ARCHITECTURE)
+ set(CMAKE_LIBRARY_ARCHITECTURE "x86_64-linux-gnu")
+endif()
+
+set(CMAKE_CXX_CL_SHOWINCLUDES_PREFIX "")
+if(CMAKE_CXX_CL_SHOWINCLUDES_PREFIX)
+ set(CMAKE_CL_SHOWINCLUDES_PREFIX "${CMAKE_CXX_CL_SHOWINCLUDES_PREFIX}")
+endif()
+
+
+
+
+
+set(CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES "/usr/include/c++/10;/usr/include/x86_64-linux-gnu/c++/10;/usr/include/c++/10/backward;/usr/lib/gcc/x86_64-linux-gnu/10/include;/usr/local/include;/usr/include/x86_64-linux-gnu;/usr/include")
+set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "stdc++;m;gcc_s;gcc;c;gcc_s;gcc")
+set(CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "/usr/lib/gcc/x86_64-linux-gnu/10;/usr/lib/x86_64-linux-gnu;/usr/lib;/lib/x86_64-linux-gnu;/lib")
+set(CMAKE_CXX_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "")
diff --git a/CMakeFiles/3.18.4/CMakeDetermineCompilerABI_C.bin b/CMakeFiles/3.18.4/CMakeDetermineCompilerABI_C.bin
new file mode 100755
index 0000000..9386501
--- /dev/null
+++ b/CMakeFiles/3.18.4/CMakeDetermineCompilerABI_C.bin
Binary files differ
diff --git a/CMakeFiles/3.18.4/CMakeDetermineCompilerABI_CXX.bin b/CMakeFiles/3.18.4/CMakeDetermineCompilerABI_CXX.bin
new file mode 100755
index 0000000..1160b1d
--- /dev/null
+++ b/CMakeFiles/3.18.4/CMakeDetermineCompilerABI_CXX.bin
Binary files differ
diff --git a/CMakeFiles/3.18.4/CMakeSystem.cmake b/CMakeFiles/3.18.4/CMakeSystem.cmake
new file mode 100644
index 0000000..319373a
--- /dev/null
+++ b/CMakeFiles/3.18.4/CMakeSystem.cmake
@@ -0,0 +1,15 @@
+set(CMAKE_HOST_SYSTEM "Linux-5.10.0-12-amd64")
+set(CMAKE_HOST_SYSTEM_NAME "Linux")
+set(CMAKE_HOST_SYSTEM_VERSION "5.10.0-12-amd64")
+set(CMAKE_HOST_SYSTEM_PROCESSOR "x86_64")
+
+
+
+set(CMAKE_SYSTEM "Linux-5.10.0-12-amd64")
+set(CMAKE_SYSTEM_NAME "Linux")
+set(CMAKE_SYSTEM_VERSION "5.10.0-12-amd64")
+set(CMAKE_SYSTEM_PROCESSOR "x86_64")
+
+set(CMAKE_CROSSCOMPILING "FALSE")
+
+set(CMAKE_SYSTEM_LOADED 1)
diff --git a/CMakeFiles/3.18.4/CompilerIdC/CMakeCCompilerId.c b/CMakeFiles/3.18.4/CompilerIdC/CMakeCCompilerId.c
new file mode 100644
index 0000000..6c0aa93
--- /dev/null
+++ b/CMakeFiles/3.18.4/CompilerIdC/CMakeCCompilerId.c
@@ -0,0 +1,674 @@
+#ifdef __cplusplus
+# error "A C++ compiler has been selected for C."
+#endif
+
+#if defined(__18CXX)
+# define ID_VOID_MAIN
+#endif
+#if defined(__CLASSIC_C__)
+/* cv-qualifiers did not exist in K&R C */
+# define const
+# define volatile
+#endif
+
+
+/* Version number components: V=Version, R=Revision, P=Patch
+ Version date components: YYYY=Year, MM=Month, DD=Day */
+
+#if defined(__INTEL_COMPILER) || defined(__ICC)
+# define COMPILER_ID "Intel"
+# if defined(_MSC_VER)
+# define SIMULATE_ID "MSVC"
+# endif
+# if defined(__GNUC__)
+# define SIMULATE_ID "GNU"
+# endif
+ /* __INTEL_COMPILER = VRP */
+# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER/100)
+# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER/10 % 10)
+# if defined(__INTEL_COMPILER_UPDATE)
+# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER_UPDATE)
+# else
+# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER % 10)
+# endif
+# if defined(__INTEL_COMPILER_BUILD_DATE)
+ /* __INTEL_COMPILER_BUILD_DATE = YYYYMMDD */
+# define COMPILER_VERSION_TWEAK DEC(__INTEL_COMPILER_BUILD_DATE)
+# endif
+# if defined(_MSC_VER)
+ /* _MSC_VER = VVRR */
+# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100)
+# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100)
+# endif
+# if defined(__GNUC__)
+# define SIMULATE_VERSION_MAJOR DEC(__GNUC__)
+# elif defined(__GNUG__)
+# define SIMULATE_VERSION_MAJOR DEC(__GNUG__)
+# endif
+# if defined(__GNUC_MINOR__)
+# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__)
+# endif
+# if defined(__GNUC_PATCHLEVEL__)
+# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__)
+# endif
+
+#elif defined(__PATHCC__)
+# define COMPILER_ID "PathScale"
+# define COMPILER_VERSION_MAJOR DEC(__PATHCC__)
+# define COMPILER_VERSION_MINOR DEC(__PATHCC_MINOR__)
+# if defined(__PATHCC_PATCHLEVEL__)
+# define COMPILER_VERSION_PATCH DEC(__PATHCC_PATCHLEVEL__)
+# endif
+
+#elif defined(__BORLANDC__) && defined(__CODEGEARC_VERSION__)
+# define COMPILER_ID "Embarcadero"
+# define COMPILER_VERSION_MAJOR HEX(__CODEGEARC_VERSION__>>24 & 0x00FF)
+# define COMPILER_VERSION_MINOR HEX(__CODEGEARC_VERSION__>>16 & 0x00FF)
+# define COMPILER_VERSION_PATCH DEC(__CODEGEARC_VERSION__ & 0xFFFF)
+
+#elif defined(__BORLANDC__)
+# define COMPILER_ID "Borland"
+ /* __BORLANDC__ = 0xVRR */
+# define COMPILER_VERSION_MAJOR HEX(__BORLANDC__>>8)
+# define COMPILER_VERSION_MINOR HEX(__BORLANDC__ & 0xFF)
+
+#elif defined(__WATCOMC__) && __WATCOMC__ < 1200
+# define COMPILER_ID "Watcom"
+ /* __WATCOMC__ = VVRR */
+# define COMPILER_VERSION_MAJOR DEC(__WATCOMC__ / 100)
+# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10)
+# if (__WATCOMC__ % 10) > 0
+# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10)
+# endif
+
+#elif defined(__WATCOMC__)
+# define COMPILER_ID "OpenWatcom"
+ /* __WATCOMC__ = VVRP + 1100 */
+# define COMPILER_VERSION_MAJOR DEC((__WATCOMC__ - 1100) / 100)
+# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10)
+# if (__WATCOMC__ % 10) > 0
+# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10)
+# endif
+
+#elif defined(__SUNPRO_C)
+# define COMPILER_ID "SunPro"
+# if __SUNPRO_C >= 0x5100
+ /* __SUNPRO_C = 0xVRRP */
+# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>12)
+# define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xFF)
+# define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF)
+# else
+ /* __SUNPRO_CC = 0xVRP */
+# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>8)
+# define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xF)
+# define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF)
+# endif
+
+#elif defined(__HP_cc)
+# define COMPILER_ID "HP"
+ /* __HP_cc = VVRRPP */
+# define COMPILER_VERSION_MAJOR DEC(__HP_cc/10000)
+# define COMPILER_VERSION_MINOR DEC(__HP_cc/100 % 100)
+# define COMPILER_VERSION_PATCH DEC(__HP_cc % 100)
+
+#elif defined(__DECC)
+# define COMPILER_ID "Compaq"
+ /* __DECC_VER = VVRRTPPPP */
+# define COMPILER_VERSION_MAJOR DEC(__DECC_VER/10000000)
+# define COMPILER_VERSION_MINOR DEC(__DECC_VER/100000 % 100)
+# define COMPILER_VERSION_PATCH DEC(__DECC_VER % 10000)
+
+#elif defined(__IBMC__) && defined(__COMPILER_VER__)
+# define COMPILER_ID "zOS"
+ /* __IBMC__ = VRP */
+# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100)
+# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10)
+# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10)
+
+#elif defined(__ibmxl__) && defined(__clang__)
+# define COMPILER_ID "XLClang"
+# define COMPILER_VERSION_MAJOR DEC(__ibmxl_version__)
+# define COMPILER_VERSION_MINOR DEC(__ibmxl_release__)
+# define COMPILER_VERSION_PATCH DEC(__ibmxl_modification__)
+# define COMPILER_VERSION_TWEAK DEC(__ibmxl_ptf_fix_level__)
+
+
+#elif defined(__IBMC__) && !defined(__COMPILER_VER__) && __IBMC__ >= 800
+# define COMPILER_ID "XL"
+ /* __IBMC__ = VRP */
+# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100)
+# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10)
+# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10)
+
+#elif defined(__IBMC__) && !defined(__COMPILER_VER__) && __IBMC__ < 800
+# define COMPILER_ID "VisualAge"
+ /* __IBMC__ = VRP */
+# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100)
+# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10)
+# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10)
+
+#elif defined(__PGI)
+# define COMPILER_ID "PGI"
+# define COMPILER_VERSION_MAJOR DEC(__PGIC__)
+# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__)
+# if defined(__PGIC_PATCHLEVEL__)
+# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__)
+# endif
+
+#elif defined(_CRAYC)
+# define COMPILER_ID "Cray"
+# define COMPILER_VERSION_MAJOR DEC(_RELEASE_MAJOR)
+# define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR)
+
+#elif defined(__TI_COMPILER_VERSION__)
+# define COMPILER_ID "TI"
+ /* __TI_COMPILER_VERSION__ = VVVRRRPPP */
+# define COMPILER_VERSION_MAJOR DEC(__TI_COMPILER_VERSION__/1000000)
+# define COMPILER_VERSION_MINOR DEC(__TI_COMPILER_VERSION__/1000 % 1000)
+# define COMPILER_VERSION_PATCH DEC(__TI_COMPILER_VERSION__ % 1000)
+
+#elif defined(__FUJITSU) || defined(__FCC_VERSION) || defined(__fcc_version)
+# define COMPILER_ID "Fujitsu"
+
+#elif defined(__ghs__)
+# define COMPILER_ID "GHS"
+/* __GHS_VERSION_NUMBER = VVVVRP */
+# ifdef __GHS_VERSION_NUMBER
+# define COMPILER_VERSION_MAJOR DEC(__GHS_VERSION_NUMBER / 100)
+# define COMPILER_VERSION_MINOR DEC(__GHS_VERSION_NUMBER / 10 % 10)
+# define COMPILER_VERSION_PATCH DEC(__GHS_VERSION_NUMBER % 10)
+# endif
+
+#elif defined(__TINYC__)
+# define COMPILER_ID "TinyCC"
+
+#elif defined(__BCC__)
+# define COMPILER_ID "Bruce"
+
+#elif defined(__SCO_VERSION__)
+# define COMPILER_ID "SCO"
+
+#elif defined(__ARMCC_VERSION) && !defined(__clang__)
+# define COMPILER_ID "ARMCC"
+#if __ARMCC_VERSION >= 1000000
+ /* __ARMCC_VERSION = VRRPPPP */
+ # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/1000000)
+ # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 100)
+ # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000)
+#else
+ /* __ARMCC_VERSION = VRPPPP */
+ # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/100000)
+ # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 10)
+ # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000)
+#endif
+
+
+#elif defined(__clang__) && defined(__apple_build_version__)
+# define COMPILER_ID "AppleClang"
+# if defined(_MSC_VER)
+# define SIMULATE_ID "MSVC"
+# endif
+# define COMPILER_VERSION_MAJOR DEC(__clang_major__)
+# define COMPILER_VERSION_MINOR DEC(__clang_minor__)
+# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__)
+# if defined(_MSC_VER)
+ /* _MSC_VER = VVRR */
+# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100)
+# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100)
+# endif
+# define COMPILER_VERSION_TWEAK DEC(__apple_build_version__)
+
+#elif defined(__clang__) && defined(__ARMCOMPILER_VERSION)
+# define COMPILER_ID "ARMClang"
+ # define COMPILER_VERSION_MAJOR DEC(__ARMCOMPILER_VERSION/1000000)
+ # define COMPILER_VERSION_MINOR DEC(__ARMCOMPILER_VERSION/10000 % 100)
+ # define COMPILER_VERSION_PATCH DEC(__ARMCOMPILER_VERSION % 10000)
+# define COMPILER_VERSION_INTERNAL DEC(__ARMCOMPILER_VERSION)
+
+#elif defined(__clang__)
+# define COMPILER_ID "Clang"
+# if defined(_MSC_VER)
+# define SIMULATE_ID "MSVC"
+# endif
+# define COMPILER_VERSION_MAJOR DEC(__clang_major__)
+# define COMPILER_VERSION_MINOR DEC(__clang_minor__)
+# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__)
+# if defined(_MSC_VER)
+ /* _MSC_VER = VVRR */
+# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100)
+# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100)
+# endif
+
+#elif defined(__GNUC__)
+# define COMPILER_ID "GNU"
+# define COMPILER_VERSION_MAJOR DEC(__GNUC__)
+# if defined(__GNUC_MINOR__)
+# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__)
+# endif
+# if defined(__GNUC_PATCHLEVEL__)
+# define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__)
+# endif
+
+#elif defined(_MSC_VER)
+# define COMPILER_ID "MSVC"
+ /* _MSC_VER = VVRR */
+# define COMPILER_VERSION_MAJOR DEC(_MSC_VER / 100)
+# define COMPILER_VERSION_MINOR DEC(_MSC_VER % 100)
+# if defined(_MSC_FULL_VER)
+# if _MSC_VER >= 1400
+ /* _MSC_FULL_VER = VVRRPPPPP */
+# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 100000)
+# else
+ /* _MSC_FULL_VER = VVRRPPPP */
+# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 10000)
+# endif
+# endif
+# if defined(_MSC_BUILD)
+# define COMPILER_VERSION_TWEAK DEC(_MSC_BUILD)
+# endif
+
+#elif defined(__VISUALDSPVERSION__) || defined(__ADSPBLACKFIN__) || defined(__ADSPTS__) || defined(__ADSP21000__)
+# define COMPILER_ID "ADSP"
+#if defined(__VISUALDSPVERSION__)
+ /* __VISUALDSPVERSION__ = 0xVVRRPP00 */
+# define COMPILER_VERSION_MAJOR HEX(__VISUALDSPVERSION__>>24)
+# define COMPILER_VERSION_MINOR HEX(__VISUALDSPVERSION__>>16 & 0xFF)
+# define COMPILER_VERSION_PATCH HEX(__VISUALDSPVERSION__>>8 & 0xFF)
+#endif
+
+#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC)
+# define COMPILER_ID "IAR"
+# if defined(__VER__) && defined(__ICCARM__)
+# define COMPILER_VERSION_MAJOR DEC((__VER__) / 1000000)
+# define COMPILER_VERSION_MINOR DEC(((__VER__) / 1000) % 1000)
+# define COMPILER_VERSION_PATCH DEC((__VER__) % 1000)
+# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__)
+# elif defined(__VER__) && (defined(__ICCAVR__) || defined(__ICCRX__) || defined(__ICCRH850__) || defined(__ICCRL78__) || defined(__ICC430__) || defined(__ICCRISCV__) || defined(__ICCV850__) || defined(__ICC8051__))
+# define COMPILER_VERSION_MAJOR DEC((__VER__) / 100)
+# define COMPILER_VERSION_MINOR DEC((__VER__) - (((__VER__) / 100)*100))
+# define COMPILER_VERSION_PATCH DEC(__SUBVERSION__)
+# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__)
+# endif
+
+#elif defined(__SDCC_VERSION_MAJOR) || defined(SDCC)
+# define COMPILER_ID "SDCC"
+# if defined(__SDCC_VERSION_MAJOR)
+# define COMPILER_VERSION_MAJOR DEC(__SDCC_VERSION_MAJOR)
+# define COMPILER_VERSION_MINOR DEC(__SDCC_VERSION_MINOR)
+# define COMPILER_VERSION_PATCH DEC(__SDCC_VERSION_PATCH)
+# else
+ /* SDCC = VRP */
+# define COMPILER_VERSION_MAJOR DEC(SDCC/100)
+# define COMPILER_VERSION_MINOR DEC(SDCC/10 % 10)
+# define COMPILER_VERSION_PATCH DEC(SDCC % 10)
+# endif
+
+
+/* These compilers are either not known or too old to define an
+ identification macro. Try to identify the platform and guess that
+ it is the native compiler. */
+#elif defined(__hpux) || defined(__hpua)
+# define COMPILER_ID "HP"
+
+#else /* unknown compiler */
+# define COMPILER_ID ""
+#endif
+
+/* Construct the string literal in pieces to prevent the source from
+ getting matched. Store it in a pointer rather than an array
+ because some compilers will just produce instructions to fill the
+ array rather than assigning a pointer to a static array. */
+char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]";
+#ifdef SIMULATE_ID
+char const* info_simulate = "INFO" ":" "simulate[" SIMULATE_ID "]";
+#endif
+
+#ifdef __QNXNTO__
+char const* qnxnto = "INFO" ":" "qnxnto[]";
+#endif
+
+#if defined(__CRAYXE) || defined(__CRAYXC)
+char const *info_cray = "INFO" ":" "compiler_wrapper[CrayPrgEnv]";
+#endif
+
+#define STRINGIFY_HELPER(X) #X
+#define STRINGIFY(X) STRINGIFY_HELPER(X)
+
+/* Identify known platforms by name. */
+#if defined(__linux) || defined(__linux__) || defined(linux)
+# define PLATFORM_ID "Linux"
+
+#elif defined(__CYGWIN__)
+# define PLATFORM_ID "Cygwin"
+
+#elif defined(__MINGW32__)
+# define PLATFORM_ID "MinGW"
+
+#elif defined(__APPLE__)
+# define PLATFORM_ID "Darwin"
+
+#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
+# define PLATFORM_ID "Windows"
+
+#elif defined(__FreeBSD__) || defined(__FreeBSD)
+# define PLATFORM_ID "FreeBSD"
+
+#elif defined(__NetBSD__) || defined(__NetBSD)
+# define PLATFORM_ID "NetBSD"
+
+#elif defined(__OpenBSD__) || defined(__OPENBSD)
+# define PLATFORM_ID "OpenBSD"
+
+#elif defined(__sun) || defined(sun)
+# define PLATFORM_ID "SunOS"
+
+#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__)
+# define PLATFORM_ID "AIX"
+
+#elif defined(__hpux) || defined(__hpux__)
+# define PLATFORM_ID "HP-UX"
+
+#elif defined(__HAIKU__)
+# define PLATFORM_ID "Haiku"
+
+#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS)
+# define PLATFORM_ID "BeOS"
+
+#elif defined(__QNX__) || defined(__QNXNTO__)
+# define PLATFORM_ID "QNX"
+
+#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__)
+# define PLATFORM_ID "Tru64"
+
+#elif defined(__riscos) || defined(__riscos__)
+# define PLATFORM_ID "RISCos"
+
+#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__)
+# define PLATFORM_ID "SINIX"
+
+#elif defined(__UNIX_SV__)
+# define PLATFORM_ID "UNIX_SV"
+
+#elif defined(__bsdos__)
+# define PLATFORM_ID "BSDOS"
+
+#elif defined(_MPRAS) || defined(MPRAS)
+# define PLATFORM_ID "MP-RAS"
+
+#elif defined(__osf) || defined(__osf__)
+# define PLATFORM_ID "OSF1"
+
+#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv)
+# define PLATFORM_ID "SCO_SV"
+
+#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX)
+# define PLATFORM_ID "ULTRIX"
+
+#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX)
+# define PLATFORM_ID "Xenix"
+
+#elif defined(__WATCOMC__)
+# if defined(__LINUX__)
+# define PLATFORM_ID "Linux"
+
+# elif defined(__DOS__)
+# define PLATFORM_ID "DOS"
+
+# elif defined(__OS2__)
+# define PLATFORM_ID "OS2"
+
+# elif defined(__WINDOWS__)
+# define PLATFORM_ID "Windows3x"
+
+# elif defined(__VXWORKS__)
+# define PLATFORM_ID "VxWorks"
+
+# else /* unknown platform */
+# define PLATFORM_ID
+# endif
+
+#elif defined(__INTEGRITY)
+# if defined(INT_178B)
+# define PLATFORM_ID "Integrity178"
+
+# else /* regular Integrity */
+# define PLATFORM_ID "Integrity"
+# endif
+
+#else /* unknown platform */
+# define PLATFORM_ID
+
+#endif
+
+/* For windows compilers MSVC and Intel we can determine
+ the architecture of the compiler being used. This is because
+ the compilers do not have flags that can change the architecture,
+ but rather depend on which compiler is being used
+*/
+#if defined(_WIN32) && defined(_MSC_VER)
+# if defined(_M_IA64)
+# define ARCHITECTURE_ID "IA64"
+
+# elif defined(_M_X64) || defined(_M_AMD64)
+# define ARCHITECTURE_ID "x64"
+
+# elif defined(_M_IX86)
+# define ARCHITECTURE_ID "X86"
+
+# elif defined(_M_ARM64)
+# define ARCHITECTURE_ID "ARM64"
+
+# elif defined(_M_ARM)
+# if _M_ARM == 4
+# define ARCHITECTURE_ID "ARMV4I"
+# elif _M_ARM == 5
+# define ARCHITECTURE_ID "ARMV5I"
+# else
+# define ARCHITECTURE_ID "ARMV" STRINGIFY(_M_ARM)
+# endif
+
+# elif defined(_M_MIPS)
+# define ARCHITECTURE_ID "MIPS"
+
+# elif defined(_M_SH)
+# define ARCHITECTURE_ID "SHx"
+
+# else /* unknown architecture */
+# define ARCHITECTURE_ID ""
+# endif
+
+#elif defined(__WATCOMC__)
+# if defined(_M_I86)
+# define ARCHITECTURE_ID "I86"
+
+# elif defined(_M_IX86)
+# define ARCHITECTURE_ID "X86"
+
+# else /* unknown architecture */
+# define ARCHITECTURE_ID ""
+# endif
+
+#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC)
+# if defined(__ICCARM__)
+# define ARCHITECTURE_ID "ARM"
+
+# elif defined(__ICCRX__)
+# define ARCHITECTURE_ID "RX"
+
+# elif defined(__ICCRH850__)
+# define ARCHITECTURE_ID "RH850"
+
+# elif defined(__ICCRL78__)
+# define ARCHITECTURE_ID "RL78"
+
+# elif defined(__ICCRISCV__)
+# define ARCHITECTURE_ID "RISCV"
+
+# elif defined(__ICCAVR__)
+# define ARCHITECTURE_ID "AVR"
+
+# elif defined(__ICC430__)
+# define ARCHITECTURE_ID "MSP430"
+
+# elif defined(__ICCV850__)
+# define ARCHITECTURE_ID "V850"
+
+# elif defined(__ICC8051__)
+# define ARCHITECTURE_ID "8051"
+
+# else /* unknown architecture */
+# define ARCHITECTURE_ID ""
+# endif
+
+#elif defined(__ghs__)
+# if defined(__PPC64__)
+# define ARCHITECTURE_ID "PPC64"
+
+# elif defined(__ppc__)
+# define ARCHITECTURE_ID "PPC"
+
+# elif defined(__ARM__)
+# define ARCHITECTURE_ID "ARM"
+
+# elif defined(__x86_64__)
+# define ARCHITECTURE_ID "x64"
+
+# elif defined(__i386__)
+# define ARCHITECTURE_ID "X86"
+
+# else /* unknown architecture */
+# define ARCHITECTURE_ID ""
+# endif
+#else
+# define ARCHITECTURE_ID
+#endif
+
+/* Convert integer to decimal digit literals. */
+#define DEC(n) \
+ ('0' + (((n) / 10000000)%10)), \
+ ('0' + (((n) / 1000000)%10)), \
+ ('0' + (((n) / 100000)%10)), \
+ ('0' + (((n) / 10000)%10)), \
+ ('0' + (((n) / 1000)%10)), \
+ ('0' + (((n) / 100)%10)), \
+ ('0' + (((n) / 10)%10)), \
+ ('0' + ((n) % 10))
+
+/* Convert integer to hex digit literals. */
+#define HEX(n) \
+ ('0' + ((n)>>28 & 0xF)), \
+ ('0' + ((n)>>24 & 0xF)), \
+ ('0' + ((n)>>20 & 0xF)), \
+ ('0' + ((n)>>16 & 0xF)), \
+ ('0' + ((n)>>12 & 0xF)), \
+ ('0' + ((n)>>8 & 0xF)), \
+ ('0' + ((n)>>4 & 0xF)), \
+ ('0' + ((n) & 0xF))
+
+/* Construct a string literal encoding the version number components. */
+#ifdef COMPILER_VERSION_MAJOR
+char const info_version[] = {
+ 'I', 'N', 'F', 'O', ':',
+ 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[',
+ COMPILER_VERSION_MAJOR,
+# ifdef COMPILER_VERSION_MINOR
+ '.', COMPILER_VERSION_MINOR,
+# ifdef COMPILER_VERSION_PATCH
+ '.', COMPILER_VERSION_PATCH,
+# ifdef COMPILER_VERSION_TWEAK
+ '.', COMPILER_VERSION_TWEAK,
+# endif
+# endif
+# endif
+ ']','\0'};
+#endif
+
+/* Construct a string literal encoding the internal version number. */
+#ifdef COMPILER_VERSION_INTERNAL
+char const info_version_internal[] = {
+ 'I', 'N', 'F', 'O', ':',
+ 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','_',
+ 'i','n','t','e','r','n','a','l','[',
+ COMPILER_VERSION_INTERNAL,']','\0'};
+#endif
+
+/* Construct a string literal encoding the version number components. */
+#ifdef SIMULATE_VERSION_MAJOR
+char const info_simulate_version[] = {
+ 'I', 'N', 'F', 'O', ':',
+ 's','i','m','u','l','a','t','e','_','v','e','r','s','i','o','n','[',
+ SIMULATE_VERSION_MAJOR,
+# ifdef SIMULATE_VERSION_MINOR
+ '.', SIMULATE_VERSION_MINOR,
+# ifdef SIMULATE_VERSION_PATCH
+ '.', SIMULATE_VERSION_PATCH,
+# ifdef SIMULATE_VERSION_TWEAK
+ '.', SIMULATE_VERSION_TWEAK,
+# endif
+# endif
+# endif
+ ']','\0'};
+#endif
+
+/* Construct the string literal in pieces to prevent the source from
+ getting matched. Store it in a pointer rather than an array
+ because some compilers will just produce instructions to fill the
+ array rather than assigning a pointer to a static array. */
+char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]";
+char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]";
+
+
+
+
+#if !defined(__STDC__)
+# if (defined(_MSC_VER) && !defined(__clang__)) \
+ || (defined(__ibmxl__) || defined(__IBMC__))
+# define C_DIALECT "90"
+# else
+# define C_DIALECT
+# endif
+#elif __STDC_VERSION__ >= 201000L
+# define C_DIALECT "11"
+#elif __STDC_VERSION__ >= 199901L
+# define C_DIALECT "99"
+#else
+# define C_DIALECT "90"
+#endif
+const char* info_language_dialect_default =
+ "INFO" ":" "dialect_default[" C_DIALECT "]";
+
+/*--------------------------------------------------------------------------*/
+
+#ifdef ID_VOID_MAIN
+void main() {}
+#else
+# if defined(__CLASSIC_C__)
+int main(argc, argv) int argc; char *argv[];
+# else
+int main(int argc, char* argv[])
+# endif
+{
+ int require = 0;
+ require += info_compiler[argc];
+ require += info_platform[argc];
+ require += info_arch[argc];
+#ifdef COMPILER_VERSION_MAJOR
+ require += info_version[argc];
+#endif
+#ifdef COMPILER_VERSION_INTERNAL
+ require += info_version_internal[argc];
+#endif
+#ifdef SIMULATE_ID
+ require += info_simulate[argc];
+#endif
+#ifdef SIMULATE_VERSION_MAJOR
+ require += info_simulate_version[argc];
+#endif
+#if defined(__CRAYXE) || defined(__CRAYXC)
+ require += info_cray[argc];
+#endif
+ require += info_language_dialect_default[argc];
+ (void)argv;
+ return require;
+}
+#endif
diff --git a/CMakeFiles/3.18.4/CompilerIdC/a.out b/CMakeFiles/3.18.4/CompilerIdC/a.out
new file mode 100755
index 0000000..dec38b4
--- /dev/null
+++ b/CMakeFiles/3.18.4/CompilerIdC/a.out
Binary files differ
diff --git a/CMakeFiles/3.18.4/CompilerIdCXX/CMakeCXXCompilerId.cpp b/CMakeFiles/3.18.4/CompilerIdCXX/CMakeCXXCompilerId.cpp
new file mode 100644
index 0000000..37c21ca
--- /dev/null
+++ b/CMakeFiles/3.18.4/CompilerIdCXX/CMakeCXXCompilerId.cpp
@@ -0,0 +1,663 @@
+/* This source file must have a .cpp extension so that all C++ compilers
+ recognize the extension without flags. Borland does not know .cxx for
+ example. */
+#ifndef __cplusplus
+# error "A C compiler has been selected for C++."
+#endif
+
+
+/* Version number components: V=Version, R=Revision, P=Patch
+ Version date components: YYYY=Year, MM=Month, DD=Day */
+
+#if defined(__COMO__)
+# define COMPILER_ID "Comeau"
+ /* __COMO_VERSION__ = VRR */
+# define COMPILER_VERSION_MAJOR DEC(__COMO_VERSION__ / 100)
+# define COMPILER_VERSION_MINOR DEC(__COMO_VERSION__ % 100)
+
+#elif defined(__INTEL_COMPILER) || defined(__ICC)
+# define COMPILER_ID "Intel"
+# if defined(_MSC_VER)
+# define SIMULATE_ID "MSVC"
+# endif
+# if defined(__GNUC__)
+# define SIMULATE_ID "GNU"
+# endif
+ /* __INTEL_COMPILER = VRP */
+# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER/100)
+# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER/10 % 10)
+# if defined(__INTEL_COMPILER_UPDATE)
+# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER_UPDATE)
+# else
+# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER % 10)
+# endif
+# if defined(__INTEL_COMPILER_BUILD_DATE)
+ /* __INTEL_COMPILER_BUILD_DATE = YYYYMMDD */
+# define COMPILER_VERSION_TWEAK DEC(__INTEL_COMPILER_BUILD_DATE)
+# endif
+# if defined(_MSC_VER)
+ /* _MSC_VER = VVRR */
+# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100)
+# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100)
+# endif
+# if defined(__GNUC__)
+# define SIMULATE_VERSION_MAJOR DEC(__GNUC__)
+# elif defined(__GNUG__)
+# define SIMULATE_VERSION_MAJOR DEC(__GNUG__)
+# endif
+# if defined(__GNUC_MINOR__)
+# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__)
+# endif
+# if defined(__GNUC_PATCHLEVEL__)
+# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__)
+# endif
+
+#elif defined(__PATHCC__)
+# define COMPILER_ID "PathScale"
+# define COMPILER_VERSION_MAJOR DEC(__PATHCC__)
+# define COMPILER_VERSION_MINOR DEC(__PATHCC_MINOR__)
+# if defined(__PATHCC_PATCHLEVEL__)
+# define COMPILER_VERSION_PATCH DEC(__PATHCC_PATCHLEVEL__)
+# endif
+
+#elif defined(__BORLANDC__) && defined(__CODEGEARC_VERSION__)
+# define COMPILER_ID "Embarcadero"
+# define COMPILER_VERSION_MAJOR HEX(__CODEGEARC_VERSION__>>24 & 0x00FF)
+# define COMPILER_VERSION_MINOR HEX(__CODEGEARC_VERSION__>>16 & 0x00FF)
+# define COMPILER_VERSION_PATCH DEC(__CODEGEARC_VERSION__ & 0xFFFF)
+
+#elif defined(__BORLANDC__)
+# define COMPILER_ID "Borland"
+ /* __BORLANDC__ = 0xVRR */
+# define COMPILER_VERSION_MAJOR HEX(__BORLANDC__>>8)
+# define COMPILER_VERSION_MINOR HEX(__BORLANDC__ & 0xFF)
+
+#elif defined(__WATCOMC__) && __WATCOMC__ < 1200
+# define COMPILER_ID "Watcom"
+ /* __WATCOMC__ = VVRR */
+# define COMPILER_VERSION_MAJOR DEC(__WATCOMC__ / 100)
+# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10)
+# if (__WATCOMC__ % 10) > 0
+# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10)
+# endif
+
+#elif defined(__WATCOMC__)
+# define COMPILER_ID "OpenWatcom"
+ /* __WATCOMC__ = VVRP + 1100 */
+# define COMPILER_VERSION_MAJOR DEC((__WATCOMC__ - 1100) / 100)
+# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10)
+# if (__WATCOMC__ % 10) > 0
+# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10)
+# endif
+
+#elif defined(__SUNPRO_CC)
+# define COMPILER_ID "SunPro"
+# if __SUNPRO_CC >= 0x5100
+ /* __SUNPRO_CC = 0xVRRP */
+# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_CC>>12)
+# define COMPILER_VERSION_MINOR HEX(__SUNPRO_CC>>4 & 0xFF)
+# define COMPILER_VERSION_PATCH HEX(__SUNPRO_CC & 0xF)
+# else
+ /* __SUNPRO_CC = 0xVRP */
+# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_CC>>8)
+# define COMPILER_VERSION_MINOR HEX(__SUNPRO_CC>>4 & 0xF)
+# define COMPILER_VERSION_PATCH HEX(__SUNPRO_CC & 0xF)
+# endif
+
+#elif defined(__HP_aCC)
+# define COMPILER_ID "HP"
+ /* __HP_aCC = VVRRPP */
+# define COMPILER_VERSION_MAJOR DEC(__HP_aCC/10000)
+# define COMPILER_VERSION_MINOR DEC(__HP_aCC/100 % 100)
+# define COMPILER_VERSION_PATCH DEC(__HP_aCC % 100)
+
+#elif defined(__DECCXX)
+# define COMPILER_ID "Compaq"
+ /* __DECCXX_VER = VVRRTPPPP */
+# define COMPILER_VERSION_MAJOR DEC(__DECCXX_VER/10000000)
+# define COMPILER_VERSION_MINOR DEC(__DECCXX_VER/100000 % 100)
+# define COMPILER_VERSION_PATCH DEC(__DECCXX_VER % 10000)
+
+#elif defined(__IBMCPP__) && defined(__COMPILER_VER__)
+# define COMPILER_ID "zOS"
+ /* __IBMCPP__ = VRP */
+# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100)
+# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10)
+# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10)
+
+#elif defined(__ibmxl__) && defined(__clang__)
+# define COMPILER_ID "XLClang"
+# define COMPILER_VERSION_MAJOR DEC(__ibmxl_version__)
+# define COMPILER_VERSION_MINOR DEC(__ibmxl_release__)
+# define COMPILER_VERSION_PATCH DEC(__ibmxl_modification__)
+# define COMPILER_VERSION_TWEAK DEC(__ibmxl_ptf_fix_level__)
+
+
+#elif defined(__IBMCPP__) && !defined(__COMPILER_VER__) && __IBMCPP__ >= 800
+# define COMPILER_ID "XL"
+ /* __IBMCPP__ = VRP */
+# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100)
+# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10)
+# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10)
+
+#elif defined(__IBMCPP__) && !defined(__COMPILER_VER__) && __IBMCPP__ < 800
+# define COMPILER_ID "VisualAge"
+ /* __IBMCPP__ = VRP */
+# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100)
+# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10)
+# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10)
+
+#elif defined(__PGI)
+# define COMPILER_ID "PGI"
+# define COMPILER_VERSION_MAJOR DEC(__PGIC__)
+# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__)
+# if defined(__PGIC_PATCHLEVEL__)
+# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__)
+# endif
+
+#elif defined(_CRAYC)
+# define COMPILER_ID "Cray"
+# define COMPILER_VERSION_MAJOR DEC(_RELEASE_MAJOR)
+# define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR)
+
+#elif defined(__TI_COMPILER_VERSION__)
+# define COMPILER_ID "TI"
+ /* __TI_COMPILER_VERSION__ = VVVRRRPPP */
+# define COMPILER_VERSION_MAJOR DEC(__TI_COMPILER_VERSION__/1000000)
+# define COMPILER_VERSION_MINOR DEC(__TI_COMPILER_VERSION__/1000 % 1000)
+# define COMPILER_VERSION_PATCH DEC(__TI_COMPILER_VERSION__ % 1000)
+
+#elif defined(__FUJITSU) || defined(__FCC_VERSION) || defined(__fcc_version)
+# define COMPILER_ID "Fujitsu"
+
+#elif defined(__ghs__)
+# define COMPILER_ID "GHS"
+/* __GHS_VERSION_NUMBER = VVVVRP */
+# ifdef __GHS_VERSION_NUMBER
+# define COMPILER_VERSION_MAJOR DEC(__GHS_VERSION_NUMBER / 100)
+# define COMPILER_VERSION_MINOR DEC(__GHS_VERSION_NUMBER / 10 % 10)
+# define COMPILER_VERSION_PATCH DEC(__GHS_VERSION_NUMBER % 10)
+# endif
+
+#elif defined(__SCO_VERSION__)
+# define COMPILER_ID "SCO"
+
+#elif defined(__ARMCC_VERSION) && !defined(__clang__)
+# define COMPILER_ID "ARMCC"
+#if __ARMCC_VERSION >= 1000000
+ /* __ARMCC_VERSION = VRRPPPP */
+ # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/1000000)
+ # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 100)
+ # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000)
+#else
+ /* __ARMCC_VERSION = VRPPPP */
+ # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/100000)
+ # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 10)
+ # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000)
+#endif
+
+
+#elif defined(__clang__) && defined(__apple_build_version__)
+# define COMPILER_ID "AppleClang"
+# if defined(_MSC_VER)
+# define SIMULATE_ID "MSVC"
+# endif
+# define COMPILER_VERSION_MAJOR DEC(__clang_major__)
+# define COMPILER_VERSION_MINOR DEC(__clang_minor__)
+# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__)
+# if defined(_MSC_VER)
+ /* _MSC_VER = VVRR */
+# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100)
+# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100)
+# endif
+# define COMPILER_VERSION_TWEAK DEC(__apple_build_version__)
+
+#elif defined(__clang__) && defined(__ARMCOMPILER_VERSION)
+# define COMPILER_ID "ARMClang"
+ # define COMPILER_VERSION_MAJOR DEC(__ARMCOMPILER_VERSION/1000000)
+ # define COMPILER_VERSION_MINOR DEC(__ARMCOMPILER_VERSION/10000 % 100)
+ # define COMPILER_VERSION_PATCH DEC(__ARMCOMPILER_VERSION % 10000)
+# define COMPILER_VERSION_INTERNAL DEC(__ARMCOMPILER_VERSION)
+
+#elif defined(__clang__)
+# define COMPILER_ID "Clang"
+# if defined(_MSC_VER)
+# define SIMULATE_ID "MSVC"
+# endif
+# define COMPILER_VERSION_MAJOR DEC(__clang_major__)
+# define COMPILER_VERSION_MINOR DEC(__clang_minor__)
+# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__)
+# if defined(_MSC_VER)
+ /* _MSC_VER = VVRR */
+# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100)
+# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100)
+# endif
+
+#elif defined(__GNUC__) || defined(__GNUG__)
+# define COMPILER_ID "GNU"
+# if defined(__GNUC__)
+# define COMPILER_VERSION_MAJOR DEC(__GNUC__)
+# else
+# define COMPILER_VERSION_MAJOR DEC(__GNUG__)
+# endif
+# if defined(__GNUC_MINOR__)
+# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__)
+# endif
+# if defined(__GNUC_PATCHLEVEL__)
+# define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__)
+# endif
+
+#elif defined(_MSC_VER)
+# define COMPILER_ID "MSVC"
+ /* _MSC_VER = VVRR */
+# define COMPILER_VERSION_MAJOR DEC(_MSC_VER / 100)
+# define COMPILER_VERSION_MINOR DEC(_MSC_VER % 100)
+# if defined(_MSC_FULL_VER)
+# if _MSC_VER >= 1400
+ /* _MSC_FULL_VER = VVRRPPPPP */
+# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 100000)
+# else
+ /* _MSC_FULL_VER = VVRRPPPP */
+# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 10000)
+# endif
+# endif
+# if defined(_MSC_BUILD)
+# define COMPILER_VERSION_TWEAK DEC(_MSC_BUILD)
+# endif
+
+#elif defined(__VISUALDSPVERSION__) || defined(__ADSPBLACKFIN__) || defined(__ADSPTS__) || defined(__ADSP21000__)
+# define COMPILER_ID "ADSP"
+#if defined(__VISUALDSPVERSION__)
+ /* __VISUALDSPVERSION__ = 0xVVRRPP00 */
+# define COMPILER_VERSION_MAJOR HEX(__VISUALDSPVERSION__>>24)
+# define COMPILER_VERSION_MINOR HEX(__VISUALDSPVERSION__>>16 & 0xFF)
+# define COMPILER_VERSION_PATCH HEX(__VISUALDSPVERSION__>>8 & 0xFF)
+#endif
+
+#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC)
+# define COMPILER_ID "IAR"
+# if defined(__VER__) && defined(__ICCARM__)
+# define COMPILER_VERSION_MAJOR DEC((__VER__) / 1000000)
+# define COMPILER_VERSION_MINOR DEC(((__VER__) / 1000) % 1000)
+# define COMPILER_VERSION_PATCH DEC((__VER__) % 1000)
+# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__)
+# elif defined(__VER__) && (defined(__ICCAVR__) || defined(__ICCRX__) || defined(__ICCRH850__) || defined(__ICCRL78__) || defined(__ICC430__) || defined(__ICCRISCV__) || defined(__ICCV850__) || defined(__ICC8051__))
+# define COMPILER_VERSION_MAJOR DEC((__VER__) / 100)
+# define COMPILER_VERSION_MINOR DEC((__VER__) - (((__VER__) / 100)*100))
+# define COMPILER_VERSION_PATCH DEC(__SUBVERSION__)
+# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__)
+# endif
+
+
+/* These compilers are either not known or too old to define an
+ identification macro. Try to identify the platform and guess that
+ it is the native compiler. */
+#elif defined(__hpux) || defined(__hpua)
+# define COMPILER_ID "HP"
+
+#else /* unknown compiler */
+# define COMPILER_ID ""
+#endif
+
+/* Construct the string literal in pieces to prevent the source from
+ getting matched. Store it in a pointer rather than an array
+ because some compilers will just produce instructions to fill the
+ array rather than assigning a pointer to a static array. */
+char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]";
+#ifdef SIMULATE_ID
+char const* info_simulate = "INFO" ":" "simulate[" SIMULATE_ID "]";
+#endif
+
+#ifdef __QNXNTO__
+char const* qnxnto = "INFO" ":" "qnxnto[]";
+#endif
+
+#if defined(__CRAYXE) || defined(__CRAYXC)
+char const *info_cray = "INFO" ":" "compiler_wrapper[CrayPrgEnv]";
+#endif
+
+#define STRINGIFY_HELPER(X) #X
+#define STRINGIFY(X) STRINGIFY_HELPER(X)
+
+/* Identify known platforms by name. */
+#if defined(__linux) || defined(__linux__) || defined(linux)
+# define PLATFORM_ID "Linux"
+
+#elif defined(__CYGWIN__)
+# define PLATFORM_ID "Cygwin"
+
+#elif defined(__MINGW32__)
+# define PLATFORM_ID "MinGW"
+
+#elif defined(__APPLE__)
+# define PLATFORM_ID "Darwin"
+
+#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
+# define PLATFORM_ID "Windows"
+
+#elif defined(__FreeBSD__) || defined(__FreeBSD)
+# define PLATFORM_ID "FreeBSD"
+
+#elif defined(__NetBSD__) || defined(__NetBSD)
+# define PLATFORM_ID "NetBSD"
+
+#elif defined(__OpenBSD__) || defined(__OPENBSD)
+# define PLATFORM_ID "OpenBSD"
+
+#elif defined(__sun) || defined(sun)
+# define PLATFORM_ID "SunOS"
+
+#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__)
+# define PLATFORM_ID "AIX"
+
+#elif defined(__hpux) || defined(__hpux__)
+# define PLATFORM_ID "HP-UX"
+
+#elif defined(__HAIKU__)
+# define PLATFORM_ID "Haiku"
+
+#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS)
+# define PLATFORM_ID "BeOS"
+
+#elif defined(__QNX__) || defined(__QNXNTO__)
+# define PLATFORM_ID "QNX"
+
+#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__)
+# define PLATFORM_ID "Tru64"
+
+#elif defined(__riscos) || defined(__riscos__)
+# define PLATFORM_ID "RISCos"
+
+#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__)
+# define PLATFORM_ID "SINIX"
+
+#elif defined(__UNIX_SV__)
+# define PLATFORM_ID "UNIX_SV"
+
+#elif defined(__bsdos__)
+# define PLATFORM_ID "BSDOS"
+
+#elif defined(_MPRAS) || defined(MPRAS)
+# define PLATFORM_ID "MP-RAS"
+
+#elif defined(__osf) || defined(__osf__)
+# define PLATFORM_ID "OSF1"
+
+#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv)
+# define PLATFORM_ID "SCO_SV"
+
+#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX)
+# define PLATFORM_ID "ULTRIX"
+
+#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX)
+# define PLATFORM_ID "Xenix"
+
+#elif defined(__WATCOMC__)
+# if defined(__LINUX__)
+# define PLATFORM_ID "Linux"
+
+# elif defined(__DOS__)
+# define PLATFORM_ID "DOS"
+
+# elif defined(__OS2__)
+# define PLATFORM_ID "OS2"
+
+# elif defined(__WINDOWS__)
+# define PLATFORM_ID "Windows3x"
+
+# elif defined(__VXWORKS__)
+# define PLATFORM_ID "VxWorks"
+
+# else /* unknown platform */
+# define PLATFORM_ID
+# endif
+
+#elif defined(__INTEGRITY)
+# if defined(INT_178B)
+# define PLATFORM_ID "Integrity178"
+
+# else /* regular Integrity */
+# define PLATFORM_ID "Integrity"
+# endif
+
+#else /* unknown platform */
+# define PLATFORM_ID
+
+#endif
+
+/* For windows compilers MSVC and Intel we can determine
+ the architecture of the compiler being used. This is because
+ the compilers do not have flags that can change the architecture,
+ but rather depend on which compiler is being used
+*/
+#if defined(_WIN32) && defined(_MSC_VER)
+# if defined(_M_IA64)
+# define ARCHITECTURE_ID "IA64"
+
+# elif defined(_M_X64) || defined(_M_AMD64)
+# define ARCHITECTURE_ID "x64"
+
+# elif defined(_M_IX86)
+# define ARCHITECTURE_ID "X86"
+
+# elif defined(_M_ARM64)
+# define ARCHITECTURE_ID "ARM64"
+
+# elif defined(_M_ARM)
+# if _M_ARM == 4
+# define ARCHITECTURE_ID "ARMV4I"
+# elif _M_ARM == 5
+# define ARCHITECTURE_ID "ARMV5I"
+# else
+# define ARCHITECTURE_ID "ARMV" STRINGIFY(_M_ARM)
+# endif
+
+# elif defined(_M_MIPS)
+# define ARCHITECTURE_ID "MIPS"
+
+# elif defined(_M_SH)
+# define ARCHITECTURE_ID "SHx"
+
+# else /* unknown architecture */
+# define ARCHITECTURE_ID ""
+# endif
+
+#elif defined(__WATCOMC__)
+# if defined(_M_I86)
+# define ARCHITECTURE_ID "I86"
+
+# elif defined(_M_IX86)
+# define ARCHITECTURE_ID "X86"
+
+# else /* unknown architecture */
+# define ARCHITECTURE_ID ""
+# endif
+
+#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC)
+# if defined(__ICCARM__)
+# define ARCHITECTURE_ID "ARM"
+
+# elif defined(__ICCRX__)
+# define ARCHITECTURE_ID "RX"
+
+# elif defined(__ICCRH850__)
+# define ARCHITECTURE_ID "RH850"
+
+# elif defined(__ICCRL78__)
+# define ARCHITECTURE_ID "RL78"
+
+# elif defined(__ICCRISCV__)
+# define ARCHITECTURE_ID "RISCV"
+
+# elif defined(__ICCAVR__)
+# define ARCHITECTURE_ID "AVR"
+
+# elif defined(__ICC430__)
+# define ARCHITECTURE_ID "MSP430"
+
+# elif defined(__ICCV850__)
+# define ARCHITECTURE_ID "V850"
+
+# elif defined(__ICC8051__)
+# define ARCHITECTURE_ID "8051"
+
+# else /* unknown architecture */
+# define ARCHITECTURE_ID ""
+# endif
+
+#elif defined(__ghs__)
+# if defined(__PPC64__)
+# define ARCHITECTURE_ID "PPC64"
+
+# elif defined(__ppc__)
+# define ARCHITECTURE_ID "PPC"
+
+# elif defined(__ARM__)
+# define ARCHITECTURE_ID "ARM"
+
+# elif defined(__x86_64__)
+# define ARCHITECTURE_ID "x64"
+
+# elif defined(__i386__)
+# define ARCHITECTURE_ID "X86"
+
+# else /* unknown architecture */
+# define ARCHITECTURE_ID ""
+# endif
+#else
+# define ARCHITECTURE_ID
+#endif
+
+/* Convert integer to decimal digit literals. */
+#define DEC(n) \
+ ('0' + (((n) / 10000000)%10)), \
+ ('0' + (((n) / 1000000)%10)), \
+ ('0' + (((n) / 100000)%10)), \
+ ('0' + (((n) / 10000)%10)), \
+ ('0' + (((n) / 1000)%10)), \
+ ('0' + (((n) / 100)%10)), \
+ ('0' + (((n) / 10)%10)), \
+ ('0' + ((n) % 10))
+
+/* Convert integer to hex digit literals. */
+#define HEX(n) \
+ ('0' + ((n)>>28 & 0xF)), \
+ ('0' + ((n)>>24 & 0xF)), \
+ ('0' + ((n)>>20 & 0xF)), \
+ ('0' + ((n)>>16 & 0xF)), \
+ ('0' + ((n)>>12 & 0xF)), \
+ ('0' + ((n)>>8 & 0xF)), \
+ ('0' + ((n)>>4 & 0xF)), \
+ ('0' + ((n) & 0xF))
+
+/* Construct a string literal encoding the version number components. */
+#ifdef COMPILER_VERSION_MAJOR
+char const info_version[] = {
+ 'I', 'N', 'F', 'O', ':',
+ 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[',
+ COMPILER_VERSION_MAJOR,
+# ifdef COMPILER_VERSION_MINOR
+ '.', COMPILER_VERSION_MINOR,
+# ifdef COMPILER_VERSION_PATCH
+ '.', COMPILER_VERSION_PATCH,
+# ifdef COMPILER_VERSION_TWEAK
+ '.', COMPILER_VERSION_TWEAK,
+# endif
+# endif
+# endif
+ ']','\0'};
+#endif
+
+/* Construct a string literal encoding the internal version number. */
+#ifdef COMPILER_VERSION_INTERNAL
+char const info_version_internal[] = {
+ 'I', 'N', 'F', 'O', ':',
+ 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','_',
+ 'i','n','t','e','r','n','a','l','[',
+ COMPILER_VERSION_INTERNAL,']','\0'};
+#endif
+
+/* Construct a string literal encoding the version number components. */
+#ifdef SIMULATE_VERSION_MAJOR
+char const info_simulate_version[] = {
+ 'I', 'N', 'F', 'O', ':',
+ 's','i','m','u','l','a','t','e','_','v','e','r','s','i','o','n','[',
+ SIMULATE_VERSION_MAJOR,
+# ifdef SIMULATE_VERSION_MINOR
+ '.', SIMULATE_VERSION_MINOR,
+# ifdef SIMULATE_VERSION_PATCH
+ '.', SIMULATE_VERSION_PATCH,
+# ifdef SIMULATE_VERSION_TWEAK
+ '.', SIMULATE_VERSION_TWEAK,
+# endif
+# endif
+# endif
+ ']','\0'};
+#endif
+
+/* Construct the string literal in pieces to prevent the source from
+ getting matched. Store it in a pointer rather than an array
+ because some compilers will just produce instructions to fill the
+ array rather than assigning a pointer to a static array. */
+char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]";
+char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]";
+
+
+
+
+#if defined(__INTEL_COMPILER) && defined(_MSVC_LANG) && _MSVC_LANG < 201403L
+# if defined(__INTEL_CXX11_MODE__)
+# if defined(__cpp_aggregate_nsdmi)
+# define CXX_STD 201402L
+# else
+# define CXX_STD 201103L
+# endif
+# else
+# define CXX_STD 199711L
+# endif
+#elif defined(_MSC_VER) && defined(_MSVC_LANG)
+# define CXX_STD _MSVC_LANG
+#else
+# define CXX_STD __cplusplus
+#endif
+
+const char* info_language_dialect_default = "INFO" ":" "dialect_default["
+#if CXX_STD > 201703L
+ "20"
+#elif CXX_STD >= 201703L
+ "17"
+#elif CXX_STD >= 201402L
+ "14"
+#elif CXX_STD >= 201103L
+ "11"
+#else
+ "98"
+#endif
+"]";
+
+/*--------------------------------------------------------------------------*/
+
+int main(int argc, char* argv[])
+{
+ int require = 0;
+ require += info_compiler[argc];
+ require += info_platform[argc];
+#ifdef COMPILER_VERSION_MAJOR
+ require += info_version[argc];
+#endif
+#ifdef COMPILER_VERSION_INTERNAL
+ require += info_version_internal[argc];
+#endif
+#ifdef SIMULATE_ID
+ require += info_simulate[argc];
+#endif
+#ifdef SIMULATE_VERSION_MAJOR
+ require += info_simulate_version[argc];
+#endif
+#if defined(__CRAYXE) || defined(__CRAYXC)
+ require += info_cray[argc];
+#endif
+ require += info_language_dialect_default[argc];
+ (void)argv;
+ return require;
+}
diff --git a/CMakeFiles/3.18.4/CompilerIdCXX/a.out b/CMakeFiles/3.18.4/CompilerIdCXX/a.out
new file mode 100755
index 0000000..5bf5fac
--- /dev/null
+++ b/CMakeFiles/3.18.4/CompilerIdCXX/a.out
Binary files differ
diff --git a/CMakeFiles/CMakeDirectoryInformation.cmake b/CMakeFiles/CMakeDirectoryInformation.cmake
new file mode 100644
index 0000000..aef4d6c
--- /dev/null
+++ b/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/CMakeFiles/CMakeError.log b/CMakeFiles/CMakeError.log
new file mode 100644
index 0000000..315c376
--- /dev/null
+++ b/CMakeFiles/CMakeError.log
@@ -0,0 +1,98 @@
+Determining if the function fseek64 exists failed with the following output:
+Change Dir: /home/calvin/src/xpdf-4.04/CMakeFiles/CMakeTmp
+
+Run Build Command(s):/usr/bin/gmake cmTC_ba6dd/fast && /usr/bin/gmake -f CMakeFiles/cmTC_ba6dd.dir/build.make CMakeFiles/cmTC_ba6dd.dir/build
+gmake[1]: Entering directory '/home/calvin/src/xpdf-4.04/CMakeFiles/CMakeTmp'
+Building C object CMakeFiles/cmTC_ba6dd.dir/CheckFunctionExists.c.o
+/usr/bin/cc -DCHECK_FUNCTION_EXISTS=fseek64 -o CMakeFiles/cmTC_ba6dd.dir/CheckFunctionExists.c.o -c /usr/share/cmake-3.18/Modules/CheckFunctionExists.c
+Linking C executable cmTC_ba6dd
+/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTC_ba6dd.dir/link.txt --verbose=1
+/usr/bin/cc -DCHECK_FUNCTION_EXISTS=fseek64 -rdynamic CMakeFiles/cmTC_ba6dd.dir/CheckFunctionExists.c.o -o cmTC_ba6dd
+/usr/bin/ld: CMakeFiles/cmTC_ba6dd.dir/CheckFunctionExists.c.o: in function `main':
+CheckFunctionExists.c:(.text+0x10): undefined reference to `fseek64'
+collect2: error: ld returned 1 exit status
+gmake[1]: *** [CMakeFiles/cmTC_ba6dd.dir/build.make:106: cmTC_ba6dd] Error 1
+gmake[1]: Leaving directory '/home/calvin/src/xpdf-4.04/CMakeFiles/CMakeTmp'
+gmake: *** [Makefile:140: cmTC_ba6dd/fast] Error 2
+
+
+
+Determining if the function _fseeki64 exists failed with the following output:
+Change Dir: /home/calvin/src/xpdf-4.04/CMakeFiles/CMakeTmp
+
+Run Build Command(s):/usr/bin/gmake cmTC_3dc46/fast && /usr/bin/gmake -f CMakeFiles/cmTC_3dc46.dir/build.make CMakeFiles/cmTC_3dc46.dir/build
+gmake[1]: Entering directory '/home/calvin/src/xpdf-4.04/CMakeFiles/CMakeTmp'
+Building C object CMakeFiles/cmTC_3dc46.dir/CheckFunctionExists.c.o
+/usr/bin/cc -DCHECK_FUNCTION_EXISTS=_fseeki64 -o CMakeFiles/cmTC_3dc46.dir/CheckFunctionExists.c.o -c /usr/share/cmake-3.18/Modules/CheckFunctionExists.c
+Linking C executable cmTC_3dc46
+/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTC_3dc46.dir/link.txt --verbose=1
+/usr/bin/cc -DCHECK_FUNCTION_EXISTS=_fseeki64 -rdynamic CMakeFiles/cmTC_3dc46.dir/CheckFunctionExists.c.o -o cmTC_3dc46
+/usr/bin/ld: CMakeFiles/cmTC_3dc46.dir/CheckFunctionExists.c.o: in function `main':
+CheckFunctionExists.c:(.text+0x10): undefined reference to `_fseeki64'
+collect2: error: ld returned 1 exit status
+gmake[1]: *** [CMakeFiles/cmTC_3dc46.dir/build.make:106: cmTC_3dc46] Error 1
+gmake[1]: Leaving directory '/home/calvin/src/xpdf-4.04/CMakeFiles/CMakeTmp'
+gmake: *** [Makefile:140: cmTC_3dc46/fast] Error 2
+
+
+
+Performing C SOURCE FILE Test CMAKE_HAVE_LIBC_PTHREAD failed with the following output:
+Change Dir: /home/calvin/src/xpdf-4.04/CMakeFiles/CMakeTmp
+
+Run Build Command(s):/usr/bin/gmake cmTC_f5f4f/fast && /usr/bin/gmake -f CMakeFiles/cmTC_f5f4f.dir/build.make CMakeFiles/cmTC_f5f4f.dir/build
+gmake[1]: Entering directory '/home/calvin/src/xpdf-4.04/CMakeFiles/CMakeTmp'
+Building C object CMakeFiles/cmTC_f5f4f.dir/src.c.o
+/usr/bin/cc -DCMAKE_HAVE_LIBC_PTHREAD -o CMakeFiles/cmTC_f5f4f.dir/src.c.o -c /home/calvin/src/xpdf-4.04/CMakeFiles/CMakeTmp/src.c
+Linking C executable cmTC_f5f4f
+/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTC_f5f4f.dir/link.txt --verbose=1
+/usr/bin/cc -DCMAKE_HAVE_LIBC_PTHREAD -rdynamic CMakeFiles/cmTC_f5f4f.dir/src.c.o -o cmTC_f5f4f
+/usr/bin/ld: CMakeFiles/cmTC_f5f4f.dir/src.c.o: in function `main':
+src.c:(.text+0x2f): undefined reference to `pthread_create'
+/usr/bin/ld: src.c:(.text+0x3b): undefined reference to `pthread_detach'
+/usr/bin/ld: src.c:(.text+0x47): undefined reference to `pthread_cancel'
+/usr/bin/ld: src.c:(.text+0x58): undefined reference to `pthread_join'
+collect2: error: ld returned 1 exit status
+gmake[1]: *** [CMakeFiles/cmTC_f5f4f.dir/build.make:106: cmTC_f5f4f] Error 1
+gmake[1]: Leaving directory '/home/calvin/src/xpdf-4.04/CMakeFiles/CMakeTmp'
+gmake: *** [Makefile:140: cmTC_f5f4f/fast] Error 2
+
+
+Source file was:
+#include <pthread.h>
+
+void* test_func(void* data)
+{
+ return data;
+}
+
+int main(void)
+{
+ pthread_t thread;
+ pthread_create(&thread, NULL, test_func, NULL);
+ pthread_detach(thread);
+ pthread_cancel(thread);
+ pthread_join(thread, NULL);
+ pthread_atfork(NULL, NULL, NULL);
+ pthread_exit(NULL);
+
+ return 0;
+}
+
+Determining if the function pthread_create exists in the pthreads failed with the following output:
+Change Dir: /home/calvin/src/xpdf-4.04/CMakeFiles/CMakeTmp
+
+Run Build Command(s):/usr/bin/gmake cmTC_08e5e/fast && /usr/bin/gmake -f CMakeFiles/cmTC_08e5e.dir/build.make CMakeFiles/cmTC_08e5e.dir/build
+gmake[1]: Entering directory '/home/calvin/src/xpdf-4.04/CMakeFiles/CMakeTmp'
+Building C object CMakeFiles/cmTC_08e5e.dir/CheckFunctionExists.c.o
+/usr/bin/cc -DCHECK_FUNCTION_EXISTS=pthread_create -o CMakeFiles/cmTC_08e5e.dir/CheckFunctionExists.c.o -c /usr/share/cmake-3.18/Modules/CheckFunctionExists.c
+Linking C executable cmTC_08e5e
+/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTC_08e5e.dir/link.txt --verbose=1
+/usr/bin/cc -DCHECK_FUNCTION_EXISTS=pthread_create -rdynamic CMakeFiles/cmTC_08e5e.dir/CheckFunctionExists.c.o -o cmTC_08e5e -lpthreads
+/usr/bin/ld: cannot find -lpthreads
+collect2: error: ld returned 1 exit status
+gmake[1]: *** [CMakeFiles/cmTC_08e5e.dir/build.make:106: cmTC_08e5e] Error 1
+gmake[1]: Leaving directory '/home/calvin/src/xpdf-4.04/CMakeFiles/CMakeTmp'
+gmake: *** [Makefile:140: cmTC_08e5e/fast] Error 2
+
+
+
diff --git a/CMakeFiles/CMakeOutput.log b/CMakeFiles/CMakeOutput.log
new file mode 100644
index 0000000..0709cc2
--- /dev/null
+++ b/CMakeFiles/CMakeOutput.log
@@ -0,0 +1,541 @@
+The system is: Linux - 5.10.0-12-amd64 - x86_64
+Compiling the C compiler identification source file "CMakeCCompilerId.c" succeeded.
+Compiler: /usr/bin/cc
+Build flags:
+Id flags:
+
+The output was:
+0
+
+
+Compilation of the C compiler identification source "CMakeCCompilerId.c" produced "a.out"
+
+The C compiler identification is GNU, found in "/home/calvin/src/xpdf-4.04/CMakeFiles/3.18.4/CompilerIdC/a.out"
+
+Compiling the CXX compiler identification source file "CMakeCXXCompilerId.cpp" succeeded.
+Compiler: /usr/bin/c++
+Build flags:
+Id flags:
+
+The output was:
+0
+
+
+Compilation of the CXX compiler identification source "CMakeCXXCompilerId.cpp" produced "a.out"
+
+The CXX compiler identification is GNU, found in "/home/calvin/src/xpdf-4.04/CMakeFiles/3.18.4/CompilerIdCXX/a.out"
+
+Detecting C compiler ABI info compiled with the following output:
+Change Dir: /home/calvin/src/xpdf-4.04/CMakeFiles/CMakeTmp
+
+Run Build Command(s):/usr/bin/gmake cmTC_16b2f/fast && /usr/bin/gmake -f CMakeFiles/cmTC_16b2f.dir/build.make CMakeFiles/cmTC_16b2f.dir/build
+gmake[1]: Entering directory '/home/calvin/src/xpdf-4.04/CMakeFiles/CMakeTmp'
+Building C object CMakeFiles/cmTC_16b2f.dir/CMakeCCompilerABI.c.o
+/usr/bin/cc -v -o CMakeFiles/cmTC_16b2f.dir/CMakeCCompilerABI.c.o -c /usr/share/cmake-3.18/Modules/CMakeCCompilerABI.c
+Using built-in specs.
+COLLECT_GCC=/usr/bin/cc
+OFFLOAD_TARGET_NAMES=nvptx-none:amdgcn-amdhsa:hsa
+OFFLOAD_TARGET_DEFAULT=1
+Target: x86_64-linux-gnu
+Configured with: ../src/configure -v --with-pkgversion='Debian 10.2.1-6' --with-bugurl=file:///usr/share/doc/gcc-10/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++,m2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-10 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --enable-libphobos-checking=release --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-10-Km9U7s/gcc-10-10.2.1/debian/tmp-nvptx/usr,amdgcn-amdhsa=/build/gcc-10-Km9U7s/gcc-10-10.2.1/debian/tmp-gcn/usr,hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu --with-build-config=bootstrap-lto-lean --enable-link-mutex
+Thread model: posix
+Supported LTO compression algorithms: zlib zstd
+gcc version 10.2.1 20210110 (Debian 10.2.1-6)
+COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_16b2f.dir/CMakeCCompilerABI.c.o' '-c' '-mtune=generic' '-march=x86-64'
+ /usr/lib/gcc/x86_64-linux-gnu/10/cc1 -quiet -v -imultiarch x86_64-linux-gnu /usr/share/cmake-3.18/Modules/CMakeCCompilerABI.c -quiet -dumpbase CMakeCCompilerABI.c -mtune=generic -march=x86-64 -auxbase-strip CMakeFiles/cmTC_16b2f.dir/CMakeCCompilerABI.c.o -version -fasynchronous-unwind-tables -o /tmp/ccHaut54.s
+GNU C17 (Debian 10.2.1-6) version 10.2.1 20210110 (x86_64-linux-gnu)
+ compiled by GNU C version 10.2.1 20210110, GMP version 6.2.1, MPFR version 4.1.0, MPC version 1.2.0, isl version isl-0.23-GMP
+
+GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
+ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu"
+ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/10/include-fixed"
+ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/10/../../../../x86_64-linux-gnu/include"
+#include "..." search starts here:
+#include <...> search starts here:
+ /usr/lib/gcc/x86_64-linux-gnu/10/include
+ /usr/local/include
+ /usr/include/x86_64-linux-gnu
+ /usr/include
+End of search list.
+GNU C17 (Debian 10.2.1-6) version 10.2.1 20210110 (x86_64-linux-gnu)
+ compiled by GNU C version 10.2.1 20210110, GMP version 6.2.1, MPFR version 4.1.0, MPC version 1.2.0, isl version isl-0.23-GMP
+
+GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
+Compiler executable checksum: 1f803793fa2e3418c492b25e7d3eac2f
+COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_16b2f.dir/CMakeCCompilerABI.c.o' '-c' '-mtune=generic' '-march=x86-64'
+ as -v --64 -o CMakeFiles/cmTC_16b2f.dir/CMakeCCompilerABI.c.o /tmp/ccHaut54.s
+GNU assembler version 2.35.2 (x86_64-linux-gnu) using BFD version (GNU Binutils for Debian) 2.35.2
+COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/
+LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../:/lib/:/usr/lib/
+COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_16b2f.dir/CMakeCCompilerABI.c.o' '-c' '-mtune=generic' '-march=x86-64'
+Linking C executable cmTC_16b2f
+/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTC_16b2f.dir/link.txt --verbose=1
+/usr/bin/cc -v -rdynamic CMakeFiles/cmTC_16b2f.dir/CMakeCCompilerABI.c.o -o cmTC_16b2f
+Using built-in specs.
+COLLECT_GCC=/usr/bin/cc
+COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/10/lto-wrapper
+OFFLOAD_TARGET_NAMES=nvptx-none:amdgcn-amdhsa:hsa
+OFFLOAD_TARGET_DEFAULT=1
+Target: x86_64-linux-gnu
+Configured with: ../src/configure -v --with-pkgversion='Debian 10.2.1-6' --with-bugurl=file:///usr/share/doc/gcc-10/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++,m2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-10 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --enable-libphobos-checking=release --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-10-Km9U7s/gcc-10-10.2.1/debian/tmp-nvptx/usr,amdgcn-amdhsa=/build/gcc-10-Km9U7s/gcc-10-10.2.1/debian/tmp-gcn/usr,hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu --with-build-config=bootstrap-lto-lean --enable-link-mutex
+Thread model: posix
+Supported LTO compression algorithms: zlib zstd
+gcc version 10.2.1 20210110 (Debian 10.2.1-6)
+COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/
+LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../:/lib/:/usr/lib/
+COLLECT_GCC_OPTIONS='-v' '-rdynamic' '-o' 'cmTC_16b2f' '-mtune=generic' '-march=x86-64'
+ /usr/lib/gcc/x86_64-linux-gnu/10/collect2 -plugin /usr/lib/gcc/x86_64-linux-gnu/10/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/10/lto-wrapper -plugin-opt=-fresolution=/tmp/ccKfcSiw.res -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed -export-dynamic -dynamic-linker /lib64/ld-linux-x86-64.so.2 -pie -o cmTC_16b2f /usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/Scrt1.o /usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/10/crtbeginS.o -L/usr/lib/gcc/x86_64-linux-gnu/10 -L/usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/10/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/10/../../.. CMakeFiles/cmTC_16b2f.dir/CMakeCCompilerABI.c.o -lgcc --push-state --as-needed -lgcc_s --pop-state -lc -lgcc --push-state --as-needed -lgcc_s --pop-state /usr/lib/gcc/x86_64-linux-gnu/10/crtendS.o /usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/crtn.o
+COLLECT_GCC_OPTIONS='-v' '-rdynamic' '-o' 'cmTC_16b2f' '-mtune=generic' '-march=x86-64'
+gmake[1]: Leaving directory '/home/calvin/src/xpdf-4.04/CMakeFiles/CMakeTmp'
+
+
+
+Parsed C implicit include dir info from above output: rv=done
+ found start of include info
+ found start of implicit include info
+ add: [/usr/lib/gcc/x86_64-linux-gnu/10/include]
+ add: [/usr/local/include]
+ add: [/usr/include/x86_64-linux-gnu]
+ add: [/usr/include]
+ end of search list found
+ collapse include dir [/usr/lib/gcc/x86_64-linux-gnu/10/include] ==> [/usr/lib/gcc/x86_64-linux-gnu/10/include]
+ collapse include dir [/usr/local/include] ==> [/usr/local/include]
+ collapse include dir [/usr/include/x86_64-linux-gnu] ==> [/usr/include/x86_64-linux-gnu]
+ collapse include dir [/usr/include] ==> [/usr/include]
+ implicit include dirs: [/usr/lib/gcc/x86_64-linux-gnu/10/include;/usr/local/include;/usr/include/x86_64-linux-gnu;/usr/include]
+
+
+Parsed C implicit link information from above output:
+ link line regex: [^( *|.*[/\])(ld|CMAKE_LINK_STARTFILE-NOTFOUND|([^/\]+-)?ld|collect2)[^/\]*( |$)]
+ ignore line: [Change Dir: /home/calvin/src/xpdf-4.04/CMakeFiles/CMakeTmp]
+ ignore line: []
+ ignore line: [Run Build Command(s):/usr/bin/gmake cmTC_16b2f/fast && /usr/bin/gmake -f CMakeFiles/cmTC_16b2f.dir/build.make CMakeFiles/cmTC_16b2f.dir/build]
+ ignore line: [gmake[1]: Entering directory '/home/calvin/src/xpdf-4.04/CMakeFiles/CMakeTmp']
+ ignore line: [Building C object CMakeFiles/cmTC_16b2f.dir/CMakeCCompilerABI.c.o]
+ ignore line: [/usr/bin/cc -v -o CMakeFiles/cmTC_16b2f.dir/CMakeCCompilerABI.c.o -c /usr/share/cmake-3.18/Modules/CMakeCCompilerABI.c]
+ ignore line: [Using built-in specs.]
+ ignore line: [COLLECT_GCC=/usr/bin/cc]
+ ignore line: [OFFLOAD_TARGET_NAMES=nvptx-none:amdgcn-amdhsa:hsa]
+ ignore line: [OFFLOAD_TARGET_DEFAULT=1]
+ ignore line: [Target: x86_64-linux-gnu]
+ ignore line: [Configured with: ../src/configure -v --with-pkgversion='Debian 10.2.1-6' --with-bugurl=file:///usr/share/doc/gcc-10/README.Bugs --enable-languages=c ada c++ go brig d fortran objc obj-c++ m2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-10 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --enable-libphobos-checking=release --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32 m64 mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-10-Km9U7s/gcc-10-10.2.1/debian/tmp-nvptx/usr amdgcn-amdhsa=/build/gcc-10-Km9U7s/gcc-10-10.2.1/debian/tmp-gcn/usr hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu --with-build-config=bootstrap-lto-lean --enable-link-mutex]
+ ignore line: [Thread model: posix]
+ ignore line: [Supported LTO compression algorithms: zlib zstd]
+ ignore line: [gcc version 10.2.1 20210110 (Debian 10.2.1-6) ]
+ ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_16b2f.dir/CMakeCCompilerABI.c.o' '-c' '-mtune=generic' '-march=x86-64']
+ ignore line: [ /usr/lib/gcc/x86_64-linux-gnu/10/cc1 -quiet -v -imultiarch x86_64-linux-gnu /usr/share/cmake-3.18/Modules/CMakeCCompilerABI.c -quiet -dumpbase CMakeCCompilerABI.c -mtune=generic -march=x86-64 -auxbase-strip CMakeFiles/cmTC_16b2f.dir/CMakeCCompilerABI.c.o -version -fasynchronous-unwind-tables -o /tmp/ccHaut54.s]
+ ignore line: [GNU C17 (Debian 10.2.1-6) version 10.2.1 20210110 (x86_64-linux-gnu)]
+ ignore line: [ compiled by GNU C version 10.2.1 20210110 GMP version 6.2.1 MPFR version 4.1.0 MPC version 1.2.0 isl version isl-0.23-GMP]
+ ignore line: []
+ ignore line: [GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072]
+ ignore line: [ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu"]
+ ignore line: [ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/10/include-fixed"]
+ ignore line: [ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/10/../../../../x86_64-linux-gnu/include"]
+ ignore line: [#include "..." search starts here:]
+ ignore line: [#include <...> search starts here:]
+ ignore line: [ /usr/lib/gcc/x86_64-linux-gnu/10/include]
+ ignore line: [ /usr/local/include]
+ ignore line: [ /usr/include/x86_64-linux-gnu]
+ ignore line: [ /usr/include]
+ ignore line: [End of search list.]
+ ignore line: [GNU C17 (Debian 10.2.1-6) version 10.2.1 20210110 (x86_64-linux-gnu)]
+ ignore line: [ compiled by GNU C version 10.2.1 20210110 GMP version 6.2.1 MPFR version 4.1.0 MPC version 1.2.0 isl version isl-0.23-GMP]
+ ignore line: []
+ ignore line: [GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072]
+ ignore line: [Compiler executable checksum: 1f803793fa2e3418c492b25e7d3eac2f]
+ ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_16b2f.dir/CMakeCCompilerABI.c.o' '-c' '-mtune=generic' '-march=x86-64']
+ ignore line: [ as -v --64 -o CMakeFiles/cmTC_16b2f.dir/CMakeCCompilerABI.c.o /tmp/ccHaut54.s]
+ ignore line: [GNU assembler version 2.35.2 (x86_64-linux-gnu) using BFD version (GNU Binutils for Debian) 2.35.2]
+ ignore line: [COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/]
+ ignore line: [LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../:/lib/:/usr/lib/]
+ ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_16b2f.dir/CMakeCCompilerABI.c.o' '-c' '-mtune=generic' '-march=x86-64']
+ ignore line: [Linking C executable cmTC_16b2f]
+ ignore line: [/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTC_16b2f.dir/link.txt --verbose=1]
+ ignore line: [/usr/bin/cc -v -rdynamic CMakeFiles/cmTC_16b2f.dir/CMakeCCompilerABI.c.o -o cmTC_16b2f ]
+ ignore line: [Using built-in specs.]
+ ignore line: [COLLECT_GCC=/usr/bin/cc]
+ ignore line: [COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/10/lto-wrapper]
+ ignore line: [OFFLOAD_TARGET_NAMES=nvptx-none:amdgcn-amdhsa:hsa]
+ ignore line: [OFFLOAD_TARGET_DEFAULT=1]
+ ignore line: [Target: x86_64-linux-gnu]
+ ignore line: [Configured with: ../src/configure -v --with-pkgversion='Debian 10.2.1-6' --with-bugurl=file:///usr/share/doc/gcc-10/README.Bugs --enable-languages=c ada c++ go brig d fortran objc obj-c++ m2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-10 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --enable-libphobos-checking=release --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32 m64 mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-10-Km9U7s/gcc-10-10.2.1/debian/tmp-nvptx/usr amdgcn-amdhsa=/build/gcc-10-Km9U7s/gcc-10-10.2.1/debian/tmp-gcn/usr hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu --with-build-config=bootstrap-lto-lean --enable-link-mutex]
+ ignore line: [Thread model: posix]
+ ignore line: [Supported LTO compression algorithms: zlib zstd]
+ ignore line: [gcc version 10.2.1 20210110 (Debian 10.2.1-6) ]
+ ignore line: [COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/]
+ ignore line: [LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../:/lib/:/usr/lib/]
+ ignore line: [COLLECT_GCC_OPTIONS='-v' '-rdynamic' '-o' 'cmTC_16b2f' '-mtune=generic' '-march=x86-64']
+ link line: [ /usr/lib/gcc/x86_64-linux-gnu/10/collect2 -plugin /usr/lib/gcc/x86_64-linux-gnu/10/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/10/lto-wrapper -plugin-opt=-fresolution=/tmp/ccKfcSiw.res -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed -export-dynamic -dynamic-linker /lib64/ld-linux-x86-64.so.2 -pie -o cmTC_16b2f /usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/Scrt1.o /usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/10/crtbeginS.o -L/usr/lib/gcc/x86_64-linux-gnu/10 -L/usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/10/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/10/../../.. CMakeFiles/cmTC_16b2f.dir/CMakeCCompilerABI.c.o -lgcc --push-state --as-needed -lgcc_s --pop-state -lc -lgcc --push-state --as-needed -lgcc_s --pop-state /usr/lib/gcc/x86_64-linux-gnu/10/crtendS.o /usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/crtn.o]
+ arg [/usr/lib/gcc/x86_64-linux-gnu/10/collect2] ==> ignore
+ arg [-plugin] ==> ignore
+ arg [/usr/lib/gcc/x86_64-linux-gnu/10/liblto_plugin.so] ==> ignore
+ arg [-plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/10/lto-wrapper] ==> ignore
+ arg [-plugin-opt=-fresolution=/tmp/ccKfcSiw.res] ==> ignore
+ arg [-plugin-opt=-pass-through=-lgcc] ==> ignore
+ arg [-plugin-opt=-pass-through=-lgcc_s] ==> ignore
+ arg [-plugin-opt=-pass-through=-lc] ==> ignore
+ arg [-plugin-opt=-pass-through=-lgcc] ==> ignore
+ arg [-plugin-opt=-pass-through=-lgcc_s] ==> ignore
+ arg [--build-id] ==> ignore
+ arg [--eh-frame-hdr] ==> ignore
+ arg [-m] ==> ignore
+ arg [elf_x86_64] ==> ignore
+ arg [--hash-style=gnu] ==> ignore
+ arg [--as-needed] ==> ignore
+ arg [-export-dynamic] ==> ignore
+ arg [-dynamic-linker] ==> ignore
+ arg [/lib64/ld-linux-x86-64.so.2] ==> ignore
+ arg [-pie] ==> ignore
+ arg [-o] ==> ignore
+ arg [cmTC_16b2f] ==> ignore
+ arg [/usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/Scrt1.o] ==> ignore
+ arg [/usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/crti.o] ==> ignore
+ arg [/usr/lib/gcc/x86_64-linux-gnu/10/crtbeginS.o] ==> ignore
+ arg [-L/usr/lib/gcc/x86_64-linux-gnu/10] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/10]
+ arg [-L/usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu]
+ arg [-L/usr/lib/gcc/x86_64-linux-gnu/10/../../../../lib] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/10/../../../../lib]
+ arg [-L/lib/x86_64-linux-gnu] ==> dir [/lib/x86_64-linux-gnu]
+ arg [-L/lib/../lib] ==> dir [/lib/../lib]
+ arg [-L/usr/lib/x86_64-linux-gnu] ==> dir [/usr/lib/x86_64-linux-gnu]
+ arg [-L/usr/lib/../lib] ==> dir [/usr/lib/../lib]
+ arg [-L/usr/lib/gcc/x86_64-linux-gnu/10/../../..] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/10/../../..]
+ arg [CMakeFiles/cmTC_16b2f.dir/CMakeCCompilerABI.c.o] ==> ignore
+ arg [-lgcc] ==> lib [gcc]
+ arg [--push-state] ==> ignore
+ arg [--as-needed] ==> ignore
+ arg [-lgcc_s] ==> lib [gcc_s]
+ arg [--pop-state] ==> ignore
+ arg [-lc] ==> lib [c]
+ arg [-lgcc] ==> lib [gcc]
+ arg [--push-state] ==> ignore
+ arg [--as-needed] ==> ignore
+ arg [-lgcc_s] ==> lib [gcc_s]
+ arg [--pop-state] ==> ignore
+ arg [/usr/lib/gcc/x86_64-linux-gnu/10/crtendS.o] ==> ignore
+ arg [/usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/crtn.o] ==> ignore
+ collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/10] ==> [/usr/lib/gcc/x86_64-linux-gnu/10]
+ collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu] ==> [/usr/lib/x86_64-linux-gnu]
+ collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/10/../../../../lib] ==> [/usr/lib]
+ collapse library dir [/lib/x86_64-linux-gnu] ==> [/lib/x86_64-linux-gnu]
+ collapse library dir [/lib/../lib] ==> [/lib]
+ collapse library dir [/usr/lib/x86_64-linux-gnu] ==> [/usr/lib/x86_64-linux-gnu]
+ collapse library dir [/usr/lib/../lib] ==> [/usr/lib]
+ collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/10/../../..] ==> [/usr/lib]
+ implicit libs: [gcc;gcc_s;c;gcc;gcc_s]
+ implicit dirs: [/usr/lib/gcc/x86_64-linux-gnu/10;/usr/lib/x86_64-linux-gnu;/usr/lib;/lib/x86_64-linux-gnu;/lib]
+ implicit fwks: []
+
+
+Detecting CXX compiler ABI info compiled with the following output:
+Change Dir: /home/calvin/src/xpdf-4.04/CMakeFiles/CMakeTmp
+
+Run Build Command(s):/usr/bin/gmake cmTC_fc2a8/fast && /usr/bin/gmake -f CMakeFiles/cmTC_fc2a8.dir/build.make CMakeFiles/cmTC_fc2a8.dir/build
+gmake[1]: Entering directory '/home/calvin/src/xpdf-4.04/CMakeFiles/CMakeTmp'
+Building CXX object CMakeFiles/cmTC_fc2a8.dir/CMakeCXXCompilerABI.cpp.o
+/usr/bin/c++ -v -o CMakeFiles/cmTC_fc2a8.dir/CMakeCXXCompilerABI.cpp.o -c /usr/share/cmake-3.18/Modules/CMakeCXXCompilerABI.cpp
+Using built-in specs.
+COLLECT_GCC=/usr/bin/c++
+OFFLOAD_TARGET_NAMES=nvptx-none:amdgcn-amdhsa:hsa
+OFFLOAD_TARGET_DEFAULT=1
+Target: x86_64-linux-gnu
+Configured with: ../src/configure -v --with-pkgversion='Debian 10.2.1-6' --with-bugurl=file:///usr/share/doc/gcc-10/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++,m2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-10 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --enable-libphobos-checking=release --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-10-Km9U7s/gcc-10-10.2.1/debian/tmp-nvptx/usr,amdgcn-amdhsa=/build/gcc-10-Km9U7s/gcc-10-10.2.1/debian/tmp-gcn/usr,hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu --with-build-config=bootstrap-lto-lean --enable-link-mutex
+Thread model: posix
+Supported LTO compression algorithms: zlib zstd
+gcc version 10.2.1 20210110 (Debian 10.2.1-6)
+COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_fc2a8.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64'
+ /usr/lib/gcc/x86_64-linux-gnu/10/cc1plus -quiet -v -imultiarch x86_64-linux-gnu -D_GNU_SOURCE /usr/share/cmake-3.18/Modules/CMakeCXXCompilerABI.cpp -quiet -dumpbase CMakeCXXCompilerABI.cpp -mtune=generic -march=x86-64 -auxbase-strip CMakeFiles/cmTC_fc2a8.dir/CMakeCXXCompilerABI.cpp.o -version -fasynchronous-unwind-tables -o /tmp/ccHQUrx0.s
+GNU C++14 (Debian 10.2.1-6) version 10.2.1 20210110 (x86_64-linux-gnu)
+ compiled by GNU C version 10.2.1 20210110, GMP version 6.2.1, MPFR version 4.1.0, MPC version 1.2.0, isl version isl-0.23-GMP
+
+GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
+ignoring duplicate directory "/usr/include/x86_64-linux-gnu/c++/10"
+ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu"
+ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/10/include-fixed"
+ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/10/../../../../x86_64-linux-gnu/include"
+#include "..." search starts here:
+#include <...> search starts here:
+ /usr/include/c++/10
+ /usr/include/x86_64-linux-gnu/c++/10
+ /usr/include/c++/10/backward
+ /usr/lib/gcc/x86_64-linux-gnu/10/include
+ /usr/local/include
+ /usr/include/x86_64-linux-gnu
+ /usr/include
+End of search list.
+GNU C++14 (Debian 10.2.1-6) version 10.2.1 20210110 (x86_64-linux-gnu)
+ compiled by GNU C version 10.2.1 20210110, GMP version 6.2.1, MPFR version 4.1.0, MPC version 1.2.0, isl version isl-0.23-GMP
+
+GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
+Compiler executable checksum: 048fcaee3460a99eb0d68522358720e1
+COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_fc2a8.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64'
+ as -v --64 -o CMakeFiles/cmTC_fc2a8.dir/CMakeCXXCompilerABI.cpp.o /tmp/ccHQUrx0.s
+GNU assembler version 2.35.2 (x86_64-linux-gnu) using BFD version (GNU Binutils for Debian) 2.35.2
+COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/
+LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../:/lib/:/usr/lib/
+COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_fc2a8.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64'
+Linking CXX executable cmTC_fc2a8
+/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTC_fc2a8.dir/link.txt --verbose=1
+/usr/bin/c++ -v -rdynamic CMakeFiles/cmTC_fc2a8.dir/CMakeCXXCompilerABI.cpp.o -o cmTC_fc2a8
+Using built-in specs.
+COLLECT_GCC=/usr/bin/c++
+COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/10/lto-wrapper
+OFFLOAD_TARGET_NAMES=nvptx-none:amdgcn-amdhsa:hsa
+OFFLOAD_TARGET_DEFAULT=1
+Target: x86_64-linux-gnu
+Configured with: ../src/configure -v --with-pkgversion='Debian 10.2.1-6' --with-bugurl=file:///usr/share/doc/gcc-10/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++,m2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-10 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --enable-libphobos-checking=release --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-10-Km9U7s/gcc-10-10.2.1/debian/tmp-nvptx/usr,amdgcn-amdhsa=/build/gcc-10-Km9U7s/gcc-10-10.2.1/debian/tmp-gcn/usr,hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu --with-build-config=bootstrap-lto-lean --enable-link-mutex
+Thread model: posix
+Supported LTO compression algorithms: zlib zstd
+gcc version 10.2.1 20210110 (Debian 10.2.1-6)
+COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/
+LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../:/lib/:/usr/lib/
+COLLECT_GCC_OPTIONS='-v' '-rdynamic' '-o' 'cmTC_fc2a8' '-shared-libgcc' '-mtune=generic' '-march=x86-64'
+ /usr/lib/gcc/x86_64-linux-gnu/10/collect2 -plugin /usr/lib/gcc/x86_64-linux-gnu/10/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/10/lto-wrapper -plugin-opt=-fresolution=/tmp/cci3ypYu.res -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed -export-dynamic -dynamic-linker /lib64/ld-linux-x86-64.so.2 -pie -o cmTC_fc2a8 /usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/Scrt1.o /usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/10/crtbeginS.o -L/usr/lib/gcc/x86_64-linux-gnu/10 -L/usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/10/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/10/../../.. CMakeFiles/cmTC_fc2a8.dir/CMakeCXXCompilerABI.cpp.o -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /usr/lib/gcc/x86_64-linux-gnu/10/crtendS.o /usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/crtn.o
+COLLECT_GCC_OPTIONS='-v' '-rdynamic' '-o' 'cmTC_fc2a8' '-shared-libgcc' '-mtune=generic' '-march=x86-64'
+gmake[1]: Leaving directory '/home/calvin/src/xpdf-4.04/CMakeFiles/CMakeTmp'
+
+
+
+Parsed CXX implicit include dir info from above output: rv=done
+ found start of include info
+ found start of implicit include info
+ add: [/usr/include/c++/10]
+ add: [/usr/include/x86_64-linux-gnu/c++/10]
+ add: [/usr/include/c++/10/backward]
+ add: [/usr/lib/gcc/x86_64-linux-gnu/10/include]
+ add: [/usr/local/include]
+ add: [/usr/include/x86_64-linux-gnu]
+ add: [/usr/include]
+ end of search list found
+ collapse include dir [/usr/include/c++/10] ==> [/usr/include/c++/10]
+ collapse include dir [/usr/include/x86_64-linux-gnu/c++/10] ==> [/usr/include/x86_64-linux-gnu/c++/10]
+ collapse include dir [/usr/include/c++/10/backward] ==> [/usr/include/c++/10/backward]
+ collapse include dir [/usr/lib/gcc/x86_64-linux-gnu/10/include] ==> [/usr/lib/gcc/x86_64-linux-gnu/10/include]
+ collapse include dir [/usr/local/include] ==> [/usr/local/include]
+ collapse include dir [/usr/include/x86_64-linux-gnu] ==> [/usr/include/x86_64-linux-gnu]
+ collapse include dir [/usr/include] ==> [/usr/include]
+ implicit include dirs: [/usr/include/c++/10;/usr/include/x86_64-linux-gnu/c++/10;/usr/include/c++/10/backward;/usr/lib/gcc/x86_64-linux-gnu/10/include;/usr/local/include;/usr/include/x86_64-linux-gnu;/usr/include]
+
+
+Parsed CXX implicit link information from above output:
+ link line regex: [^( *|.*[/\])(ld|CMAKE_LINK_STARTFILE-NOTFOUND|([^/\]+-)?ld|collect2)[^/\]*( |$)]
+ ignore line: [Change Dir: /home/calvin/src/xpdf-4.04/CMakeFiles/CMakeTmp]
+ ignore line: []
+ ignore line: [Run Build Command(s):/usr/bin/gmake cmTC_fc2a8/fast && /usr/bin/gmake -f CMakeFiles/cmTC_fc2a8.dir/build.make CMakeFiles/cmTC_fc2a8.dir/build]
+ ignore line: [gmake[1]: Entering directory '/home/calvin/src/xpdf-4.04/CMakeFiles/CMakeTmp']
+ ignore line: [Building CXX object CMakeFiles/cmTC_fc2a8.dir/CMakeCXXCompilerABI.cpp.o]
+ ignore line: [/usr/bin/c++ -v -o CMakeFiles/cmTC_fc2a8.dir/CMakeCXXCompilerABI.cpp.o -c /usr/share/cmake-3.18/Modules/CMakeCXXCompilerABI.cpp]
+ ignore line: [Using built-in specs.]
+ ignore line: [COLLECT_GCC=/usr/bin/c++]
+ ignore line: [OFFLOAD_TARGET_NAMES=nvptx-none:amdgcn-amdhsa:hsa]
+ ignore line: [OFFLOAD_TARGET_DEFAULT=1]
+ ignore line: [Target: x86_64-linux-gnu]
+ ignore line: [Configured with: ../src/configure -v --with-pkgversion='Debian 10.2.1-6' --with-bugurl=file:///usr/share/doc/gcc-10/README.Bugs --enable-languages=c ada c++ go brig d fortran objc obj-c++ m2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-10 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --enable-libphobos-checking=release --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32 m64 mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-10-Km9U7s/gcc-10-10.2.1/debian/tmp-nvptx/usr amdgcn-amdhsa=/build/gcc-10-Km9U7s/gcc-10-10.2.1/debian/tmp-gcn/usr hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu --with-build-config=bootstrap-lto-lean --enable-link-mutex]
+ ignore line: [Thread model: posix]
+ ignore line: [Supported LTO compression algorithms: zlib zstd]
+ ignore line: [gcc version 10.2.1 20210110 (Debian 10.2.1-6) ]
+ ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_fc2a8.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64']
+ ignore line: [ /usr/lib/gcc/x86_64-linux-gnu/10/cc1plus -quiet -v -imultiarch x86_64-linux-gnu -D_GNU_SOURCE /usr/share/cmake-3.18/Modules/CMakeCXXCompilerABI.cpp -quiet -dumpbase CMakeCXXCompilerABI.cpp -mtune=generic -march=x86-64 -auxbase-strip CMakeFiles/cmTC_fc2a8.dir/CMakeCXXCompilerABI.cpp.o -version -fasynchronous-unwind-tables -o /tmp/ccHQUrx0.s]
+ ignore line: [GNU C++14 (Debian 10.2.1-6) version 10.2.1 20210110 (x86_64-linux-gnu)]
+ ignore line: [ compiled by GNU C version 10.2.1 20210110 GMP version 6.2.1 MPFR version 4.1.0 MPC version 1.2.0 isl version isl-0.23-GMP]
+ ignore line: []
+ ignore line: [GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072]
+ ignore line: [ignoring duplicate directory "/usr/include/x86_64-linux-gnu/c++/10"]
+ ignore line: [ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu"]
+ ignore line: [ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/10/include-fixed"]
+ ignore line: [ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/10/../../../../x86_64-linux-gnu/include"]
+ ignore line: [#include "..." search starts here:]
+ ignore line: [#include <...> search starts here:]
+ ignore line: [ /usr/include/c++/10]
+ ignore line: [ /usr/include/x86_64-linux-gnu/c++/10]
+ ignore line: [ /usr/include/c++/10/backward]
+ ignore line: [ /usr/lib/gcc/x86_64-linux-gnu/10/include]
+ ignore line: [ /usr/local/include]
+ ignore line: [ /usr/include/x86_64-linux-gnu]
+ ignore line: [ /usr/include]
+ ignore line: [End of search list.]
+ ignore line: [GNU C++14 (Debian 10.2.1-6) version 10.2.1 20210110 (x86_64-linux-gnu)]
+ ignore line: [ compiled by GNU C version 10.2.1 20210110 GMP version 6.2.1 MPFR version 4.1.0 MPC version 1.2.0 isl version isl-0.23-GMP]
+ ignore line: []
+ ignore line: [GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072]
+ ignore line: [Compiler executable checksum: 048fcaee3460a99eb0d68522358720e1]
+ ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_fc2a8.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64']
+ ignore line: [ as -v --64 -o CMakeFiles/cmTC_fc2a8.dir/CMakeCXXCompilerABI.cpp.o /tmp/ccHQUrx0.s]
+ ignore line: [GNU assembler version 2.35.2 (x86_64-linux-gnu) using BFD version (GNU Binutils for Debian) 2.35.2]
+ ignore line: [COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/]
+ ignore line: [LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../:/lib/:/usr/lib/]
+ ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_fc2a8.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64']
+ ignore line: [Linking CXX executable cmTC_fc2a8]
+ ignore line: [/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTC_fc2a8.dir/link.txt --verbose=1]
+ ignore line: [/usr/bin/c++ -v -rdynamic CMakeFiles/cmTC_fc2a8.dir/CMakeCXXCompilerABI.cpp.o -o cmTC_fc2a8 ]
+ ignore line: [Using built-in specs.]
+ ignore line: [COLLECT_GCC=/usr/bin/c++]
+ ignore line: [COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/10/lto-wrapper]
+ ignore line: [OFFLOAD_TARGET_NAMES=nvptx-none:amdgcn-amdhsa:hsa]
+ ignore line: [OFFLOAD_TARGET_DEFAULT=1]
+ ignore line: [Target: x86_64-linux-gnu]
+ ignore line: [Configured with: ../src/configure -v --with-pkgversion='Debian 10.2.1-6' --with-bugurl=file:///usr/share/doc/gcc-10/README.Bugs --enable-languages=c ada c++ go brig d fortran objc obj-c++ m2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-10 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --enable-libphobos-checking=release --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32 m64 mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-10-Km9U7s/gcc-10-10.2.1/debian/tmp-nvptx/usr amdgcn-amdhsa=/build/gcc-10-Km9U7s/gcc-10-10.2.1/debian/tmp-gcn/usr hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu --with-build-config=bootstrap-lto-lean --enable-link-mutex]
+ ignore line: [Thread model: posix]
+ ignore line: [Supported LTO compression algorithms: zlib zstd]
+ ignore line: [gcc version 10.2.1 20210110 (Debian 10.2.1-6) ]
+ ignore line: [COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/]
+ ignore line: [LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../:/lib/:/usr/lib/]
+ ignore line: [COLLECT_GCC_OPTIONS='-v' '-rdynamic' '-o' 'cmTC_fc2a8' '-shared-libgcc' '-mtune=generic' '-march=x86-64']
+ link line: [ /usr/lib/gcc/x86_64-linux-gnu/10/collect2 -plugin /usr/lib/gcc/x86_64-linux-gnu/10/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/10/lto-wrapper -plugin-opt=-fresolution=/tmp/cci3ypYu.res -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed -export-dynamic -dynamic-linker /lib64/ld-linux-x86-64.so.2 -pie -o cmTC_fc2a8 /usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/Scrt1.o /usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/10/crtbeginS.o -L/usr/lib/gcc/x86_64-linux-gnu/10 -L/usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/10/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/10/../../.. CMakeFiles/cmTC_fc2a8.dir/CMakeCXXCompilerABI.cpp.o -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /usr/lib/gcc/x86_64-linux-gnu/10/crtendS.o /usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/crtn.o]
+ arg [/usr/lib/gcc/x86_64-linux-gnu/10/collect2] ==> ignore
+ arg [-plugin] ==> ignore
+ arg [/usr/lib/gcc/x86_64-linux-gnu/10/liblto_plugin.so] ==> ignore
+ arg [-plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/10/lto-wrapper] ==> ignore
+ arg [-plugin-opt=-fresolution=/tmp/cci3ypYu.res] ==> ignore
+ arg [-plugin-opt=-pass-through=-lgcc_s] ==> ignore
+ arg [-plugin-opt=-pass-through=-lgcc] ==> ignore
+ arg [-plugin-opt=-pass-through=-lc] ==> ignore
+ arg [-plugin-opt=-pass-through=-lgcc_s] ==> ignore
+ arg [-plugin-opt=-pass-through=-lgcc] ==> ignore
+ arg [--build-id] ==> ignore
+ arg [--eh-frame-hdr] ==> ignore
+ arg [-m] ==> ignore
+ arg [elf_x86_64] ==> ignore
+ arg [--hash-style=gnu] ==> ignore
+ arg [--as-needed] ==> ignore
+ arg [-export-dynamic] ==> ignore
+ arg [-dynamic-linker] ==> ignore
+ arg [/lib64/ld-linux-x86-64.so.2] ==> ignore
+ arg [-pie] ==> ignore
+ arg [-o] ==> ignore
+ arg [cmTC_fc2a8] ==> ignore
+ arg [/usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/Scrt1.o] ==> ignore
+ arg [/usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/crti.o] ==> ignore
+ arg [/usr/lib/gcc/x86_64-linux-gnu/10/crtbeginS.o] ==> ignore
+ arg [-L/usr/lib/gcc/x86_64-linux-gnu/10] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/10]
+ arg [-L/usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu]
+ arg [-L/usr/lib/gcc/x86_64-linux-gnu/10/../../../../lib] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/10/../../../../lib]
+ arg [-L/lib/x86_64-linux-gnu] ==> dir [/lib/x86_64-linux-gnu]
+ arg [-L/lib/../lib] ==> dir [/lib/../lib]
+ arg [-L/usr/lib/x86_64-linux-gnu] ==> dir [/usr/lib/x86_64-linux-gnu]
+ arg [-L/usr/lib/../lib] ==> dir [/usr/lib/../lib]
+ arg [-L/usr/lib/gcc/x86_64-linux-gnu/10/../../..] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/10/../../..]
+ arg [CMakeFiles/cmTC_fc2a8.dir/CMakeCXXCompilerABI.cpp.o] ==> ignore
+ arg [-lstdc++] ==> lib [stdc++]
+ arg [-lm] ==> lib [m]
+ arg [-lgcc_s] ==> lib [gcc_s]
+ arg [-lgcc] ==> lib [gcc]
+ arg [-lc] ==> lib [c]
+ arg [-lgcc_s] ==> lib [gcc_s]
+ arg [-lgcc] ==> lib [gcc]
+ arg [/usr/lib/gcc/x86_64-linux-gnu/10/crtendS.o] ==> ignore
+ arg [/usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/crtn.o] ==> ignore
+ collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/10] ==> [/usr/lib/gcc/x86_64-linux-gnu/10]
+ collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu] ==> [/usr/lib/x86_64-linux-gnu]
+ collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/10/../../../../lib] ==> [/usr/lib]
+ collapse library dir [/lib/x86_64-linux-gnu] ==> [/lib/x86_64-linux-gnu]
+ collapse library dir [/lib/../lib] ==> [/lib]
+ collapse library dir [/usr/lib/x86_64-linux-gnu] ==> [/usr/lib/x86_64-linux-gnu]
+ collapse library dir [/usr/lib/../lib] ==> [/usr/lib]
+ collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/10/../../..] ==> [/usr/lib]
+ implicit libs: [stdc++;m;gcc_s;gcc;c;gcc_s;gcc]
+ implicit dirs: [/usr/lib/gcc/x86_64-linux-gnu/10;/usr/lib/x86_64-linux-gnu;/usr/lib;/lib/x86_64-linux-gnu;/lib]
+ implicit fwks: []
+
+
+Determining if the function mkstemp exists passed with the following output:
+Change Dir: /home/calvin/src/xpdf-4.04/CMakeFiles/CMakeTmp
+
+Run Build Command(s):/usr/bin/gmake cmTC_b13a8/fast && /usr/bin/gmake -f CMakeFiles/cmTC_b13a8.dir/build.make CMakeFiles/cmTC_b13a8.dir/build
+gmake[1]: Entering directory '/home/calvin/src/xpdf-4.04/CMakeFiles/CMakeTmp'
+Building C object CMakeFiles/cmTC_b13a8.dir/CheckFunctionExists.c.o
+/usr/bin/cc -DCHECK_FUNCTION_EXISTS=mkstemp -o CMakeFiles/cmTC_b13a8.dir/CheckFunctionExists.c.o -c /usr/share/cmake-3.18/Modules/CheckFunctionExists.c
+Linking C executable cmTC_b13a8
+/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTC_b13a8.dir/link.txt --verbose=1
+/usr/bin/cc -DCHECK_FUNCTION_EXISTS=mkstemp -rdynamic CMakeFiles/cmTC_b13a8.dir/CheckFunctionExists.c.o -o cmTC_b13a8
+gmake[1]: Leaving directory '/home/calvin/src/xpdf-4.04/CMakeFiles/CMakeTmp'
+
+
+
+Determining if the function mkstemps exists passed with the following output:
+Change Dir: /home/calvin/src/xpdf-4.04/CMakeFiles/CMakeTmp
+
+Run Build Command(s):/usr/bin/gmake cmTC_16446/fast && /usr/bin/gmake -f CMakeFiles/cmTC_16446.dir/build.make CMakeFiles/cmTC_16446.dir/build
+gmake[1]: Entering directory '/home/calvin/src/xpdf-4.04/CMakeFiles/CMakeTmp'
+Building C object CMakeFiles/cmTC_16446.dir/CheckFunctionExists.c.o
+/usr/bin/cc -DCHECK_FUNCTION_EXISTS=mkstemps -o CMakeFiles/cmTC_16446.dir/CheckFunctionExists.c.o -c /usr/share/cmake-3.18/Modules/CheckFunctionExists.c
+Linking C executable cmTC_16446
+/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTC_16446.dir/link.txt --verbose=1
+/usr/bin/cc -DCHECK_FUNCTION_EXISTS=mkstemps -rdynamic CMakeFiles/cmTC_16446.dir/CheckFunctionExists.c.o -o cmTC_16446
+gmake[1]: Leaving directory '/home/calvin/src/xpdf-4.04/CMakeFiles/CMakeTmp'
+
+
+
+Determining if the function popen exists passed with the following output:
+Change Dir: /home/calvin/src/xpdf-4.04/CMakeFiles/CMakeTmp
+
+Run Build Command(s):/usr/bin/gmake cmTC_10620/fast && /usr/bin/gmake -f CMakeFiles/cmTC_10620.dir/build.make CMakeFiles/cmTC_10620.dir/build
+gmake[1]: Entering directory '/home/calvin/src/xpdf-4.04/CMakeFiles/CMakeTmp'
+Building C object CMakeFiles/cmTC_10620.dir/CheckFunctionExists.c.o
+/usr/bin/cc -DCHECK_FUNCTION_EXISTS=popen -o CMakeFiles/cmTC_10620.dir/CheckFunctionExists.c.o -c /usr/share/cmake-3.18/Modules/CheckFunctionExists.c
+Linking C executable cmTC_10620
+/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTC_10620.dir/link.txt --verbose=1
+/usr/bin/cc -DCHECK_FUNCTION_EXISTS=popen -rdynamic CMakeFiles/cmTC_10620.dir/CheckFunctionExists.c.o -o cmTC_10620
+gmake[1]: Leaving directory '/home/calvin/src/xpdf-4.04/CMakeFiles/CMakeTmp'
+
+
+
+Performing C++ SOURCE FILE Test HAVE_STD_SORT succeeded with the following output:
+Change Dir: /home/calvin/src/xpdf-4.04/CMakeFiles/CMakeTmp
+
+Run Build Command(s):/usr/bin/gmake cmTC_efb18/fast && /usr/bin/gmake -f CMakeFiles/cmTC_efb18.dir/build.make CMakeFiles/cmTC_efb18.dir/build
+gmake[1]: Entering directory '/home/calvin/src/xpdf-4.04/CMakeFiles/CMakeTmp'
+Building CXX object CMakeFiles/cmTC_efb18.dir/src.cxx.o
+/usr/bin/c++ -DHAVE_STD_SORT -o CMakeFiles/cmTC_efb18.dir/src.cxx.o -c /home/calvin/src/xpdf-4.04/CMakeFiles/CMakeTmp/src.cxx
+Linking CXX executable cmTC_efb18
+/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTC_efb18.dir/link.txt --verbose=1
+/usr/bin/c++ -DHAVE_STD_SORT -rdynamic CMakeFiles/cmTC_efb18.dir/src.cxx.o -o cmTC_efb18
+gmake[1]: Leaving directory '/home/calvin/src/xpdf-4.04/CMakeFiles/CMakeTmp'
+
+
+Source file was:
+#include <algorithm>
+ bool cmp(const int &x, const int &y) { return x < y; }
+ int a[100];
+ int main() { std::sort(a, a+100, &cmp); }
+Determining if the function fseeko exists passed with the following output:
+Change Dir: /home/calvin/src/xpdf-4.04/CMakeFiles/CMakeTmp
+
+Run Build Command(s):/usr/bin/gmake cmTC_2f9eb/fast && /usr/bin/gmake -f CMakeFiles/cmTC_2f9eb.dir/build.make CMakeFiles/cmTC_2f9eb.dir/build
+gmake[1]: Entering directory '/home/calvin/src/xpdf-4.04/CMakeFiles/CMakeTmp'
+Building C object CMakeFiles/cmTC_2f9eb.dir/CheckFunctionExists.c.o
+/usr/bin/cc -DCHECK_FUNCTION_EXISTS=fseeko -o CMakeFiles/cmTC_2f9eb.dir/CheckFunctionExists.c.o -c /usr/share/cmake-3.18/Modules/CheckFunctionExists.c
+Linking C executable cmTC_2f9eb
+/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTC_2f9eb.dir/link.txt --verbose=1
+/usr/bin/cc -DCHECK_FUNCTION_EXISTS=fseeko -rdynamic CMakeFiles/cmTC_2f9eb.dir/CheckFunctionExists.c.o -o cmTC_2f9eb
+gmake[1]: Leaving directory '/home/calvin/src/xpdf-4.04/CMakeFiles/CMakeTmp'
+
+
+
+Determining if the include file pthread.h exists passed with the following output:
+Change Dir: /home/calvin/src/xpdf-4.04/CMakeFiles/CMakeTmp
+
+Run Build Command(s):/usr/bin/gmake cmTC_b8f7f/fast && /usr/bin/gmake -f CMakeFiles/cmTC_b8f7f.dir/build.make CMakeFiles/cmTC_b8f7f.dir/build
+gmake[1]: Entering directory '/home/calvin/src/xpdf-4.04/CMakeFiles/CMakeTmp'
+Building C object CMakeFiles/cmTC_b8f7f.dir/CheckIncludeFile.c.o
+/usr/bin/cc -o CMakeFiles/cmTC_b8f7f.dir/CheckIncludeFile.c.o -c /home/calvin/src/xpdf-4.04/CMakeFiles/CMakeTmp/CheckIncludeFile.c
+Linking C executable cmTC_b8f7f
+/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTC_b8f7f.dir/link.txt --verbose=1
+/usr/bin/cc -rdynamic CMakeFiles/cmTC_b8f7f.dir/CheckIncludeFile.c.o -o cmTC_b8f7f
+gmake[1]: Leaving directory '/home/calvin/src/xpdf-4.04/CMakeFiles/CMakeTmp'
+
+
+
+Determining if the function pthread_create exists in the pthread passed with the following output:
+Change Dir: /home/calvin/src/xpdf-4.04/CMakeFiles/CMakeTmp
+
+Run Build Command(s):/usr/bin/gmake cmTC_b9c83/fast && /usr/bin/gmake -f CMakeFiles/cmTC_b9c83.dir/build.make CMakeFiles/cmTC_b9c83.dir/build
+gmake[1]: Entering directory '/home/calvin/src/xpdf-4.04/CMakeFiles/CMakeTmp'
+Building C object CMakeFiles/cmTC_b9c83.dir/CheckFunctionExists.c.o
+/usr/bin/cc -DCHECK_FUNCTION_EXISTS=pthread_create -o CMakeFiles/cmTC_b9c83.dir/CheckFunctionExists.c.o -c /usr/share/cmake-3.18/Modules/CheckFunctionExists.c
+Linking C executable cmTC_b9c83
+/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTC_b9c83.dir/link.txt --verbose=1
+/usr/bin/cc -DCHECK_FUNCTION_EXISTS=pthread_create -rdynamic CMakeFiles/cmTC_b9c83.dir/CheckFunctionExists.c.o -o cmTC_b9c83 -lpthread
+gmake[1]: Leaving directory '/home/calvin/src/xpdf-4.04/CMakeFiles/CMakeTmp'
+
+
+
diff --git a/CMakeFiles/CMakeRuleHashes.txt b/CMakeFiles/CMakeRuleHashes.txt
new file mode 100644
index 0000000..1daea97
--- /dev/null
+++ b/CMakeFiles/CMakeRuleHashes.txt
@@ -0,0 +1,5 @@
+# Hashes of file build rules.
+f823ae307d0367346d1d3212c50505e1 xpdf-qt/moc_XpdfApp.cpp
+121199ba92f30640e519e8f5406bbc5c xpdf-qt/moc_XpdfViewer.cpp
+ce270b52549c050e6cc24103664fe6fa xpdf-qt/moc_XpdfWidget.cpp
+4fc19c467d2488eeb9947f89c7433af1 xpdf-qt/qrc_icons.cpp
diff --git a/CMakeFiles/Makefile.cmake b/CMakeFiles/Makefile.cmake
new file mode 100644
index 0000000..9885ad9
--- /dev/null
+++ b/CMakeFiles/Makefile.cmake
@@ -0,0 +1,214 @@
+# CMAKE generated file: DO NOT EDIT!
+# Generated by "Unix Makefiles" Generator, CMake Version 3.18
+
+# The generator used is:
+set(CMAKE_DEPENDS_GENERATOR "Unix Makefiles")
+
+# The top level Makefile was generated from the following files:
+set(CMAKE_MAKEFILE_DEPENDS
+ "CMakeCache.txt"
+ "CMakeFiles/3.18.4/CMakeCCompiler.cmake"
+ "CMakeFiles/3.18.4/CMakeCXXCompiler.cmake"
+ "CMakeFiles/3.18.4/CMakeSystem.cmake"
+ "CMakeLists.txt"
+ "aconf.h.in"
+ "cmake-config.txt"
+ "fofi/CMakeLists.txt"
+ "goo/CMakeLists.txt"
+ "splash/CMakeLists.txt"
+ "xpdf-qt/CMakeLists.txt"
+ "xpdf-qt/icons.qrc"
+ "xpdf/CMakeLists.txt"
+ "/usr/lib/x86_64-linux-gnu/cmake/Qt5Core/Qt5CoreConfig.cmake"
+ "/usr/lib/x86_64-linux-gnu/cmake/Qt5Core/Qt5CoreConfigExtras.cmake"
+ "/usr/lib/x86_64-linux-gnu/cmake/Qt5Core/Qt5CoreConfigExtrasMkspecDir.cmake"
+ "/usr/lib/x86_64-linux-gnu/cmake/Qt5Core/Qt5CoreConfigVersion.cmake"
+ "/usr/lib/x86_64-linux-gnu/cmake/Qt5Core/Qt5CoreMacros.cmake"
+ "/usr/lib/x86_64-linux-gnu/cmake/Qt5Gui/Qt5GuiConfig.cmake"
+ "/usr/lib/x86_64-linux-gnu/cmake/Qt5Gui/Qt5GuiConfigExtras.cmake"
+ "/usr/lib/x86_64-linux-gnu/cmake/Qt5Gui/Qt5GuiConfigVersion.cmake"
+ "/usr/lib/x86_64-linux-gnu/cmake/Qt5Gui/Qt5Gui_QComposePlatformInputContextPlugin.cmake"
+ "/usr/lib/x86_64-linux-gnu/cmake/Qt5Gui/Qt5Gui_QEglFSEmulatorIntegrationPlugin.cmake"
+ "/usr/lib/x86_64-linux-gnu/cmake/Qt5Gui/Qt5Gui_QEglFSIntegrationPlugin.cmake"
+ "/usr/lib/x86_64-linux-gnu/cmake/Qt5Gui/Qt5Gui_QEglFSKmsEglDeviceIntegrationPlugin.cmake"
+ "/usr/lib/x86_64-linux-gnu/cmake/Qt5Gui/Qt5Gui_QEglFSKmsGbmIntegrationPlugin.cmake"
+ "/usr/lib/x86_64-linux-gnu/cmake/Qt5Gui/Qt5Gui_QEglFSX11IntegrationPlugin.cmake"
+ "/usr/lib/x86_64-linux-gnu/cmake/Qt5Gui/Qt5Gui_QEvdevKeyboardPlugin.cmake"
+ "/usr/lib/x86_64-linux-gnu/cmake/Qt5Gui/Qt5Gui_QEvdevMousePlugin.cmake"
+ "/usr/lib/x86_64-linux-gnu/cmake/Qt5Gui/Qt5Gui_QEvdevTabletPlugin.cmake"
+ "/usr/lib/x86_64-linux-gnu/cmake/Qt5Gui/Qt5Gui_QEvdevTouchScreenPlugin.cmake"
+ "/usr/lib/x86_64-linux-gnu/cmake/Qt5Gui/Qt5Gui_QGifPlugin.cmake"
+ "/usr/lib/x86_64-linux-gnu/cmake/Qt5Gui/Qt5Gui_QICOPlugin.cmake"
+ "/usr/lib/x86_64-linux-gnu/cmake/Qt5Gui/Qt5Gui_QIbusPlatformInputContextPlugin.cmake"
+ "/usr/lib/x86_64-linux-gnu/cmake/Qt5Gui/Qt5Gui_QJpegPlugin.cmake"
+ "/usr/lib/x86_64-linux-gnu/cmake/Qt5Gui/Qt5Gui_QLibInputPlugin.cmake"
+ "/usr/lib/x86_64-linux-gnu/cmake/Qt5Gui/Qt5Gui_QLinuxFbIntegrationPlugin.cmake"
+ "/usr/lib/x86_64-linux-gnu/cmake/Qt5Gui/Qt5Gui_QMinimalEglIntegrationPlugin.cmake"
+ "/usr/lib/x86_64-linux-gnu/cmake/Qt5Gui/Qt5Gui_QMinimalIntegrationPlugin.cmake"
+ "/usr/lib/x86_64-linux-gnu/cmake/Qt5Gui/Qt5Gui_QOffscreenIntegrationPlugin.cmake"
+ "/usr/lib/x86_64-linux-gnu/cmake/Qt5Gui/Qt5Gui_QSvgIconPlugin.cmake"
+ "/usr/lib/x86_64-linux-gnu/cmake/Qt5Gui/Qt5Gui_QSvgPlugin.cmake"
+ "/usr/lib/x86_64-linux-gnu/cmake/Qt5Gui/Qt5Gui_QTuioTouchPlugin.cmake"
+ "/usr/lib/x86_64-linux-gnu/cmake/Qt5Gui/Qt5Gui_QVncIntegrationPlugin.cmake"
+ "/usr/lib/x86_64-linux-gnu/cmake/Qt5Gui/Qt5Gui_QXcbEglIntegrationPlugin.cmake"
+ "/usr/lib/x86_64-linux-gnu/cmake/Qt5Gui/Qt5Gui_QXcbGlxIntegrationPlugin.cmake"
+ "/usr/lib/x86_64-linux-gnu/cmake/Qt5Gui/Qt5Gui_QXcbIntegrationPlugin.cmake"
+ "/usr/lib/x86_64-linux-gnu/cmake/Qt5Network/Qt5NetworkConfig.cmake"
+ "/usr/lib/x86_64-linux-gnu/cmake/Qt5Network/Qt5NetworkConfigVersion.cmake"
+ "/usr/lib/x86_64-linux-gnu/cmake/Qt5Network/Qt5Network_QConnmanEnginePlugin.cmake"
+ "/usr/lib/x86_64-linux-gnu/cmake/Qt5Network/Qt5Network_QGenericEnginePlugin.cmake"
+ "/usr/lib/x86_64-linux-gnu/cmake/Qt5Network/Qt5Network_QNetworkManagerEnginePlugin.cmake"
+ "/usr/lib/x86_64-linux-gnu/cmake/Qt5PrintSupport/Qt5PrintSupportConfig.cmake"
+ "/usr/lib/x86_64-linux-gnu/cmake/Qt5PrintSupport/Qt5PrintSupportConfigVersion.cmake"
+ "/usr/lib/x86_64-linux-gnu/cmake/Qt5PrintSupport/Qt5PrintSupport_QCupsPrinterSupportPlugin.cmake"
+ "/usr/lib/x86_64-linux-gnu/cmake/Qt5Widgets/Qt5WidgetsConfig.cmake"
+ "/usr/lib/x86_64-linux-gnu/cmake/Qt5Widgets/Qt5WidgetsConfigExtras.cmake"
+ "/usr/lib/x86_64-linux-gnu/cmake/Qt5Widgets/Qt5WidgetsConfigVersion.cmake"
+ "/usr/lib/x86_64-linux-gnu/cmake/Qt5Widgets/Qt5WidgetsMacros.cmake"
+ "/usr/share/cmake-3.18/Modules/CMakeCCompiler.cmake.in"
+ "/usr/share/cmake-3.18/Modules/CMakeCCompilerABI.c"
+ "/usr/share/cmake-3.18/Modules/CMakeCInformation.cmake"
+ "/usr/share/cmake-3.18/Modules/CMakeCXXCompiler.cmake.in"
+ "/usr/share/cmake-3.18/Modules/CMakeCXXCompilerABI.cpp"
+ "/usr/share/cmake-3.18/Modules/CMakeCXXInformation.cmake"
+ "/usr/share/cmake-3.18/Modules/CMakeCheckCompilerFlagCommonPatterns.cmake"
+ "/usr/share/cmake-3.18/Modules/CMakeCommonLanguageInclude.cmake"
+ "/usr/share/cmake-3.18/Modules/CMakeCompilerIdDetection.cmake"
+ "/usr/share/cmake-3.18/Modules/CMakeDetermineCCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/CMakeDetermineCXXCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/CMakeDetermineCompileFeatures.cmake"
+ "/usr/share/cmake-3.18/Modules/CMakeDetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/CMakeDetermineCompilerABI.cmake"
+ "/usr/share/cmake-3.18/Modules/CMakeDetermineCompilerId.cmake"
+ "/usr/share/cmake-3.18/Modules/CMakeDetermineSystem.cmake"
+ "/usr/share/cmake-3.18/Modules/CMakeFindBinUtils.cmake"
+ "/usr/share/cmake-3.18/Modules/CMakeGenericSystem.cmake"
+ "/usr/share/cmake-3.18/Modules/CMakeInitializeConfigs.cmake"
+ "/usr/share/cmake-3.18/Modules/CMakeLanguageInformation.cmake"
+ "/usr/share/cmake-3.18/Modules/CMakeParseArguments.cmake"
+ "/usr/share/cmake-3.18/Modules/CMakeParseImplicitIncludeInfo.cmake"
+ "/usr/share/cmake-3.18/Modules/CMakeParseImplicitLinkInfo.cmake"
+ "/usr/share/cmake-3.18/Modules/CMakeSystem.cmake.in"
+ "/usr/share/cmake-3.18/Modules/CMakeSystemSpecificInformation.cmake"
+ "/usr/share/cmake-3.18/Modules/CMakeSystemSpecificInitialize.cmake"
+ "/usr/share/cmake-3.18/Modules/CMakeTestCCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/CMakeTestCXXCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/CMakeTestCompilerCommon.cmake"
+ "/usr/share/cmake-3.18/Modules/CMakeUnixFindMake.cmake"
+ "/usr/share/cmake-3.18/Modules/CheckCSourceCompiles.cmake"
+ "/usr/share/cmake-3.18/Modules/CheckCXXSourceCompiles.cmake"
+ "/usr/share/cmake-3.18/Modules/CheckFunctionExists.c"
+ "/usr/share/cmake-3.18/Modules/CheckFunctionExists.cmake"
+ "/usr/share/cmake-3.18/Modules/CheckIncludeFile.c.in"
+ "/usr/share/cmake-3.18/Modules/CheckIncludeFile.cmake"
+ "/usr/share/cmake-3.18/Modules/CheckLibraryExists.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/ADSP-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/ARMCC-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/ARMClang-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/AppleClang-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/Borland-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/Bruce-C-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/CMakeCommonCompilerMacros.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/Clang-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/Clang-DetermineCompilerInternal.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/Comeau-CXX-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/Compaq-C-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/Compaq-CXX-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/Cray-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/Embarcadero-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/Fujitsu-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/GHS-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/GNU-C-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/GNU-C.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/GNU-CXX-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/GNU-CXX.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/GNU-FindBinUtils.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/GNU.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/HP-C-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/HP-CXX-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/IAR-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/IBMCPP-CXX-DetermineVersionInternal.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/Intel-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/MSVC-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/NVIDIA-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/OpenWatcom-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/PGI-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/PathScale-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/SCO-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/SDCC-C-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/SunPro-C-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/SunPro-CXX-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/TI-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/TinyCC-C-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/VisualAge-C-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/VisualAge-CXX-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/Watcom-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/XL-C-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/XL-CXX-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/XLClang-C-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/XLClang-CXX-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/zOS-C-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/zOS-CXX-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/FindCups.cmake"
+ "/usr/share/cmake-3.18/Modules/FindPNG.cmake"
+ "/usr/share/cmake-3.18/Modules/FindPackageHandleStandardArgs.cmake"
+ "/usr/share/cmake-3.18/Modules/FindPackageMessage.cmake"
+ "/usr/share/cmake-3.18/Modules/FindThreads.cmake"
+ "/usr/share/cmake-3.18/Modules/FindZLIB.cmake"
+ "/usr/share/cmake-3.18/Modules/GNUInstallDirs.cmake"
+ "/usr/share/cmake-3.18/Modules/Internal/CMakeCheckCompilerFlag.cmake"
+ "/usr/share/cmake-3.18/Modules/Internal/FeatureTesting.cmake"
+ "/usr/share/cmake-3.18/Modules/Platform/Linux-Determine-CXX.cmake"
+ "/usr/share/cmake-3.18/Modules/Platform/Linux-GNU-C.cmake"
+ "/usr/share/cmake-3.18/Modules/Platform/Linux-GNU-CXX.cmake"
+ "/usr/share/cmake-3.18/Modules/Platform/Linux-GNU.cmake"
+ "/usr/share/cmake-3.18/Modules/Platform/Linux.cmake"
+ "/usr/share/cmake-3.18/Modules/Platform/UnixPaths.cmake"
+ "/usr/share/cmake-3.18/Modules/SelectLibraryConfigurations.cmake"
+ )
+
+# The corresponding makefile is:
+set(CMAKE_MAKEFILE_OUTPUTS
+ "Makefile"
+ "CMakeFiles/cmake.check_cache"
+ )
+
+# Byproducts of CMake generate step:
+set(CMAKE_MAKEFILE_PRODUCTS
+ "CMakeFiles/3.18.4/CMakeSystem.cmake"
+ "CMakeFiles/3.18.4/CMakeCCompiler.cmake"
+ "CMakeFiles/3.18.4/CMakeCXXCompiler.cmake"
+ "CMakeFiles/3.18.4/CMakeCCompiler.cmake"
+ "CMakeFiles/3.18.4/CMakeCXXCompiler.cmake"
+ "aconf.h"
+ "CMakeFiles/CMakeDirectoryInformation.cmake"
+ "goo/CMakeFiles/CMakeDirectoryInformation.cmake"
+ "fofi/CMakeFiles/CMakeDirectoryInformation.cmake"
+ "splash/CMakeFiles/CMakeDirectoryInformation.cmake"
+ "xpdf/CMakeFiles/CMakeDirectoryInformation.cmake"
+ "xpdf-qt/icons.qrc.depends"
+ "xpdf-qt/CMakeFiles/CMakeDirectoryInformation.cmake"
+ )
+
+# Dependency information for all targets:
+set(CMAKE_DEPEND_INFO_FILES
+ "goo/CMakeFiles/goo.dir/DependInfo.cmake"
+ "goo/CMakeFiles/goo_objs.dir/DependInfo.cmake"
+ "fofi/CMakeFiles/fofi.dir/DependInfo.cmake"
+ "fofi/CMakeFiles/fofi_objs.dir/DependInfo.cmake"
+ "splash/CMakeFiles/splash.dir/DependInfo.cmake"
+ "splash/CMakeFiles/splash_objs.dir/DependInfo.cmake"
+ "xpdf/CMakeFiles/xpdf_objs.dir/DependInfo.cmake"
+ "xpdf/CMakeFiles/pdftohtml.dir/DependInfo.cmake"
+ "xpdf/CMakeFiles/pdftoppm.dir/DependInfo.cmake"
+ "xpdf/CMakeFiles/pdftopng.dir/DependInfo.cmake"
+ "xpdf/CMakeFiles/pdftotext.dir/DependInfo.cmake"
+ "xpdf/CMakeFiles/xpdf_widget_objs.dir/DependInfo.cmake"
+ "xpdf/CMakeFiles/pdfinfo.dir/DependInfo.cmake"
+ "xpdf/CMakeFiles/pdfdetach.dir/DependInfo.cmake"
+ "xpdf/CMakeFiles/pdftops.dir/DependInfo.cmake"
+ "xpdf/CMakeFiles/pdffonts.dir/DependInfo.cmake"
+ "xpdf/CMakeFiles/pdfimages.dir/DependInfo.cmake"
+ "xpdf-qt/CMakeFiles/xpdf.dir/DependInfo.cmake"
+ )
diff --git a/CMakeFiles/Makefile2 b/CMakeFiles/Makefile2
new file mode 100644
index 0000000..84cc91c
--- /dev/null
+++ b/CMakeFiles/Makefile2
@@ -0,0 +1,738 @@
+# 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
+
+#=============================================================================
+# 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
+
+#=============================================================================
+# Directory level rules for the build root directory
+
+# The main recursive "all" target.
+all: goo/all
+all: fofi/all
+all: splash/all
+all: xpdf/all
+all: xpdf-qt/all
+
+.PHONY : all
+
+# The main recursive "preinstall" target.
+preinstall: goo/preinstall
+preinstall: fofi/preinstall
+preinstall: splash/preinstall
+preinstall: xpdf/preinstall
+preinstall: xpdf-qt/preinstall
+
+.PHONY : preinstall
+
+# The main recursive "clean" target.
+clean: goo/clean
+clean: fofi/clean
+clean: splash/clean
+clean: xpdf/clean
+clean: xpdf-qt/clean
+
+.PHONY : clean
+
+#=============================================================================
+# Directory level rules for directory fofi
+
+# Recursive "all" directory target.
+fofi/all: fofi/CMakeFiles/fofi.dir/all
+fofi/all: fofi/CMakeFiles/fofi_objs.dir/all
+
+.PHONY : fofi/all
+
+# Recursive "preinstall" directory target.
+fofi/preinstall:
+
+.PHONY : fofi/preinstall
+
+# Recursive "clean" directory target.
+fofi/clean: fofi/CMakeFiles/fofi.dir/clean
+fofi/clean: fofi/CMakeFiles/fofi_objs.dir/clean
+
+.PHONY : fofi/clean
+
+#=============================================================================
+# Directory level rules for directory goo
+
+# Recursive "all" directory target.
+goo/all: goo/CMakeFiles/goo.dir/all
+goo/all: goo/CMakeFiles/goo_objs.dir/all
+
+.PHONY : goo/all
+
+# Recursive "preinstall" directory target.
+goo/preinstall:
+
+.PHONY : goo/preinstall
+
+# Recursive "clean" directory target.
+goo/clean: goo/CMakeFiles/goo.dir/clean
+goo/clean: goo/CMakeFiles/goo_objs.dir/clean
+
+.PHONY : goo/clean
+
+#=============================================================================
+# Directory level rules for directory splash
+
+# Recursive "all" directory target.
+splash/all: splash/CMakeFiles/splash.dir/all
+splash/all: splash/CMakeFiles/splash_objs.dir/all
+
+.PHONY : splash/all
+
+# Recursive "preinstall" directory target.
+splash/preinstall:
+
+.PHONY : splash/preinstall
+
+# Recursive "clean" directory target.
+splash/clean: splash/CMakeFiles/splash.dir/clean
+splash/clean: splash/CMakeFiles/splash_objs.dir/clean
+
+.PHONY : splash/clean
+
+#=============================================================================
+# Directory level rules for directory xpdf
+
+# Recursive "all" directory target.
+xpdf/all: xpdf/CMakeFiles/xpdf_objs.dir/all
+xpdf/all: xpdf/CMakeFiles/pdftohtml.dir/all
+xpdf/all: xpdf/CMakeFiles/pdftoppm.dir/all
+xpdf/all: xpdf/CMakeFiles/pdftopng.dir/all
+xpdf/all: xpdf/CMakeFiles/pdftotext.dir/all
+xpdf/all: xpdf/CMakeFiles/xpdf_widget_objs.dir/all
+xpdf/all: xpdf/CMakeFiles/pdfinfo.dir/all
+xpdf/all: xpdf/CMakeFiles/pdfdetach.dir/all
+xpdf/all: xpdf/CMakeFiles/pdftops.dir/all
+xpdf/all: xpdf/CMakeFiles/pdffonts.dir/all
+xpdf/all: xpdf/CMakeFiles/pdfimages.dir/all
+
+.PHONY : xpdf/all
+
+# Recursive "preinstall" directory target.
+xpdf/preinstall:
+
+.PHONY : xpdf/preinstall
+
+# Recursive "clean" directory target.
+xpdf/clean: xpdf/CMakeFiles/xpdf_objs.dir/clean
+xpdf/clean: xpdf/CMakeFiles/pdftohtml.dir/clean
+xpdf/clean: xpdf/CMakeFiles/pdftoppm.dir/clean
+xpdf/clean: xpdf/CMakeFiles/pdftopng.dir/clean
+xpdf/clean: xpdf/CMakeFiles/pdftotext.dir/clean
+xpdf/clean: xpdf/CMakeFiles/xpdf_widget_objs.dir/clean
+xpdf/clean: xpdf/CMakeFiles/pdfinfo.dir/clean
+xpdf/clean: xpdf/CMakeFiles/pdfdetach.dir/clean
+xpdf/clean: xpdf/CMakeFiles/pdftops.dir/clean
+xpdf/clean: xpdf/CMakeFiles/pdffonts.dir/clean
+xpdf/clean: xpdf/CMakeFiles/pdfimages.dir/clean
+
+.PHONY : xpdf/clean
+
+#=============================================================================
+# Directory level rules for directory xpdf-qt
+
+# Recursive "all" directory target.
+xpdf-qt/all: xpdf-qt/CMakeFiles/xpdf.dir/all
+
+.PHONY : xpdf-qt/all
+
+# Recursive "preinstall" directory target.
+xpdf-qt/preinstall:
+
+.PHONY : xpdf-qt/preinstall
+
+# Recursive "clean" directory target.
+xpdf-qt/clean: xpdf-qt/CMakeFiles/xpdf.dir/clean
+
+.PHONY : xpdf-qt/clean
+
+#=============================================================================
+# Target rules for target goo/CMakeFiles/goo.dir
+
+# All Build rule for target.
+goo/CMakeFiles/goo.dir/all: goo/CMakeFiles/goo_objs.dir/all
+ $(MAKE) $(MAKESILENT) -f goo/CMakeFiles/goo.dir/build.make goo/CMakeFiles/goo.dir/depend
+ $(MAKE) $(MAKESILENT) -f goo/CMakeFiles/goo.dir/build.make goo/CMakeFiles/goo.dir/build
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num= "Built target goo"
+.PHONY : goo/CMakeFiles/goo.dir/all
+
+# Build rule for subdir invocation for target.
+goo/CMakeFiles/goo.dir/rule: cmake_check_build_system
+ $(CMAKE_COMMAND) -E cmake_progress_start /home/calvin/src/xpdf-4.04/CMakeFiles 7
+ $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 goo/CMakeFiles/goo.dir/all
+ $(CMAKE_COMMAND) -E cmake_progress_start /home/calvin/src/xpdf-4.04/CMakeFiles 0
+.PHONY : goo/CMakeFiles/goo.dir/rule
+
+# Convenience name for target.
+goo: goo/CMakeFiles/goo.dir/rule
+
+.PHONY : goo
+
+# clean rule for target.
+goo/CMakeFiles/goo.dir/clean:
+ $(MAKE) $(MAKESILENT) -f goo/CMakeFiles/goo.dir/build.make goo/CMakeFiles/goo.dir/clean
+.PHONY : goo/CMakeFiles/goo.dir/clean
+
+#=============================================================================
+# Target rules for target goo/CMakeFiles/goo_objs.dir
+
+# All Build rule for target.
+goo/CMakeFiles/goo_objs.dir/all:
+ $(MAKE) $(MAKESILENT) -f goo/CMakeFiles/goo_objs.dir/build.make goo/CMakeFiles/goo_objs.dir/depend
+ $(MAKE) $(MAKESILENT) -f goo/CMakeFiles/goo_objs.dir/build.make goo/CMakeFiles/goo_objs.dir/build
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=6,7,8,9,10,11,12 "Built target goo_objs"
+.PHONY : goo/CMakeFiles/goo_objs.dir/all
+
+# Build rule for subdir invocation for target.
+goo/CMakeFiles/goo_objs.dir/rule: cmake_check_build_system
+ $(CMAKE_COMMAND) -E cmake_progress_start /home/calvin/src/xpdf-4.04/CMakeFiles 7
+ $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 goo/CMakeFiles/goo_objs.dir/all
+ $(CMAKE_COMMAND) -E cmake_progress_start /home/calvin/src/xpdf-4.04/CMakeFiles 0
+.PHONY : goo/CMakeFiles/goo_objs.dir/rule
+
+# Convenience name for target.
+goo_objs: goo/CMakeFiles/goo_objs.dir/rule
+
+.PHONY : goo_objs
+
+# clean rule for target.
+goo/CMakeFiles/goo_objs.dir/clean:
+ $(MAKE) $(MAKESILENT) -f goo/CMakeFiles/goo_objs.dir/build.make goo/CMakeFiles/goo_objs.dir/clean
+.PHONY : goo/CMakeFiles/goo_objs.dir/clean
+
+#=============================================================================
+# Target rules for target fofi/CMakeFiles/fofi.dir
+
+# All Build rule for target.
+fofi/CMakeFiles/fofi.dir/all: fofi/CMakeFiles/fofi_objs.dir/all
+ $(MAKE) $(MAKESILENT) -f fofi/CMakeFiles/fofi.dir/build.make fofi/CMakeFiles/fofi.dir/depend
+ $(MAKE) $(MAKESILENT) -f fofi/CMakeFiles/fofi.dir/build.make fofi/CMakeFiles/fofi.dir/build
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num= "Built target fofi"
+.PHONY : fofi/CMakeFiles/fofi.dir/all
+
+# Build rule for subdir invocation for target.
+fofi/CMakeFiles/fofi.dir/rule: cmake_check_build_system
+ $(CMAKE_COMMAND) -E cmake_progress_start /home/calvin/src/xpdf-4.04/CMakeFiles 5
+ $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 fofi/CMakeFiles/fofi.dir/all
+ $(CMAKE_COMMAND) -E cmake_progress_start /home/calvin/src/xpdf-4.04/CMakeFiles 0
+.PHONY : fofi/CMakeFiles/fofi.dir/rule
+
+# Convenience name for target.
+fofi: fofi/CMakeFiles/fofi.dir/rule
+
+.PHONY : fofi
+
+# clean rule for target.
+fofi/CMakeFiles/fofi.dir/clean:
+ $(MAKE) $(MAKESILENT) -f fofi/CMakeFiles/fofi.dir/build.make fofi/CMakeFiles/fofi.dir/clean
+.PHONY : fofi/CMakeFiles/fofi.dir/clean
+
+#=============================================================================
+# Target rules for target fofi/CMakeFiles/fofi_objs.dir
+
+# All Build rule for target.
+fofi/CMakeFiles/fofi_objs.dir/all:
+ $(MAKE) $(MAKESILENT) -f fofi/CMakeFiles/fofi_objs.dir/build.make fofi/CMakeFiles/fofi_objs.dir/depend
+ $(MAKE) $(MAKESILENT) -f fofi/CMakeFiles/fofi_objs.dir/build.make fofi/CMakeFiles/fofi_objs.dir/build
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=1,2,3,4,5 "Built target fofi_objs"
+.PHONY : fofi/CMakeFiles/fofi_objs.dir/all
+
+# Build rule for subdir invocation for target.
+fofi/CMakeFiles/fofi_objs.dir/rule: cmake_check_build_system
+ $(CMAKE_COMMAND) -E cmake_progress_start /home/calvin/src/xpdf-4.04/CMakeFiles 5
+ $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 fofi/CMakeFiles/fofi_objs.dir/all
+ $(CMAKE_COMMAND) -E cmake_progress_start /home/calvin/src/xpdf-4.04/CMakeFiles 0
+.PHONY : fofi/CMakeFiles/fofi_objs.dir/rule
+
+# Convenience name for target.
+fofi_objs: fofi/CMakeFiles/fofi_objs.dir/rule
+
+.PHONY : fofi_objs
+
+# clean rule for target.
+fofi/CMakeFiles/fofi_objs.dir/clean:
+ $(MAKE) $(MAKESILENT) -f fofi/CMakeFiles/fofi_objs.dir/build.make fofi/CMakeFiles/fofi_objs.dir/clean
+.PHONY : fofi/CMakeFiles/fofi_objs.dir/clean
+
+#=============================================================================
+# Target rules for target splash/CMakeFiles/splash.dir
+
+# All Build rule for target.
+splash/CMakeFiles/splash.dir/all: splash/CMakeFiles/splash_objs.dir/all
+ $(MAKE) $(MAKESILENT) -f splash/CMakeFiles/splash.dir/build.make splash/CMakeFiles/splash.dir/depend
+ $(MAKE) $(MAKESILENT) -f splash/CMakeFiles/splash.dir/build.make splash/CMakeFiles/splash.dir/build
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num= "Built target splash"
+.PHONY : splash/CMakeFiles/splash.dir/all
+
+# Build rule for subdir invocation for target.
+splash/CMakeFiles/splash.dir/rule: cmake_check_build_system
+ $(CMAKE_COMMAND) -E cmake_progress_start /home/calvin/src/xpdf-4.04/CMakeFiles 12
+ $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 splash/CMakeFiles/splash.dir/all
+ $(CMAKE_COMMAND) -E cmake_progress_start /home/calvin/src/xpdf-4.04/CMakeFiles 0
+.PHONY : splash/CMakeFiles/splash.dir/rule
+
+# Convenience name for target.
+splash: splash/CMakeFiles/splash.dir/rule
+
+.PHONY : splash
+
+# clean rule for target.
+splash/CMakeFiles/splash.dir/clean:
+ $(MAKE) $(MAKESILENT) -f splash/CMakeFiles/splash.dir/build.make splash/CMakeFiles/splash.dir/clean
+.PHONY : splash/CMakeFiles/splash.dir/clean
+
+#=============================================================================
+# Target rules for target splash/CMakeFiles/splash_objs.dir
+
+# All Build rule for target.
+splash/CMakeFiles/splash_objs.dir/all:
+ $(MAKE) $(MAKESILENT) -f splash/CMakeFiles/splash_objs.dir/build.make splash/CMakeFiles/splash_objs.dir/depend
+ $(MAKE) $(MAKESILENT) -f splash/CMakeFiles/splash_objs.dir/build.make splash/CMakeFiles/splash_objs.dir/build
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=38,39,40,41,42,43,44,45,46,47,48,49 "Built target splash_objs"
+.PHONY : splash/CMakeFiles/splash_objs.dir/all
+
+# Build rule for subdir invocation for target.
+splash/CMakeFiles/splash_objs.dir/rule: cmake_check_build_system
+ $(CMAKE_COMMAND) -E cmake_progress_start /home/calvin/src/xpdf-4.04/CMakeFiles 12
+ $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 splash/CMakeFiles/splash_objs.dir/all
+ $(CMAKE_COMMAND) -E cmake_progress_start /home/calvin/src/xpdf-4.04/CMakeFiles 0
+.PHONY : splash/CMakeFiles/splash_objs.dir/rule
+
+# Convenience name for target.
+splash_objs: splash/CMakeFiles/splash_objs.dir/rule
+
+.PHONY : splash_objs
+
+# clean rule for target.
+splash/CMakeFiles/splash_objs.dir/clean:
+ $(MAKE) $(MAKESILENT) -f splash/CMakeFiles/splash_objs.dir/build.make splash/CMakeFiles/splash_objs.dir/clean
+.PHONY : splash/CMakeFiles/splash_objs.dir/clean
+
+#=============================================================================
+# Target rules for target xpdf/CMakeFiles/xpdf_objs.dir
+
+# All Build rule for target.
+xpdf/CMakeFiles/xpdf_objs.dir/all:
+ $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/depend
+ $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/build
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=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 "Built target xpdf_objs"
+.PHONY : xpdf/CMakeFiles/xpdf_objs.dir/all
+
+# Build rule for subdir invocation for target.
+xpdf/CMakeFiles/xpdf_objs.dir/rule: cmake_check_build_system
+ $(CMAKE_COMMAND) -E cmake_progress_start /home/calvin/src/xpdf-4.04/CMakeFiles 32
+ $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 xpdf/CMakeFiles/xpdf_objs.dir/all
+ $(CMAKE_COMMAND) -E cmake_progress_start /home/calvin/src/xpdf-4.04/CMakeFiles 0
+.PHONY : xpdf/CMakeFiles/xpdf_objs.dir/rule
+
+# Convenience name for target.
+xpdf_objs: xpdf/CMakeFiles/xpdf_objs.dir/rule
+
+.PHONY : xpdf_objs
+
+# clean rule for target.
+xpdf/CMakeFiles/xpdf_objs.dir/clean:
+ $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/clean
+.PHONY : xpdf/CMakeFiles/xpdf_objs.dir/clean
+
+#=============================================================================
+# Target rules for target xpdf/CMakeFiles/pdftohtml.dir
+
+# All Build rule for target.
+xpdf/CMakeFiles/pdftohtml.dir/all: goo/CMakeFiles/goo.dir/all
+xpdf/CMakeFiles/pdftohtml.dir/all: fofi/CMakeFiles/fofi.dir/all
+xpdf/CMakeFiles/pdftohtml.dir/all: splash/CMakeFiles/splash.dir/all
+xpdf/CMakeFiles/pdftohtml.dir/all: xpdf/CMakeFiles/xpdf_objs.dir/all
+ $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftohtml.dir/build.make xpdf/CMakeFiles/pdftohtml.dir/depend
+ $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftohtml.dir/build.make xpdf/CMakeFiles/pdftohtml.dir/build
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=20,21,22,23,24 "Built target pdftohtml"
+.PHONY : xpdf/CMakeFiles/pdftohtml.dir/all
+
+# Build rule for subdir invocation for target.
+xpdf/CMakeFiles/pdftohtml.dir/rule: cmake_check_build_system
+ $(CMAKE_COMMAND) -E cmake_progress_start /home/calvin/src/xpdf-4.04/CMakeFiles 61
+ $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 xpdf/CMakeFiles/pdftohtml.dir/all
+ $(CMAKE_COMMAND) -E cmake_progress_start /home/calvin/src/xpdf-4.04/CMakeFiles 0
+.PHONY : xpdf/CMakeFiles/pdftohtml.dir/rule
+
+# Convenience name for target.
+pdftohtml: xpdf/CMakeFiles/pdftohtml.dir/rule
+
+.PHONY : pdftohtml
+
+# clean rule for target.
+xpdf/CMakeFiles/pdftohtml.dir/clean:
+ $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftohtml.dir/build.make xpdf/CMakeFiles/pdftohtml.dir/clean
+.PHONY : xpdf/CMakeFiles/pdftohtml.dir/clean
+
+#=============================================================================
+# Target rules for target xpdf/CMakeFiles/pdftoppm.dir
+
+# All Build rule for target.
+xpdf/CMakeFiles/pdftoppm.dir/all: goo/CMakeFiles/goo.dir/all
+xpdf/CMakeFiles/pdftoppm.dir/all: fofi/CMakeFiles/fofi.dir/all
+xpdf/CMakeFiles/pdftoppm.dir/all: splash/CMakeFiles/splash.dir/all
+xpdf/CMakeFiles/pdftoppm.dir/all: xpdf/CMakeFiles/xpdf_objs.dir/all
+ $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftoppm.dir/build.make xpdf/CMakeFiles/pdftoppm.dir/depend
+ $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftoppm.dir/build.make xpdf/CMakeFiles/pdftoppm.dir/build
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=28,29,30 "Built target pdftoppm"
+.PHONY : xpdf/CMakeFiles/pdftoppm.dir/all
+
+# Build rule for subdir invocation for target.
+xpdf/CMakeFiles/pdftoppm.dir/rule: cmake_check_build_system
+ $(CMAKE_COMMAND) -E cmake_progress_start /home/calvin/src/xpdf-4.04/CMakeFiles 59
+ $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 xpdf/CMakeFiles/pdftoppm.dir/all
+ $(CMAKE_COMMAND) -E cmake_progress_start /home/calvin/src/xpdf-4.04/CMakeFiles 0
+.PHONY : xpdf/CMakeFiles/pdftoppm.dir/rule
+
+# Convenience name for target.
+pdftoppm: xpdf/CMakeFiles/pdftoppm.dir/rule
+
+.PHONY : pdftoppm
+
+# clean rule for target.
+xpdf/CMakeFiles/pdftoppm.dir/clean:
+ $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftoppm.dir/build.make xpdf/CMakeFiles/pdftoppm.dir/clean
+.PHONY : xpdf/CMakeFiles/pdftoppm.dir/clean
+
+#=============================================================================
+# Target rules for target xpdf/CMakeFiles/pdftopng.dir
+
+# All Build rule for target.
+xpdf/CMakeFiles/pdftopng.dir/all: goo/CMakeFiles/goo.dir/all
+xpdf/CMakeFiles/pdftopng.dir/all: fofi/CMakeFiles/fofi.dir/all
+xpdf/CMakeFiles/pdftopng.dir/all: splash/CMakeFiles/splash.dir/all
+xpdf/CMakeFiles/pdftopng.dir/all: xpdf/CMakeFiles/xpdf_objs.dir/all
+ $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftopng.dir/build.make xpdf/CMakeFiles/pdftopng.dir/depend
+ $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftopng.dir/build.make xpdf/CMakeFiles/pdftopng.dir/build
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=25,26,27 "Built target pdftopng"
+.PHONY : xpdf/CMakeFiles/pdftopng.dir/all
+
+# Build rule for subdir invocation for target.
+xpdf/CMakeFiles/pdftopng.dir/rule: cmake_check_build_system
+ $(CMAKE_COMMAND) -E cmake_progress_start /home/calvin/src/xpdf-4.04/CMakeFiles 59
+ $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 xpdf/CMakeFiles/pdftopng.dir/all
+ $(CMAKE_COMMAND) -E cmake_progress_start /home/calvin/src/xpdf-4.04/CMakeFiles 0
+.PHONY : xpdf/CMakeFiles/pdftopng.dir/rule
+
+# Convenience name for target.
+pdftopng: xpdf/CMakeFiles/pdftopng.dir/rule
+
+.PHONY : pdftopng
+
+# clean rule for target.
+xpdf/CMakeFiles/pdftopng.dir/clean:
+ $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftopng.dir/build.make xpdf/CMakeFiles/pdftopng.dir/clean
+.PHONY : xpdf/CMakeFiles/pdftopng.dir/clean
+
+#=============================================================================
+# Target rules for target xpdf/CMakeFiles/pdftotext.dir
+
+# All Build rule for target.
+xpdf/CMakeFiles/pdftotext.dir/all: goo/CMakeFiles/goo.dir/all
+xpdf/CMakeFiles/pdftotext.dir/all: fofi/CMakeFiles/fofi.dir/all
+xpdf/CMakeFiles/pdftotext.dir/all: xpdf/CMakeFiles/xpdf_objs.dir/all
+ $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftotext.dir/build.make xpdf/CMakeFiles/pdftotext.dir/depend
+ $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftotext.dir/build.make xpdf/CMakeFiles/pdftotext.dir/build
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=35,36,37 "Built target pdftotext"
+.PHONY : xpdf/CMakeFiles/pdftotext.dir/all
+
+# Build rule for subdir invocation for target.
+xpdf/CMakeFiles/pdftotext.dir/rule: cmake_check_build_system
+ $(CMAKE_COMMAND) -E cmake_progress_start /home/calvin/src/xpdf-4.04/CMakeFiles 47
+ $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 xpdf/CMakeFiles/pdftotext.dir/all
+ $(CMAKE_COMMAND) -E cmake_progress_start /home/calvin/src/xpdf-4.04/CMakeFiles 0
+.PHONY : xpdf/CMakeFiles/pdftotext.dir/rule
+
+# Convenience name for target.
+pdftotext: xpdf/CMakeFiles/pdftotext.dir/rule
+
+.PHONY : pdftotext
+
+# clean rule for target.
+xpdf/CMakeFiles/pdftotext.dir/clean:
+ $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftotext.dir/build.make xpdf/CMakeFiles/pdftotext.dir/clean
+.PHONY : xpdf/CMakeFiles/pdftotext.dir/clean
+
+#=============================================================================
+# Target rules for target xpdf/CMakeFiles/xpdf_widget_objs.dir
+
+# All Build rule for target.
+xpdf/CMakeFiles/xpdf_widget_objs.dir/all:
+ $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_widget_objs.dir/build.make xpdf/CMakeFiles/xpdf_widget_objs.dir/depend
+ $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_widget_objs.dir/build.make xpdf/CMakeFiles/xpdf_widget_objs.dir/build
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=93,94,95,96,97,98,99,100 "Built target xpdf_widget_objs"
+.PHONY : xpdf/CMakeFiles/xpdf_widget_objs.dir/all
+
+# Build rule for subdir invocation for target.
+xpdf/CMakeFiles/xpdf_widget_objs.dir/rule: cmake_check_build_system
+ $(CMAKE_COMMAND) -E cmake_progress_start /home/calvin/src/xpdf-4.04/CMakeFiles 8
+ $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 xpdf/CMakeFiles/xpdf_widget_objs.dir/all
+ $(CMAKE_COMMAND) -E cmake_progress_start /home/calvin/src/xpdf-4.04/CMakeFiles 0
+.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
+
+# clean rule for target.
+xpdf/CMakeFiles/xpdf_widget_objs.dir/clean:
+ $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_widget_objs.dir/build.make xpdf/CMakeFiles/xpdf_widget_objs.dir/clean
+.PHONY : xpdf/CMakeFiles/xpdf_widget_objs.dir/clean
+
+#=============================================================================
+# Target rules for target xpdf/CMakeFiles/pdfinfo.dir
+
+# All Build rule for target.
+xpdf/CMakeFiles/pdfinfo.dir/all: goo/CMakeFiles/goo.dir/all
+xpdf/CMakeFiles/pdfinfo.dir/all: fofi/CMakeFiles/fofi.dir/all
+xpdf/CMakeFiles/pdfinfo.dir/all: xpdf/CMakeFiles/xpdf_objs.dir/all
+ $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdfinfo.dir/build.make xpdf/CMakeFiles/pdfinfo.dir/depend
+ $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdfinfo.dir/build.make xpdf/CMakeFiles/pdfinfo.dir/build
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=18,19 "Built target pdfinfo"
+.PHONY : xpdf/CMakeFiles/pdfinfo.dir/all
+
+# Build rule for subdir invocation for target.
+xpdf/CMakeFiles/pdfinfo.dir/rule: cmake_check_build_system
+ $(CMAKE_COMMAND) -E cmake_progress_start /home/calvin/src/xpdf-4.04/CMakeFiles 46
+ $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 xpdf/CMakeFiles/pdfinfo.dir/all
+ $(CMAKE_COMMAND) -E cmake_progress_start /home/calvin/src/xpdf-4.04/CMakeFiles 0
+.PHONY : xpdf/CMakeFiles/pdfinfo.dir/rule
+
+# Convenience name for target.
+pdfinfo: xpdf/CMakeFiles/pdfinfo.dir/rule
+
+.PHONY : pdfinfo
+
+# clean rule for target.
+xpdf/CMakeFiles/pdfinfo.dir/clean:
+ $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdfinfo.dir/build.make xpdf/CMakeFiles/pdfinfo.dir/clean
+.PHONY : xpdf/CMakeFiles/pdfinfo.dir/clean
+
+#=============================================================================
+# Target rules for target xpdf/CMakeFiles/pdfdetach.dir
+
+# All Build rule for target.
+xpdf/CMakeFiles/pdfdetach.dir/all: goo/CMakeFiles/goo.dir/all
+xpdf/CMakeFiles/pdfdetach.dir/all: fofi/CMakeFiles/fofi.dir/all
+xpdf/CMakeFiles/pdfdetach.dir/all: xpdf/CMakeFiles/xpdf_objs.dir/all
+ $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdfdetach.dir/build.make xpdf/CMakeFiles/pdfdetach.dir/depend
+ $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdfdetach.dir/build.make xpdf/CMakeFiles/pdfdetach.dir/build
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=13,14 "Built target pdfdetach"
+.PHONY : xpdf/CMakeFiles/pdfdetach.dir/all
+
+# Build rule for subdir invocation for target.
+xpdf/CMakeFiles/pdfdetach.dir/rule: cmake_check_build_system
+ $(CMAKE_COMMAND) -E cmake_progress_start /home/calvin/src/xpdf-4.04/CMakeFiles 46
+ $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 xpdf/CMakeFiles/pdfdetach.dir/all
+ $(CMAKE_COMMAND) -E cmake_progress_start /home/calvin/src/xpdf-4.04/CMakeFiles 0
+.PHONY : xpdf/CMakeFiles/pdfdetach.dir/rule
+
+# Convenience name for target.
+pdfdetach: xpdf/CMakeFiles/pdfdetach.dir/rule
+
+.PHONY : pdfdetach
+
+# clean rule for target.
+xpdf/CMakeFiles/pdfdetach.dir/clean:
+ $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdfdetach.dir/build.make xpdf/CMakeFiles/pdfdetach.dir/clean
+.PHONY : xpdf/CMakeFiles/pdfdetach.dir/clean
+
+#=============================================================================
+# Target rules for target xpdf/CMakeFiles/pdftops.dir
+
+# All Build rule for target.
+xpdf/CMakeFiles/pdftops.dir/all: goo/CMakeFiles/goo.dir/all
+xpdf/CMakeFiles/pdftops.dir/all: fofi/CMakeFiles/fofi.dir/all
+xpdf/CMakeFiles/pdftops.dir/all: splash/CMakeFiles/splash.dir/all
+xpdf/CMakeFiles/pdftops.dir/all: xpdf/CMakeFiles/xpdf_objs.dir/all
+ $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftops.dir/build.make xpdf/CMakeFiles/pdftops.dir/depend
+ $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftops.dir/build.make xpdf/CMakeFiles/pdftops.dir/build
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=31,32,33,34 "Built target pdftops"
+.PHONY : xpdf/CMakeFiles/pdftops.dir/all
+
+# Build rule for subdir invocation for target.
+xpdf/CMakeFiles/pdftops.dir/rule: cmake_check_build_system
+ $(CMAKE_COMMAND) -E cmake_progress_start /home/calvin/src/xpdf-4.04/CMakeFiles 60
+ $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 xpdf/CMakeFiles/pdftops.dir/all
+ $(CMAKE_COMMAND) -E cmake_progress_start /home/calvin/src/xpdf-4.04/CMakeFiles 0
+.PHONY : xpdf/CMakeFiles/pdftops.dir/rule
+
+# Convenience name for target.
+pdftops: xpdf/CMakeFiles/pdftops.dir/rule
+
+.PHONY : pdftops
+
+# clean rule for target.
+xpdf/CMakeFiles/pdftops.dir/clean:
+ $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftops.dir/build.make xpdf/CMakeFiles/pdftops.dir/clean
+.PHONY : xpdf/CMakeFiles/pdftops.dir/clean
+
+#=============================================================================
+# Target rules for target xpdf/CMakeFiles/pdffonts.dir
+
+# All Build rule for target.
+xpdf/CMakeFiles/pdffonts.dir/all: goo/CMakeFiles/goo.dir/all
+xpdf/CMakeFiles/pdffonts.dir/all: fofi/CMakeFiles/fofi.dir/all
+xpdf/CMakeFiles/pdffonts.dir/all: xpdf/CMakeFiles/xpdf_objs.dir/all
+ $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdffonts.dir/build.make xpdf/CMakeFiles/pdffonts.dir/depend
+ $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdffonts.dir/build.make xpdf/CMakeFiles/pdffonts.dir/build
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=15 "Built target pdffonts"
+.PHONY : xpdf/CMakeFiles/pdffonts.dir/all
+
+# Build rule for subdir invocation for target.
+xpdf/CMakeFiles/pdffonts.dir/rule: cmake_check_build_system
+ $(CMAKE_COMMAND) -E cmake_progress_start /home/calvin/src/xpdf-4.04/CMakeFiles 45
+ $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 xpdf/CMakeFiles/pdffonts.dir/all
+ $(CMAKE_COMMAND) -E cmake_progress_start /home/calvin/src/xpdf-4.04/CMakeFiles 0
+.PHONY : xpdf/CMakeFiles/pdffonts.dir/rule
+
+# Convenience name for target.
+pdffonts: xpdf/CMakeFiles/pdffonts.dir/rule
+
+.PHONY : pdffonts
+
+# clean rule for target.
+xpdf/CMakeFiles/pdffonts.dir/clean:
+ $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdffonts.dir/build.make xpdf/CMakeFiles/pdffonts.dir/clean
+.PHONY : xpdf/CMakeFiles/pdffonts.dir/clean
+
+#=============================================================================
+# Target rules for target xpdf/CMakeFiles/pdfimages.dir
+
+# All Build rule for target.
+xpdf/CMakeFiles/pdfimages.dir/all: goo/CMakeFiles/goo.dir/all
+xpdf/CMakeFiles/pdfimages.dir/all: fofi/CMakeFiles/fofi.dir/all
+xpdf/CMakeFiles/pdfimages.dir/all: xpdf/CMakeFiles/xpdf_objs.dir/all
+ $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdfimages.dir/build.make xpdf/CMakeFiles/pdfimages.dir/depend
+ $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdfimages.dir/build.make xpdf/CMakeFiles/pdfimages.dir/build
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=16,17 "Built target pdfimages"
+.PHONY : xpdf/CMakeFiles/pdfimages.dir/all
+
+# Build rule for subdir invocation for target.
+xpdf/CMakeFiles/pdfimages.dir/rule: cmake_check_build_system
+ $(CMAKE_COMMAND) -E cmake_progress_start /home/calvin/src/xpdf-4.04/CMakeFiles 46
+ $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 xpdf/CMakeFiles/pdfimages.dir/all
+ $(CMAKE_COMMAND) -E cmake_progress_start /home/calvin/src/xpdf-4.04/CMakeFiles 0
+.PHONY : xpdf/CMakeFiles/pdfimages.dir/rule
+
+# Convenience name for target.
+pdfimages: xpdf/CMakeFiles/pdfimages.dir/rule
+
+.PHONY : pdfimages
+
+# clean rule for target.
+xpdf/CMakeFiles/pdfimages.dir/clean:
+ $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdfimages.dir/build.make xpdf/CMakeFiles/pdfimages.dir/clean
+.PHONY : xpdf/CMakeFiles/pdfimages.dir/clean
+
+#=============================================================================
+# Target rules for target xpdf-qt/CMakeFiles/xpdf.dir
+
+# All Build rule for target.
+xpdf-qt/CMakeFiles/xpdf.dir/all: goo/CMakeFiles/goo_objs.dir/all
+xpdf-qt/CMakeFiles/xpdf.dir/all: fofi/CMakeFiles/fofi_objs.dir/all
+xpdf-qt/CMakeFiles/xpdf.dir/all: splash/CMakeFiles/splash_objs.dir/all
+xpdf-qt/CMakeFiles/xpdf.dir/all: xpdf/CMakeFiles/xpdf_objs.dir/all
+xpdf-qt/CMakeFiles/xpdf.dir/all: xpdf/CMakeFiles/xpdf_widget_objs.dir/all
+ $(MAKE) $(MAKESILENT) -f xpdf-qt/CMakeFiles/xpdf.dir/build.make xpdf-qt/CMakeFiles/xpdf.dir/depend
+ $(MAKE) $(MAKESILENT) -f xpdf-qt/CMakeFiles/xpdf.dir/build.make xpdf-qt/CMakeFiles/xpdf.dir/build
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=50,51,52,53,54,55,56,57,58,59,60 "Built target xpdf"
+.PHONY : xpdf-qt/CMakeFiles/xpdf.dir/all
+
+# Build rule for subdir invocation for target.
+xpdf-qt/CMakeFiles/xpdf.dir/rule: cmake_check_build_system
+ $(CMAKE_COMMAND) -E cmake_progress_start /home/calvin/src/xpdf-4.04/CMakeFiles 75
+ $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 xpdf-qt/CMakeFiles/xpdf.dir/all
+ $(CMAKE_COMMAND) -E cmake_progress_start /home/calvin/src/xpdf-4.04/CMakeFiles 0
+.PHONY : xpdf-qt/CMakeFiles/xpdf.dir/rule
+
+# Convenience name for target.
+xpdf: xpdf-qt/CMakeFiles/xpdf.dir/rule
+
+.PHONY : xpdf
+
+# clean rule for target.
+xpdf-qt/CMakeFiles/xpdf.dir/clean:
+ $(MAKE) $(MAKESILENT) -f xpdf-qt/CMakeFiles/xpdf.dir/build.make xpdf-qt/CMakeFiles/xpdf.dir/clean
+.PHONY : xpdf-qt/CMakeFiles/xpdf.dir/clean
+
+#=============================================================================
+# 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:
+ $(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/CMakeFiles/TargetDirectories.txt b/CMakeFiles/TargetDirectories.txt
new file mode 100644
index 0000000..5c9283c
--- /dev/null
+++ b/CMakeFiles/TargetDirectories.txt
@@ -0,0 +1,54 @@
+/home/calvin/src/xpdf-4.04/CMakeFiles/install/strip.dir
+/home/calvin/src/xpdf-4.04/CMakeFiles/install/local.dir
+/home/calvin/src/xpdf-4.04/CMakeFiles/install.dir
+/home/calvin/src/xpdf-4.04/CMakeFiles/list_install_components.dir
+/home/calvin/src/xpdf-4.04/CMakeFiles/rebuild_cache.dir
+/home/calvin/src/xpdf-4.04/CMakeFiles/edit_cache.dir
+/home/calvin/src/xpdf-4.04/goo/CMakeFiles/install/strip.dir
+/home/calvin/src/xpdf-4.04/goo/CMakeFiles/install/local.dir
+/home/calvin/src/xpdf-4.04/goo/CMakeFiles/install.dir
+/home/calvin/src/xpdf-4.04/goo/CMakeFiles/list_install_components.dir
+/home/calvin/src/xpdf-4.04/goo/CMakeFiles/rebuild_cache.dir
+/home/calvin/src/xpdf-4.04/goo/CMakeFiles/edit_cache.dir
+/home/calvin/src/xpdf-4.04/goo/CMakeFiles/goo.dir
+/home/calvin/src/xpdf-4.04/goo/CMakeFiles/goo_objs.dir
+/home/calvin/src/xpdf-4.04/fofi/CMakeFiles/install/strip.dir
+/home/calvin/src/xpdf-4.04/fofi/CMakeFiles/install/local.dir
+/home/calvin/src/xpdf-4.04/fofi/CMakeFiles/install.dir
+/home/calvin/src/xpdf-4.04/fofi/CMakeFiles/list_install_components.dir
+/home/calvin/src/xpdf-4.04/fofi/CMakeFiles/rebuild_cache.dir
+/home/calvin/src/xpdf-4.04/fofi/CMakeFiles/edit_cache.dir
+/home/calvin/src/xpdf-4.04/fofi/CMakeFiles/fofi.dir
+/home/calvin/src/xpdf-4.04/fofi/CMakeFiles/fofi_objs.dir
+/home/calvin/src/xpdf-4.04/splash/CMakeFiles/install/strip.dir
+/home/calvin/src/xpdf-4.04/splash/CMakeFiles/install/local.dir
+/home/calvin/src/xpdf-4.04/splash/CMakeFiles/install.dir
+/home/calvin/src/xpdf-4.04/splash/CMakeFiles/list_install_components.dir
+/home/calvin/src/xpdf-4.04/splash/CMakeFiles/rebuild_cache.dir
+/home/calvin/src/xpdf-4.04/splash/CMakeFiles/edit_cache.dir
+/home/calvin/src/xpdf-4.04/splash/CMakeFiles/splash.dir
+/home/calvin/src/xpdf-4.04/splash/CMakeFiles/splash_objs.dir
+/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/install/strip.dir
+/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/install/local.dir
+/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/list_install_components.dir
+/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_objs.dir
+/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/install.dir
+/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/pdftohtml.dir
+/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/pdftoppm.dir
+/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/pdftopng.dir
+/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/pdftotext.dir
+/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_widget_objs.dir
+/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/pdfinfo.dir
+/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/pdfdetach.dir
+/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/pdftops.dir
+/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/pdffonts.dir
+/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/rebuild_cache.dir
+/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/pdfimages.dir
+/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/edit_cache.dir
+/home/calvin/src/xpdf-4.04/xpdf-qt/CMakeFiles/install/strip.dir
+/home/calvin/src/xpdf-4.04/xpdf-qt/CMakeFiles/install/local.dir
+/home/calvin/src/xpdf-4.04/xpdf-qt/CMakeFiles/install.dir
+/home/calvin/src/xpdf-4.04/xpdf-qt/CMakeFiles/list_install_components.dir
+/home/calvin/src/xpdf-4.04/xpdf-qt/CMakeFiles/rebuild_cache.dir
+/home/calvin/src/xpdf-4.04/xpdf-qt/CMakeFiles/edit_cache.dir
+/home/calvin/src/xpdf-4.04/xpdf-qt/CMakeFiles/xpdf.dir
diff --git a/CMakeFiles/cmake.check_cache b/CMakeFiles/cmake.check_cache
new file mode 100644
index 0000000..3dccd73
--- /dev/null
+++ b/CMakeFiles/cmake.check_cache
@@ -0,0 +1 @@
+# This file is generated by cmake for dependency checking of the CMakeCache.txt file
diff --git a/CMakeFiles/progress.marks b/CMakeFiles/progress.marks
new file mode 100644
index 0000000..29d6383
--- /dev/null
+++ b/CMakeFiles/progress.marks
@@ -0,0 +1 @@
+100
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..90cefe3
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,41 @@
+#========================================================================
+#
+# cmake-xpdf.txt
+#
+# CMake script for the Xpdf package.
+#
+# Copyright 2021 Glyph & Cog, LLC
+#
+#========================================================================
+
+cmake_minimum_required(VERSION 2.8.12)
+
+project(xpdf)
+
+include(cmake-config.txt)
+
+add_subdirectory(goo)
+add_subdirectory(fofi)
+add_subdirectory(splash)
+add_subdirectory(xpdf)
+add_subdirectory(xpdf-qt)
+
+if (NOT HAVE_FREETYPE_H)
+ message(WARNING "Couldn't find FreeType -- will not build pdftoppm, pdftopng, pdftohtml, or xpdf.")
+endif ()
+
+if (NOT PNG_FOUND)
+ message(WARNING "Couldn't find libpng -- will not build pdftopng or pdftohtml.")
+endif ()
+
+if (NOT QT4_FOUND AND NOT Qt5Widgets_FOUND AND NOT Qt6Widgets_FOUND)
+ message(WARNING "Couldn't find Qt4/5/6 -- will not build xpdf.")
+endif ()
+
+if (NOT MULTITHREADED)
+ message(WARNING "Multithreading is disabled -- will not build xpdf.")
+endif ()
+
+if (NOT USE_EXCEPTIONS)
+ message(WARNING "C++ exceptions are disabled -- will not build xpdf.")
+endif ()
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..a43ea21
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/COPYING3 b/COPYING3
new file mode 100644
index 0000000..94a9ed0
--- /dev/null
+++ b/COPYING3
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ <program> Copyright (C) <year> <name of author>
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/INSTALL b/INSTALL
new file mode 100644
index 0000000..57ff61f
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,196 @@
+Xpdf
+====
+
+version 4.04
+2022-apr-18
+
+The Xpdf software and documentation are
+copyright 1996-2022 Glyph & Cog, LLC.
+
+Email: xpdf@xpdfreader.com
+WWW: http://www.xpdfreader.com/
+
+
+Compiling xpdf
+--------------
+
+Xpdf is written in C++ (with a little bit of C). It should work with
+any ANSI-compliant C++ and C compilers. The systems and compilers
+it's been tested with are listed on the xpdf web page.
+
+Xpdf requires the Qt toolkit. The non-GUI command line tools do not
+use Qt.
+
+The following notes give specific instructions for compiling on
+different systems.
+
+
+*********************
+*** Linux, OS X ***
+*********************
+
+* Make sure you have the following installed:
+
+ - CMake 2.8.8 or newer
+ - FreeType 2.0.5 or newer
+ - Qt 5.x or 6.x (for xpdf only)
+ - libpng (for pdftoppm and pdftohtml)
+ - zlib (for pdftoppm and pdftohtml)
+
+ If Qt isn't found, the GUI viewer (xpdf) won't be built, but the
+ command line tools will still be built.
+
+* Create a build directory. These instructions assume that you create
+ a directory called "build" under the top-level xpdf source
+ directory, but the build directory can be anywhere you like. Create
+ the directory and cd into it:
+
+ cd ..../xpdf-X.YY
+ mkdir build
+ cd build
+
+* Run cmake:
+
+ cmake -DCMAKE_BUILD_TYPE=Release {other options - see below} ..
+
+ If your build directory isn't under the source, use the full path to
+ the source directory:
+
+ cmake -DCMAKE_BUILD_TYPE=Release {other options} ..../xpdf-X.YY
+
+* If cmake doesn't find FreeType, you can set FREETYPE_DIR to point to
+ the FreeType install directory. Add this to the cmake command line:
+
+ -DFREETYPE_DIR=/opt/freetype
+
+ Cmake will look for ${FREETYPE_DIR}/include.
+
+ You can also set the FreeType library location with:
+
+ -DFREETYPE_LIBRARY=/opt/freetype/lib/libfreetype.so
+
+* If cmake doesn't find Qt, make sure qmake is on your executable
+ search path.
+
+* To change the xpdf install directory, use:
+
+ -DCMAKE_INSTALL_PREFIX=/opt/xpdf
+
+ If you're familiar with autoconf, this is similar to the "--prefix"
+ option.
+
+* Other configuration options are:
+
+ -DSPLASH_CMYK=ON
+ Enable CMYK rasterization support.
+
+ -DA4_PAPER=ON
+ Switches the default paper size for PostScript output (xpdf
+ and pdftops) to A4. The default is Letter size.
+
+ -DNO_TEXT_SELECT=ON
+ With this option, xpdf will not copy text. (This is only
+ useful on closed systems where the user can't get at the PDF
+ file directly.)
+
+ -DOPI_SUPPORT=ON
+ Enables support for generation of OPI (Open Prepress
+ Interface) comments with pdftops.
+
+ -DNO_FONTCONFIG=ON
+ Disables use of libfontconfig, which is used to locate system
+ fonts on Linux/Unix systems. The default is to search for the
+ library, and to use it if found.
+
+ -DMULTITHREADED=0
+ Disables multithreading, which also disables building the GUI
+ viewer (xpdf). This does not affect the command line tools.
+ Disabling multithreading should only be necessary if you're
+ building with a compiler other than gcc, clang, or Microsoft
+ Visual Studio.
+
+ -DXPDFWIDGET_PRINTING=OFF
+ Disable printing support.
+
+ -DSYSTEM_XPDFRC="/etc/xpdfrc"
+ Look for a system-wide xpdfrc config file in this directory.
+
+ -DXPDFRC_DATADIR="/usr/share/xpdf"
+ The ${DATADIR} variable in xpdfrc config files will expand to
+ this string.
+
+ -DCMAKE_DISABLE_FIND_PACKAGE_Qt4=1
+ -DCMAKE_DISABLE_FIND_PACKAGE_Qt5Widgets=1
+ Do not search for the Qt4/Qt5 libraries. This will disable
+ building the GUI viewer (xpdf). Cmake will look for a "qmake"
+ binary -- make sure the first qmake binary on your executable
+ search path matches the desired version of Qt.
+
+ -DCMAKE_C_FLAGS="..."
+ -DCMAKE_CXX_FLAGS="..."
+ Set additional options to pass to the C and/or C++ compilers.
+
+ -DCMAKE_EXE_LINKER_FLAGS="..."
+ Set additional options to pass to the linker.
+
+ -DCMAKE_INSTALL_BINDIR
+ Set the bin directory, relative to CMAKE_INSTALL_PREFIX
+ (typically "bin").
+
+ -DCMAKE_INSTALL_MANDIR
+ Set the man directory, relative to CMAKE_INSTALL_PREFIX
+ (typically "man" or "share/man").
+
+* Build:
+
+ make
+
+ This will build the executables in the build directory:
+
+ xpdf/xpdf
+ xpdf/pdftops
+ xpdf/pdftotext
+ xpdf/pdftohtml
+ xpdf/pdfinfo
+ xpdf/pdffonts
+ xpdf/pdfdetach
+ xpdf/pdftoppm
+ xpdf/pdftopng
+ xpdf/pdfimages
+ xpdf-qt/xpdf
+
+* If desired, install the binaries and man pages:
+
+ make install
+
+If you want to run a quick test, there is a tiny PDF file included
+with xpdf, as misc/hello.pdf .
+
+
+*****************
+*** Windows ***
+*****************
+
+The Windows build procedure is essentially the same as for Unix. If
+building with cygwin, the procedure is identical to Unix.
+
+If building with Visual Studio:
+
+* Make sure you have CMake, FreeType, libpng, and zlib installed.
+
+* You'll need to set the FREETYPE_DIR variable to point to your
+ FreeType installation, CMAKE_INCLUDE_PATH to point to your libpng
+ includes, CMAKE_LIBRARY_PATH to point to your libpng library, and
+ ZLIB_ROOT to point to your zlib installation.
+
+ cmake -G "NMake Makefiles"
+ -DCMAKE_BUILD_TYPE=Release
+ -DFREETYPE_DIR="c:/software/freetype"
+ -DCMAKE_INCLUDE_PATH="c:/software/libpng"
+ -DCMAKE_LIBRARY_PATH="c:/software/libpng"
+ -DZLIB_ROOT="c:/software/zlib"
+ ..
+
+* Build:
+
+ nmake
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..b469628
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,455 @@
+# 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 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 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 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
+ $(CMAKE_COMMAND) -E cmake_progress_start /home/calvin/src/xpdf-4.04/CMakeFiles /home/calvin/src/xpdf-4.04//CMakeFiles/progress.marks
+ $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 all
+ $(CMAKE_COMMAND) -E cmake_progress_start /home/calvin/src/xpdf-4.04/CMakeFiles 0
+.PHONY : all
+
+# The main clean target
+clean:
+ $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 clean
+.PHONY : clean
+
+# The main clean target
+clean/fast: clean
+
+.PHONY : clean/fast
+
+# Prepare targets for installation.
+preinstall: all
+ $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 preinstall
+.PHONY : preinstall
+
+# Prepare targets for installation.
+preinstall/fast:
+ $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 preinstall
+.PHONY : preinstall/fast
+
+# clear depends
+depend:
+ $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 1
+.PHONY : depend
+
+#=============================================================================
+# Target rules for targets named goo
+
+# Build rule for target.
+goo: cmake_check_build_system
+ $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 goo
+.PHONY : goo
+
+# fast build rule for target.
+goo/fast:
+ $(MAKE) $(MAKESILENT) -f goo/CMakeFiles/goo.dir/build.make goo/CMakeFiles/goo.dir/build
+.PHONY : goo/fast
+
+#=============================================================================
+# Target rules for targets named goo_objs
+
+# Build rule for target.
+goo_objs: cmake_check_build_system
+ $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 goo_objs
+.PHONY : goo_objs
+
+# fast build rule for target.
+goo_objs/fast:
+ $(MAKE) $(MAKESILENT) -f goo/CMakeFiles/goo_objs.dir/build.make goo/CMakeFiles/goo_objs.dir/build
+.PHONY : goo_objs/fast
+
+#=============================================================================
+# Target rules for targets named fofi
+
+# Build rule for target.
+fofi: cmake_check_build_system
+ $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 fofi
+.PHONY : fofi
+
+# fast build rule for target.
+fofi/fast:
+ $(MAKE) $(MAKESILENT) -f fofi/CMakeFiles/fofi.dir/build.make fofi/CMakeFiles/fofi.dir/build
+.PHONY : fofi/fast
+
+#=============================================================================
+# Target rules for targets named fofi_objs
+
+# Build rule for target.
+fofi_objs: cmake_check_build_system
+ $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 fofi_objs
+.PHONY : fofi_objs
+
+# fast build rule for target.
+fofi_objs/fast:
+ $(MAKE) $(MAKESILENT) -f fofi/CMakeFiles/fofi_objs.dir/build.make fofi/CMakeFiles/fofi_objs.dir/build
+.PHONY : fofi_objs/fast
+
+#=============================================================================
+# Target rules for targets named splash
+
+# Build rule for target.
+splash: cmake_check_build_system
+ $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 splash
+.PHONY : splash
+
+# fast build rule for target.
+splash/fast:
+ $(MAKE) $(MAKESILENT) -f splash/CMakeFiles/splash.dir/build.make splash/CMakeFiles/splash.dir/build
+.PHONY : splash/fast
+
+#=============================================================================
+# Target rules for targets named splash_objs
+
+# Build rule for target.
+splash_objs: cmake_check_build_system
+ $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 splash_objs
+.PHONY : splash_objs
+
+# fast build rule for target.
+splash_objs/fast:
+ $(MAKE) $(MAKESILENT) -f splash/CMakeFiles/splash_objs.dir/build.make splash/CMakeFiles/splash_objs.dir/build
+.PHONY : splash_objs/fast
+
+#=============================================================================
+# Target rules for targets named xpdf_objs
+
+# Build rule for target.
+xpdf_objs: cmake_check_build_system
+ $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 xpdf_objs
+.PHONY : xpdf_objs
+
+# fast build rule for target.
+xpdf_objs/fast:
+ $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_objs.dir/build.make xpdf/CMakeFiles/xpdf_objs.dir/build
+.PHONY : xpdf_objs/fast
+
+#=============================================================================
+# Target rules for targets named pdftohtml
+
+# Build rule for target.
+pdftohtml: cmake_check_build_system
+ $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 pdftohtml
+.PHONY : pdftohtml
+
+# fast build rule for target.
+pdftohtml/fast:
+ $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftohtml.dir/build.make xpdf/CMakeFiles/pdftohtml.dir/build
+.PHONY : pdftohtml/fast
+
+#=============================================================================
+# Target rules for targets named pdftoppm
+
+# Build rule for target.
+pdftoppm: cmake_check_build_system
+ $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 pdftoppm
+.PHONY : pdftoppm
+
+# fast build rule for target.
+pdftoppm/fast:
+ $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftoppm.dir/build.make xpdf/CMakeFiles/pdftoppm.dir/build
+.PHONY : pdftoppm/fast
+
+#=============================================================================
+# Target rules for targets named pdftopng
+
+# Build rule for target.
+pdftopng: cmake_check_build_system
+ $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 pdftopng
+.PHONY : pdftopng
+
+# fast build rule for target.
+pdftopng/fast:
+ $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftopng.dir/build.make xpdf/CMakeFiles/pdftopng.dir/build
+.PHONY : pdftopng/fast
+
+#=============================================================================
+# Target rules for targets named pdftotext
+
+# Build rule for target.
+pdftotext: cmake_check_build_system
+ $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 pdftotext
+.PHONY : pdftotext
+
+# fast build rule for target.
+pdftotext/fast:
+ $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftotext.dir/build.make xpdf/CMakeFiles/pdftotext.dir/build
+.PHONY : pdftotext/fast
+
+#=============================================================================
+# Target rules for targets named xpdf_widget_objs
+
+# Build rule for target.
+xpdf_widget_objs: cmake_check_build_system
+ $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 xpdf_widget_objs
+.PHONY : xpdf_widget_objs
+
+# fast build rule for target.
+xpdf_widget_objs/fast:
+ $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/xpdf_widget_objs.dir/build.make xpdf/CMakeFiles/xpdf_widget_objs.dir/build
+.PHONY : xpdf_widget_objs/fast
+
+#=============================================================================
+# Target rules for targets named pdfinfo
+
+# Build rule for target.
+pdfinfo: cmake_check_build_system
+ $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 pdfinfo
+.PHONY : pdfinfo
+
+# fast build rule for target.
+pdfinfo/fast:
+ $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdfinfo.dir/build.make xpdf/CMakeFiles/pdfinfo.dir/build
+.PHONY : pdfinfo/fast
+
+#=============================================================================
+# Target rules for targets named pdfdetach
+
+# Build rule for target.
+pdfdetach: cmake_check_build_system
+ $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 pdfdetach
+.PHONY : pdfdetach
+
+# fast build rule for target.
+pdfdetach/fast:
+ $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdfdetach.dir/build.make xpdf/CMakeFiles/pdfdetach.dir/build
+.PHONY : pdfdetach/fast
+
+#=============================================================================
+# Target rules for targets named pdftops
+
+# Build rule for target.
+pdftops: cmake_check_build_system
+ $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 pdftops
+.PHONY : pdftops
+
+# fast build rule for target.
+pdftops/fast:
+ $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdftops.dir/build.make xpdf/CMakeFiles/pdftops.dir/build
+.PHONY : pdftops/fast
+
+#=============================================================================
+# Target rules for targets named pdffonts
+
+# Build rule for target.
+pdffonts: cmake_check_build_system
+ $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 pdffonts
+.PHONY : pdffonts
+
+# fast build rule for target.
+pdffonts/fast:
+ $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdffonts.dir/build.make xpdf/CMakeFiles/pdffonts.dir/build
+.PHONY : pdffonts/fast
+
+#=============================================================================
+# Target rules for targets named pdfimages
+
+# Build rule for target.
+pdfimages: cmake_check_build_system
+ $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 pdfimages
+.PHONY : pdfimages
+
+# fast build rule for target.
+pdfimages/fast:
+ $(MAKE) $(MAKESILENT) -f xpdf/CMakeFiles/pdfimages.dir/build.make xpdf/CMakeFiles/pdfimages.dir/build
+.PHONY : pdfimages/fast
+
+#=============================================================================
+# Target rules for targets named xpdf
+
+# Build rule for target.
+xpdf: cmake_check_build_system
+ $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 xpdf
+.PHONY : xpdf
+
+# fast build rule for target.
+xpdf/fast:
+ $(MAKE) $(MAKESILENT) -f xpdf-qt/CMakeFiles/xpdf.dir/build.make xpdf-qt/CMakeFiles/xpdf.dir/build
+.PHONY : xpdf/fast
+
+# 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 "... fofi"
+ @echo "... fofi_objs"
+ @echo "... goo"
+ @echo "... goo_objs"
+ @echo "... pdfdetach"
+ @echo "... pdffonts"
+ @echo "... pdfimages"
+ @echo "... pdfinfo"
+ @echo "... pdftohtml"
+ @echo "... pdftopng"
+ @echo "... pdftoppm"
+ @echo "... pdftops"
+ @echo "... pdftotext"
+ @echo "... splash"
+ @echo "... splash_objs"
+ @echo "... xpdf"
+ @echo "... xpdf_objs"
+ @echo "... xpdf_widget_objs"
+.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:
+ $(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/README b/README
new file mode 100644
index 0000000..026460d
--- /dev/null
+++ b/README
@@ -0,0 +1,392 @@
+Xpdf
+====
+
+version 4.04
+2022-apr-18
+
+The Xpdf software and documentation are
+copyright 1996-2022 Glyph & Cog, LLC.
+
+Email: xpdf@xpdfreader.com
+WWW: http://www.xpdfreader.com/
+
+The PDF data structures, operators, and specification are
+documented in ISO 32000-2:2020.
+
+
+What is Xpdf?
+-------------
+
+Xpdf is an open source viewer for Portable Document Format (PDF)
+files. (These are also sometimes also called 'Acrobat' files, from
+the name of Adobe's PDF software.) The Xpdf project also includes a
+PDF text extractor, PDF-to-PostScript converter, and various other
+utilities.
+
+The Xpdf viewer uses the Qt cross-platform GUI toolkit. The other
+command line utilties do not require Qt.
+
+
+License & Distribution
+----------------------
+
+Xpdf is licensed under the GNU General Public License (GPL), version 2
+or 3. This means that you can distribute derivatives of Xpdf under
+any of the following:
+ - GPL v2 only
+ - GPL v3 only
+ - GPL v2 or v3
+
+The Xpdf source package includes the text of both GPL versions:
+COPYING for GPL v2, COPYING3 for GPL v3.
+
+Please note that Xpdf is NOT licensed under "any later version" of the
+GPL, as I have no idea what those versions will look like.
+
+If you are redistributing unmodified copies of Xpdf (or any of the
+Xpdf tools) in binary form, you need to include all of the
+documentation: README, man pages (or help files), COPYING, and
+COPYING3.
+
+If you want to incorporate the Xpdf source code into another program
+(or create a modified version of Xpdf), and you are distributing that
+program, you have two options: release your program under the GPL (v2
+and/or v3), or purchase a commercial Xpdf source license.
+
+If you're interested in commercial licensing, please see the Glyph &
+Cog web site:
+
+ http://www.glyphandcog.com/
+
+
+Compatibility
+-------------
+
+Xpdf uses the Qt toolkit and runs on Linux, Windows, and OS X -- and
+probably other systems that have a Qt port.
+
+The non-GUI command line utilities (pdftops, pdftotext, pdftohtml,
+pdfinfo, pdffonts, pdfdetach, pdftoppm, pdftopng, and pdfimages) run
+on Linux, Windows, and OS X -- and should run on pretty much any
+system with a decent C++ compiler.
+
+If you compile Xpdf for a system not listed on the web page, please
+let me know. If you're willing to make your binary available by ftp
+or on the web, I'll be happy to add a link from the Xpdf web page. I
+have decided not to host any binaries I didn't compile myself (for
+disk space and support reasons).
+
+If you can't get Xpdf to compile on your system, send me email and
+I'll try to help.
+
+
+Getting Xpdf
+------------
+
+The latest version is available from:
+
+ http://www.xpdfreader.com/
+
+Source code and several precompiled executables are available.
+
+Announcements of new versions are posted to comp.text.pdf and emailed
+to a list of people. If you'd like to receive email notification of
+new versions, just let me know.
+
+
+Running Xpdf
+------------
+
+To run xpdf, simply type:
+
+ xpdf file.pdf
+
+To generate a PostScript file, run pdftops:
+
+ pdftops file.pdf
+
+To generate a plain text file, run pdftotext:
+
+ pdftotext file.pdf
+
+There are several additional utilities (which are fully described in
+their man pages):
+
+ pdftohtml -- converts a PDF file to HTML
+ pdfinfo -- dumps a PDF file's Info dictionary (plus some other
+ useful information)
+ pdffonts -- lists the fonts used in a PDF file along with various
+ information for each font
+ pdfdetach -- lists or extracts embedded files (attachments) from a
+ PDF file
+ pdftoppm -- converts a PDF file to a series of PPM/PGM/PBM-format
+ bitmaps
+ pdftopng -- converts a PDF file to a series of PNG image files
+ pdfimages -- extracts the images from a PDF file
+
+Command line options and many other details are described in the man
+pages: xpdf(1), etc.
+
+All of these utilities read an optional configuration file: see the
+xpdfrc(5) man page.
+
+
+Compiling Xpdf
+--------------
+
+See the separate file, INSTALL.
+
+
+Bugs
+----
+
+If you find a bug in Xpdf, i.e., if it prints an error message,
+crashes, or incorrectly displays a document, and you don't see that
+bug listed here, please send me email, with a pointer (URL, ftp site,
+etc.) to the PDF file.
+
+
+Third-Party Libraries
+---------------------
+
+Xpdf uses the following libraries:
+* FreeType [http://www.freetype.org/]
+* libpng [http://www.libpng.com/pub/png/libpng.html] (used by pdftohtml
+ and pdftopng)
+* zlib [http://zlib.net/] (used by pdftohtml)
+* Qt [https://www.qt.io/]
+
+
+Acknowledgments
+---------------
+
+Thanks to:
+
+* Patrick Voigt for help with the remote server code.
+* Patrick Moreau, Martin P.J. Zinser, and David Mathog for the VMS
+ port.
+* David Boldt and Rick Rodgers for sample man pages.
+* Brendan Miller for the icon idea.
+* Olly Betts for help testing pdftotext.
+* Peter Ganten for the OS/2 port.
+* Michael Richmond for the Win32 port of pdftops and pdftotext and the
+ xpdf/cygwin/XFree86 build instructions.
+* Frank M. Siegert for improvements in the PostScript code.
+* Leo Smiers for the decryption patches.
+* Rainer Menzner for creating t1lib, and for helping me adapt it to
+ xpdf.
+* Pine Tree Systems A/S for funding the OPI and EPS support in
+ pdftops.
+* Easy Software Products for funding several improvements to the
+ PostScript output code.
+* Tom Kacvinsky for help with FreeType and for being my interface to
+ the FreeType team.
+* Theppitak Karoonboonyanan for help with Thai support.
+* Leonard Rosenthol for help and contributions on a bunch of things.
+* Alexandros Diamantidis and Maria Adaloglou for help with Greek
+ support.
+* Lawrence Lai for help with the CJK Unicode maps.
+
+Various people have contributed modifications made for use by the
+pdftex project:
+
+* Han The Thanh
+* Martin Schröder of ArtCom GmbH
+
+
+References
+----------
+
+Adobe Systems Inc., _PostScript Language Reference_, 3rd ed.
+Addison-Wesley, 1999, ISBN 0-201-37922-8.
+[The official PostScript manual.]
+
+Adobe Systems, Inc., _The Type 42 Font Format Specification_,
+Adobe Developer Support Technical Specification #5012. 1998.
+http://partners.adobe.com/asn/developer/pdfs/tn/5012.Type42_Spec.pdf
+[Type 42 is the format used to embed TrueType fonts in PostScript
+files.]
+
+Adobe Systems, Inc., _Adobe CMap and CIDFont Files Specification_,
+Adobe Developer Support Technical Specification #5014. 1995.
+http://www.adobe.com/supportservice/devrelations/PDFS/TN/5014.CIDFont_Spec.pdf
+[CMap file format needed for Japanese and Chinese font support.]
+
+Adobe Systems, Inc., _Adobe-Japan1-4 Character Collection for
+CID-Keyed Fonts_, Adobe Developer Support Technical Note #5078.
+2000.
+http://partners.adobe.com/asn/developer/PDFS/TN/5078.CID_Glyph.pdf
+[The Adobe Japanese character set.]
+
+Adobe Systems, Inc., _Adobe-GB1-4 Character Collection for
+CID-Keyed Fonts_, Adobe Developer Support Technical Note #5079.
+2000.
+http://partners.adobe.com/asn/developer/pdfs/tn/5079.Adobe-GB1-4.pdf
+[The Adobe Chinese GB (simplified) character set.]
+
+Adobe Systems, Inc., _Adobe-CNS1-3 Character Collection for
+CID-Keyed Fonts_, Adobe Developer Support Technical Note #5080.
+2000.
+http://partners.adobe.com/asn/developer/PDFS/TN/5080.CNS_CharColl.pdf
+[The Adobe Chinese CNS (traditional) character set.]
+
+Adobe Systems Inc., _Supporting the DCT Filters in PostScript Level
+2_, Adobe Developer Support Technical Note #5116. 1992.
+http://www.adobe.com/supportservice/devrelations/PDFS/TN/5116.PS2_DCT.PDF
+[Description of the DCTDecode filter parameters.]
+
+Adobe Systems Inc., _Open Prepress Interface (OPI) Specification -
+Version 2.0_, Adobe Developer Support Technical Note #5660. 2000.
+http://partners.adobe.com/asn/developer/PDFS/TN/5660.OPI_2.0.pdf
+
+Adobe Systems Inc., CMap files.
+ftp://ftp.oreilly.com/pub/examples/nutshell/cjkv/adobe/
+[The actual CMap files for the 16-bit CJK encodings.]
+
+Adobe Systems Inc., Unicode glyph lists.
+http://partners.adobe.com/asn/developer/type/unicodegn.html
+http://partners.adobe.com/asn/developer/type/glyphlist.txt
+http://partners.adobe.com/asn/developer/type/corporateuse.txt
+http://partners.adobe.com/asn/developer/type/zapfdingbats.txt
+[Mappings between character names to Unicode.]
+
+Adobe Systems Inc., OpenType Specification v. 1.4.
+http://partners.adobe.com/public/developer/opentype/index_spec.html
+[The OpenType font format spec.]
+
+Aldus Corp., _OPI: Open Prepress Interface Specification 1.3_. 1993.
+http://partners.adobe.com/asn/developer/PDFS/TN/OPI_13.pdf
+
+Anonymous, RC4 source code.
+ftp://ftp.ox.ac.uk/pub/crypto/misc/rc4.tar.gz
+ftp://idea.sec.dsi.unimi.it/pub/crypt/code/rc4.tar.gz
+[This is the algorithm used to encrypt PDF files.]
+
+T. Boutell, et al., "PNG (Portable Network Graphics) Specification,
+Version 1.0". RFC 2083.
+[PDF uses the PNG filter algorithms.]
+
+CCITT, "Information Technology - Digital Compression and Coding of
+Continuous-tone Still Images - Requirements and Guidelines", CCITT
+Recommendation T.81.
+http://www.w3.org/Graphics/JPEG/
+[The official JPEG spec.]
+
+A. Chernov, "Registration of a Cyrillic Character Set". RFC 1489.
+[Documentation for the KOI8-R Cyrillic encoding.]
+
+Roman Czyborra, "The ISO 8859 Alphabet Soup".
+http://czyborra.com/charsets/iso8859.html
+[Documentation on the various ISO 859 encodings.]
+
+L. Peter Deutsch, "ZLIB Compressed Data Format Specification version
+3.3". RFC 1950.
+[Information on the general format used in FlateDecode streams.]
+
+L. Peter Deutsch, "DEFLATE Compressed Data Format Specification
+version 1.3". RFC 1951.
+[The definition of the compression algorithm used in FlateDecode
+streams.]
+
+Morris Dworkin, "Recommendation for Block Cipher Modes of Operation",
+National Institute of Standards, NIST Special Publication 800-38A,
+2001.
+[The cipher block chaining (CBC) mode used with AES in PDF files.]
+
+Federal Information Processing Standards Publication 197 (FIPS PUBS
+197), "Advanced Encryption Standard (AES)", November 26, 2001.
+[AES encryption, used in PDF 1.6.]
+
+Jim Flowers, "X Logical Font Description Conventions", Version 1.5, X
+Consortium Standard, X Version 11, Release 6.1.
+ftp://ftp.x.org/pub/R6.1/xc/doc/hardcopy/XLFD/xlfd.PS.Z
+[The official specification of X font descriptors, including font
+transformation matrices.]
+
+Foley, van Dam, Feiner, and Hughes, _Computer Graphics: Principles and
+Practice_, 2nd ed. Addison-Wesley, 1990, ISBN 0-201-12110-7.
+[Colorspace conversion functions, Bezier spline math.]
+
+Robert L. Hummel, _Programmer's Technical Reference: Data and Fax
+Communications_. Ziff-Davis Press, 1993, ISBN 1-56276-077-7.
+[CCITT Group 3 and 4 fax decoding.]
+
+ISO/IEC, _Information technology -- Lossy/lossless coding of bi-level
+images_. ISO/IEC 14492, First edition (2001-12-15).
+http://webstore.ansi.org/
+[The official JBIG2 standard. The final draft of this spec is
+available from http://www.jpeg.org/jbighomepage.html.]
+
+ISO/IEC, _Information technology -- JPEG 2000 image coding system --
+Part 1: Core coding system_. ISO/IEC 15444-1, First edition
+(2000-12-15).
+http://webstore.ansi.org/
+[The official JPEG 2000 standard. The final committee draft of this
+spec is available from http://www.jpeg.org/JPEG2000.html, but there
+were changes made to the bitstream format between that draft and the
+published spec.]
+
+ISO, International Standard -- Document Management - Portable document
+format - Part 2: PDF 2.0. ISO 32000-2:2020.
+[The specification for PDF version 2.0.]
+
+ITU, "Standardization of Group 3 facsimile terminals for document
+transmission", ITU-T Recommendation T.4, 1999.
+ITU, "Facsimile coding schemes and coding control functions for Group 4
+facsimile apparatus", ITU-T Recommendation T.6, 1993.
+http://www.itu.int/
+[The official Group 3 and 4 fax standards - used by the CCITTFaxDecode
+stream, as well as the JBIG2Decode stream.]
+
+B. Kaliski, "PKCS #5: Password-Based Cryptography Specification,
+Version 2.0". RFC 2898.
+[Defines the padding scheme used with AES encryption in PDF files.]
+
+Christoph Loeffler, Adriaan Ligtenberg, George S. Moschytz, "Practical
+Fast 1-D DCT Algorithms with 11 Multiplications". IEEE Intl. Conf. on
+Acoustics, Speech & Signal Processing, 1989, 988-991.
+[The fast IDCT algorithm used in the DCTDecode filter.]
+
+Microsoft, _TrueType 1.0 Font Files_, rev. 1.66. 1995.
+http://www.microsoft.com/typography/tt/tt.htm
+[The TrueType font spec (in MS Word format, naturally).]
+
+V. Ostromoukhov, R.D. Hersch, "Stochastic Clustered-Dot Dithering",
+Conf. Color Imaging: Device-Independent Color, Color Hardcopy, and
+Graphic Arts IV, 1999, SPIE Vol. 3648, 496-505.
+http://diwww.epfl.ch/w3lsp/publications/colour/scd.html
+[The stochastic dithering algorithm used in Xpdf.]
+
+P. Peterlin, "ISO 8859-2 (Latin 2) Resources".
+http://sizif.mf.uni-lj.si/linux/cee/iso8859-2.html
+[This is a web page with all sorts of useful Latin-2 character set and
+font information.]
+
+Charles Poynton, "Color FAQ".
+http://www.inforamp.net/~poynton/ColorFAQ.html
+[The mapping from the CIE 1931 (XYZ) color space to RGB.]
+
+R. Rivest, "The MD5 Message-Digest Algorithm". RFC 1321.
+[MD5 is used in PDF document encryption.]
+
+Thai Industrial Standard, "Standard for Thai Character Codes for
+Computers", TIS-620-2533 (1990).
+http://www.nectec.or.th/it-standards/std620/std620.htm
+[The TIS-620 Thai encoding.]
+
+Unicode Consortium, "Unicode Home Page".
+http://www.unicode.org/
+[Online copy of the Unicode spec.]
+
+W3C Recommendation, "PNG (Portable Network Graphics) Specification
+Version 1.0".
+http://www.w3.org/Graphics/PNG/
+[Defines the PNG image predictor.]
+
+Gregory K. Wallace, "The JPEG Still Picture Compression Standard".
+ftp://ftp.uu.net/graphics/jpeg/wallace.ps.gz
+[Good description of the JPEG standard. Also published in CACM, April
+1991, and submitted to IEEE Transactions on Consumer Electronics.]
+
+F. Yergeau, "UTF-8, a transformation format of ISO 10646". RFC 2279.
+[A commonly used Unicode encoding.]
diff --git a/aconf.h b/aconf.h
new file mode 100644
index 0000000..9a2e7f7
--- /dev/null
+++ b/aconf.h
@@ -0,0 +1,124 @@
+/*
+ * aconf.h
+ *
+ * This file is modified by cmake.
+ *
+ * Copyright 2002-2015 Glyph & Cog, LLC
+ */
+
+#ifndef ACONF_H
+#define ACONF_H
+
+#include <aconf2.h>
+
+/*
+ * Use A4 paper size instead of Letter for PostScript output.
+ */
+/* #undef A4_PAPER */
+
+/*
+ * Do not allow text selection.
+ */
+/* #undef NO_TEXT_SELECT */
+
+/*
+ * Include support for OPI comments.
+ */
+#define OPI_SUPPORT 0
+
+/*
+ * Enable multithreading support.
+ */
+#define MULTITHREADED 1
+
+/*
+ * Enable C++ exceptions.
+ */
+#define USE_EXCEPTIONS 1
+
+/*
+ * Use fixed point (instead of floating point) arithmetic.
+ */
+#define USE_FIXEDPOINT 0
+
+/*
+ * Enable support for CMYK output.
+ */
+#define SPLASH_CMYK 0
+
+/*
+ * Enable support for DeviceN output.
+ */
+#define SPLASH_DEVICEN 0
+
+/*
+ * Enable support for highlighted regions.
+ */
+/* #undef HIGHLIGHTED_REGIONS */
+
+/*
+ * Full path for the system-wide xpdfrc file.
+ */
+/* #undef SYSTEM_XPDFRC */
+
+/*
+ * Directory to use for the variable in the xpdfrc config
+ * file.
+ */
+/* #undef XPDFRC_DATADIR */
+
+/*
+ * Various include files and functions.
+ */
+#define HAVE_MKSTEMP 1
+#define HAVE_MKSTEMPS 1
+#define HAVE_POPEN
+#define HAVE_STD_SORT 1
+#define HAVE_FSEEKO 1
+#define HAVE_FSEEK64 0
+#define HAVE_FSEEKI64 0
+#define _FILE_OFFSET_BITS 64
+#define _LARGE_FILES 1
+#define _LARGEFILE_SOURCE 1
+
+/*
+ * This is defined if using FreeType 2.
+ */
+#define HAVE_FREETYPE_H 1
+
+/*
+ * This is defined if using D-Type 4.
+ */
+#define HAVE_DTYPE4_H 0
+
+/*
+ * This is defined if using libpaper.
+ */
+#define HAVE_PAPER_H 0
+
+/*
+ * This is defined if using libfontconfig.
+ */
+#define HAVE_FONTCONFIG 1
+
+/*
+ * Defined if the Splash library is avaiable.
+ */
+#define HAVE_SPLASH 1
+
+/*
+ * Defined if using lcms2.
+ */
+#define HAVE_LCMS 0
+
+/*
+ * Defined for evaluation mode.
+ */
+#define EVAL_MODE 0
+
+/*
+ * Defined when building the closed source XpdfReader binary.
+ */
+#define BUILDING_XPDFREADER 0
+
+#endif
diff --git a/aconf.h.in b/aconf.h.in
new file mode 100644
index 0000000..99eb78b
--- /dev/null
+++ b/aconf.h.in
@@ -0,0 +1,124 @@
+/*
+ * aconf.h
+ *
+ * This file is modified by cmake.
+ *
+ * Copyright 2002-2015 Glyph & Cog, LLC
+ */
+
+#ifndef ACONF_H
+#define ACONF_H
+
+#include <aconf2.h>
+
+/*
+ * Use A4 paper size instead of Letter for PostScript output.
+ */
+#cmakedefine A4_PAPER
+
+/*
+ * Do not allow text selection.
+ */
+#cmakedefine NO_TEXT_SELECT
+
+/*
+ * Include support for OPI comments.
+ */
+#cmakedefine01 OPI_SUPPORT
+
+/*
+ * Enable multithreading support.
+ */
+#cmakedefine01 MULTITHREADED
+
+/*
+ * Enable C++ exceptions.
+ */
+#cmakedefine01 USE_EXCEPTIONS
+
+/*
+ * Use fixed point (instead of floating point) arithmetic.
+ */
+#cmakedefine01 USE_FIXEDPOINT
+
+/*
+ * Enable support for CMYK output.
+ */
+#cmakedefine01 SPLASH_CMYK
+
+/*
+ * Enable support for DeviceN output.
+ */
+#cmakedefine01 SPLASH_DEVICEN
+
+/*
+ * Enable support for highlighted regions.
+ */
+#cmakedefine HIGHLIGHTED_REGIONS
+
+/*
+ * Full path for the system-wide xpdfrc file.
+ */
+@SYSTEM_XPDFRC_DEFINE@
+
+/*
+ * Directory to use for the ${DATADIR} variable in the xpdfrc config
+ * file.
+ */
+@XPDFRC_DATADIR_DEFINE@
+
+/*
+ * Various include files and functions.
+ */
+#cmakedefine01 HAVE_MKSTEMP
+#cmakedefine01 HAVE_MKSTEMPS
+#cmakedefine HAVE_POPEN
+#cmakedefine01 HAVE_STD_SORT
+#cmakedefine01 HAVE_FSEEKO
+#cmakedefine01 HAVE_FSEEK64
+#cmakedefine01 HAVE_FSEEKI64
+#define _FILE_OFFSET_BITS 64
+#define _LARGE_FILES 1
+#define _LARGEFILE_SOURCE 1
+
+/*
+ * This is defined if using FreeType 2.
+ */
+#cmakedefine01 HAVE_FREETYPE_H
+
+/*
+ * This is defined if using D-Type 4.
+ */
+#cmakedefine01 HAVE_DTYPE4_H
+
+/*
+ * This is defined if using libpaper.
+ */
+#cmakedefine01 HAVE_PAPER_H
+
+/*
+ * This is defined if using libfontconfig.
+ */
+#cmakedefine01 HAVE_FONTCONFIG
+
+/*
+ * Defined if the Splash library is avaiable.
+ */
+#cmakedefine01 HAVE_SPLASH
+
+/*
+ * Defined if using lcms2.
+ */
+#cmakedefine01 HAVE_LCMS
+
+/*
+ * Defined for evaluation mode.
+ */
+#cmakedefine01 EVAL_MODE
+
+/*
+ * Defined when building the closed source XpdfReader binary.
+ */
+#cmakedefine01 BUILDING_XPDFREADER
+
+#endif
diff --git a/aconf2.h b/aconf2.h
new file mode 100644
index 0000000..05d785c
--- /dev/null
+++ b/aconf2.h
@@ -0,0 +1,41 @@
+/*
+ * aconf2.h
+ *
+ * This gets included by aconf.h, and contains miscellaneous global
+ * settings not directly controlled by autoconf. This is a separate
+ * file because otherwise the configure script will munge any
+ * #define/#undef constructs.
+ *
+ * Copyright 2002-2003 Glyph & Cog, LLC
+ */
+
+#ifndef ACONF2_H
+#define ACONF2_H
+
+/*
+ * This controls the use of the interface/implementation pragmas.
+ */
+#if defined(__GNUC__) && !defined(__clang__)
+#define USE_GCC_PRAGMAS
+#endif
+/* There is a bug in the version of gcc which ships with MacOS X 10.2 */
+#if defined(__APPLE__) && defined(__MACH__)
+# include <AvailabilityMacros.h>
+#endif
+#ifdef MAC_OS_X_VERSION_MAX_ALLOWED
+# if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_2
+# undef USE_GCC_PRAGMAS
+# endif
+#endif
+
+/*
+ * Speed up Windows compilation. This will only work for the command
+ * line tools.
+ */
+/*
+ *#ifdef _WIN32
+ *# define WIN32_LEAN_AND_MEAN
+ *#endif
+ */
+
+#endif
diff --git a/cmake-config.txt b/cmake-config.txt
new file mode 100644
index 0000000..f9339b9
--- /dev/null
+++ b/cmake-config.txt
@@ -0,0 +1,333 @@
+#========================================================================
+#
+# cmake-config.txt
+#
+# CMake script to do misc cmake config and platform-specific config.
+#
+# Copyright 2021 Glyph & Cog, LLC
+#
+#========================================================================
+
+if (POLICY CMP0074)
+ cmake_policy(SET CMP0074 NEW)
+endif ()
+
+if (APPLE)
+ if (POLICY CMP0042)
+ cmake_policy(SET CMP0042 NEW)
+ endif ()
+ set(CMAKE_MACOSX_RPATH 1)
+endif ()
+
+include(CheckFunctionExists)
+include(CheckCXXSourceCompiles)
+include(GNUInstallDirs)
+
+enable_language(CXX)
+
+#--- add a 'Profiling' build mode
+if (CMAKE_GENERATOR STREQUAL "Unix Makefiles")
+ set(CMAKE_C_FLAGS_PROFILING "-g -pg -O -Wall"
+ CACHE STRING "C compiler flags for profiling mode"
+ FORCE)
+ set(CMAKE_CXX_FLAGS_PROFILING "-g -pg -O -Wall"
+ CACHE STRING "C++ compiler flags for profiling mode"
+ FORCE)
+ set(CMAKE_EXE_LINKER_FLAGS_PROFILING "-g -pg -O -Wall"
+ CACHE STRING "linker flags for profiling mode"
+ FORCE)
+ set(CMAKE_SHARED_LINKER_FLAGS_PROFILING "-g -pg -O -Wall"
+ CACHE STRING "shared linker flags for profiling mode"
+ FORCE)
+ mark_as_advanced(
+ CMAKE_C_FLAGS_PROFILING
+ CMAKE_CXX_FLAGS_PROFILING
+ CMAKE_EXE_LINKER_FLAGS_PROFILING
+ CMAKE_SHARED_LINKER_FLAGS_PROFILING)
+ set(CMAKE_BUILD_TYPE "${CMAKE_BUILD_TYPE}" CACHE STRING
+ "Choose build mode - options are: None Debug Release RelWithDebInfo MinSizeRel Profiling"
+ FORCE)
+endif ()
+
+#--- set default C/C++ compiler flags for Windows
+if (MSVC)
+ option(USE_MT_IN_DEBUG "use /MT instead of /MTd in debug builds" OFF)
+ foreach (var CMAKE_C_FLAGS_DEBUG CMAKE_CXX_FLAGS_DEBUG
+ CMAKE_C_FLAGS_RELEASE CMAKE_CXX_FLAGS_RELEASE
+ CMAKE_C_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_MINSIZEREL
+ CMAKE_C_FLAGS_RELWITHDEBINFO CMAKE_CXX_FLAGS_RELWITHDEBINFO)
+ # note: this converts /MD to /MT and /MDd to /MTd
+ string(REGEX REPLACE "/MD" "/MT" ${var} "${${var}}")
+ endforeach ()
+ if (USE_MT_IN_DEBUG)
+ string(REPLACE "/MTd" "/MT" CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}")
+ string(REPLACE "/MTd" "/MT" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
+ else ()
+ set(CMAKE_EXE_LINKER_FLAGS_DEBUG "/NODEFAULTLIB:libcmt ${CMAKE_EXE_LINKER_FLAGS_DEBUG}")
+ set(CMAKE_SHARED_LINKER_FLAGS_DEBUG "/NODEFAULTLIB:libcmt ${CMAKE_SHARED_LINKER_FLAGS_DEBUG}")
+ endif ()
+ foreach (var CMAKE_C_FLAGS_DEBUG
+ CMAKE_C_FLAGS_RELEASE
+ CMAKE_C_FLAGS_MINSIZEREL
+ CMAKE_C_FLAGS_RELWITHDEBINFO)
+ set(${var} "${${var}} /D_CRT_SECURE_NO_WARNINGS /wd4290 /wd4996")
+ endforeach ()
+ foreach (var CMAKE_CXX_FLAGS_DEBUG
+ CMAKE_CXX_FLAGS_RELEASE
+ CMAKE_CXX_FLAGS_MINSIZEREL
+ CMAKE_CXX_FLAGS_RELWITHDEBINFO)
+ set(${var} "${${var}} /D_CRT_SECURE_NO_WARNINGS /wd4290 /wd4996 /EHsc")
+ endforeach ()
+endif ()
+
+#--- don't set an rpath
+set(CMAKE_SKIP_RPATH FALSE)
+
+#--- miscellaneous options
+option(A4_PAPER "use A4 (instead of Letter) paper size by default for PostScript output" OFF)
+option(NO_TEXT_SELECT "do not allow text selection" OFF)
+option(OPI_SUPPORT "include support for OPI comments" OFF)
+option(MULTITHREADED "include support for multithreading" ON)
+option(USE_EXCEPTIONS "use C++ exceptions" ON)
+option(USE_FIXEDPOINT "use fixed point (instead of floating point) arithmetic" OFF)
+option(SPLASH_CMYK "include support for CMYK rasterization" OFF)
+option(NO_FONTCONFIG "disable support for libfontconfig" OFF)
+option(SYSTEM_XPDFRC "full path for system-wide xpdfrc file" "")
+if (SYSTEM_XPDFRC)
+ set(SYSTEM_XPDFRC_DEFINE "#define SYSTEM_XPDFRC \"${SYSTEM_XPDFRC}\"")
+else ()
+ set(SYSTEM_XPDFRC_DEFINE "/* #undef SYSTEM_XPDFRC */")
+endif ()
+option(XPDFRC_DATADIR "directory to use for the DATADIR xpdfrc variable" "")
+if (XPDFRC_DATADIR)
+ set(XPDFRC_DATADIR_DEFINE "#define XPDFRC_DATADIR \"${XPDFRC_DATADIR}\"")
+else ()
+ set(XPDFRC_DATADIR_DEFINE "/* #undef XPDFRC_DATADIR */")
+endif ()
+if (WIN32)
+ option(XPDFWIDGET_PRINTING "include printing support in XpdfWidget" OFF)
+else ()
+ option(XPDFWIDGET_PRINTING "include printing support in XpdfWidget" ON)
+endif ()
+
+#--- check for various library functions
+check_function_exists(mkstemp HAVE_MKSTEMP)
+check_function_exists(mkstemps HAVE_MKSTEMPS)
+check_function_exists(popen HAVE_POPEN)
+check_cxx_source_compiles(
+ "#include <algorithm>
+ bool cmp(const int &x, const int &y) { return x < y; }
+ int a[100];
+ int main() { std::sort(a, a+100, &cmp); }"
+ HAVE_STD_SORT)
+
+#--- set up 64-bit file seeks
+check_function_exists(fseeko HAVE_FSEEKO)
+check_function_exists(fseek64 HAVE_FSEEK64)
+check_function_exists(_fseeki64 HAVE_FSEEKI64)
+
+#--- look for FreeType
+# This could use cmake's FindFreetype, except that it would require
+# a newer version of cmake -- because FreeType changed their include
+# paths around. Older versions of FreeType require two separate
+# -I switches (typically ..../include and ..../include/freetype2);
+# while newer versions require just one (typically ..../include/freetype2)
+find_path(FREETYPE_INCLUDE_DIR_ft2build ft2build.h
+ HINTS
+ ${FREETYPE_DIR}
+ PATHS
+ /usr/local/include
+ /usr/local/X11R6/include
+ /usr/local/X11/include
+ /usr/freeware/include
+ PATH_SUFFIXES freetype2 include/freetype2 include
+)
+find_path(FREETYPE_INCLUDE_DIR_freetype freetype.h
+ HINTS
+ ${FREETYPE_DIR}
+ PATHS
+ /usr/local/include
+ /usr/local/X11R6/include
+ /usr/local/X11/include
+ /usr/freeware/include
+ PATH_SUFFIXES freetype2 include/freetype2 include
+)
+find_path(FREETYPE_INCLUDE_DIR_freetype_freetype freetype/freetype.h
+ HINTS
+ ${FREETYPE_DIR}
+ PATHS
+ /usr/local/include
+ /usr/local/X11R6/include
+ /usr/local/X11/include
+ /usr/freeware/include
+ PATH_SUFFIXES freetype2 include/freetype2 include
+)
+find_library(FREETYPE_LIBRARY
+ NAMES freetype libfreetype freetype2 freetype219
+ HINTS
+ ${FREETYPE_DIR}
+ PATH_SUFFIXES lib64 lib
+ PATHS
+ /usr/local
+ /usr/local/X11R6
+ /usr/local/X11
+ /usr/freeware
+)
+if (FREETYPE_INCLUDE_DIR_ft2build
+ AND FREETYPE_INCLUDE_DIR_freetype
+ AND (FREETYPE_INCLUDE_DIR_ft2build STREQUAL FREETYPE_INCLUDE_DIR_freetype)
+ AND FREETYPE_LIBRARY)
+ set(FREETYPE_INCLUDE_DIRS "${FREETYPE_INCLUDE_DIR_ft2build}")
+ set(HAVE_FREETYPE_H TRUE)
+ message(STATUS "Found FreeType (new-style includes): ${FREETYPE_LIBRARY}")
+elseif (FREETYPE_INCLUDE_DIR_ft2build
+ AND FREETYPE_INCLUDE_DIR_freetype_freetype
+ AND FREETYPE_LIBRARY)
+ set(FREETYPE_INCLUDE_DIRS
+ "${FREETYPE_INCLUDE_DIR_ft2build};${FREETYPE_INCLUDE_DIR_freetype_freetype}")
+ set(HAVE_FREETYPE_H TRUE)
+ message(STATUS "Found FreeType (old-style includes): ${FREETYPE_LIBRARY}")
+else ()
+ message(STATUS "FreeType not found")
+endif ()
+if (HAVE_FREETYPE_H)
+ set(HAVE_SPLASH TRUE)
+endif ()
+
+
+#--- look for zlib
+find_package(ZLIB)
+
+#--- look for libpng
+find_package(PNG)
+
+
+
+
+#--- look for Qt
+find_package(Qt6Widgets QUIET)
+if (Qt6Widgets_FOUND)
+ find_package(Qt6Network)
+ find_package(Qt6PrintSupport)
+else ()
+ find_package(Qt5Widgets QUIET)
+ if (Qt5Widgets_FOUND)
+ find_package(Qt5Network)
+ find_package(Qt5PrintSupport)
+ else ()
+ find_package(Qt4 COMPONENTS QtCore QtGui QtNetwork)
+ endif ()
+endif ()
+if (Qt5Widgets_FOUND)
+ message(STATUS "Qt5 found")
+ if (XPDFWIDGET_PRINTING)
+ set(QT_INCLUDES "${Qt5Widgets_INCLUDE_DIRS} ${Qt5Network_INCLUDE_DIRS} ${Qt5PrintSupport_INCLUDE_DIRS}")
+ set(QT_DEFINITIONS "${Qt5Widgets_DEFINITIONS} ${Qt5Network_DEFINITIONS} ${Qt5PrintSupport_DEFINITIONS}")
+ set(QT_LIBRARIES Qt5::Widgets Qt5::Network Qt5::PrintSupport)
+ else ()
+ set(QT_INCLUDES "${Qt5Widgets_INCLUDE_DIRS} ${Qt5Network_INCLUDE_DIRS}")
+ set(QT_DEFINITIONS "${Qt5Widgets_DEFINITIONS} ${Qt5Network_DEFINITIONS}")
+ set(QT_LIBRARIES Qt5::Widgets Qt5::Network)
+ endif ()
+ if (XPDFWIDGET_PRINTING)
+ if (APPLE)
+ set(EXTRA_QT_LIBRARIES "-framework ApplicationServices")
+ elseif (UNIX)
+ find_package(Cups)
+ if (CUPS_FOUND)
+ set(EXTRA_QT_LIBRARIES ${CUPS_LIBRARIES})
+ else ()
+ set (XPDFWIDGET_PRINTING OFF)
+ endif ()
+ else ()
+ set(EXTRA_QT_LIBRARIES "")
+ endif ()
+ endif ()
+ # remove "-fPIE" here because we added "-fPIC" above
+ string(REPLACE "-fPIE" "" QT_CFLAGS "${Qt5Widgets_EXECUTABLE_COMPILE_FLAGS}")
+elseif (Qt6Widgets_FOUND)
+ message(STATUS "Qt6 found")
+ if (XPDFWIDGET_PRINTING)
+ set(QT_INCLUDES "${Qt6Widgets_INCLUDE_DIRS} ${Qt6Network_INCLUDE_DIRS} ${Qt6PrintSupport_INCLUDE_DIRS}")
+ set(QT_DEFINITIONS "${Qt6Widgets_DEFINITIONS} ${Qt6Network_DEFINITIONS} ${Qt6PrintSupport_DEFINITIONS}")
+ set(QT_LIBRARIES Qt6::Widgets Qt6::Network Qt6::PrintSupport)
+ else ()
+ set(QT_INCLUDES "${Qt6Widgets_INCLUDE_DIRS} ${Qt6Network_INCLUDE_DIRS}")
+ set(QT_DEFINITIONS "${Qt6Widgets_DEFINITIONS} ${Qt6Network_DEFINITIONS}")
+ set(QT_LIBRARIES Qt6::Widgets Qt6::Network)
+ endif ()
+ if (XPDFWIDGET_PRINTING)
+ if (APPLE)
+ set(EXTRA_QT_LIBRARIES "-framework ApplicationServices")
+ elseif (UNIX)
+ find_package(Cups)
+ if (CUPS_FOUND)
+ set(EXTRA_QT_LIBRARIES ${CUPS_LIBRARIES})
+ else ()
+ set (XPDFWIDGET_PRINTING OFF)
+ endif ()
+ else ()
+ set(EXTRA_QT_LIBRARIES "")
+ endif ()
+ endif ()
+ # remove "-fPIE" here because we added "-fPIC" above
+ string(REPLACE "-fPIE" "" QT_CFLAGS "${Qt6Widgets_EXECUTABLE_COMPILE_FLAGS}")
+elseif (QT4_FOUND)
+ message(STATUS "Qt4 found")
+ if (XPDFWIDGET_PRINTING)
+ if (APPLE)
+ set(EXTRA_QT_LIBRARIES "-framework ApplicationServices")
+ elseif (UNIX)
+ find_package(Cups)
+ if (CUPS_FOUND)
+ set(EXTRA_QT_LIBRARIES ${CUPS_LIBRARIES})
+ else ()
+ set (XPDFWIDGET_PRINTING OFF)
+ endif ()
+ else ()
+ set(EXTRA_QT_LIBRARIES "")
+ endif ()
+ endif ()
+else ()
+ message(STATUS "No Qt library found")
+endif ()
+
+#--- look for libpaper
+find_library(PAPER_LIBRARY
+ NAMES paper libpaper
+ PATH_SUFFIXES lib64 lib
+)
+if (PAPER_LIBRARY)
+ set(HAVE_PAPER_H TRUE)
+else ()
+ set(HAVE_PAPER_H FALSE)
+ set(PAPER_LIBRARY "")
+endif ()
+
+#--- look for fontconfig
+if (NOT NO_FONTCONFIG)
+ find_library(FONTCONFIG_LIBRARY
+ NAMES fontconfig libfontconfig
+ PATH_SUFFIXES lib64 lib
+ )
+ if (FONTCONFIG_LIBRARY)
+ set(HAVE_FONTCONFIG TRUE)
+ message(STATUS "Found fontconfig")
+ else ()
+ set(HAVE_FONTCONFIG FALSE)
+ set(FONTCONFIG_LIBRARY "")
+ endif ()
+else ()
+ set(HAVE_FONTCONFIG FALSE)
+ set(FONTCONFIG_LIBRARY "")
+endif ()
+
+#--- look for pthreads
+if (MULTITHREADED)
+ find_package(Threads)
+else ()
+ set(CMAKE_THREAD_LIBS_INIT "")
+endif ()
+
+#--- create aconf.h
+configure_file("aconf.h.in" "aconf.h")
diff --git a/cmake_install.cmake b/cmake_install.cmake
new file mode 100644
index 0000000..cbc2ac7
--- /dev/null
+++ b/cmake_install.cmake
@@ -0,0 +1,64 @@
+# Install script for directory: /home/calvin/src/xpdf-4.04
+
+# 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(NOT CMAKE_INSTALL_LOCAL_ONLY)
+ # Include the install script for each subdirectory.
+ include("/home/calvin/src/xpdf-4.04/goo/cmake_install.cmake")
+ include("/home/calvin/src/xpdf-4.04/fofi/cmake_install.cmake")
+ include("/home/calvin/src/xpdf-4.04/splash/cmake_install.cmake")
+ include("/home/calvin/src/xpdf-4.04/xpdf/cmake_install.cmake")
+ include("/home/calvin/src/xpdf-4.04/xpdf-qt/cmake_install.cmake")
+
+endif()
+
+if(CMAKE_INSTALL_COMPONENT)
+ set(CMAKE_INSTALL_MANIFEST "install_manifest_${CMAKE_INSTALL_COMPONENT}.txt")
+else()
+ set(CMAKE_INSTALL_MANIFEST "install_manifest.txt")
+endif()
+
+string(REPLACE ";" "\n" CMAKE_INSTALL_MANIFEST_CONTENT
+ "${CMAKE_INSTALL_MANIFEST_FILES}")
+file(WRITE "/home/calvin/src/xpdf-4.04/${CMAKE_INSTALL_MANIFEST}"
+ "${CMAKE_INSTALL_MANIFEST_CONTENT}")
diff --git a/doc/pdfdetach.1 b/doc/pdfdetach.1
new file mode 100644
index 0000000..4d00f37
--- /dev/null
+++ b/doc/pdfdetach.1
@@ -0,0 +1,106 @@
+.\" Copyright 2013-2022 Glyph & Cog, LLC
+.TH pdfdetach 1 "18 Apr 2022"
+.SH NAME
+pdfdetach \- Portable Document Format (PDF) document embedded file
+extractor (version 4.04)
+.SH SYNOPSIS
+.B pdfdetach
+[options]
+.RI [ PDF-file ]
+.SH DESCRIPTION
+.B Pdfdetach
+lists or extracts embedded files (attachments) from a Portable
+Document Format (PDF) file.
+.SH CONFIGURATION FILE
+Pdfdetach reads a configuration file at startup. It first tries to
+find the user's private config file, ~/.xpdfrc. If that doesn't
+exist, it looks for a system-wide config file, typically /etc/xpdfrc
+(but this location can be changed when pdfinfo is built). See the
+.BR xpdfrc (5)
+man page for details.
+.SH OPTIONS
+Some of the following options can be set with configuration file
+commands. These are listed in square brackets with the description of
+the corresponding command line option.
+.TP
+.B \-list
+List all of the embedded files in the PDF file. File names are
+converted to the text encoding specified by the "\-enc" switch.
+.TP
+.BI \-save " number"
+Save the specified embedded file. By default, this uses the file name
+associated with the embedded file (as printed by the "\-list" switch);
+the file name can be changed with the "\-o" switch.
+.TP
+.BI \-saveall
+Save all of the embedded files. This uses the file names associated
+with the embedded files (as printed by the "\-list" switch). By
+default, the files are saved in the current directory; this can be
+changed with the "\-o" switch.
+.TP
+.BI \-o " path"
+Set the file name used when saving an embedded file with the "\-save"
+switch, or the directory used by "\-saveall".
+.TP
+.BI \-enc " encoding-name"
+Sets the encoding to use for text output (embedded file names). The
+.I encoding\-name
+must be defined with the unicodeMap command (see
+.BR xpdfrc (5)).
+This defaults to "Latin1" (which is a built-in encoding).
+.RB "[config file: " textEncoding ]
+.TP
+.BI \-opw " password"
+Specify the owner password for the PDF file. Providing this will
+bypass all security restrictions.
+.TP
+.BI \-upw " password"
+Specify the user password for the PDF file.
+.TP
+.BI \-cfg " config-file"
+Read
+.I config-file
+in place of ~/.xpdfrc or the system-wide config file.
+.TP
+.B \-v
+Print copyright and version information.
+.TP
+.B \-h
+Print usage information.
+.RB ( \-help
+and
+.B \-\-help
+are equivalent.)
+.SH EXIT CODES
+The Xpdf tools use the following exit codes:
+.TP
+0
+No error.
+.TP
+1
+Error opening a PDF file.
+.TP
+2
+Error opening an output file.
+.TP
+3
+Error related to PDF permissions.
+.TP
+99
+Other error.
+.SH AUTHOR
+The pdfinfo software and documentation are copyright 1996-2022 Glyph &
+Cog, LLC.
+.SH "SEE ALSO"
+.BR xpdf (1),
+.BR pdftops (1),
+.BR pdftotext (1),
+.BR pdftohtml (1),
+.BR pdfinfo (1),
+.BR pdffonts (1),
+.BR pdftoppm (1),
+.BR pdftopng (1),
+.BR pdfimages (1),
+.BR xpdfrc (5)
+.br
+.B http://www.xpdfreader.com/
diff --git a/doc/pdfdetach.cat b/doc/pdfdetach.cat
new file mode 100644
index 0000000..220bb75
--- /dev/null
+++ b/doc/pdfdetach.cat
@@ -0,0 +1,92 @@
+pdfdetach(1) General Commands Manual pdfdetach(1)
+
+
+
+NAME
+ pdfdetach - Portable Document Format (PDF) document embedded file
+ extractor (version 4.04)
+
+SYNOPSIS
+ pdfdetach [options] [PDF-file]
+
+DESCRIPTION
+ Pdfdetach lists or extracts embedded files (attachments) from a Porta-
+ ble Document Format (PDF) file.
+
+CONFIGURATION FILE
+ Pdfdetach reads a configuration file at startup. It first tries to
+ find the user's private config file, ~/.xpdfrc. If that doesn't exist,
+ it looks for a system-wide config file, typically /etc/xpdfrc (but this
+ location can be changed when pdfinfo is built). See the xpdfrc(5) man
+ page for details.
+
+OPTIONS
+ Some of the following options can be set with configuration file com-
+ mands. These are listed in square brackets with the description of the
+ corresponding command line option.
+
+ -list List all of the embedded files in the PDF file. File names are
+ converted to the text encoding specified by the "-enc" switch.
+
+ -save number
+ Save the specified embedded file. By default, this uses the
+ file name associated with the embedded file (as printed by the
+ "-list" switch); the file name can be changed with the "-o"
+ switch.
+
+ -saveall
+ Save all of the embedded files. This uses the file names asso-
+ ciated with the embedded files (as printed by the "-list"
+ switch). By default, the files are saved in the current direc-
+ tory; this can be changed with the "-o" switch.
+
+ -o path
+ Set the file name used when saving an embedded file with the
+ "-save" switch, or the directory used by "-saveall".
+
+ -enc encoding-name
+ Sets the encoding to use for text output (embedded file names).
+ The encoding-name must be defined with the unicodeMap command
+ (see xpdfrc(5)). This defaults to "Latin1" (which is a built-in
+ encoding). [config file: textEncoding]
+
+ -opw password
+ Specify the owner password for the PDF file. Providing this
+ will bypass all security restrictions.
+
+ -upw password
+ Specify the user password for the PDF file.
+
+ -cfg config-file
+ Read config-file in place of ~/.xpdfrc or the system-wide config
+ file.
+
+ -v Print copyright and version information.
+
+ -h Print usage information. (-help and --help are equivalent.)
+
+EXIT CODES
+ The Xpdf tools use the following exit codes:
+
+ 0 No error.
+
+ 1 Error opening a PDF file.
+
+ 2 Error opening an output file.
+
+ 3 Error related to PDF permissions.
+
+ 99 Other error.
+
+AUTHOR
+ The pdfinfo software and documentation are copyright 1996-2022 Glyph &
+ Cog, LLC.
+
+SEE ALSO
+ xpdf(1), pdftops(1), pdftotext(1), pdftohtml(1), pdfinfo(1), pdf-
+ fonts(1), pdftoppm(1), pdftopng(1), pdfimages(1), xpdfrc(5)
+ http://www.xpdfreader.com/
+
+
+
+ 18 Apr 2022 pdfdetach(1)
diff --git a/doc/pdffonts.1 b/doc/pdffonts.1
new file mode 100644
index 0000000..6ee0226
--- /dev/null
+++ b/doc/pdffonts.1
@@ -0,0 +1,163 @@
+.\" Copyright 1999-2022 Glyph & Cog, LLC
+.TH pdffonts 1 "18 Apr 2022"
+.SH NAME
+pdffonts \- Portable Document Format (PDF) font analyzer (version
+4.04)
+.SH SYNOPSIS
+.B pdffonts
+[options]
+.RI [ PDF-file ]
+.SH DESCRIPTION
+.B Pdffonts
+lists the fonts used in a Portable Document Format (PDF) file along
+with various information for each font.
+.PP
+The following information is listed for each font:
+.TP
+.B name
+the font name, exactly as given in the PDF file (potentially including
+a subset prefix)
+.TP
+.B type
+the font type -- see below for details
+.TP
+.B emb
+"yes" if the font is embedded in the PDF file
+.TP
+.B sub
+"yes" if the font is a subset
+.TP
+.B uni
+"yes" if there is an explicit "ToUnicode" map in the PDF file (the
+absence of a ToUnicode map doesn't necessarily mean that the text
+can't be converted to Unicode)
+.TP
+.B prob
+"X" if this font is likely to be problematic when converting text to
+Unicode
+.TP
+.B object ID
+the font dictionary object ID (number and generation)
+.TP
+.B location
+the font location (see the
+.B \-loc
+and
+.B \-locPS
+options).
+.PP
+PDF files can contain the following types of fonts:
+.PP
+.RS
+Type 1
+.RE
+.RS
+Type 1C -- aka Compact Font Format (CFF)
+.RE
+.RS
+Type 1C (OT) -- OpenType with 8-bit CFF data
+.RE
+.RS
+Type 3
+.RE
+.RS
+TrueType
+.RE
+.RS
+TrueType (OT) -- OpenType with 8-bit TrueType data
+.RE
+.RS
+CID Type 0 -- 16-bit font with no specified type
+.RE
+.RS
+CID Type 0C -- 16-bit PostScript CFF font
+.RE
+.RS
+CID Type 0C (OT) -- OpenType with CID CFF data
+.RE
+.RS
+CID TrueType -- 16-bit TrueType font
+.RE
+.RS
+CID TrueType (OT) -- OpenType with CID TrueType data
+.RE
+.SH CONFIGURATION FILE
+Pdffonts reads a configuration file at startup. It first tries to
+find the user's private config file, ~/.xpdfrc. If that doesn't
+exist, it looks for a system-wide config file, typically /etc/xpdfrc
+(but this location can be changed when pdffonts is built). See the
+.BR xpdfrc (5)
+man page for details.
+.SH OPTIONS
+Many of the following options can be set with configuration file
+commands. These are listed in square brackets with the description of
+the corresponding command line option.
+.TP
+.BI \-f " number"
+Specifies the first page to analyze.
+.TP
+.B \-loc
+Shows additional information on the location of the font that will be
+used when the PDF file is rasterized (with xpdf, pdftoppm, etc.).
+.TP
+.B \-locPS
+Shows additional information on the location of the font that will be
+used when the PDF file is converted to PostScript (with pdftops).
+.TP
+.BI \-l " number"
+Specifies the last page to analyze.
+.TP
+.BI \-opw " password"
+Specify the owner password for the PDF file. Providing this will
+bypass all security restrictions.
+.TP
+.BI \-upw " password"
+Specify the user password for the PDF file.
+.TP
+.BI \-cfg " config-file"
+Read
+.I config-file
+in place of ~/.xpdfrc or the system-wide config file.
+.TP
+.B \-v
+Print copyright and version information.
+.TP
+.B \-h
+Print usage information.
+.RB ( \-help
+and
+.B \-\-help
+are equivalent.)
+.SH EXIT CODES
+The Xpdf tools use the following exit codes:
+.TP
+0
+No error.
+.TP
+1
+Error opening a PDF file.
+.TP
+2
+Error opening an output file.
+.TP
+3
+Error related to PDF permissions.
+.TP
+99
+Other error.
+.SH AUTHOR
+The pdffonts software and documentation are copyright 1996-2022 Glyph
+& Cog, LLC.
+.SH "SEE ALSO"
+.BR xpdf (1),
+.BR pdftops (1),
+.BR pdftotext (1),
+.BR pdftohtml (1),
+.BR pdfinfo (1),
+.BR pdfdetach (1),
+.BR pdftoppm (1),
+.BR pdftopng (1),
+.BR pdfimages (1),
+.BR xpdfrc (5)
+.br
+.B http://www.xpdfreader.com/
diff --git a/doc/pdffonts.cat b/doc/pdffonts.cat
new file mode 100644
index 0000000..77fef55
--- /dev/null
+++ b/doc/pdffonts.cat
@@ -0,0 +1,118 @@
+pdffonts(1) General Commands Manual pdffonts(1)
+
+
+
+NAME
+ pdffonts - Portable Document Format (PDF) font analyzer (version 4.04)
+
+SYNOPSIS
+ pdffonts [options] [PDF-file]
+
+DESCRIPTION
+ Pdffonts lists the fonts used in a Portable Document Format (PDF) file
+ along with various information for each font.
+
+ The following information is listed for each font:
+
+ name the font name, exactly as given in the PDF file (potentially
+ including a subset prefix)
+
+ type the font type -- see below for details
+
+ emb "yes" if the font is embedded in the PDF file
+
+ sub "yes" if the font is a subset
+
+ uni "yes" if there is an explicit "ToUnicode" map in the PDF file
+ (the absence of a ToUnicode map doesn't necessarily mean that
+ the text can't be converted to Unicode)
+
+ prob "X" if this font is likely to be problematic when converting
+ text to Unicode
+
+ object ID
+ the font dictionary object ID (number and generation)
+
+ location
+ the font location (see the -loc and -locPS options).
+
+ PDF files can contain the following types of fonts:
+
+ Type 1
+ Type 1C -- aka Compact Font Format (CFF)
+ Type 1C (OT) -- OpenType with 8-bit CFF data
+ Type 3
+ TrueType
+ TrueType (OT) -- OpenType with 8-bit TrueType data
+ CID Type 0 -- 16-bit font with no specified type
+ CID Type 0C -- 16-bit PostScript CFF font
+ CID Type 0C (OT) -- OpenType with CID CFF data
+ CID TrueType -- 16-bit TrueType font
+ CID TrueType (OT) -- OpenType with CID TrueType data
+
+CONFIGURATION FILE
+ Pdffonts reads a configuration file at startup. It first tries to find
+ the user's private config file, ~/.xpdfrc. If that doesn't exist, it
+ looks for a system-wide config file, typically /etc/xpdfrc (but this
+ location can be changed when pdffonts is built). See the xpdfrc(5) man
+ page for details.
+
+OPTIONS
+ Many of the following options can be set with configuration file com-
+ mands. These are listed in square brackets with the description of the
+ corresponding command line option.
+
+ -f number
+ Specifies the first page to analyze.
+
+ -loc Shows additional information on the location of the font that
+ will be used when the PDF file is rasterized (with xpdf,
+ pdftoppm, etc.).
+
+ -locPS Shows additional information on the location of the font that
+ will be used when the PDF file is converted to PostScript (with
+ pdftops).
+
+ -l number
+ Specifies the last page to analyze.
+
+ -opw password
+ Specify the owner password for the PDF file. Providing this
+ will bypass all security restrictions.
+
+ -upw password
+ Specify the user password for the PDF file.
+
+ -cfg config-file
+ Read config-file in place of ~/.xpdfrc or the system-wide config
+ file.
+
+ -v Print copyright and version information.
+
+ -h Print usage information. (-help and --help are equivalent.)
+
+EXIT CODES
+ The Xpdf tools use the following exit codes:
+
+ 0 No error.
+
+ 1 Error opening a PDF file.
+
+ 2 Error opening an output file.
+
+ 3 Error related to PDF permissions.
+
+ 99 Other error.
+
+AUTHOR
+ The pdffonts software and documentation are copyright 1996-2022 Glyph &
+ Cog, LLC.
+
+SEE ALSO
+ xpdf(1), pdftops(1), pdftotext(1), pdftohtml(1), pdfinfo(1), pdfde-
+ tach(1), pdftoppm(1), pdftopng(1), pdfimages(1), xpdfrc(5)
+ http://www.xpdfreader.com/
+
+
+
+ 18 Apr 2022 pdffonts(1)
diff --git a/doc/pdfimages.1 b/doc/pdfimages.1
new file mode 100644
index 0000000..06a9c1f
--- /dev/null
+++ b/doc/pdfimages.1
@@ -0,0 +1,122 @@
+.\" Copyright 1998-2022 Glyph & Cog, LLC
+.TH pdfimages 1 "18 Apr 2022"
+.SH NAME
+pdfimages \- Portable Document Format (PDF) image extractor
+(version 4.04)
+.SH SYNOPSIS
+.B pdfimages
+[options]
+.I PDF-file image-root
+.SH DESCRIPTION
+.B Pdfimages
+saves images from a Portable Document Format (PDF) file as Portable
+Pixmap (PPM), Portable Graymap (PGM), Portable Bitmap (PBM), or JPEG
+files.
+.PP
+Pdfimages reads the PDF file, scans one or more pages,
+.IR PDF-file ,
+and writes one PPM, PGM, PBM, or JPEG file for each image,
+.IR image-root - nnnn . xxx ,
+where
+.I nnnn
+is the image number and
+.I xxx
+is the image type (.ppm, .pgm, .pbm, .jpg).
+.PP
+NB: pdfimages extracts the raw image data from the PDF file, without
+performing any additional transforms. Any rotation, clipping,
+color inversion, etc. done by the PDF content stream is ignored.
+.SH CONFIGURATION FILE
+Pdfimages reads a configuration file at startup. It first tries to
+find the user's private config file, ~/.xpdfrc. If that doesn't
+exist, it looks for a system-wide config file, typically /etc/xpdfrc
+(but this location can be changed when pdfimages is built). See the
+.BR xpdfrc (5)
+man page for details.
+.SH OPTIONS
+Many of the following options can be set with configuration file
+commands. These are listed in square brackets with the description of
+the corresponding command line option.
+.TP
+.BI \-f " number"
+Specifies the first page to scan.
+.TP
+.BI \-l " number"
+Specifies the last page to scan.
+.TP
+.B \-j
+Normally, all images are written as PBM (for monochrome images), PGM
+(for grayscale images), or PPM (for color images) files. With this
+option, images in DCT format are saved as JPEG files. All non-DCT
+images are saved in PBM/PGM/PPM format as usual. (Inline images are
+always saved in PBM/PGM/PPM format.)
+.TP
+.B \-raw
+Write all images in PDF-native formats. Most of the formats are not
+standard image formats, so this option is primarily useful as input to
+a tool that generates PDF files. (Inline images are always saved in
+PBM/PGM/PPM format.)
+.TP
+.B \-list
+Write a one-line summary to stdout for each image. The summary
+provides the image file name, the page number, the image width and
+height, the horizontal and vertical resolution (DPI) as drawn, the
+color space type, and the number of bits per component (BPC).
+.TP
+.BI \-opw " password"
+Specify the owner password for the PDF file. Providing this will
+bypass all security restrictions.
+.TP
+.BI \-upw " password"
+Specify the user password for the PDF file.
+.TP
+.B \-verbose
+Print a status message (to stdout) before processing each page.
+.RB "[config file: " printStatusInfo ]
+.TP
+.B \-q
+Don't print any messages or errors.
+.RB "[config file: " errQuiet ]
+.TP
+.B \-v
+Print copyright and version information.
+.TP
+.B \-h
+Print usage information.
+.RB ( \-help
+and
+.B \-\-help
+are equivalent.)
+.SH EXIT CODES
+The Xpdf tools use the following exit codes:
+.TP
+0
+No error.
+.TP
+1
+Error opening a PDF file.
+.TP
+2
+Error opening an output file.
+.TP
+3
+Error related to PDF permissions.
+.TP
+99
+Other error.
+.SH AUTHOR
+The pdfimages software and documentation are copyright 1998-2022 Glyph
+& Cog, LLC.
+.SH "SEE ALSO"
+.BR xpdf (1),
+.BR pdftops (1),
+.BR pdftotext (1),
+.BR pdftohtml (1),
+.BR pdfinfo (1),
+.BR pdffonts (1),
+.BR pdfdetach (1),
+.BR pdftoppm (1),
+.BR pdftopng (1),
+.BR xpdfrc (5)
+.br
+.B http://www.xpdfreader.com/
diff --git a/doc/pdfimages.cat b/doc/pdfimages.cat
new file mode 100644
index 0000000..7361a3b
--- /dev/null
+++ b/doc/pdfimages.cat
@@ -0,0 +1,102 @@
+pdfimages(1) General Commands Manual pdfimages(1)
+
+
+
+NAME
+ pdfimages - Portable Document Format (PDF) image extractor (version
+ 4.04)
+
+SYNOPSIS
+ pdfimages [options] PDF-file image-root
+
+DESCRIPTION
+ Pdfimages saves images from a Portable Document Format (PDF) file as
+ Portable Pixmap (PPM), Portable Graymap (PGM), Portable Bitmap (PBM),
+ or JPEG files.
+
+ Pdfimages reads the PDF file, scans one or more pages, PDF-file, and
+ writes one PPM, PGM, PBM, or JPEG file for each image, image-root-
+ nnnn.xxx, where nnnn is the image number and xxx is the image type
+ (.ppm, .pgm, .pbm, .jpg).
+
+ NB: pdfimages extracts the raw image data from the PDF file, without
+ performing any additional transforms. Any rotation, clipping, color
+ inversion, etc. done by the PDF content stream is ignored.
+
+CONFIGURATION FILE
+ Pdfimages reads a configuration file at startup. It first tries to
+ find the user's private config file, ~/.xpdfrc. If that doesn't exist,
+ it looks for a system-wide config file, typically /etc/xpdfrc (but this
+ location can be changed when pdfimages is built). See the xpdfrc(5)
+ man page for details.
+
+OPTIONS
+ Many of the following options can be set with configuration file com-
+ mands. These are listed in square brackets with the description of the
+ corresponding command line option.
+
+ -f number
+ Specifies the first page to scan.
+
+ -l number
+ Specifies the last page to scan.
+
+ -j Normally, all images are written as PBM (for monochrome images),
+ PGM (for grayscale images), or PPM (for color images) files.
+ With this option, images in DCT format are saved as JPEG files.
+ All non-DCT images are saved in PBM/PGM/PPM format as usual.
+ (Inline images are always saved in PBM/PGM/PPM format.)
+
+ -raw Write all images in PDF-native formats. Most of the formats are
+ not standard image formats, so this option is primarily useful
+ as input to a tool that generates PDF files. (Inline images are
+ always saved in PBM/PGM/PPM format.)
+
+ -list Write a one-line summary to stdout for each image. The summary
+ provides the image file name, the page number, the image width
+ and height, the horizontal and vertical resolution (DPI) as
+ drawn, the color space type, and the number of bits per compo-
+ nent (BPC).
+
+ -opw password
+ Specify the owner password for the PDF file. Providing this
+ will bypass all security restrictions.
+
+ -upw password
+ Specify the user password for the PDF file.
+
+ -verbose
+ Print a status message (to stdout) before processing each page.
+ [config file: printStatusInfo]
+
+ -q Don't print any messages or errors. [config file: errQuiet]
+
+ -v Print copyright and version information.
+
+ -h Print usage information. (-help and --help are equivalent.)
+
+EXIT CODES
+ The Xpdf tools use the following exit codes:
+
+ 0 No error.
+
+ 1 Error opening a PDF file.
+
+ 2 Error opening an output file.
+
+ 3 Error related to PDF permissions.
+
+ 99 Other error.
+
+AUTHOR
+ The pdfimages software and documentation are copyright 1998-2022 Glyph
+ & Cog, LLC.
+
+SEE ALSO
+ xpdf(1), pdftops(1), pdftotext(1), pdftohtml(1), pdfinfo(1), pdf-
+ fonts(1), pdfdetach(1), pdftoppm(1), pdftopng(1), xpdfrc(5)
+ http://www.xpdfreader.com/
+
+
+
+ 18 Apr 2022 pdfimages(1)
diff --git a/doc/pdfinfo.1 b/doc/pdfinfo.1
new file mode 100644
index 0000000..66f3e70
--- /dev/null
+++ b/doc/pdfinfo.1
@@ -0,0 +1,167 @@
+.\" Copyright 1999-2022 Glyph & Cog, LLC
+.TH pdfinfo 1 "18 Apr 2022"
+.SH NAME
+pdfinfo \- Portable Document Format (PDF) document information
+extractor (version 4.04)
+.SH SYNOPSIS
+.B pdfinfo
+[options]
+.RI [ PDF-file ]
+.SH DESCRIPTION
+.B Pdfinfo
+prints the contents of the \'Info' dictionary (plus some other useful
+information) from a Portable Document Format (PDF) file.
+.PP
+The \'Info' dictionary contains the following values:
+.PP
+.RS
+title
+.RE
+.RS
+subject
+.RE
+.RS
+keywords
+.RE
+.RS
+author
+.RE
+.RS
+creator
+.RE
+.RS
+producer
+.RE
+.RS
+creation date
+.RE
+.RS
+modification date
+.RE
+.PP
+In addition, the following information is printed:
+.PP
+.RS
+tagged (yes/no)
+.RE
+.RS
+form (AcroForm / static XFA / dynamic XFA / none)
+.RE
+.RS
+page count
+.RE
+.RS
+encrypted flag (yes/no)
+.RE
+.RS
+print and copy permissions (if encrypted)
+.RE
+.RS
+page size and rotation
+.RE
+.RS
+file size
+.RE
+.RS
+linearized (yes/no)
+.RE
+.RS
+PDF version
+.RE
+.RS
+metadata (only if requested)
+.RE
+.SH CONFIGURATION FILE
+Pdfinfo reads a configuration file at startup. It first tries to find
+the user's private config file, ~/.xpdfrc. If that doesn't exist, it
+looks for a system-wide config file, typically /etc/xpdfrc (but this
+location can be changed when pdfinfo is built). See the
+.BR xpdfrc (5)
+man page for details.
+.SH OPTIONS
+Many of the following options can be set with configuration file
+commands. These are listed in square brackets with the description of
+the corresponding command line option.
+.TP
+.BI \-f " number"
+Specifies the first page to examine. If multiple pages are requested
+using the "\-f" and "\-l" options, the size of each requested page
+(and, optionally, the bounding boxes for each requested page) are
+printed. Otherwise, only page one is examined.
+.TP
+.BI \-l " number"
+Specifies the last page to examine.
+.TP
+.B \-box
+Prints the page box bounding boxes: MediaBox, CropBox, BleedBox,
+TrimBox, and ArtBox.
+.TP
+.B \-meta
+Prints document-level metadata. (This is the "Metadata" stream from
+the PDF file's Catalog object.)
+.TP
+.B \-rawdates
+Prints the raw (undecoded) date strings, directly from the PDF file.
+.TP
+.BI \-enc " encoding-name"
+Sets the encoding to use for text output. The
+.I encoding\-name
+must be defined with the unicodeMap command (see
+.BR xpdfrc (5)).
+This defaults to "Latin1" (which is a built-in encoding).
+.RB "[config file: " textEncoding ]
+.TP
+.BI \-opw " password"
+Specify the owner password for the PDF file. Providing this will
+bypass all security restrictions.
+.TP
+.BI \-upw " password"
+Specify the user password for the PDF file.
+.TP
+.BI \-cfg " config-file"
+Read
+.I config-file
+in place of ~/.xpdfrc or the system-wide config file.
+.TP
+.B \-v
+Print copyright and version information.
+.TP
+.B \-h
+Print usage information.
+.RB ( \-help
+and
+.B \-\-help
+are equivalent.)
+.SH EXIT CODES
+The Xpdf tools use the following exit codes:
+.TP
+0
+No error.
+.TP
+1
+Error opening a PDF file.
+.TP
+2
+Error opening an output file.
+.TP
+3
+Error related to PDF permissions.
+.TP
+99
+Other error.
+.SH AUTHOR
+The pdfinfo software and documentation are copyright 1996-2022 Glyph &
+Cog, LLC.
+.SH "SEE ALSO"
+.BR xpdf (1),
+.BR pdftops (1),
+.BR pdftotext (1),
+.BR pdftohtml (1),
+.BR pdffonts (1),
+.BR pdfdetach (1),
+.BR pdftoppm (1),
+.BR pdftopng (1),
+.BR pdfimages (1),
+.BR xpdfrc (5)
+.br
+.B http://www.xpdfreader.com/
diff --git a/doc/pdfinfo.cat b/doc/pdfinfo.cat
new file mode 100644
index 0000000..05dbc38
--- /dev/null
+++ b/doc/pdfinfo.cat
@@ -0,0 +1,117 @@
+pdfinfo(1) General Commands Manual pdfinfo(1)
+
+
+
+NAME
+ pdfinfo - Portable Document Format (PDF) document information extractor
+ (version 4.04)
+
+SYNOPSIS
+ pdfinfo [options] [PDF-file]
+
+DESCRIPTION
+ Pdfinfo prints the contents of the 'Info' dictionary (plus some other
+ useful information) from a Portable Document Format (PDF) file.
+
+ The 'Info' dictionary contains the following values:
+
+ title
+ subject
+ keywords
+ author
+ creator
+ producer
+ creation date
+ modification date
+
+ In addition, the following information is printed:
+
+ tagged (yes/no)
+ form (AcroForm / static XFA / dynamic XFA / none)
+ page count
+ encrypted flag (yes/no)
+ print and copy permissions (if encrypted)
+ page size and rotation
+ file size
+ linearized (yes/no)
+ PDF version
+ metadata (only if requested)
+
+CONFIGURATION FILE
+ Pdfinfo reads a configuration file at startup. It first tries to find
+ the user's private config file, ~/.xpdfrc. If that doesn't exist, it
+ looks for a system-wide config file, typically /etc/xpdfrc (but this
+ location can be changed when pdfinfo is built). See the xpdfrc(5) man
+ page for details.
+
+OPTIONS
+ Many of the following options can be set with configuration file com-
+ mands. These are listed in square brackets with the description of the
+ corresponding command line option.
+
+ -f number
+ Specifies the first page to examine. If multiple pages are
+ requested using the "-f" and "-l" options, the size of each
+ requested page (and, optionally, the bounding boxes for each
+ requested page) are printed. Otherwise, only page one is exam-
+ ined.
+
+ -l number
+ Specifies the last page to examine.
+
+ -box Prints the page box bounding boxes: MediaBox, CropBox, BleedBox,
+ TrimBox, and ArtBox.
+
+ -meta Prints document-level metadata. (This is the "Metadata" stream
+ from the PDF file's Catalog object.)
+
+ -rawdates
+ Prints the raw (undecoded) date strings, directly from the PDF
+ file.
+
+ -enc encoding-name
+ Sets the encoding to use for text output. The encoding-name
+ must be defined with the unicodeMap command (see xpdfrc(5)).
+ This defaults to "Latin1" (which is a built-in encoding). [con-
+ fig file: textEncoding]
+
+ -opw password
+ Specify the owner password for the PDF file. Providing this
+ will bypass all security restrictions.
+
+ -upw password
+ Specify the user password for the PDF file.
+
+ -cfg config-file
+ Read config-file in place of ~/.xpdfrc or the system-wide config
+ file.
+
+ -v Print copyright and version information.
+
+ -h Print usage information. (-help and --help are equivalent.)
+
+EXIT CODES
+ The Xpdf tools use the following exit codes:
+
+ 0 No error.
+
+ 1 Error opening a PDF file.
+
+ 2 Error opening an output file.
+
+ 3 Error related to PDF permissions.
+
+ 99 Other error.
+
+AUTHOR
+ The pdfinfo software and documentation are copyright 1996-2022 Glyph &
+ Cog, LLC.
+
+SEE ALSO
+ xpdf(1), pdftops(1), pdftotext(1), pdftohtml(1), pdffonts(1), pdfde-
+ tach(1), pdftoppm(1), pdftopng(1), pdfimages(1), xpdfrc(5)
+ http://www.xpdfreader.com/
+
+
+
+ 18 Apr 2022 pdfinfo(1)
diff --git a/doc/pdftohtml.1 b/doc/pdftohtml.1
new file mode 100644
index 0000000..5129f0d
--- /dev/null
+++ b/doc/pdftohtml.1
@@ -0,0 +1,158 @@
+.\" Copyright 1997-2022 Glyph & Cog, LLC
+.TH pdftohtml 1 "18 Apr 2022"
+.SH NAME
+pdftohtml \- Portable Document Format (PDF) to HTML converter
+(version 4.04)
+.SH SYNOPSIS
+.B pdftohtml
+[options]
+.I PDF-file
+.I HTML-dir
+.SH DESCRIPTION
+.B Pdftohtml
+converts Portable Document Format (PDF) files to HTML.
+.PP
+Pdftohtml reads the PDF file,
+.IR PDF-file ,
+and places an HTML file for each page, along with auxiliary images
+in the directory,
+.IR HTML-dir .
+The HTML directory will be created; if it already exists, pdftohtml
+will report an error.
+.SH CONFIGURATION FILE
+Pdftohtml reads a configuration file at startup. It first tries to
+find the user's private config file, ~/.xpdfrc. If that doesn't
+exist, it looks for a system-wide config file, typically /etc/xpdfrc
+(but this location can be changed when pdftohtml is built). See the
+.BR xpdfrc (5)
+man page for details.
+.SH OPTIONS
+Many of the following options can be set with configuration file
+commands. These are listed in square brackets with the description of
+the corresponding command line option.
+.TP
+.BI \-f " number"
+Specifies the first page to convert.
+.TP
+.BI \-l " number"
+Specifies the last page to convert.
+.TP
+.BI \-z " number"
+Specifies the initial zoom level. The default is 1.0, which means
+72dpi, i.e., 1 point in the PDF file will be 1 pixel in the HTML.
+Using \'-z 1.5', for example, will make the initial view 50% larger.
+.TP
+.BI \-r " number"
+Specifies the resolution, in DPI, for background images. This
+controls the pixel size of the background image files. The initial
+zoom level is controlled by the \'-z' option. Specifying a larger
+\'-r' value will allow the viewer to zoom in farther without upscaling
+artifacts in the background.
+.TP
+.BI \-vstretch " number"
+Specifies a vertical stretch factor. Setting this to a value greater
+than 1.0 will stretch each page vertically, spreading out the lines.
+This also stretches the background image to match.
+.TP
+.B \-embedbackground
+Embeds the background image as base64-encoded data directly in the
+HTML file, rather than storing it as a separate file.
+.TP
+.B \-nofonts
+Disable extraction of embedded fonts. By default, pdftohtml extracts
+TrueType and OpenType fonts. Disabling extraction can work around
+problems with buggy fonts.
+.TP
+.B \-embedfonts
+Embeds any extracted fonts as base64-encoded data directly in the HTML
+file, rather than storing them as separate files.
+.TP
+.B \-skipinvisible
+Don't draw invisible text. By default, invisible text (commonly used
+in OCR'ed PDF files) is drawn as transparent (alpha=0) HTML text.
+This option tells pdftohtml to discard invisible text entirely.
+.TP
+.B \-allinvisible
+Treat all text as invisible. By default, regular (non-invisible) text
+is not drawn in the background image, and is instead drawn with HTML
+on top of the image. This option tells pdftohtml to include the
+regular text in the background image, and then draw it as transparent
+(alpha=0) HTML text.
+.TP
+.B \-formfields
+Convert AcroForm text and checkbox fields to HTML input elements.
+This also removes text (e.g., underscore characters) and erases
+background image content (e.g., lines or boxes) in the field areas.
+.TP
+.B \-table
+Use table mode when performing the underlying text extraction. This
+will generally produce better output when the PDF content is a
+full-page table. NB: This does not generate HTML tables; it just
+changes the way text is split up.
+.TP
+.BI \-opw " password"
+Specify the owner password for the PDF file. Providing this will
+bypass all security restrictions.
+.TP
+.BI \-upw " password"
+Specify the user password for the PDF file.
+.TP
+.B \-verbose
+Print a status message (to stdout) before processing each page.
+.RB "[config file: " printStatusInfo ]
+.TP
+.B \-q
+Don't print any messages or errors.
+.RB "[config file: " errQuiet ]
+.TP
+.BI \-cfg " config-file"
+Read
+.I config-file
+in place of ~/.xpdfrc or the system-wide config file.
+.TP
+.B \-v
+Print copyright and version information.
+.TP
+.B \-h
+Print usage information.
+.RB ( \-help
+and
+.B \-\-help
+are equivalent.)
+.SH BUGS
+Some PDF files contain fonts whose encodings have been mangled beyond
+recognition. There is no way (short of OCR) to extract text from
+these files.
+.SH EXIT CODES
+The Xpdf tools use the following exit codes:
+.TP
+0
+No error.
+.TP
+1
+Error opening a PDF file.
+.TP
+2
+Error opening an output file.
+.TP
+3
+Error related to PDF permissions.
+.TP
+99
+Other error.
+.SH AUTHOR
+The pdftohtml software and documentation are copyright 1996-2022 Glyph
+& Cog, LLC.
+.SH "SEE ALSO"
+.BR xpdf (1),
+.BR pdftops (1),
+.BR pdftotext (1),
+.BR pdfinfo (1),
+.BR pdffonts (1),
+.BR pdfdetach (1),
+.BR pdftoppm (1),
+.BR pdftopng (1),
+.BR pdfimages (1),
+.BR xpdfrc (5)
+.br
+.B http://www.xpdfreader.com/
diff --git a/doc/pdftohtml.cat b/doc/pdftohtml.cat
new file mode 100644
index 0000000..5ddbfa0
--- /dev/null
+++ b/doc/pdftohtml.cat
@@ -0,0 +1,144 @@
+pdftohtml(1) General Commands Manual pdftohtml(1)
+
+
+
+NAME
+ pdftohtml - Portable Document Format (PDF) to HTML converter (version
+ 4.04)
+
+SYNOPSIS
+ pdftohtml [options] PDF-file HTML-dir
+
+DESCRIPTION
+ Pdftohtml converts Portable Document Format (PDF) files to HTML.
+
+ Pdftohtml reads the PDF file, PDF-file, and places an HTML file for
+ each page, along with auxiliary images in the directory, HTML-dir. The
+ HTML directory will be created; if it already exists, pdftohtml will
+ report an error.
+
+CONFIGURATION FILE
+ Pdftohtml reads a configuration file at startup. It first tries to
+ find the user's private config file, ~/.xpdfrc. If that doesn't exist,
+ it looks for a system-wide config file, typically /etc/xpdfrc (but this
+ location can be changed when pdftohtml is built). See the xpdfrc(5)
+ man page for details.
+
+OPTIONS
+ Many of the following options can be set with configuration file com-
+ mands. These are listed in square brackets with the description of the
+ corresponding command line option.
+
+ -f number
+ Specifies the first page to convert.
+
+ -l number
+ Specifies the last page to convert.
+
+ -z number
+ Specifies the initial zoom level. The default is 1.0, which
+ means 72dpi, i.e., 1 point in the PDF file will be 1 pixel in
+ the HTML. Using '-z 1.5', for example, will make the initial
+ view 50% larger.
+
+ -r number
+ Specifies the resolution, in DPI, for background images. This
+ controls the pixel size of the background image files. The ini-
+ tial zoom level is controlled by the '-z' option. Specifying a
+ larger '-r' value will allow the viewer to zoom in farther with-
+ out upscaling artifacts in the background.
+
+ -vstretch number
+ Specifies a vertical stretch factor. Setting this to a value
+ greater than 1.0 will stretch each page vertically, spreading
+ out the lines. This also stretches the background image to
+ match.
+
+ -embedbackground
+ Embeds the background image as base64-encoded data directly in
+ the HTML file, rather than storing it as a separate file.
+
+ -nofonts
+ Disable extraction of embedded fonts. By default, pdftohtml
+ extracts TrueType and OpenType fonts. Disabling extraction can
+ work around problems with buggy fonts.
+
+ -embedfonts
+ Embeds any extracted fonts as base64-encoded data directly in
+ the HTML file, rather than storing them as separate files.
+
+ -skipinvisible
+ Don't draw invisible text. By default, invisible text (commonly
+ used in OCR'ed PDF files) is drawn as transparent (alpha=0) HTML
+ text. This option tells pdftohtml to discard invisible text
+ entirely.
+
+ -allinvisible
+ Treat all text as invisible. By default, regular (non-invisi-
+ ble) text is not drawn in the background image, and is instead
+ drawn with HTML on top of the image. This option tells pdfto-
+ html to include the regular text in the background image, and
+ then draw it as transparent (alpha=0) HTML text.
+
+ -formfields
+ Convert AcroForm text and checkbox fields to HTML input ele-
+ ments. This also removes text (e.g., underscore characters) and
+ erases background image content (e.g., lines or boxes) in the
+ field areas.
+
+ -table Use table mode when performing the underlying text extraction.
+ This will generally produce better output when the PDF content
+ is a full-page table. NB: This does not generate HTML tables;
+ it just changes the way text is split up.
+
+ -opw password
+ Specify the owner password for the PDF file. Providing this
+ will bypass all security restrictions.
+
+ -upw password
+ Specify the user password for the PDF file.
+
+ -verbose
+ Print a status message (to stdout) before processing each page.
+ [config file: printStatusInfo]
+
+ -q Don't print any messages or errors. [config file: errQuiet]
+
+ -cfg config-file
+ Read config-file in place of ~/.xpdfrc or the system-wide config
+ file.
+
+ -v Print copyright and version information.
+
+ -h Print usage information. (-help and --help are equivalent.)
+
+BUGS
+ Some PDF files contain fonts whose encodings have been mangled beyond
+ recognition. There is no way (short of OCR) to extract text from these
+ files.
+
+EXIT CODES
+ The Xpdf tools use the following exit codes:
+
+ 0 No error.
+
+ 1 Error opening a PDF file.
+
+ 2 Error opening an output file.
+
+ 3 Error related to PDF permissions.
+
+ 99 Other error.
+
+AUTHOR
+ The pdftohtml software and documentation are copyright 1996-2022 Glyph
+ & Cog, LLC.
+
+SEE ALSO
+ xpdf(1), pdftops(1), pdftotext(1), pdfinfo(1), pdffonts(1), pdfde-
+ tach(1), pdftoppm(1), pdftopng(1), pdfimages(1), xpdfrc(5)
+ http://www.xpdfreader.com/
+
+
+
+ 18 Apr 2022 pdftohtml(1)
diff --git a/doc/pdftopng.1 b/doc/pdftopng.1
new file mode 100644
index 0000000..1193120
--- /dev/null
+++ b/doc/pdftopng.1
@@ -0,0 +1,130 @@
+.\" Copyright 2017-2022 Glyph & Cog, LLC
+.TH pdftopng 1 "18 Apr 2022"
+.SH NAME
+pdftopng \- Portable Document Format (PDF) to Portable Network Graphics
+(PNG) converter (version 4.04)
+.SH SYNOPSIS
+.B pdftopng
+[options]
+.I PDF-file PNG-root
+.SH DESCRIPTION
+.B Pdftopng
+converts Portable Document Format (PDF) files to color, grayscale, or
+monochrome image files in Portable Network Graphics (PNG) format.
+.PP
+Pdftopng reads the PDF file,
+.IR PDF-file ,
+and writes one PNG file for each page,
+.IR PNG-root - nnnnnn .png,
+where
+.I nnnnnn
+is the page number.
+If
+.I PNG-root
+is \'-', the image is sent to stdout (this is probably only useful
+when converting a single page).
+.SH CONFIGURATION FILE
+Pdftopng reads a configuration file at startup. It first tries to
+find the user's private config file, ~/.xpdfrc. If that doesn't
+exist, it looks for a system-wide config file, typically /etc/xpdfrc
+(but this location can be changed when pdftopng is built). See the
+.BR xpdfrc (5)
+man page for details.
+.SH OPTIONS
+Many of the following options can be set with configuration file
+commands. These are listed in square brackets with the description of
+the corresponding command line option.
+.TP
+.BI \-f " number"
+Specifies the first page to convert.
+.TP
+.BI \-l " number"
+Specifies the last page to convert.
+.TP
+.BI \-r " number"
+Specifies the resolution, in DPI. The default is 150 DPI.
+.TP
+.B \-mono
+Generate a monochrome image (instead of a color image).
+.TP
+.B \-gray
+Generate a grayscale image (instead of a color image).
+.TP
+.B \-alpha
+Generate an alpha channel in the PNG file. This is only useful with
+PDF files that have been constructed with a transparent background.
+The \-alpha flag cannot be used with \-mono.
+.TP
+.BI \-rot " angle"
+Rotate pages by 0 (the default), 90, 180, or 270 degrees.
+.TP
+.BI \-freetype " yes | no"
+Enable or disable FreeType (a TrueType / Type 1 font rasterizer).
+This defaults to "yes".
+.RB "[config file: " enableFreeType ]
+.TP
+.BI \-aa " yes | no"
+Enable or disable font anti-aliasing. This defaults to "yes".
+.RB "[config file: " antialias ]
+.TP
+.BI \-aaVector " yes | no"
+Enable or disable vector anti-aliasing. This defaults to "yes".
+.RB "[config file: " vectorAntialias ]
+.TP
+.BI \-opw " password"
+Specify the owner password for the PDF file. Providing this will
+bypass all security restrictions.
+.TP
+.BI \-upw " password"
+Specify the user password for the PDF file.
+.TP
+.B \-verbose
+Print a status message (to stdout) before processing each page.
+.RB "[config file: " printStatusInfo ]
+.TP
+.B \-q
+Don't print any messages or errors.
+.RB "[config file: " errQuiet ]
+.TP
+.B \-v
+Print copyright and version information.
+.TP
+.B \-h
+Print usage information.
+.RB ( \-help
+and
+.B \-\-help
+are equivalent.)
+.SH EXIT CODES
+The Xpdf tools use the following exit codes:
+.TP
+0
+No error.
+.TP
+1
+Error opening a PDF file.
+.TP
+2
+Error opening an output file.
+.TP
+3
+Error related to PDF permissions.
+.TP
+99
+Other error.
+.SH AUTHOR
+The pdftopng software and documentation are copyright 1996-2022 Glyph
+& Cog, LLC.
+.SH "SEE ALSO"
+.BR xpdf (1),
+.BR pdftops (1),
+.BR pdftotext (1),
+.BR pdftohtml (1),
+.BR pdfinfo (1),
+.BR pdffonts (1),
+.BR pdfdetach (1),
+.BR pdftoppm (1),
+.BR pdfimages (1),
+.BR xpdfrc (5)
+.br
+.B http://www.xpdfreader.com/
diff --git a/doc/pdftopng.cat b/doc/pdftopng.cat
new file mode 100644
index 0000000..10a4408
--- /dev/null
+++ b/doc/pdftopng.cat
@@ -0,0 +1,107 @@
+pdftopng(1) General Commands Manual pdftopng(1)
+
+
+
+NAME
+ pdftopng - Portable Document Format (PDF) to Portable Network Graphics
+ (PNG) converter (version 4.04)
+
+SYNOPSIS
+ pdftopng [options] PDF-file PNG-root
+
+DESCRIPTION
+ Pdftopng converts Portable Document Format (PDF) files to color,
+ grayscale, or monochrome image files in Portable Network Graphics (PNG)
+ format.
+
+ Pdftopng reads the PDF file, PDF-file, and writes one PNG file for each
+ page, PNG-root-nnnnnn.png, where nnnnnn is the page number. If PNG-
+ root is '-', the image is sent to stdout (this is probably only useful
+ when converting a single page).
+
+CONFIGURATION FILE
+ Pdftopng reads a configuration file at startup. It first tries to find
+ the user's private config file, ~/.xpdfrc. If that doesn't exist, it
+ looks for a system-wide config file, typically /etc/xpdfrc (but this
+ location can be changed when pdftopng is built). See the xpdfrc(5) man
+ page for details.
+
+OPTIONS
+ Many of the following options can be set with configuration file com-
+ mands. These are listed in square brackets with the description of the
+ corresponding command line option.
+
+ -f number
+ Specifies the first page to convert.
+
+ -l number
+ Specifies the last page to convert.
+
+ -r number
+ Specifies the resolution, in DPI. The default is 150 DPI.
+
+ -mono Generate a monochrome image (instead of a color image).
+
+ -gray Generate a grayscale image (instead of a color image).
+
+ -alpha Generate an alpha channel in the PNG file. This is only useful
+ with PDF files that have been constructed with a transparent
+ background. The -alpha flag cannot be used with -mono.
+
+ -rot angle
+ Rotate pages by 0 (the default), 90, 180, or 270 degrees.
+
+ -freetype yes | no
+ Enable or disable FreeType (a TrueType / Type 1 font raster-
+ izer). This defaults to "yes". [config file: enableFreeType]
+
+ -aa yes | no
+ Enable or disable font anti-aliasing. This defaults to "yes".
+ [config file: antialias]
+
+ -aaVector yes | no
+ Enable or disable vector anti-aliasing. This defaults to "yes".
+ [config file: vectorAntialias]
+
+ -opw password
+ Specify the owner password for the PDF file. Providing this
+ will bypass all security restrictions.
+
+ -upw password
+ Specify the user password for the PDF file.
+
+ -verbose
+ Print a status message (to stdout) before processing each page.
+ [config file: printStatusInfo]
+
+ -q Don't print any messages or errors. [config file: errQuiet]
+
+ -v Print copyright and version information.
+
+ -h Print usage information. (-help and --help are equivalent.)
+
+EXIT CODES
+ The Xpdf tools use the following exit codes:
+
+ 0 No error.
+
+ 1 Error opening a PDF file.
+
+ 2 Error opening an output file.
+
+ 3 Error related to PDF permissions.
+
+ 99 Other error.
+
+AUTHOR
+ The pdftopng software and documentation are copyright 1996-2022 Glyph &
+ Cog, LLC.
+
+SEE ALSO
+ xpdf(1), pdftops(1), pdftotext(1), pdftohtml(1), pdfinfo(1), pdf-
+ fonts(1), pdfdetach(1), pdftoppm(1), pdfimages(1), xpdfrc(5)
+ http://www.xpdfreader.com/
+
+
+
+ 18 Apr 2022 pdftopng(1)
diff --git a/doc/pdftoppm.1 b/doc/pdftoppm.1
new file mode 100644
index 0000000..d485b2b
--- /dev/null
+++ b/doc/pdftoppm.1
@@ -0,0 +1,130 @@
+.\" Copyright 2005-2022 Glyph & Cog, LLC
+.TH pdftoppm 1 "18 Apr 2022"
+.SH NAME
+pdftoppm \- Portable Document Format (PDF) to Portable Pixmap (PPM)
+converter (version 4.04)
+.SH SYNOPSIS
+.B pdftoppm
+[options]
+.I PDF-file PPM-root
+.SH DESCRIPTION
+.B Pdftoppm
+converts Portable Document Format (PDF) files to color image files in
+Portable Pixmap (PPM) format, grayscale image files in Portable
+Graymap (PGM) format, or monochrome image files in Portable Bitmap
+(PBM) format.
+.PP
+Pdftoppm reads the PDF file,
+.IR PDF-file ,
+and writes one PPM file for each page,
+.IR PPM-root - nnnnnn .ppm,
+where
+.I nnnnnn
+is the page number.
+If
+.I PPM-root
+is \'-', the image is sent to stdout (this is probably only useful
+when converting a single page).
+.SH CONFIGURATION FILE
+Pdftoppm reads a configuration file at startup. It first tries to
+find the user's private config file, ~/.xpdfrc. If that doesn't
+exist, it looks for a system-wide config file, typically /etc/xpdfrc
+(but this location can be changed when pdftoppm is built). See the
+.BR xpdfrc (5)
+man page for details.
+.SH OPTIONS
+Many of the following options can be set with configuration file
+commands. These are listed in square brackets with the description of
+the corresponding command line option.
+.TP
+.BI \-f " number"
+Specifies the first page to convert.
+.TP
+.BI \-l " number"
+Specifies the last page to convert.
+.TP
+.BI \-r " number"
+Specifies the resolution, in DPI. The default is 150 DPI.
+.TP
+.B \-mono
+Generate a monochrome PBM file (instead of an RGB PPM file).
+.TP
+.B \-gray
+Generate a grayscale PGM file (instead of an RGB PPM file).
+.TP
+.B \-cmyk
+Generate a CMYK PAM file (instead of an RGB PPM file).
+.TP
+.BI \-rot " angle"
+Rotate pages by 0 (the default), 90, 180, or 270 degrees.
+.TP
+.BI \-freetype " yes | no"
+Enable or disable FreeType (a TrueType / Type 1 font rasterizer).
+This defaults to "yes".
+.RB "[config file: " enableFreeType ]
+.TP
+.BI \-aa " yes | no"
+Enable or disable font anti-aliasing. This defaults to "yes".
+.RB "[config file: " antialias ]
+.TP
+.BI \-aaVector " yes | no"
+Enable or disable vector anti-aliasing. This defaults to "yes".
+.RB "[config file: " vectorAntialias ]
+.TP
+.BI \-opw " password"
+Specify the owner password for the PDF file. Providing this will
+bypass all security restrictions.
+.TP
+.BI \-upw " password"
+Specify the user password for the PDF file.
+.TP
+.B \-verbose
+Print a status message (to stdout) before processing each page.
+.RB "[config file: " printStatusInfo ]
+.TP
+.B \-q
+Don't print any messages or errors.
+.RB "[config file: " errQuiet ]
+.TP
+.B \-v
+Print copyright and version information.
+.TP
+.B \-h
+Print usage information.
+.RB ( \-help
+and
+.B \-\-help
+are equivalent.)
+.SH EXIT CODES
+The Xpdf tools use the following exit codes:
+.TP
+0
+No error.
+.TP
+1
+Error opening a PDF file.
+.TP
+2
+Error opening an output file.
+.TP
+3
+Error related to PDF permissions.
+.TP
+99
+Other error.
+.SH AUTHOR
+The pdftoppm software and documentation are copyright 1996-2022 Glyph
+& Cog, LLC.
+.SH "SEE ALSO"
+.BR xpdf (1),
+.BR pdftops (1),
+.BR pdftotext (1),
+.BR pdftohtml (1),
+.BR pdfinfo (1),
+.BR pdffonts (1),
+.BR pdfdetach (1),
+.BR pdftopng (1),
+.BR pdfimages (1),
+.BR xpdfrc (5)
+.br
+.B http://www.xpdfreader.com/
diff --git a/doc/pdftoppm.cat b/doc/pdftoppm.cat
new file mode 100644
index 0000000..30d012d
--- /dev/null
+++ b/doc/pdftoppm.cat
@@ -0,0 +1,106 @@
+pdftoppm(1) General Commands Manual pdftoppm(1)
+
+
+
+NAME
+ pdftoppm - Portable Document Format (PDF) to Portable Pixmap (PPM) con-
+ verter (version 4.04)
+
+SYNOPSIS
+ pdftoppm [options] PDF-file PPM-root
+
+DESCRIPTION
+ Pdftoppm converts Portable Document Format (PDF) files to color image
+ files in Portable Pixmap (PPM) format, grayscale image files in Porta-
+ ble Graymap (PGM) format, or monochrome image files in Portable Bitmap
+ (PBM) format.
+
+ Pdftoppm reads the PDF file, PDF-file, and writes one PPM file for each
+ page, PPM-root-nnnnnn.ppm, where nnnnnn is the page number. If PPM-
+ root is '-', the image is sent to stdout (this is probably only useful
+ when converting a single page).
+
+CONFIGURATION FILE
+ Pdftoppm reads a configuration file at startup. It first tries to find
+ the user's private config file, ~/.xpdfrc. If that doesn't exist, it
+ looks for a system-wide config file, typically /etc/xpdfrc (but this
+ location can be changed when pdftoppm is built). See the xpdfrc(5) man
+ page for details.
+
+OPTIONS
+ Many of the following options can be set with configuration file com-
+ mands. These are listed in square brackets with the description of the
+ corresponding command line option.
+
+ -f number
+ Specifies the first page to convert.
+
+ -l number
+ Specifies the last page to convert.
+
+ -r number
+ Specifies the resolution, in DPI. The default is 150 DPI.
+
+ -mono Generate a monochrome PBM file (instead of an RGB PPM file).
+
+ -gray Generate a grayscale PGM file (instead of an RGB PPM file).
+
+ -cmyk Generate a CMYK PAM file (instead of an RGB PPM file).
+
+ -rot angle
+ Rotate pages by 0 (the default), 90, 180, or 270 degrees.
+
+ -freetype yes | no
+ Enable or disable FreeType (a TrueType / Type 1 font raster-
+ izer). This defaults to "yes". [config file: enableFreeType]
+
+ -aa yes | no
+ Enable or disable font anti-aliasing. This defaults to "yes".
+ [config file: antialias]
+
+ -aaVector yes | no
+ Enable or disable vector anti-aliasing. This defaults to "yes".
+ [config file: vectorAntialias]
+
+ -opw password
+ Specify the owner password for the PDF file. Providing this
+ will bypass all security restrictions.
+
+ -upw password
+ Specify the user password for the PDF file.
+
+ -verbose
+ Print a status message (to stdout) before processing each page.
+ [config file: printStatusInfo]
+
+ -q Don't print any messages or errors. [config file: errQuiet]
+
+ -v Print copyright and version information.
+
+ -h Print usage information. (-help and --help are equivalent.)
+
+EXIT CODES
+ The Xpdf tools use the following exit codes:
+
+ 0 No error.
+
+ 1 Error opening a PDF file.
+
+ 2 Error opening an output file.
+
+ 3 Error related to PDF permissions.
+
+ 99 Other error.
+
+AUTHOR
+ The pdftoppm software and documentation are copyright 1996-2022 Glyph &
+ Cog, LLC.
+
+SEE ALSO
+ xpdf(1), pdftops(1), pdftotext(1), pdftohtml(1), pdfinfo(1), pdf-
+ fonts(1), pdfdetach(1), pdftopng(1), pdfimages(1), xpdfrc(5)
+ http://www.xpdfreader.com/
+
+
+
+ 18 Apr 2022 pdftoppm(1)
diff --git a/doc/pdftops.1 b/doc/pdftops.1
new file mode 100644
index 0000000..028e983
--- /dev/null
+++ b/doc/pdftops.1
@@ -0,0 +1,257 @@
+.\" Copyright 1996-2022 Glyph & Cog, LLC
+.TH pdftops 1 "18 Apr 2022"
+.SH NAME
+pdftops \- Portable Document Format (PDF) to PostScript converter
+(version 4.04)
+.SH SYNOPSIS
+.B pdftops
+[options]
+.RI [ PDF-file
+.RI [ PS-file ]]
+.SH DESCRIPTION
+.B Pdftops
+converts Portable Document Format (PDF) files to PostScript so they
+can be printed.
+.PP
+Pdftops reads the PDF file,
+.IR PDF-file ,
+and writes a PostScript file,
+.IR PS-file .
+If
+.I PS-file
+is not specified, pdftops converts
+.I file.pdf
+to
+.I file.ps
+(or
+.I file.eps
+with the \-eps option). If
+.I PS-file
+is \'-', the PostScript is sent to stdout.
+.SH CONFIGURATION FILE
+Pdftops reads a configuration file at startup. It first tries to find
+the user's private config file, ~/.xpdfrc. If that doesn't exist, it
+looks for a system-wide config file, typically /etc/xpdfrc (but this
+location can be changed when pdftops is built). See the
+.BR xpdfrc (5)
+man page for details.
+.SH OPTIONS
+Many of the following options can be set with configuration file
+commands. These are listed in square brackets with the description of
+the corresponding command line option.
+.TP
+.BI \-f " number"
+Specifies the first page to print.
+.TP
+.BI \-l " number"
+Specifies the last page to print.
+.TP
+.B \-level1
+Generate Level 1 PostScript. The resulting PostScript files will be
+significantly larger (if they contain images), but will print on Level
+1 printers. This also converts all images to black and white. No
+more than one of the PostScript level options (\-level1, \-level1sep,
+\-level2, \-level2sep, \-level3, \-level3sep) may be given.
+.RB "[config file: " psLevel ]
+.TP
+.B \-level1sep
+Generate Level 1 separable PostScript. All colors are converted to
+CMYK. Images are written with separate stream data for the four
+components.
+.RB "[config file: " psLevel ]
+.TP
+.B \-level2
+Generate Level 2 PostScript. Level 2 supports color images and image
+compression. This is the default setting.
+.RB "[config file: " psLevel ]
+.TP
+.B \-level2gray
+Generate grayscale Level 2 PostScript. All colors, including images,
+are converted to grayscale.
+.RB "[config file: " psLevel ]
+.TP
+.B \-level2sep
+Generate Level 2 separable PostScript. All colors are converted to
+CMYK. The PostScript separation convention operators are used to
+handle custom (spot) colors.
+.RB "[config file: " psLevel ]
+.TP
+.B \-level3
+Generate Level 3 PostScript. This enables all Level 2 features plus
+CID font embedding and masked image generation.
+.RB "[config file: " psLevel ]
+.TP
+.B \-level3gray
+Generate grayscale Level 3 PostScript. All colors, including images,
+are converted to grayscale.
+.RB "[config file: " psLevel ]
+.TP
+.B \-level3sep
+Generate Level 3 separable PostScript. The separation handling is the
+same as for \-level2sep.
+.RB "[config file: " psLevel ]
+.TP
+.B \-eps
+Generate an Encapsulated PostScript (EPS) file. An EPS file contains
+a single image, so if you use this option with a multi-page PDF file,
+you must use \-f and \-l to specify a single page. No more than one of
+the mode options (\-eps, \-form) may be given.
+.TP
+.B \-form
+Generate a PostScript form which can be imported by software that
+understands forms. A form contains a single page, so if you use this
+option with a multi-page PDF file, you must use \-f and \-l to specify a
+single page. The \-level1 option cannot be used with \-form.
+.TP
+.B \-opi
+Generate OPI comments for all images and forms which have OPI
+information. (This option is only available if pdftops was compiled
+with OPI support.)
+.RB "[config file: " psOPI ]
+.TP
+.B \-noembt1
+By default, any Type 1 fonts which are embedded in the PDF file are
+copied into the PostScript file. This option causes pdftops to
+substitute base fonts instead. Embedded fonts make PostScript files
+larger, but may be necessary for readable output.
+.RB "[config file: " psEmbedType1Fonts ]
+.TP
+.B \-noembtt
+By default, any TrueType fonts which are embedded in the PDF file are
+copied into the PostScript file. This option causes pdftops to
+substitute base fonts instead. Embedded fonts make PostScript files
+larger, but may be necessary for readable output. Also, some
+PostScript interpreters do not have TrueType rasterizers.
+.RB "[config file: " psEmbedTrueTypeFonts ]
+.TP
+.B \-noembcidps
+By default, any CID PostScript fonts which are embedded in the PDF
+file are copied into the PostScript file. This option disables that
+embedding. No attempt is made to substitute for non-embedded CID
+PostScript fonts.
+.RB "[config file: " psEmbedCIDPostScriptFonts ]
+.TP
+.B \-noembcidtt
+By default, any CID TrueType fonts which are embedded in the PDF file
+are copied into the PostScript file. This option disables that
+embedding. No attempt is made to substitute for non-embedded CID
+TrueType fonts.
+.RB "[config file: " psEmbedCIDTrueTypeFonts ]
+.TP
+.B \-preload
+Convert PDF forms to PS procedures, and preload image data. This uses
+more memory in the PostScript interpreter, but generates significantly
+smaller PS files in situations where, e.g., the same image is drawn on
+every page of a long document.
+.TP
+.BI \-paper " size"
+Set the paper size to one of "letter", "legal", "A4", or "A3". This
+can also be set to "match", which will set the paper size to match the
+size specified in the PDF file.
+.RB "[config file: " psPaperSize ]
+.TP
+.BI \-paperw " size"
+Set the paper width, in points.
+.RB "[config file: " psPaperSize ]
+.TP
+.BI \-paperh " size"
+Set the paper height, in points.
+.RB "[config file: " psPaperSize ]
+.TP
+.B \-nocrop
+By default, output is cropped to the CropBox specified in the PDF
+file. This option disables cropping.
+.RB "[config file: " psCrop ]
+.TP
+.B \-expand
+Expand PDF pages smaller than the paper to fill the paper. By
+default, these pages are not scaled.
+.RB "[config file: " psExpandSmaller ]
+.TP
+.B \-noshrink
+Don't scale PDF pages which are larger than the paper. By default,
+pages larger than the paper are shrunk to fit.
+.RB "[config file: " psShrinkLarger ]
+.TP
+.B \-nocenter
+By default, PDF pages smaller than the paper (after any scaling) are
+centered on the paper. This option causes them to be aligned to the
+lower-left corner of the paper instead.
+.RB "[config file: " psCenter ]
+.TP
+.B \-pagecrop
+Treat the CropBox as the PDF page size. By default, the MediaBox is
+used as the page size.
+.RB "[config file: " psUseCropBoxAsPage ]
+.TP
+.B \-userunit
+Honor the UserUnit settings on PDF pages when computing page/paper
+size. By default, pdftops ignores UserUnit.
+.TP
+.B \-duplex
+Set the Duplex pagedevice entry in the PostScript file. This tells
+duplex-capable printers to enable duplexing.
+.RB "[config file: " psDuplex ]
+.TP
+.BI \-opw " password"
+Specify the owner password for the PDF file. Providing this will
+bypass all security restrictions.
+.TP
+.BI \-upw " password"
+Specify the user password for the PDF file.
+.TP
+.B \-verbose
+Print a status message (to stdout) before processing each page.
+.RB "[config file: " printStatusInfo ]
+.TP
+.B \-q
+Don't print any messages or errors.
+.RB "[config file: " errQuiet ]
+.TP
+.BI \-cfg " config-file"
+Read
+.I config-file
+in place of ~/.xpdfrc or the system-wide config file.
+.TP
+.B \-v
+Print copyright and version information.
+.TP
+.B \-h
+Print usage information.
+.RB ( \-help
+and
+.B \-\-help
+are equivalent.)
+.SH EXIT CODES
+The Xpdf tools use the following exit codes:
+.TP
+0
+No error.
+.TP
+1
+Error opening a PDF file.
+.TP
+2
+Error opening an output file.
+.TP
+3
+Error related to PDF permissions.
+.TP
+99
+Other error.
+.SH AUTHOR
+The pdftops software and documentation are copyright 1996-2022 Glyph &
+Cog, LLC.
+.SH "SEE ALSO"
+.BR xpdf (1),
+.BR pdftotext (1),
+.BR pdftohtml (1),
+.BR pdfinfo (1),
+.BR pdffonts (1),
+.BR pdfdetach (1),
+.BR pdftoppm (1),
+.BR pdftopng (1),
+.BR pdfimages (1),
+.BR xpdfrc (5)
+.br
+.B http://www.xpdfreader.com/
diff --git a/doc/pdftops.cat b/doc/pdftops.cat
new file mode 100644
index 0000000..ed1c8b7
--- /dev/null
+++ b/doc/pdftops.cat
@@ -0,0 +1,218 @@
+pdftops(1) General Commands Manual pdftops(1)
+
+
+
+NAME
+ pdftops - Portable Document Format (PDF) to PostScript converter (ver-
+ sion 4.04)
+
+SYNOPSIS
+ pdftops [options] [PDF-file [PS-file]]
+
+DESCRIPTION
+ Pdftops converts Portable Document Format (PDF) files to PostScript so
+ they can be printed.
+
+ Pdftops reads the PDF file, PDF-file, and writes a PostScript file, PS-
+ file. If PS-file is not specified, pdftops converts file.pdf to
+ file.ps (or file.eps with the -eps option). If PS-file is '-', the
+ PostScript is sent to stdout.
+
+CONFIGURATION FILE
+ Pdftops reads a configuration file at startup. It first tries to find
+ the user's private config file, ~/.xpdfrc. If that doesn't exist, it
+ looks for a system-wide config file, typically /etc/xpdfrc (but this
+ location can be changed when pdftops is built). See the xpdfrc(5) man
+ page for details.
+
+OPTIONS
+ Many of the following options can be set with configuration file com-
+ mands. These are listed in square brackets with the description of the
+ corresponding command line option.
+
+ -f number
+ Specifies the first page to print.
+
+ -l number
+ Specifies the last page to print.
+
+ -level1
+ Generate Level 1 PostScript. The resulting PostScript files
+ will be significantly larger (if they contain images), but will
+ print on Level 1 printers. This also converts all images to
+ black and white. No more than one of the PostScript level
+ options (-level1, -level1sep, -level2, -level2sep, -level3,
+ -level3sep) may be given. [config file: psLevel]
+
+ -level1sep
+ Generate Level 1 separable PostScript. All colors are converted
+ to CMYK. Images are written with separate stream data for the
+ four components. [config file: psLevel]
+
+ -level2
+ Generate Level 2 PostScript. Level 2 supports color images and
+ image compression. This is the default setting. [config file:
+ psLevel]
+
+ -level2gray
+ Generate grayscale Level 2 PostScript. All colors, including
+ images, are converted to grayscale. [config file: psLevel]
+
+ -level2sep
+ Generate Level 2 separable PostScript. All colors are converted
+ to CMYK. The PostScript separation convention operators are
+ used to handle custom (spot) colors. [config file: psLevel]
+
+ -level3
+ Generate Level 3 PostScript. This enables all Level 2 features
+ plus CID font embedding and masked image generation. [config
+ file: psLevel]
+
+ -level3gray
+ Generate grayscale Level 3 PostScript. All colors, including
+ images, are converted to grayscale. [config file: psLevel]
+
+ -level3sep
+ Generate Level 3 separable PostScript. The separation handling
+ is the same as for -level2sep. [config file: psLevel]
+
+ -eps Generate an Encapsulated PostScript (EPS) file. An EPS file
+ contains a single image, so if you use this option with a multi-
+ page PDF file, you must use -f and -l to specify a single page.
+ No more than one of the mode options (-eps, -form) may be given.
+
+ -form Generate a PostScript form which can be imported by software
+ that understands forms. A form contains a single page, so if
+ you use this option with a multi-page PDF file, you must use -f
+ and -l to specify a single page. The -level1 option cannot be
+ used with -form.
+
+ -opi Generate OPI comments for all images and forms which have OPI
+ information. (This option is only available if pdftops was com-
+ piled with OPI support.) [config file: psOPI]
+
+ -noembt1
+ By default, any Type 1 fonts which are embedded in the PDF file
+ are copied into the PostScript file. This option causes pdftops
+ to substitute base fonts instead. Embedded fonts make Post-
+ Script files larger, but may be necessary for readable output.
+ [config file: psEmbedType1Fonts]
+
+ -noembtt
+ By default, any TrueType fonts which are embedded in the PDF
+ file are copied into the PostScript file. This option causes
+ pdftops to substitute base fonts instead. Embedded fonts make
+ PostScript files larger, but may be necessary for readable out-
+ put. Also, some PostScript interpreters do not have TrueType
+ rasterizers. [config file: psEmbedTrueTypeFonts]
+
+ -noembcidps
+ By default, any CID PostScript fonts which are embedded in the
+ PDF file are copied into the PostScript file. This option dis-
+ ables that embedding. No attempt is made to substitute for non-
+ embedded CID PostScript fonts. [config file: psEmbedCID-
+ PostScriptFonts]
+
+ -noembcidtt
+ By default, any CID TrueType fonts which are embedded in the PDF
+ file are copied into the PostScript file. This option disables
+ that embedding. No attempt is made to substitute for non-embed-
+ ded CID TrueType fonts. [config file: psEmbedCIDTrueTypeFonts]
+
+ -preload
+ Convert PDF forms to PS procedures, and preload image data.
+ This uses more memory in the PostScript interpreter, but gener-
+ ates significantly smaller PS files in situations where, e.g.,
+ the same image is drawn on every page of a long document.
+
+ -paper size
+ Set the paper size to one of "letter", "legal", "A4", or "A3".
+ This can also be set to "match", which will set the paper size
+ to match the size specified in the PDF file. [config file:
+ psPaperSize]
+
+ -paperw size
+ Set the paper width, in points. [config file: psPaperSize]
+
+ -paperh size
+ Set the paper height, in points. [config file: psPaperSize]
+
+ -nocrop
+ By default, output is cropped to the CropBox specified in the
+ PDF file. This option disables cropping. [config file: psCrop]
+
+ -expand
+ Expand PDF pages smaller than the paper to fill the paper. By
+ default, these pages are not scaled. [config file: psExpandS-
+ maller]
+
+ -noshrink
+ Don't scale PDF pages which are larger than the paper. By
+ default, pages larger than the paper are shrunk to fit. [config
+ file: psShrinkLarger]
+
+ -nocenter
+ By default, PDF pages smaller than the paper (after any scaling)
+ are centered on the paper. This option causes them to be
+ aligned to the lower-left corner of the paper instead. [config
+ file: psCenter]
+
+ -pagecrop
+ Treat the CropBox as the PDF page size. By default, the Media-
+ Box is used as the page size. [config file: psUseCropBoxAsPage]
+
+ -userunit
+ Honor the UserUnit settings on PDF pages when computing
+ page/paper size. By default, pdftops ignores UserUnit.
+
+ -duplex
+ Set the Duplex pagedevice entry in the PostScript file. This
+ tells duplex-capable printers to enable duplexing. [config
+ file: psDuplex]
+
+ -opw password
+ Specify the owner password for the PDF file. Providing this
+ will bypass all security restrictions.
+
+ -upw password
+ Specify the user password for the PDF file.
+
+ -verbose
+ Print a status message (to stdout) before processing each page.
+ [config file: printStatusInfo]
+
+ -q Don't print any messages or errors. [config file: errQuiet]
+
+ -cfg config-file
+ Read config-file in place of ~/.xpdfrc or the system-wide config
+ file.
+
+ -v Print copyright and version information.
+
+ -h Print usage information. (-help and --help are equivalent.)
+
+EXIT CODES
+ The Xpdf tools use the following exit codes:
+
+ 0 No error.
+
+ 1 Error opening a PDF file.
+
+ 2 Error opening an output file.
+
+ 3 Error related to PDF permissions.
+
+ 99 Other error.
+
+AUTHOR
+ The pdftops software and documentation are copyright 1996-2022 Glyph &
+ Cog, LLC.
+
+SEE ALSO
+ xpdf(1), pdftotext(1), pdftohtml(1), pdfinfo(1), pdffonts(1), pdfde-
+ tach(1), pdftoppm(1), pdftopng(1), pdfimages(1), xpdfrc(5)
+ http://www.xpdfreader.com/
+
+
+
+ 18 Apr 2022 pdftops(1)
diff --git a/doc/pdftotext.1 b/doc/pdftotext.1
new file mode 100644
index 0000000..e5e7d65
--- /dev/null
+++ b/doc/pdftotext.1
@@ -0,0 +1,222 @@
+.\" Copyright 1997-2022 Glyph & Cog, LLC
+.TH pdftotext 1 "18 Apr 2022"
+.SH NAME
+pdftotext \- Portable Document Format (PDF) to text converter
+(version 4.04)
+.SH SYNOPSIS
+.B pdftotext
+[options]
+.RI [ PDF-file
+.RI [ text-file ]]
+.SH DESCRIPTION
+.B Pdftotext
+converts Portable Document Format (PDF) files to plain text.
+.PP
+Pdftotext reads the PDF file,
+.IR PDF-file ,
+and writes a text file,
+.IR text-file .
+If
+.I text-file
+is not specified, pdftotext converts
+.I file.pdf
+to
+.IR file.txt .
+If
+.I text-file
+is \'-', the text is sent to stdout.
+.SH CONFIGURATION FILE
+Pdftotext reads a configuration file at startup. It first tries to
+find the user's private config file, ~/.xpdfrc. If that doesn't
+exist, it looks for a system-wide config file, typically /etc/xpdfrc
+(but this location can be changed when pdftotext is built). See the
+.BR xpdfrc (5)
+man page for details.
+.SH OPTIONS
+Many of the following options can be set with configuration file
+commands. These are listed in square brackets with the description of
+the corresponding command line option.
+.TP
+.BI \-f " number"
+Specifies the first page to convert.
+.TP
+.BI \-l " number"
+Specifies the last page to convert.
+.TP
+.B \-layout
+Maintain (as best as possible) the original physical layout of the
+text. The default is to \'undo' physical layout (columns,
+hyphenation, etc.) and output the text in reading order. If the
+.B \-fixed
+option is given, character spacing within each line will be determined
+by the specified character pitch.
+.TP
+.B \-simple
+Similar to
+.BR \-layout ,
+but optimized for simple one-column pages. This mode will do a better
+job of maintaining horizontal spacing, but it will only work properly
+with a single column of text.
+.TP
+.B \-simple2
+Similar to
+.BR \-simple ,
+but handles slightly rotated text (e.g., OCR output) better. Only works
+for pages with a single column of text.
+.TP
+.B \-table
+Table mode is similar to physical layout mode, but optimized for
+tabular data, with the goal of keeping rows and columns aligned (at
+the expense of inserting extra whitespace). If the
+.B \-fixed
+option is given, character spacing within each line will be determined
+by the specified character pitch.
+.TP
+.B \-lineprinter
+Line printer mode uses a strict fixed-character-pitch and -height
+layout. That is, the page is broken into a grid, and characters are
+placed into that grid. If the grid spacing is too small for the
+actual characters, the result is extra whitespace. If the grid
+spacing is too large, the result is missing whitespace. The grid
+spacing can be specified using the
+.B \-fixed
+and
+.B \-linespacing
+options.
+If one or both are not given on the command line, pdftotext will
+attempt to compute appropriate value(s).
+.TP
+.B \-raw
+Keep the text in content stream order. Depending on how the PDF file
+was generated, this may or may not be useful.
+.TP
+.BI \-fixed " number"
+Specify the character pitch (character width), in points, for physical
+layout, table, or line printer mode. This is ignored in all other
+modes.
+.TP
+.BI \-linespacing " number"
+Specify the line spacing, in points, for line printer mode. This is
+ignored in all other modes.
+.TP
+.B \-clip
+Text which is hidden because of clipping is removed before doing
+layout, and then added back in. This can be helpful for tables where
+clipped (invisible) text would overlap the next column.
+.TP
+.B \-nodiag
+Diagonal text, i.e., text that is not close to one of the 0, 90, 180,
+or 270 degree axes, is discarded. This is useful to skip watermarks
+drawn on top of body text, etc.
+.TP
+.BI \-enc " encoding-name"
+Sets the encoding to use for text output. The
+.I encoding\-name
+must be defined with the unicodeMap command (see
+.BR xpdfrc (5)).
+The encoding name is case-sensitive. This defaults to "Latin1" (which
+is a built-in encoding).
+.RB "[config file: " textEncoding ]
+.TP
+.BI \-eol " unix | dos | mac"
+Sets the end-of-line convention to use for text output.
+.RB "[config file: " textEOL ]
+.TP
+.B \-nopgbrk
+Don't insert a page breaks (form feed character) at the end of each
+page.
+.RB "[config file: " textPageBreaks ]
+.TP
+.B \-bom
+Insert a Unicode byte order marker (BOM) at the start of the text
+output.
+.TP
+.BI \-marginl " number"
+Specifies the left margin, in points. Text in the left margin (i.e.,
+within that many points of the left edge of the page) is discarded.
+The default value is zero.
+.TP
+.BI \-marginr " number"
+Specifies the right margin, in points. Text in the right margin
+(i.e., within that many points of the right edge of the page) is
+discarded. The default value is zero.
+.TP
+.BI \-margint " number"
+Specifies the top margin, in points. Text in the top margin (i.e.,
+within that many points of the top edge of the page) is discarded.
+The default value is zero.
+.TP
+.BI \-marginb " number"
+Specifies the bottom margin, in points. Text in the bottom margin
+(i.e., within that many points of the bottom edge of the page) is
+discarded. The default value is zero.
+.TP
+.BI \-opw " password"
+Specify the owner password for the PDF file. Providing this will
+bypass all security restrictions.
+.TP
+.BI \-upw " password"
+Specify the user password for the PDF file.
+.TP
+.B \-verbose
+Print a status message (to stdout) before processing each page.
+.RB "[config file: " printStatusInfo ]
+.TP
+.B \-q
+Don't print any messages or errors.
+.RB "[config file: " errQuiet ]
+.TP
+.BI \-cfg " config-file"
+Read
+.I config-file
+in place of ~/.xpdfrc or the system-wide config file.
+.TP
+.B \-listencodings
+List all available text output encodings, then exit.
+.TP
+.B \-v
+Print copyright and version information, then exit.
+.TP
+.B \-h
+Print usage information, then exit.
+.RB ( \-help
+and
+.B \-\-help
+are equivalent.)
+.SH BUGS
+Some PDF files contain fonts whose encodings have been mangled beyond
+recognition. There is no way (short of OCR) to extract text from
+these files.
+.SH EXIT CODES
+The Xpdf tools use the following exit codes:
+.TP
+0
+No error.
+.TP
+1
+Error opening a PDF file.
+.TP
+2
+Error opening an output file.
+.TP
+3
+Error related to PDF permissions.
+.TP
+99
+Other error.
+.SH AUTHOR
+The pdftotext software and documentation are copyright 1996-2022 Glyph
+& Cog, LLC.
+.SH "SEE ALSO"
+.BR xpdf (1),
+.BR pdftops (1),
+.BR pdftohtml (1),
+.BR pdfinfo (1),
+.BR pdffonts (1),
+.BR pdfdetach (1),
+.BR pdftoppm (1),
+.BR pdftopng (1),
+.BR pdfimages (1),
+.BR xpdfrc (5)
+.br
+.B http://www.xpdfreader.com/
diff --git a/doc/pdftotext.cat b/doc/pdftotext.cat
new file mode 100644
index 0000000..face257
--- /dev/null
+++ b/doc/pdftotext.cat
@@ -0,0 +1,184 @@
+pdftotext(1) General Commands Manual pdftotext(1)
+
+
+
+NAME
+ pdftotext - Portable Document Format (PDF) to text converter (version
+ 4.04)
+
+SYNOPSIS
+ pdftotext [options] [PDF-file [text-file]]
+
+DESCRIPTION
+ Pdftotext converts Portable Document Format (PDF) files to plain text.
+
+ Pdftotext reads the PDF file, PDF-file, and writes a text file, text-
+ file. If text-file is not specified, pdftotext converts file.pdf to
+ file.txt. If text-file is '-', the text is sent to stdout.
+
+CONFIGURATION FILE
+ Pdftotext reads a configuration file at startup. It first tries to
+ find the user's private config file, ~/.xpdfrc. If that doesn't exist,
+ it looks for a system-wide config file, typically /etc/xpdfrc (but this
+ location can be changed when pdftotext is built). See the xpdfrc(5)
+ man page for details.
+
+OPTIONS
+ Many of the following options can be set with configuration file com-
+ mands. These are listed in square brackets with the description of the
+ corresponding command line option.
+
+ -f number
+ Specifies the first page to convert.
+
+ -l number
+ Specifies the last page to convert.
+
+ -layout
+ Maintain (as best as possible) the original physical layout of
+ the text. The default is to 'undo' physical layout (columns,
+ hyphenation, etc.) and output the text in reading order. If the
+ -fixed option is given, character spacing within each line will
+ be determined by the specified character pitch.
+
+ -simple
+ Similar to -layout, but optimized for simple one-column pages.
+ This mode will do a better job of maintaining horizontal spac-
+ ing, but it will only work properly with a single column of
+ text.
+
+ -simple2
+ Similar to -simple, but handles slightly rotated text (e.g., OCR
+ output) better. Only works for pages with a single column of
+ text.
+
+ -table Table mode is similar to physical layout mode, but optimized for
+ tabular data, with the goal of keeping rows and columns aligned
+ (at the expense of inserting extra whitespace). If the -fixed
+ option is given, character spacing within each line will be
+ determined by the specified character pitch.
+
+ -lineprinter
+ Line printer mode uses a strict fixed-character-pitch and
+ -height layout. That is, the page is broken into a grid, and
+ characters are placed into that grid. If the grid spacing is
+ too small for the actual characters, the result is extra white-
+ space. If the grid spacing is too large, the result is missing
+ whitespace. The grid spacing can be specified using the -fixed
+ and -linespacing options. If one or both are not given on the
+ command line, pdftotext will attempt to compute appropriate
+ value(s).
+
+ -raw Keep the text in content stream order. Depending on how the PDF
+ file was generated, this may or may not be useful.
+
+ -fixed number
+ Specify the character pitch (character width), in points, for
+ physical layout, table, or line printer mode. This is ignored
+ in all other modes.
+
+ -linespacing number
+ Specify the line spacing, in points, for line printer mode.
+ This is ignored in all other modes.
+
+ -clip Text which is hidden because of clipping is removed before doing
+ layout, and then added back in. This can be helpful for tables
+ where clipped (invisible) text would overlap the next column.
+
+ -nodiag
+ Diagonal text, i.e., text that is not close to one of the 0, 90,
+ 180, or 270 degree axes, is discarded. This is useful to skip
+ watermarks drawn on top of body text, etc.
+
+ -enc encoding-name
+ Sets the encoding to use for text output. The encoding-name
+ must be defined with the unicodeMap command (see xpdfrc(5)).
+ The encoding name is case-sensitive. This defaults to "Latin1"
+ (which is a built-in encoding). [config file: textEncoding]
+
+ -eol unix | dos | mac
+ Sets the end-of-line convention to use for text output. [config
+ file: textEOL]
+
+ -nopgbrk
+ Don't insert a page breaks (form feed character) at the end of
+ each page. [config file: textPageBreaks]
+
+ -bom Insert a Unicode byte order marker (BOM) at the start of the
+ text output.
+
+ -marginl number
+ Specifies the left margin, in points. Text in the left margin
+ (i.e., within that many points of the left edge of the page) is
+ discarded. The default value is zero.
+
+ -marginr number
+ Specifies the right margin, in points. Text in the right margin
+ (i.e., within that many points of the right edge of the page) is
+ discarded. The default value is zero.
+
+ -margint number
+ Specifies the top margin, in points. Text in the top margin
+ (i.e., within that many points of the top edge of the page) is
+ discarded. The default value is zero.
+
+ -marginb number
+ Specifies the bottom margin, in points. Text in the bottom mar-
+ gin (i.e., within that many points of the bottom edge of the
+ page) is discarded. The default value is zero.
+
+ -opw password
+ Specify the owner password for the PDF file. Providing this
+ will bypass all security restrictions.
+
+ -upw password
+ Specify the user password for the PDF file.
+
+ -verbose
+ Print a status message (to stdout) before processing each page.
+ [config file: printStatusInfo]
+
+ -q Don't print any messages or errors. [config file: errQuiet]
+
+ -cfg config-file
+ Read config-file in place of ~/.xpdfrc or the system-wide config
+ file.
+
+ -listencodings
+ List all available text output encodings, then exit.
+
+ -v Print copyright and version information, then exit.
+
+ -h Print usage information, then exit. (-help and --help are
+ equivalent.)
+
+BUGS
+ Some PDF files contain fonts whose encodings have been mangled beyond
+ recognition. There is no way (short of OCR) to extract text from these
+ files.
+
+EXIT CODES
+ The Xpdf tools use the following exit codes:
+
+ 0 No error.
+
+ 1 Error opening a PDF file.
+
+ 2 Error opening an output file.
+
+ 3 Error related to PDF permissions.
+
+ 99 Other error.
+
+AUTHOR
+ The pdftotext software and documentation are copyright 1996-2022 Glyph
+ & Cog, LLC.
+
+SEE ALSO
+ xpdf(1), pdftops(1), pdftohtml(1), pdfinfo(1), pdffonts(1), pdfde-
+ tach(1), pdftoppm(1), pdftopng(1), pdfimages(1), xpdfrc(5)
+ http://www.xpdfreader.com/
+
+
+
+ 18 Apr 2022 pdftotext(1)
diff --git a/doc/sample-xpdfrc b/doc/sample-xpdfrc
new file mode 100644
index 0000000..76b45c6
--- /dev/null
+++ b/doc/sample-xpdfrc
@@ -0,0 +1,86 @@
+#========================================================================
+#
+# Sample xpdfrc file
+#
+# The Xpdf tools look for a config file in two places:
+# 1. ~/.xpdfrc
+# 2. in a system-wide directory, typically /usr/local/etc/xpdfrc
+#
+# This sample config file demonstrates some of the more common
+# configuration options. Everything here is commented out. You
+# should edit things (especially the file/directory paths, since
+# they'll likely be different on your system), and uncomment whichever
+# options you want to use. For complete details on config file syntax
+# and available options, please see the xpdfrc(5) man page.
+#
+# Also, the Xpdf language support packages each include a set of
+# options to be added to the xpdfrc file.
+#
+# http://www.xpdfreader.com/
+#
+#========================================================================
+
+#----- display fonts
+
+# These map the Base-14 fonts to the Type 1 fonts that ship with
+# ghostscript. You'll almost certainly want to use something like
+# this, but you'll need to adjust this to point to wherever
+# ghostscript is installed on your system. (But if the fonts are
+# installed in a "standard" location, xpdf will find them
+# automatically.)
+
+#fontFile Times-Roman /usr/local/share/ghostscript/fonts/n021003l.pfb
+#fontFile Times-Italic /usr/local/share/ghostscript/fonts/n021023l.pfb
+#fontFile Times-Bold /usr/local/share/ghostscript/fonts/n021004l.pfb
+#fontFile Times-BoldItalic /usr/local/share/ghostscript/fonts/n021024l.pfb
+#fontFile Helvetica /usr/local/share/ghostscript/fonts/n019003l.pfb
+#fontFile Helvetica-Oblique /usr/local/share/ghostscript/fonts/n019023l.pfb
+#fontFile Helvetica-Bold /usr/local/share/ghostscript/fonts/n019004l.pfb
+#fontFile Helvetica-BoldOblique /usr/local/share/ghostscript/fonts/n019024l.pfb
+#fontFile Courier /usr/local/share/ghostscript/fonts/n022003l.pfb
+#fontFile Courier-Oblique /usr/local/share/ghostscript/fonts/n022023l.pfb
+#fontFile Courier-Bold /usr/local/share/ghostscript/fonts/n022004l.pfb
+#fontFile Courier-BoldOblique /usr/local/share/ghostscript/fonts/n022024l.pfb
+#fontFile Symbol /usr/local/share/ghostscript/fonts/s050000l.pfb
+#fontFile ZapfDingbats /usr/local/share/ghostscript/fonts/d050000l.pfb
+
+# If you need to display PDF files that refer to non-embedded fonts,
+# you should add one or more fontDir options to point to the
+# directories containing the font files. Xpdf will only look at .pfa,
+# .pfb, .ttf, and .ttc files in those directories (other files will
+# simply be ignored).
+
+#fontDir /usr/local/fonts/bakoma
+
+#----- PostScript output control
+
+# Set the default PostScript paper size -- this can be letter, legal,
+# A4, or A3. You can also specify a paper size as width and height
+# (in points).
+
+#psPaperSize letter
+
+#----- text output control
+
+# Choose a text encoding for copy-and-paste and for pdftotext output.
+# The Latin1, ASCII7, and UTF-8 encodings are built into Xpdf. Other
+# encodings are available in the language support packages.
+
+#textEncoding UTF-8
+
+# Choose the end-of-line convention for multi-line copy-and-past and
+# for pdftotext output. The available options are unix, mac, and dos.
+
+#textEOL unix
+
+#----- misc settings
+
+# Enable FreeType, and anti-aliased text.
+
+#enableFreeType yes
+#antialias yes
+
+# Set the command used to run a web browser when a URL hyperlink is
+# clicked.
+
+#launchCommand viewer-script
diff --git a/doc/xpdf.1 b/doc/xpdf.1
new file mode 100644
index 0000000..2eaa95a
--- /dev/null
+++ b/doc/xpdf.1
@@ -0,0 +1,965 @@
+.\" Copyright 1996-2022 Glyph & Cog, LLC
+.TH xpdf 1 "18 Apr 2022"
+.SH NAME
+xpdf \- Portable Document Format (PDF) file viewer (version 4.04)
+.SH SYNOPSIS
+.B xpdf
+[options]
+.RI [ PDF-file
+.RI [: page " | +" dest "]] ..."
+.PP
+.B xpdf
+[options]
+.B -remote
+.IR remote-name " [" command " ...]"
+.PP
+.B xpdf
+[options]
+.B -open
+.RI "[" PDF-file "]"
+.SH DESCRIPTION
+.B Xpdf
+is a viewer for Portable Document Format (PDF) files. (These are also
+sometimes also called \'Acrobat' files, from the name of Adobe's PDF
+software.) Xpdf uses the Qt GUI toolkit and runs on Unix, OS X, and
+Windows.
+.PP
+To run xpdf, type:
+.PP
+.RS
+xpdf file.pdf
+.RE
+.PP
+where
+.I file.pdf
+is your PDF file. The file name can be followed by a page number to
+be displayed, prefixed with a colon:
+.PP
+.RS
+xpdf file.pdf :18
+.RE
+.PP
+or by a named destination, prefixed with \'+' (this is only useful
+with PDF files that provide named destination targets):
+.PP
+.RS
+xpdf file.pdf +destinationA
+.RE
+.PP
+If you specify multiple files, they will each be opened in a separate
+tab:
+.PP
+.RS
+xpdf file1.pdf file2.pdf :18 file3.pdf
+.RE
+.PP
+You can also start xpdf without opening any files:
+.PP
+.RS
+xpdf
+.RE
+.SH CONFIGURATION FILE
+Xpdf reads a configuration file at startup. It first tries to find
+the user's private config file, ~/.xpdfrc. If that doesn't exist, it
+looks for a system-wide config file, typically /etc/xpdfrc (but this
+location can be changed when xpdf is built). See the
+.BR xpdfrc (5)
+man page for details.
+.SH OPTIONS
+The following command line options are available. All command line
+options must come before any PDF files to be opened.
+.PP
+Many of the options can be set with configuration file commands.
+These are listed in square brackets with the description of the
+corresponding command line option.
+.TP
+.BI \-geometry " geometry"
+Set the initial window geometry.
+.TP
+.BI \-title " title"
+Set the window title. By default, the title will be "xpdf: foo.pdf".
+.TP
+.BI \-open " \fR[\fPPDF-file\fR]\fP"
+This option sets up a default remote server. If Xpdf is already
+running (with the "-open" switch), the PDF file (if any) is opened in
+a new tab. If Xpdf (with the "-open" switch) is not already running,
+starts Xpdf and opens the PDF file (if any). This is useful for GUI
+desktop environments, e.g., the typical double-click on a PDF file
+case.
+.TP
+.B \-rv
+Set reverse video mode. This reverses the colors of everything except
+images. It may not always produce great results for PDF files which
+do weird things with color. This also causes the paper color to
+default to black.
+.TP
+.BI \-papercolor " color"
+Set the "paper color", i.e., the background of the page display. The
+color can be #RRGGBB (hexadecimal) or a named color. This option will
+not work well with PDF files that do things like filling in white
+behind the text.
+.RB "[config file: " paperColor ]
+.TP
+.BI \-mattecolor " color"
+Set the matte color, i.e., the color used for background outside the
+actual page area. The color can be #RRGGBB (hexadecimal) or a named
+color.
+.RB "[config file: " matteColor ]
+.TP
+.BI \-fsmattecolor " color"
+Set the matte color for full-screen mode. The color can be #RRGGBB
+(hexadecimal) or a named color.
+.RB "[config file: " fullScreenMatteColor ]
+.TP
+.BI \-z " zoom"
+Set the initial zoom factor. A number specifies a zoom percentage,
+where 100 means 72 dpi. You may also specify \'page', to fit the page
+to the window size, or \'width', to fit the page width to the window
+width.
+.RB "[config file: " initialZoom ]
+.TP
+.BI \-rot " angle"
+Rotate pages by 0 (the default), 90, 180, or 270 degrees.
+.TP
+.BI \-aa " yes | no"
+Enable or disable font anti-aliasing. This defaults to "yes".
+.RB "[config file: " antialias ]
+.TP
+.BI \-aaVector " yes | no"
+Enable or disable vector anti-aliasing. This defaults to "yes".
+.RB "[config file: " vectorAntialias ]
+.TP
+.BI \-enc " encoding-name"
+Sets the encoding to use for text output. The
+.I encoding\-name
+must be defined with the unicodeMap command (see
+.BR xpdfrc (5)).
+This defaults to "Latin1" (which is a built-in encoding).
+.RB "[config file: " textEncoding ]
+.TP
+.BI \-pw " password"
+Specify the password for the PDF file. This can be either the owner
+password (which will bypass all security restrictions) or the user
+password.
+.TP
+.B \-fullscreen
+Open xpdf in full-screen mode, useful for presentations.
+.TP
+.BI \-remote " remote-name"
+Start Xpdf in remote server mode. See the REMOVE SERVER MODE section.
+.TP
+.BI \-display " display"
+Set the X display (only available with X11).
+.TP
+.B \-cmd
+Print commands as they're executed (useful for debugging).
+.RB "[config file: " printCommands ]
+.TP
+.BI \-tabstate " tabstate-file"
+Sets the file used by the loadTabState and saveTabState commands.
+.RB "[config file: " tabStateFile ]
+.TP
+.BI \-cfg " config-file"
+Read
+.I config-file
+in place of ~/.xpdfrc or the system-wide config file.
+.TP
+.B \-v
+Print copyright and version information.
+.TP
+.B \-h
+Print usage information.
+.RB ( \-help
+and
+.B \-\-help
+are equivalent.)
+.PP
+.SH CONTROLS
+.SS Toolbar
+.TP
+.B "toggle sidebar button"
+Toggles (i.e., shows or hides) the sidebar.
+.TP
+.B "status indicator"
+This icon is animated while Xpdf is rendering a page. It turns red
+when an error or warning has been issued. Clicking on it opens the
+error dialog.
+.TP
+.B "selection mode"
+This icon is an "I-beam" in linear selection mode, and an arrow in
+block selection mode. Clicking on it toggles between the two
+selection modes.
+.TP
+.B "page number entry box"
+Move to a specific page number. Click in the box to activate it, type
+the page number, then hit return. This will instead display and
+accept page labels, if the "view - page labels" menu item is checked.
+.TP
+.B "left/right arrow buttons"
+Go backward or forward along the history path.
+.TP
+.B "zoom out/in buttons"
+Zoom out or in (i.e., change magnification) incrementally.
+.TP
+.B "zoom popup menu"
+Change the zoom factor (see the description of the \-z option above).
+.TP
+.B "fit width button"
+Change the zoom factor to fit the page width to the window width.
+.TP
+.B "fit page button"
+Change the zoom factor to fit the page to the window size.
+.TP
+.B "find entry box"
+Find a text string. Click in the box to activate it, type a search
+string, then hit return.
+.TP
+.B "find next button"
+Find the next occurrence of the search string.
+.TP
+.B "find previous button"
+Find the previous occurrence of the search string.
+.TP
+.B "find settings button"
+Display the current find settings: case sensitive (on/off), find whole
+words (on/off).
+.PP
+.SS Menu bar
+The menu bar is above the toolbar. The menu items should be
+self-explanatory.
+.PP
+.SS Tab list
+The tab list is on the left, just below the toolbar. It lists all
+open tabs.
+.PP
+.SS Outline/layers/attachments pane
+This pane is on the left, below the tab list. The popup allows you to
+select from outline, layers, or attachments.
+.PP
+The outline is a tree-like structure of bookmarks that allows moving
+within the PDF file. Not all PDF files have outlines.
+.PP
+Layers (a.k.a. optional content) allow parts of the PDF content to be
+shown or hidden. Not all PDF files have layers.
+.PP
+Attachments are other files embedded within the PDF file. There is
+a 'save' button for each attached file. Not all PDF files have
+attachments.
+.PP
+.SS Text selection
+In block selection mode, dragging the mouse with the left button held
+down will highlight an arbitrary rectangle. Shift-clicking will
+extend the selection.
+.PP
+In linear selection mode, dragging with the left button will highlight
+text in reading order. Double-clicking or triple-clicking will select
+a word or a line, respectively. Shift-clicking will extend the
+selection.
+.PP
+Selected text can be copied to the clipboard (with the edit/copy menu
+item). On X11, selected text will be available in the X selection
+buffer.
+.PP
+.SS Links
+When the mouse is over a hyperlink, the link target will be shown in a
+popup near the bottom of the window.
+.PP
+Clicking on a hyperlink will jump to the link's destination. A link
+to another PDF document will make xpdf load that document. A
+\'launch' link to an executable program will display a dialog, and if
+you click \'ok', execute the program. URL links are opened in a
+system-dependent way. (On UNIX, Qt uses the $BROWSER environment
+variable.)
+.PP
+.SS Mouse bindings
+The left mouse button is used to select text (see above).
+.PP
+Clicking on a link with the middle button opens the link in a new tab.
+.PP
+Dragging the mouse with the middle button held down pans the window.
+.PP
+The right mouse button opens a popup menu (see
+.BR popupMenuCmd " in " xpdfrc (5)).
+.PP
+.SS Key bindings
+This section lists the default key bindings. Bindings can be changed
+using the config file (see
+.BR xpdfrc (5)).
+.TP
+.B control-o
+Open a new PDF file via a file requester.
+.TP
+.B control-r
+Reload the current PDF file. Note that Xpdf will reload the file
+automatically (on a page change or redraw) if it has changed since it
+was last loaded.
+.TP
+.B control-f
+Find a text string. This sets keyboard focus to the \'find' box.
+.TP
+.B control-G
+Find next occurrence.
+.TP
+.B control-C
+Copy selected text to the clipboard.
+.TP
+.B control-P
+Print.
+.TP
+.BR control-0 " (control-zero)"
+Set the zoom factor to 125%.
+.TP
+.BR control-+ " (control-plus)"
+Zoom in (increment the zoom factor by 1).
+.TP
+.BR control-- " (control-minus)"
+Zoom out (decrement the zoom factor by 1).
+.TP
+.B control-s
+Save PDF via a file requester.
+.TP
+.B control-t
+Open a new tab.
+.TP
+.B control-n
+Open a new window.
+.TP
+.B control-w
+Close the current tab. Closes the window if this was the last open
+tab. Quits the application if this was the last open window.
+.TP
+.B control-l
+Toggle between full-screen and window modes.
+.TP
+.B control-q
+Quit.
+.TP
+.B control-<tab>
+Next tab.
+.TP
+.B control-shift-<tab>
+Previous tab.
+.TP
+.B control-?
+Help.
+.TP
+.B alt-<left-arrow>
+Go backward along the history path.
+.TP
+.B alt-<right-arrow>
+Go forward along the history path.
+.TP
+.B home
+Go to the top left of current page.
+.TP
+.B control-<home>
+Go to the first page.
+.TP
+.B end
+Go to the bottom right of current page.
+.TP
+.B control-<end>
+Go to the last page.
+.TP
+.BR <space> " or " <PageDown>
+Scroll down on the current page; if already at bottom, move to next
+page.
+.TP
+.BR control-<PageDown> " or " control-<down-arrow>
+Go to the next page. If <ScrollLock> is active, this maintains the
+relative position on the page.
+.TP
+.B <PageUp>
+Scroll up on the current page; if already at top, move to previous
+page.
+.TP
+.BR control-<PageUp> " or " control-<up-arrow>
+Go to the previous page. If <ScrollLock> is active, this maintains
+the relative position on the page.
+.TP
+.B <esc>
+Exit full-screen mode.
+.TP
+.B arrows
+Scroll the current page.
+.TP
+.B g
+Set keyboard focus to the page number entry box.
+.TP
+.B z
+Set the zoom factor to \'page' (fit page to window).
+.TP
+.B w
+Set the zoom factor to \'width' (fit page width to window).
+.SH Full-screen mode
+Xpdf can be placed into full-screen mode via the
+.B \-fullscreen
+command line option, the \'full screen' menu item, or a binding to the
+.B fullScreenMode
+or
+.B toggleFullScreenMode
+command.
+.PP
+Entering full-screen mode automatically switches to single-page view
+mode and to the fit-page zoom factor.
+.PP
+Full-screen mode can be exited via the default <esc> key binding,
+or via a binding to the
+.B windowMode
+or
+.BR toggleFullScreenMode command .
+.SH COMMANDS
+Xpdf's key and mouse bindings are user-configurable, using the bind
+and unbind commands in the config file (see
+.BR xpdfrc (5)).
+The bind command allows you to bind a key or mouse button to a
+sequence of one or more commands.
+.PP
+In commands that take arguments (inside parentheses), special
+characters (namely '(', ')', ',', and '\\x01') can be escaped by
+preceding them with a '\\x01' character. This is mostly useful in
+things like scripts that need to be able to open arbitrary PDF files,
+using the \'openFile' command.
+.PP
+The following commands are supported:
+.TP
+.B about
+Open the \'about' dialog.
+.TP
+.B blockSelectMode
+Set block selection mode. In this mode, the selection is a simple
+rectangle. Any part of the page can be selected, regardless of the
+content on the page.
+.TP
+.BI checkOpenFile( file )
+Check that
+.I file
+is open in the current tab, and open it if not.
+.TP
+.BI checkOpenFileAtDest( file, dest )
+Check that
+.I file
+is open in the current tab, and open it if not. In either case go to
+the specified named destination.
+.TP
+.BI checkOpenFileAtPage( file, page )
+Check that
+.I file
+is open in the current tab, and open it if not. In either case go to
+the specified page.
+.TP
+.B closeSidebar
+Close the sidebar.
+.TP
+.B closeSidebarMoveResizeWin
+Close the sidebar, resizing the window so that the document size
+doesn't change, and moving the window so that the document stays in
+the same place on the screen.
+.TP
+.B closeSidebarResizeWin
+Close the sidebar, resizing the window so that the document size
+doesn't change.
+.TP
+.B closeTabOrQuit
+Close the tab. If this was the last open tab, close the window. If
+this was the last window open, quit.
+.TP
+.B closeWindowOrQuit
+Close the window. If this was the last open window, quit.
+.TP
+.B continuousMode
+Switch to continuous view mode.
+.TP
+.B copy
+Copy selected text to the clipboard.
+.TP
+.B copyLinkTarget
+Copy the target of the link under the mouse cursor to the clipboard.
+.TP
+.B endPan
+End a pan operation.
+.TP
+.B endSelection
+End a selection.
+.TP
+.BI expandSidebar( n )
+Expand the sidebar by
+.I n
+pixels. Opens the sidebar if it is currently closed.
+.TP
+.B find
+Set keyboard focus to the \'find' box.
+.TP
+.B findFirst
+Find the first occurrence of the search string.
+.TP
+.B findNext
+Find the next occurrence of the search string.
+.TP
+.B findPrevious
+Find the previous occurrence of the search string.
+.TP
+.B focusToDocWin
+Set keyboard focus to the main document window.
+.TP
+.B focusToPageNum
+Set keyboard focus to the page number text box.
+.TP
+.B followLink
+Follow a hyperlink (does nothing if the mouse is not over a link).
+.TP
+.B followLinkInNewTab
+Follow a hyperlink, opening PDF files in a new tab (does nothing if
+the mouse is not over a link). For links to non-PDF files, this
+command is identical to followLink.
+.TP
+.B followLinkInNewTabNoSel
+Same as followLinkInNewTab, but does nothing if there is a non-empty
+selection. (This is useful as a mouse button binding.)
+.TP
+.B followLinkInNewWin
+Follow a hyperlink, opening PDF files in a new window (does nothing if
+the mouse is not over a link). For links to non-PDF files, this
+command is identical to followLink.
+.TP
+.B followLinkInNewWinNoSel
+Same as followLinkInNewWin, but does nothing if there is a non-empty
+selection. (This is useful as a mouse button binding.)
+.TP
+.B followLinkNoSel
+Same as followLink, but does nothing if there is a non-empty selection.
+(This is useful as a mouse button binding.)
+.TP
+.B fullScreenMode
+Go to full-screen mode.
+.TP
+.B goBackward
+Move backward along the history path.
+.TP
+.B goForward
+Move forward along the history path.
+.TP
+.BI gotoDest( dest )
+Go to a named destination.
+.TP
+.B gotoLastPage
+Go to the last page in the PDF file.
+.TP
+.BI gotoPage( page )
+Go to the specified page.
+.TP
+.BI help
+Open the help URL.
+.TP
+.B hideMenuBar
+Hide the menu bar.
+.TP
+.B hideToolbar
+Hide the toolbar.
+.TP
+.B horizontalContinuousMode
+Switch to horizontal continuous view mode.
+.TP
+.B linearSelectMode
+Set linear selection mode. In this mode, the selection follows text.
+Non-text regions cannot be selected.
+.TP
+.BI loadTabState
+Load the tab state file (which was written via the saveTabState
+command), and restore the tabs listed in that file. The path for the
+tab state file is specified with the tabStateFile setting (see
+.BR xpdfrc (5)).
+.TP
+.B newTab
+Open an empty new tab.
+.TP
+.B newWindow
+Open an empty new window.
+.TP
+.B nextPage
+Go to the next page.
+.TP
+.B nextPageNoScroll
+Go to the next page, with the current relative scroll position.
+.TP
+.B nextTab
+Switch to the next tab.
+.TP
+.B open
+Open a PDF file in the current tab, using the open dialog.
+.TP
+.B openErrorWindow
+Open the error window.
+.TP
+.BI openFile( file )
+Open the specified file in the current tab.
+.TP
+.BI openFile2( file, page, dest, passwd, location )
+Open the specified file. If
+.I dest
+is not empty, go to the specified named destination. Else, if
+.I page
+is not empty, go to the specified page number. If
+.I password
+is not empty, it is used as the PDF password. If
+.I location
+is "win", open the file in a new window; if it is "tab", open in a new
+tab; if it is "check", open in the current tab, but only if the
+specified PDF file isn't already open; else open in the current tab.
+Any/all of the arguments, other than
+.IR file ,
+can be empty strings. For example:
+.nf
+openFile2(test.pdf,7,,,tab)
+.fi
+.TP
+.BI openFileAtDest( file, dest )
+Open the specified file in the current tab at the specified named
+destination.
+.TP
+.BI openFileAtDestIn( file, dest, location )
+Open the specified file at the specified named destination. Location
+must be "win" for a new window or "tab" for a new tab.
+.TP
+.BI openFileAtPage( file, page )
+Open the specified file in the current tab at the specified page.
+.TP
+.BI openFileAtPageIn( file, page, location )
+Open the specified file at the specified page. Location must be "win"
+for a new window or "tab" for a new tab.
+.TP
+.BI openFileIn( file, location )
+Open the specified file. Location must be "win" for a new window or
+"tab" for a new tab.
+.TP
+.BI openIn( location )
+Open a PDF file, using the open dialog. Location must be "win" for a
+new window or "tab" for a new tab.
+.TP
+.B openSidebar
+Open the sidebar.
+.TP
+.B openSidebarMoveResizeWin
+Open the sidebar, resizing the window so that the document size
+doesn't change, and moving the window so that the document stays in
+the same place on the screen.
+.TP
+.B openSidebarResizeWin
+Open the sidebar, resizing the window so that the document size
+doesn't change.
+.TP
+.B pageDown
+Scroll down by one screenful.
+.TP
+.B pageUp
+Scroll up by one screenful.
+.TP
+.B postPopupMenu
+Display the popup menu.
+.TP
+.B prevPage
+Go to the previous page.
+.TP
+.B prevPageNoScroll
+Go to the previous page, with the current relative scroll position.
+.TP
+.B prevTab
+Switch to the previous tab.
+.TP
+.B print
+Open the \'print' dialog.
+.TP
+.B quit
+Quit from xpdf.
+.TP
+.B raise
+Bring the xpdf window to the front.
+.TP
+.B reload
+Reload the current PDF file.
+.TP
+.B rotateCCW
+Rotate the page 90 degrees counterclockwise.
+.TP
+.B rotateCW
+Rotate the page 90 degrees clockwise.
+.TP
+.BI run( external-command-string )
+Run an external command. The following escapes are allowed in the
+command string:
+.nf
+
+ %f => PDF file name (or an empty string if no
+ file is open)
+ %b => PDF file base name, i.e., file name minus
+ the extension (or an empty string if no
+ file is open)
+ %u => link URL (or an empty string if not over
+ a URL link)
+ %p => current page number (or an empty string if
+ no file is open)
+ %x => selection upper-left x coordinate
+ (or 0 if there is no selection)
+ %y => selection upper-left y coordinate
+ (or 0 if there is no selection)
+ %X => selection lower-right x coordinate
+ (or 0 if there is no selection)
+ %Y => selection lower-right y coordinate
+ (or 0 if there is no selection)
+ %i => page containing the mouse pointer
+ %j => x coordinate of the mouse pointer
+ %k => y coordinate of the mouse pointer
+ %% => %
+
+.fi
+The external command string will often contain spaces, so the whole
+command must be quoted in the xpdfrc file:
+.nf
+
+ bind x "run(ls -l)"
+
+.fi
+The command string may not be run through a shell. It is recommended
+to keep the command simple, so that it doesn't depend on specific
+shell functionality. For complex things, you can have the command
+string run a shell script.
+.TP
+.B saveAs
+Save PDF via a file requester.
+.TP
+.B saveImage
+Open the \'save image' dialog.
+.TP
+.BI saveTabState
+Save a list of all tabs open in this window to the tab state file.
+For each tab, this writes the PDF file name and page number (on
+separate lines). This file can be loaded later with the loadTabState
+command. The path for the tab state file is specified with the
+tabStateFile setting (see
+.BR xpdfrc (5)).
+.TP
+.BI scrollDown( n )
+Scroll down by
+.I n
+pixels.
+.TP
+.BI scrollDownNextPage( n )
+Scroll down by
+.I n
+pixels, moving to the next page if appropriate.
+.TP
+.BI scrollLeft( n )
+Scroll left by
+.I n
+pixels.
+.TP
+.BI scrollOutlineDown( n )
+Scroll the outline down by
+.I n
+increments.
+.TP
+.BI scrollOutlineUp( n )
+Scroll the outline up by
+.I n
+increments.
+.TP
+.BI scrollRight( n )
+Scroll right by
+.I n
+pixels.
+.TP
+.B scrollToBottomEdge
+Scroll to the bottom edge of the last displayed page, with no
+horizontal movement.
+.TP
+.B scrollToBottomRight
+Scroll to the bottom-right corner of the last displayed page.
+.TP
+.B scrollToLeftEdge
+Scroll to the left edge of the current page, with no vertical
+movement.
+.TP
+.B scrollToRightEdge
+Scroll to the right edge of the current page, with no vertical
+movement.
+.TP
+.B scrollToTopEdge
+Scroll to the top edge of the first displayed page, with no horizontal
+movement.
+.TP
+.B scrollToTopLeft
+Scroll to the top-left corner of the first displayed page.
+.TP
+.BI scrollUp( n )
+Scroll up by
+.I n
+pixels.
+.TP
+.BI scrollUpPrevPage( n )
+Scroll up by
+.I n
+pixels, moving to the previous page if appropriate.
+.TP
+.B selectLine
+Set the selection to the line at the current mouse position.
+.TP
+.B selectWord
+Set the selection to the word at the current mouse position.
+.TP
+.BI setSelection( pg , ulx , uly , lrx , lry )
+Set the selection to the specified coordinates on the specified page.
+.TP
+.B showAttachmentsPane
+Shows the attachments in the outline/layers/attachments pane.
+.TP
+.B showDocumentInfo
+Open the document information dialog.
+.TP
+.B showKeyBindings
+Open the key bindings dialog.
+.TP
+.B showLayersPane
+Shows the layers in the outline/layers/attachments pane.
+.TP
+.B showMenuBar
+Show the menu bar.
+.TP
+.B showOutlinePane
+Shows the outline in the outline/layers/attachments pane.
+.TP
+.B showToolbar
+Show the toolbar.
+.TP
+.BI shrinkSidebar( n )
+Shrink the sidebar by
+.I n
+pixels. Closes the sidebar if shrinking it would go below the minimum
+allowed side.
+.TP
+.B sideBySideContinuousMode
+Switch to side-by-side continuous view mode.
+.TP
+.B sideBySideSingleMode
+Switch to side-by-side two-page view mode.
+.TP
+.B singlePageMode
+Switch to single-page view mode.
+.TP
+.B startExtendedSelection
+Extend the selection to the current mouse position, and continue
+extending as the mouse moves.
+.TP
+.B startPan
+Start a pan operation at the current mouse position, which will scroll
+the document as the mouse moves.
+.TP
+.B startSelection
+Start a selection at the current mouse position, which will be
+extended as the mouse moves.
+.TP
+.B toggleContinuousMode
+Toggle between continuous and single page view modes.
+.TP
+.B toggleFullScreenMode
+Toggle between full-screen and window modes.
+.TP
+.B toggleMenuBar
+Toggle the menu bar between shown and hidden.
+.TP
+.B toggleSelectMode
+Toggle between block and linear selection mode.
+.TP
+.B toggleSidebar
+Toggle the sidebar between open and closed.
+.TP
+.B toggleSidebarMoveResizeWin
+Toggle the sidebar between open and closed, resizing the window so
+that the document size doesn't change, and moving the window so that
+the document stays in the same place on the screen.
+.TP
+.B toggleSidebarResizeWin
+Toggle the sidebar between open and closed, resizing the window so
+that the document size doesn't change.
+.TP
+.B toggleToolbar
+Toggle the toolbar between shown and hidden.
+.TP
+.B viewPageLabels
+Show page labels (if the PDF file has them), rather than page numbers.
+.TP
+.B viewPageNumbers
+Show page numbers, rather than page labels.
+.TP
+.B windowMode
+Go to window (non-full-screen) mode.
+.TP
+.B zoomFitPage
+Set the zoom factor to fit-page.
+.TP
+.B zoomFitWidth
+Set the zoom factor to fit-width.
+.TP
+.B zoomIn
+Zoom in - go to the next higher zoom factor.
+.TP
+.B zoomOut
+Zoom out - go the next lower zoom factor.
+.TP
+.BI zoomPercent( z )
+Set the zoom factor to
+.IR z %.
+.TP
+.B zoomToSelection
+Zoom to the current selection.
+.SH REMOTE SERVER MODE
+Starting xpdf with the "-remote" switch puts it into remote server
+mode. All remaining command line options are commands (see the
+COMMANDS section). Subsequent invocations of "xpdf -remote" with the
+same remote server name will send commands to the already-running
+instance of xpdf. The "checkOpenFile" commands are useful here for
+things like changing pages.
+For example:
+.PP
+.RS
+ # Start up xpdf, and open something.pdf.
+ xpdf -remote foo 'openFile(something.pdf)'
+
+ # Switch to page 7 in the already-open something.pdf. If the user
+ # has closed xpdf in the meantime, this will restart it and reopen
+ # the file.
+ xpdf -remote foo 'checkOpenFileAtPage(something.pdf, 7)'
+.RE
+.PP
+.SH EXIT CODES
+The Xpdf tools use the following exit codes:
+.TP
+0
+No error.
+.TP
+1
+Error opening a PDF file.
+.TP
+2
+Error opening an output file.
+.TP
+3
+Error related to PDF permissions.
+.TP
+99
+Other error.
+.SH AUTHOR
+The xpdf software and documentation are copyright 1996-2022 Glyph &
+Cog, LLC.
+.SH "SEE ALSO"
+.BR pdftops (1),
+.BR pdftotext (1),
+.BR pdftohtml (1),
+.BR pdfinfo (1),
+.BR pdffonts (1),
+.BR pdfdetach (1),
+.BR pdftoppm (1),
+.BR pdftopng (1),
+.BR pdfimages (1),
+.BR xpdfrc (5)
+.br
+.B http://www.xpdfreader.com/
diff --git a/doc/xpdf.cat b/doc/xpdf.cat
new file mode 100644
index 0000000..ba20911
--- /dev/null
+++ b/doc/xpdf.cat
@@ -0,0 +1,871 @@
+xpdf(1) General Commands Manual xpdf(1)
+
+
+
+NAME
+ xpdf - Portable Document Format (PDF) file viewer (version 4.04)
+
+SYNOPSIS
+ xpdf [options] [PDF-file [:page | +dest]] ...
+
+ xpdf [options] -remote remote-name [command ...]
+
+ xpdf [options] -open [PDF-file]
+
+DESCRIPTION
+ Xpdf is a viewer for Portable Document Format (PDF) files. (These are
+ also sometimes also called 'Acrobat' files, from the name of Adobe's
+ PDF software.) Xpdf uses the Qt GUI toolkit and runs on Unix, OS X,
+ and Windows.
+
+ To run xpdf, type:
+
+ xpdf file.pdf
+
+ where file.pdf is your PDF file. The file name can be followed by a
+ page number to be displayed, prefixed with a colon:
+
+ xpdf file.pdf :18
+
+ or by a named destination, prefixed with '+' (this is only useful with
+ PDF files that provide named destination targets):
+
+ xpdf file.pdf +destinationA
+
+ If you specify multiple files, they will each be opened in a separate
+ tab:
+
+ xpdf file1.pdf file2.pdf :18 file3.pdf
+
+ You can also start xpdf without opening any files:
+
+ xpdf
+
+CONFIGURATION FILE
+ Xpdf reads a configuration file at startup. It first tries to find the
+ user's private config file, ~/.xpdfrc. If that doesn't exist, it looks
+ for a system-wide config file, typically /etc/xpdfrc (but this location
+ can be changed when xpdf is built). See the xpdfrc(5) man page for
+ details.
+
+OPTIONS
+ The following command line options are available. All command line
+ options must come before any PDF files to be opened.
+
+ Many of the options can be set with configuration file commands. These
+ are listed in square brackets with the description of the corresponding
+ command line option.
+
+ -geometry geometry
+ Set the initial window geometry.
+
+ -title title
+ Set the window title. By default, the title will be "xpdf:
+ foo.pdf".
+
+ -open [PDF-file]
+ This option sets up a default remote server. If Xpdf is already
+ running (with the "-open" switch), the PDF file (if any) is
+ opened in a new tab. If Xpdf (with the "-open" switch) is not
+ already running, starts Xpdf and opens the PDF file (if any).
+ This is useful for GUI desktop environments, e.g., the typical
+ double-click on a PDF file case.
+
+ -rv Set reverse video mode. This reverses the colors of everything
+ except images. It may not always produce great results for PDF
+ files which do weird things with color. This also causes the
+ paper color to default to black.
+
+ -papercolor color
+ Set the "paper color", i.e., the background of the page display.
+ The color can be #RRGGBB (hexadecimal) or a named color. This
+ option will not work well with PDF files that do things like
+ filling in white behind the text. [config file: paperColor]
+
+ -mattecolor color
+ Set the matte color, i.e., the color used for background outside
+ the actual page area. The color can be #RRGGBB (hexadecimal) or
+ a named color. [config file: matteColor]
+
+ -fsmattecolor color
+ Set the matte color for full-screen mode. The color can be
+ #RRGGBB (hexadecimal) or a named color. [config file:
+ fullScreenMatteColor]
+
+ -z zoom
+ Set the initial zoom factor. A number specifies a zoom percent-
+ age, where 100 means 72 dpi. You may also specify 'page', to
+ fit the page to the window size, or 'width', to fit the page
+ width to the window width. [config file: initialZoom]
+
+ -rot angle
+ Rotate pages by 0 (the default), 90, 180, or 270 degrees.
+
+ -aa yes | no
+ Enable or disable font anti-aliasing. This defaults to "yes".
+ [config file: antialias]
+
+ -aaVector yes | no
+ Enable or disable vector anti-aliasing. This defaults to "yes".
+ [config file: vectorAntialias]
+
+ -enc encoding-name
+ Sets the encoding to use for text output. The encoding-name
+ must be defined with the unicodeMap command (see xpdfrc(5)).
+ This defaults to "Latin1" (which is a built-in encoding). [con-
+ fig file: textEncoding]
+
+ -pw password
+ Specify the password for the PDF file. This can be either the
+ owner password (which will bypass all security restrictions) or
+ the user password.
+
+ -fullscreen
+ Open xpdf in full-screen mode, useful for presentations.
+
+ -remote remote-name
+ Start Xpdf in remote server mode. See the REMOVE SERVER MODE
+ section.
+
+ -display display
+ Set the X display (only available with X11).
+
+ -cmd Print commands as they're executed (useful for debugging).
+ [config file: printCommands]
+
+ -tabstate tabstate-file
+ Sets the file used by the loadTabState and saveTabState com-
+ mands. [config file: tabStateFile]
+
+ -cfg config-file
+ Read config-file in place of ~/.xpdfrc or the system-wide config
+ file.
+
+ -v Print copyright and version information.
+
+ -h Print usage information. (-help and --help are equivalent.)
+
+CONTROLS
+ Toolbar
+ toggle sidebar button
+ Toggles (i.e., shows or hides) the sidebar.
+
+ status indicator
+ This icon is animated while Xpdf is rendering a page. It turns
+ red when an error or warning has been issued. Clicking on it
+ opens the error dialog.
+
+ selection mode
+ This icon is an "I-beam" in linear selection mode, and an arrow
+ in block selection mode. Clicking on it toggles between the two
+ selection modes.
+
+ page number entry box
+ Move to a specific page number. Click in the box to activate
+ it, type the page number, then hit return. This will instead
+ display and accept page labels, if the "view - page labels" menu
+ item is checked.
+
+ left/right arrow buttons
+ Go backward or forward along the history path.
+
+ zoom out/in buttons
+ Zoom out or in (i.e., change magnification) incrementally.
+
+ zoom popup menu
+ Change the zoom factor (see the description of the -z option
+ above).
+
+ fit width button
+ Change the zoom factor to fit the page width to the window
+ width.
+
+ fit page button
+ Change the zoom factor to fit the page to the window size.
+
+ find entry box
+ Find a text string. Click in the box to activate it, type a
+ search string, then hit return.
+
+ find next button
+ Find the next occurrence of the search string.
+
+ find previous button
+ Find the previous occurrence of the search string.
+
+ find settings button
+ Display the current find settings: case sensitive (on/off), find
+ whole words (on/off).
+
+ Menu bar
+ The menu bar is above the toolbar. The menu items should be self-
+ explanatory.
+
+ Tab list
+ The tab list is on the left, just below the toolbar. It lists all open
+ tabs.
+
+ Outline/layers/attachments pane
+ This pane is on the left, below the tab list. The popup allows you to
+ select from outline, layers, or attachments.
+
+ The outline is a tree-like structure of bookmarks that allows moving
+ within the PDF file. Not all PDF files have outlines.
+
+ Layers (a.k.a. optional content) allow parts of the PDF content to be
+ shown or hidden. Not all PDF files have layers.
+
+ Attachments are other files embedded within the PDF file. There is a
+ 'save' button for each attached file. Not all PDF files have attach-
+ ments.
+
+ Text selection
+ In block selection mode, dragging the mouse with the left button held
+ down will highlight an arbitrary rectangle. Shift-clicking will extend
+ the selection.
+
+ In linear selection mode, dragging with the left button will highlight
+ text in reading order. Double-clicking or triple-clicking will select
+ a word or a line, respectively. Shift-clicking will extend the selec-
+ tion.
+
+ Selected text can be copied to the clipboard (with the edit/copy menu
+ item). On X11, selected text will be available in the X selection buf-
+ fer.
+
+ Links
+ When the mouse is over a hyperlink, the link target will be shown in a
+ popup near the bottom of the window.
+
+ Clicking on a hyperlink will jump to the link's destination. A link to
+ another PDF document will make xpdf load that document. A 'launch'
+ link to an executable program will display a dialog, and if you click
+ 'ok', execute the program. URL links are opened in a system-dependent
+ way. (On UNIX, Qt uses the $BROWSER environment variable.)
+
+ Mouse bindings
+ The left mouse button is used to select text (see above).
+
+ Clicking on a link with the middle button opens the link in a new tab.
+
+ Dragging the mouse with the middle button held down pans the window.
+
+ The right mouse button opens a popup menu (see popupMenuCmd in
+ xpdfrc(5)).
+
+ Key bindings
+ This section lists the default key bindings. Bindings can be changed
+ using the config file (see xpdfrc(5)).
+
+ control-o
+ Open a new PDF file via a file requester.
+
+ control-r
+ Reload the current PDF file. Note that Xpdf will reload the
+ file automatically (on a page change or redraw) if it has
+ changed since it was last loaded.
+
+ control-f
+ Find a text string. This sets keyboard focus to the 'find' box.
+
+ control-G
+ Find next occurrence.
+
+ control-C
+ Copy selected text to the clipboard.
+
+ control-P
+ Print.
+
+ control-0 (control-zero)
+ Set the zoom factor to 125%.
+
+ control-+ (control-plus)
+ Zoom in (increment the zoom factor by 1).
+
+ control-- (control-minus)
+ Zoom out (decrement the zoom factor by 1).
+
+ control-s
+ Save PDF via a file requester.
+
+ control-t
+ Open a new tab.
+
+ control-n
+ Open a new window.
+
+ control-w
+ Close the current tab. Closes the window if this was the last
+ open tab. Quits the application if this was the last open win-
+ dow.
+
+ control-l
+ Toggle between full-screen and window modes.
+
+ control-q
+ Quit.
+
+ control-<tab>
+ Next tab.
+
+ control-shift-<tab>
+ Previous tab.
+
+ control-?
+ Help.
+
+ alt-<left-arrow>
+ Go backward along the history path.
+
+ alt-<right-arrow>
+ Go forward along the history path.
+
+ home Go to the top left of current page.
+
+ control-<home>
+ Go to the first page.
+
+ end Go to the bottom right of current page.
+
+ control-<end>
+ Go to the last page.
+
+ <space> or <PageDown>
+ Scroll down on the current page; if already at bottom, move to
+ next page.
+
+ control-<PageDown> or control-<down-arrow>
+ Go to the next page. If <ScrollLock> is active, this maintains
+ the relative position on the page.
+
+ <PageUp>
+ Scroll up on the current page; if already at top, move to previ-
+ ous page.
+
+ control-<PageUp> or control-<up-arrow>
+ Go to the previous page. If <ScrollLock> is active, this main-
+ tains the relative position on the page.
+
+ <esc> Exit full-screen mode.
+
+ arrows Scroll the current page.
+
+ g Set keyboard focus to the page number entry box.
+
+ z Set the zoom factor to 'page' (fit page to window).
+
+ w Set the zoom factor to 'width' (fit page width to window).
+
+Full-screen mode
+ Xpdf can be placed into full-screen mode via the -fullscreen command
+ line option, the 'full screen' menu item, or a binding to the
+ fullScreenMode or toggleFullScreenMode command.
+
+ Entering full-screen mode automatically switches to single-page view
+ mode and to the fit-page zoom factor.
+
+ Full-screen mode can be exited via the default <esc> key binding, or
+ via a binding to the windowMode or toggleFullScreenModecommand.
+
+COMMANDS
+ Xpdf's key and mouse bindings are user-configurable, using the bind and
+ unbind commands in the config file (see xpdfrc(5)). The bind command
+ allows you to bind a key or mouse button to a sequence of one or more
+ commands.
+
+ In commands that take arguments (inside parentheses), special charac-
+ ters (namely '(', ')', ',', and '\x01') can be escaped by preceding
+ them with a '\x01' character. This is mostly useful in things like
+ scripts that need to be able to open arbitrary PDF files, using the
+ 'openFile' command.
+
+ The following commands are supported:
+
+ about Open the 'about' dialog.
+
+ blockSelectMode
+ Set block selection mode. In this mode, the selection is a sim-
+ ple rectangle. Any part of the page can be selected, regardless
+ of the content on the page.
+
+ checkOpenFile(file)
+ Check that file is open in the current tab, and open it if not.
+
+ checkOpenFileAtDest(file,dest)
+ Check that file is open in the current tab, and open it if not.
+ In either case go to the specified named destination.
+
+ checkOpenFileAtPage(file,page)
+ Check that file is open in the current tab, and open it if not.
+ In either case go to the specified page.
+
+ closeSidebar
+ Close the sidebar.
+
+ closeSidebarMoveResizeWin
+ Close the sidebar, resizing the window so that the document size
+ doesn't change, and moving the window so that the document stays
+ in the same place on the screen.
+
+ closeSidebarResizeWin
+ Close the sidebar, resizing the window so that the document size
+ doesn't change.
+
+ closeTabOrQuit
+ Close the tab. If this was the last open tab, close the window.
+ If this was the last window open, quit.
+
+ closeWindowOrQuit
+ Close the window. If this was the last open window, quit.
+
+ continuousMode
+ Switch to continuous view mode.
+
+ copy Copy selected text to the clipboard.
+
+ copyLinkTarget
+ Copy the target of the link under the mouse cursor to the clip-
+ board.
+
+ endPan End a pan operation.
+
+ endSelection
+ End a selection.
+
+ expandSidebar(n)
+ Expand the sidebar by n pixels. Opens the sidebar if it is cur-
+ rently closed.
+
+ find Set keyboard focus to the 'find' box.
+
+ findFirst
+ Find the first occurrence of the search string.
+
+ findNext
+ Find the next occurrence of the search string.
+
+ findPrevious
+ Find the previous occurrence of the search string.
+
+ focusToDocWin
+ Set keyboard focus to the main document window.
+
+ focusToPageNum
+ Set keyboard focus to the page number text box.
+
+ followLink
+ Follow a hyperlink (does nothing if the mouse is not over a
+ link).
+
+ followLinkInNewTab
+ Follow a hyperlink, opening PDF files in a new tab (does nothing
+ if the mouse is not over a link). For links to non-PDF files,
+ this command is identical to followLink.
+
+ followLinkInNewTabNoSel
+ Same as followLinkInNewTab, but does nothing if there is a non-
+ empty selection. (This is useful as a mouse button binding.)
+
+ followLinkInNewWin
+ Follow a hyperlink, opening PDF files in a new window (does
+ nothing if the mouse is not over a link). For links to non-PDF
+ files, this command is identical to followLink.
+
+ followLinkInNewWinNoSel
+ Same as followLinkInNewWin, but does nothing if there is a non-
+ empty selection. (This is useful as a mouse button binding.)
+
+ followLinkNoSel
+ Same as followLink, but does nothing if there is a non-empty
+ selection. (This is useful as a mouse button binding.)
+
+ fullScreenMode
+ Go to full-screen mode.
+
+ goBackward
+ Move backward along the history path.
+
+ goForward
+ Move forward along the history path.
+
+ gotoDest(dest)
+ Go to a named destination.
+
+ gotoLastPage
+ Go to the last page in the PDF file.
+
+ gotoPage(page)
+ Go to the specified page.
+
+ help Open the help URL.
+
+ hideMenuBar
+ Hide the menu bar.
+
+ hideToolbar
+ Hide the toolbar.
+
+ horizontalContinuousMode
+ Switch to horizontal continuous view mode.
+
+ linearSelectMode
+ Set linear selection mode. In this mode, the selection follows
+ text. Non-text regions cannot be selected.
+
+ loadTabState
+ Load the tab state file (which was written via the saveTabState
+ command), and restore the tabs listed in that file. The path
+ for the tab state file is specified with the tabStateFile set-
+ ting (see xpdfrc(5)).
+
+ newTab Open an empty new tab.
+
+ newWindow
+ Open an empty new window.
+
+ nextPage
+ Go to the next page.
+
+ nextPageNoScroll
+ Go to the next page, with the current relative scroll position.
+
+ nextTab
+ Switch to the next tab.
+
+ open Open a PDF file in the current tab, using the open dialog.
+
+ openErrorWindow
+ Open the error window.
+
+ openFile(file)
+ Open the specified file in the current tab.
+
+ openFile2(file,page,dest,passwd,location)
+ Open the specified file. If dest is not empty, go to the speci-
+ fied named destination. Else, if page is not empty, go to the
+ specified page number. If password is not empty, it is used as
+ the PDF password. If location is "win", open the file in a new
+ window; if it is "tab", open in a new tab; if it is "check",
+ open in the current tab, but only if the specified PDF file
+ isn't already open; else open in the current tab. Any/all of
+ the arguments, other than file, can be empty strings. For exam-
+ ple:
+ openFile2(test.pdf,7,,,tab)
+
+ openFileAtDest(file,dest)
+ Open the specified file in the current tab at the specified
+ named destination.
+
+ openFileAtDestIn(file,dest,location)
+ Open the specified file at the specified named destination.
+ Location must be "win" for a new window or "tab" for a new tab.
+
+ openFileAtPage(file,page)
+ Open the specified file in the current tab at the specified
+ page.
+
+ openFileAtPageIn(file,page,location)
+ Open the specified file at the specified page. Location must be
+ "win" for a new window or "tab" for a new tab.
+
+ openFileIn(file,location)
+ Open the specified file. Location must be "win" for a new win-
+ dow or "tab" for a new tab.
+
+ openIn(location)
+ Open a PDF file, using the open dialog. Location must be "win"
+ for a new window or "tab" for a new tab.
+
+ openSidebar
+ Open the sidebar.
+
+ openSidebarMoveResizeWin
+ Open the sidebar, resizing the window so that the document size
+ doesn't change, and moving the window so that the document stays
+ in the same place on the screen.
+
+ openSidebarResizeWin
+ Open the sidebar, resizing the window so that the document size
+ doesn't change.
+
+ pageDown
+ Scroll down by one screenful.
+
+ pageUp Scroll up by one screenful.
+
+ postPopupMenu
+ Display the popup menu.
+
+ prevPage
+ Go to the previous page.
+
+ prevPageNoScroll
+ Go to the previous page, with the current relative scroll posi-
+ tion.
+
+ prevTab
+ Switch to the previous tab.
+
+ print Open the 'print' dialog.
+
+ quit Quit from xpdf.
+
+ raise Bring the xpdf window to the front.
+
+ reload Reload the current PDF file.
+
+ rotateCCW
+ Rotate the page 90 degrees counterclockwise.
+
+ rotateCW
+ Rotate the page 90 degrees clockwise.
+
+ run(external-command-string)
+ Run an external command. The following escapes are allowed in
+ the command string:
+
+ %f => PDF file name (or an empty string if no
+ file is open)
+ %b => PDF file base name, i.e., file name minus
+ the extension (or an empty string if no
+ file is open)
+ %u => link URL (or an empty string if not over
+ a URL link)
+ %p => current page number (or an empty string if
+ no file is open)
+ %x => selection upper-left x coordinate
+ (or 0 if there is no selection)
+ %y => selection upper-left y coordinate
+ (or 0 if there is no selection)
+ %X => selection lower-right x coordinate
+ (or 0 if there is no selection)
+ %Y => selection lower-right y coordinate
+ (or 0 if there is no selection)
+ %i => page containing the mouse pointer
+ %j => x coordinate of the mouse pointer
+ %k => y coordinate of the mouse pointer
+ %% => %
+
+ The external command string will often contain spaces, so the
+ whole command must be quoted in the xpdfrc file:
+
+ bind x "run(ls -l)"
+
+ The command string may not be run through a shell. It is recom-
+ mended to keep the command simple, so that it doesn't depend on
+ specific shell functionality. For complex things, you can have
+ the command string run a shell script.
+
+ saveAs Save PDF via a file requester.
+
+ saveImage
+ Open the 'save image' dialog.
+
+ saveTabState
+ Save a list of all tabs open in this window to the tab state
+ file. For each tab, this writes the PDF file name and page num-
+ ber (on separate lines). This file can be loaded later with the
+ loadTabState command. The path for the tab state file is speci-
+ fied with the tabStateFile setting (see xpdfrc(5)).
+
+ scrollDown(n)
+ Scroll down by n pixels.
+
+ scrollDownNextPage(n)
+ Scroll down by n pixels, moving to the next page if appropriate.
+
+ scrollLeft(n)
+ Scroll left by n pixels.
+
+ scrollOutlineDown(n)
+ Scroll the outline down by n increments.
+
+ scrollOutlineUp(n)
+ Scroll the outline up by n increments.
+
+ scrollRight(n)
+ Scroll right by n pixels.
+
+ scrollToBottomEdge
+ Scroll to the bottom edge of the last displayed page, with no
+ horizontal movement.
+
+ scrollToBottomRight
+ Scroll to the bottom-right corner of the last displayed page.
+
+ scrollToLeftEdge
+ Scroll to the left edge of the current page, with no vertical
+ movement.
+
+ scrollToRightEdge
+ Scroll to the right edge of the current page, with no vertical
+ movement.
+
+ scrollToTopEdge
+ Scroll to the top edge of the first displayed page, with no hor-
+ izontal movement.
+
+ scrollToTopLeft
+ Scroll to the top-left corner of the first displayed page.
+
+ scrollUp(n)
+ Scroll up by n pixels.
+
+ scrollUpPrevPage(n)
+ Scroll up by n pixels, moving to the previous page if appropri-
+ ate.
+
+ selectLine
+ Set the selection to the line at the current mouse position.
+
+ selectWord
+ Set the selection to the word at the current mouse position.
+
+ setSelection(pg,ulx,uly,lrx,lry)
+ Set the selection to the specified coordinates on the specified
+ page.
+
+ showAttachmentsPane
+ Shows the attachments in the outline/layers/attachments pane.
+
+ showDocumentInfo
+ Open the document information dialog.
+
+ showKeyBindings
+ Open the key bindings dialog.
+
+ showLayersPane
+ Shows the layers in the outline/layers/attachments pane.
+
+ showMenuBar
+ Show the menu bar.
+
+ showOutlinePane
+ Shows the outline in the outline/layers/attachments pane.
+
+ showToolbar
+ Show the toolbar.
+
+ shrinkSidebar(n)
+ Shrink the sidebar by n pixels. Closes the sidebar if shrinking
+ it would go below the minimum allowed side.
+
+ sideBySideContinuousMode
+ Switch to side-by-side continuous view mode.
+
+ sideBySideSingleMode
+ Switch to side-by-side two-page view mode.
+
+ singlePageMode
+ Switch to single-page view mode.
+
+ startExtendedSelection
+ Extend the selection to the current mouse position, and continue
+ extending as the mouse moves.
+
+ startPan
+ Start a pan operation at the current mouse position, which will
+ scroll the document as the mouse moves.
+
+ startSelection
+ Start a selection at the current mouse position, which will be
+ extended as the mouse moves.
+
+ toggleContinuousMode
+ Toggle between continuous and single page view modes.
+
+ toggleFullScreenMode
+ Toggle between full-screen and window modes.
+
+ toggleMenuBar
+ Toggle the menu bar between shown and hidden.
+
+ toggleSelectMode
+ Toggle between block and linear selection mode.
+
+ toggleSidebar
+ Toggle the sidebar between open and closed.
+
+ toggleSidebarMoveResizeWin
+ Toggle the sidebar between open and closed, resizing the window
+ so that the document size doesn't change, and moving the window
+ so that the document stays in the same place on the screen.
+
+ toggleSidebarResizeWin
+ Toggle the sidebar between open and closed, resizing the window
+ so that the document size doesn't change.
+
+ toggleToolbar
+ Toggle the toolbar between shown and hidden.
+
+ viewPageLabels
+ Show page labels (if the PDF file has them), rather than page
+ numbers.
+
+ viewPageNumbers
+ Show page numbers, rather than page labels.
+
+ windowMode
+ Go to window (non-full-screen) mode.
+
+ zoomFitPage
+ Set the zoom factor to fit-page.
+
+ zoomFitWidth
+ Set the zoom factor to fit-width.
+
+ zoomIn Zoom in - go to the next higher zoom factor.
+
+ zoomOut
+ Zoom out - go the next lower zoom factor.
+
+ zoomPercent(z)
+ Set the zoom factor to z%.
+
+ zoomToSelection
+ Zoom to the current selection.
+
+REMOTE SERVER MODE
+ Starting xpdf with the "-remote" switch puts it into remote server
+ mode. All remaining command line options are commands (see the COM-
+ MANDS section). Subsequent invocations of "xpdf -remote" with the same
+ remote server name will send commands to the already-running instance
+ of xpdf. The "checkOpenFile" commands are useful here for things like
+ changing pages. For example:
+
+ # Start up xpdf, and open something.pdf.
+ xpdf -remote foo 'openFile(something.pdf)'
+
+ # Switch to page 7 in the already-open something.pdf. If
+ the user
+ # has closed xpdf in the meantime, this will restart it and
+ reopen
+ # the file.
+ xpdf -remote foo 'checkOpenFileAtPage(something.pdf, 7)'
+
+EXIT CODES
+ The Xpdf tools use the following exit codes:
+
+ 0 No error.
+
+ 1 Error opening a PDF file.
+
+ 2 Error opening an output file.
+
+ 3 Error related to PDF permissions.
+
+ 99 Other error.
+
+AUTHOR
+ The xpdf software and documentation are copyright 1996-2022 Glyph &
+ Cog, LLC.
+
+SEE ALSO
+ pdftops(1), pdftotext(1), pdftohtml(1), pdfinfo(1), pdffonts(1), pdfde-
+ tach(1), pdftoppm(1), pdftopng(1), pdfimages(1), xpdfrc(5)
+ http://www.xpdfreader.com/
+
+
+
+ 18 Apr 2022 xpdf(1)
diff --git a/doc/xpdfrc.5 b/doc/xpdfrc.5
new file mode 100644
index 0000000..1c47e2e
--- /dev/null
+++ b/doc/xpdfrc.5
@@ -0,0 +1,854 @@
+.\" Copyright 2002-2022 Glyph & Cog, LLC
+.TH xpdfrc 5 "18 Apr 202"
+.SH NAME
+xpdfrc \- configuration file for Xpdf tools (version 4.04)
+.SH DESCRIPTION
+All of the Xpdf tools read a single configuration file.
+.PP
+On Linux/Unix/MacOS: if you have a
+.I .xpdfrc
+file in your home directory, it will be read. Otherwise, a
+system-wide configuration file will be read from
+.IR /etc/xpdfrc ,
+if it exists. (This is its default location; depending on build
+options, it may be placed elsewhere.)
+.PP
+On Windows: the file must be named
+.I xpdfrc
+(no leading dot, no extension), and must be placed in the same
+directory as the executable (pdftotext.exe, xpdf.exe, etc.)
+.PP
+The xpdfrc file consists of a series of configuration options, one
+per line. Blank lines and lines starting with a \'#' (comments) are
+ignored.
+.PP
+Arguments can be single-quoted or double-quoted, e.g., for file names
+that contain spaces ("aaa bbb", 'aaa bbb'). This quoting does not
+provide any escaping, so there's no way to include a double quote in a
+double-quoted argument or a single quote in a single-quoted argument.
+.PP
+
+Arguments can also be at-quoted: @"aaa bbb". At-quoted strings allow
+use of the DATADIR variable, which is set to the 'data' subdirectory
+in the xpdf install directory. The percent sign (%) is an escape
+character: a percent sign followed by any other character is replaced
+with that character.
+.PP
+.RS
+.nf
+@"abc %"def%" ghi" --> abc "def" ghi
+@"${DATADIR}/foo" --> ...install-dir.../data/foo
+@"%${DATADIR}/foo" --> ${DATADIR}/foo
+.fi
+.RE
+.PP
+The following sections list all of the configuration options, sorted
+into functional groups. There is an examples section at the end.
+.SH INCLUDE FILES
+.TP
+.BI include " config\-file"
+Includes the specified config file. The effect of this is equivalent
+to inserting the contents of
+.I config\-file
+directly into the parent config file in place of the
+.I include
+command. Config files can be nested arbitrarily deeply.
+.SH GENERAL FONT CONFIGURATION
+.TP
+.BI fontFile " PDF\-font\-name font\-file"
+Maps a PDF font,
+.IR PDF\-font\-name ,
+to a font for display or PostScript output. The font file,
+.IR font\-file ,
+can be any type allowed in a PDF file. This command can be used for
+8-bit or 16-bit (CID) fonts.
+.TP
+.BI fontDir " dir"
+Specifies a search directory for font files. There can be multiple
+fontDir commands; all of the specified directories will be searched in
+order. The font files can be Type 1 (.pfa or .pfb) or TrueType (.ttf
+or .ttc); other files in the directory will be ignored. The font file
+name (not including the extension) must exactly match the PDF font
+name. This search is performed if the font name doesn't match any of
+the fonts declared with the fontFile command. There are no default
+fontDir directories.
+.TP
+.BI fontFileCC " registry\-ordering font\-file"
+Maps the
+.I registry\-ordering
+character collection to a font for display or PostScript output. This
+mapping is used if the font name doesn't match any of the fonts
+declared with the fontFile, fontDir, psResidentFont16, or
+psResidentFontCC commands.
+.SH POSTSCRIPT FONT CONFIGURATION
+.TP
+.BR psFontPassthrough " yes | no"
+If set to "yes", pass 8-bit font names through to the PostScript
+output without substitution. Fonts which are not embedded in the PDF
+file are expected to be available on the printer. This defaults to
+"no".
+.TP
+.BI psResidentFont " PDF\-font\-name PS\-font\-name"
+When the 8-bit font
+.I PDF\-font\-name
+is used (without embedding) in a PDF file, it will be translated to
+the PostScript font
+.IR PS\-font\-name ,
+which is assumed to be resident in the printer. Typically,
+.I PDF\-font\-name
+and
+.I PS\-font\-name
+are the same. By default, only the Base-14 fonts are assumed to be
+resident.
+.TP
+.BI psResidentFont16 " PDF\-font\-name wMode PS\-font\-name encoding"
+When the 16-bit (CID) font
+.I PDF\-font\-name
+with writing mode
+.I wMode
+is used (without embedding) in a PDF file, it will be translated to
+the PostScript font
+.IR PS\-font\-name ,
+which is assumed to be resident in the printer. The writing mode
+must be either \'H' for horizontal or \'V' for vertical. The resident
+font is assumed to use the specified encoding (which must have been
+defined with the unicodeMap command).
+.TP
+.BI psResidentFontCC " registry\-ordering wMode PS\-font\-name encoding"
+When a 16-bit (CID) font using the
+.I registry\-ordering
+character collection and
+.I wMode
+writing mode is used (without embedding) in a PDF file, the PostScript
+font,
+.IR PS\-font\-name ,
+is substituted for it. The substituted font is assumed to be
+resident in the printer. The writing mode must be either \'H' for
+horizontal or \'V' for vertical. The resident font is assumed to use
+the specified encoding (which must have been defined with the
+unicodeMap command).
+.TP
+.BR psEmbedType1Fonts " yes | no"
+If set to "no", prevents embedding of Type 1 fonts in generated
+PostScript. This defaults to "yes".
+.TP
+.BR psEmbedTrueTypeFonts " yes | no"
+If set to "no", prevents embedding of TrueType fonts in generated
+PostScript. This defaults to "yes".
+.TP
+.BR psEmbedCIDTrueTypeFonts " yes | no"
+If set to "no", prevents embedding of CID TrueType fonts in generated
+PostScript. For Level 3 PostScript, this generates a CID font, for
+lower levels it generates a non-CID composite font. This defaults to
+"yes".
+.TP
+.BR psEmbedCIDPostScriptFonts " yes | no"
+If set to "no", prevents embedding of CID PostScript fonts in
+generated PostScript. For Level 3 PostScript, this generates a CID
+font, for lower levels it generates a non-CID composite font. This
+defaults to "yes".
+.SH POSTSCRIPT CONTROL
+.TP
+.BI psPaperSize " width(pts) height(pts)"
+Sets the paper size for PostScript output. The
+.I width
+and
+.I height
+parameters give the paper size in PostScript points (1 point = 1/72
+inch).
+.TP
+.BR psPaperSize " letter | legal | A4 | A3 | match"
+Sets the paper size for PostScript output to a standard size. The
+default paper size is set when xpdf and pdftops are built, typically
+to "letter" or "A4". This can also be set to "match", which will set
+the paper size to match the size specified in the PDF file.
+.TP
+.BR psImageableArea " llx lly urx ury"
+Sets the imageable area for PostScript output. The four integers are
+the coordinates of the lower-left and upper-right corners of the
+imageable region, specified in points (with the origin being the
+lower-left corner of the paper). This defaults to the full paper
+size; the psPaperSize option will reset the imageable area
+coordinates.
+.TP
+.BR psCrop " yes | no"
+If set to "yes", PostScript output is cropped to the CropBox specified
+in the PDF file; otherwise no cropping is done. This defaults to
+"yes".
+.TP
+.BR psUseCropBoxAsPage " yes | no"
+If set to "yes", PostScript output treats the CropBox as the page size.
+By default, this is "no", and the MediaBox is used as the page size.
+.TP
+.BR psExpandSmaller " yes | no"
+If set to "yes", PDF pages smaller than the PostScript imageable area
+are expanded to fill the imageable area. Otherwise, no scaling is
+done on smaller pages. This defaults to "no".
+.TP
+.BR psShrinkLarger " yes | no"
+If set to yes, PDF pages larger than the PostScript imageable area are
+shrunk to fit the imageable area. Otherwise, no scaling is done on
+larger pages. This defaults to "yes".
+.TP
+.BR psCenter " yes | no"
+If set to yes, PDF pages smaller than the PostScript imageable area
+(after any scaling) are centered in the imageable area. Otherwise,
+they are aligned at the lower-left corner of the imageable area. This
+defaults to "yes".
+.TP
+.BR psDuplex " yes | no"
+If set to "yes", the generated PostScript will set the "Duplex"
+pagedevice entry. This tells duplex-capable printers to enable
+duplexing. This defaults to "no".
+.TP
+.BR psLevel " level1 | level1sep | level2 | level2gray | level2sep | level3 | level3gray | level3Sep"
+Sets the PostScript level to generate. This defaults to "level2".
+.TP
+.BR psPreload " yes | no"
+If set to "yes", PDF forms are converted to PS procedures, and image
+data is preloaded. This uses more memory in the PostScript
+interpreter, but generates significantly smaller PS files in
+situations where, e.g., the same image is drawn on every page of a
+long document. This defaults to "no".
+.TP
+.BR psOPI " yes | no"
+If set to "yes", generates PostScript OPI comments for all images and
+forms which have OPI information. This option is only available if
+the Xpdf tools were compiled with OPI support. This defaults to "no".
+.TP
+.BR psASCIIHex " yes | no"
+If set to "yes", the ASCIIHexEncode filter will be used instead of
+ASCII85Encode for binary data. This defaults to "no".
+.TP
+.BR psLZW " yes | no"
+If set to "yes", the LZWEncode filter will be used for lossless
+compression in PostScript output; if set to "no", the RunLengthEncode
+filter will be used instead. LZW generates better compression
+(smaller PS files), but may not be supported by some printers. This
+defaults to "yes".
+.TP
+.BR psUncompressPreloadedImages " yes | no"
+If set to "yes", all preloaded images in PS files will uncompressed.
+If set to "no", the original compressed images will be used when
+possible. The "yes" setting is useful to work around certain buggy
+PostScript interpreters. This defaults to "no".
+.TP
+.BR psMinLineWidth " float"
+Set the minimum line width, in points, for PostScript output. The
+default value is 0 (no minimum).
+.TP
+.BR psRasterResolution " float"
+Set the resolution (in dpi) for rasterized pages in PostScript output.
+(Pdftops will rasterize pages which use transparency.) This defaults
+to 300.
+.TP
+.BR psRasterMono " yes | no"
+If set to "yes", rasterized pages in PS files will be monochrome
+(8-bit gray) instead of color. This defaults to "no".
+.TP
+.BR psRasterSliceSize " pixels"
+When rasterizing pages, pdftops splits the page into horizontal
+"slices", to limit memory usage. This option sets the maximum slice
+size, in pixels. This defaults to 20000000 (20 million).
+.TP
+.BR psAlwaysRasterize " yes | no"
+If set to "yes", all PostScript output will be rasterized. This
+defaults to "no".
+.TP
+.BR psNeverRasterize " yes | no"
+Pdftops rasterizes an pages that use transparency (because PostScript
+doesn't support transparency). If psNeverRasterize is set to "yes",
+rasterization is disabled: pages will never be rasterized, even if
+they contain transparency. This will likely result in incorrect
+output for PDF files that use transparency, and a warning message to
+that effect will be printed. This defaults to "no".
+.TP
+.BI fontDir " dir"
+See the description above, in the DISPLAY FONTS section.
+.SH TEXT CONTROL AND CHARACTER MAPPING
+.TP
+.BI textEncoding " encoding\-name"
+Sets the encoding to use for text output. (This can be overridden
+with the "\-enc" switch on the command line.) The
+.I encoding\-name
+must be defined with the unicodeMap command (see above). This
+defaults to "Latin1".
+.TP
+.BR textEOL " unix | dos | mac"
+Sets the end-of-line convention to use for text output. The options
+are:
+.nf
+
+ unix = LF
+ dos = CR+LF
+ mac = CR
+
+.fi
+(This can be overridden with the "\-eol" switch on the command line.)
+The default value is based on the OS where xpdf and pdftotext were
+built.
+.TP
+.BR textPageBreaks " yes | no"
+If set to "yes", text extraction will insert page breaks (form feed
+characters) between pages. This defaults to "yes".
+.TP
+.BR textKeepTinyChars " yes | no"
+If set to "yes", text extraction will keep all characters. If set to
+"no", text extraction will discard tiny (smaller than 3 point)
+characters after the first 50000 per page, avoiding extremely slow run
+times for PDF files that use special fonts to do shading or
+cross-hatching. This defaults to "yes".
+.TP
+.BI nameToUnicode " map\-file"
+Specifies a file with the mapping from character names to Unicode.
+This is used to handle PDF fonts that have valid encodings but no
+ToUnicode entry. Each line of a nameToUnicode file looks like this:
+
+.I " " hex\-string name
+
+The
+.I hex\-string
+is the Unicode (UCS-2) character index, and
+.I name
+is the corresponding character name. Multiple nameToUnicode files can
+be used; if a character name is given more than once, the code in the
+last specified file is used. There is a built-in default
+nameToUnicode table with all of Adobe's standard character names.
+.TP
+.BI cidToUnicode " registry\-ordering map\-file"
+Specifies the file with the mapping from character collection to
+Unicode. Each line of a cidToUnicode file represents one character:
+
+.I " " hex\-string
+
+The
+.I hex\-string
+is the Unicode (UCS-2) index for that character. The first line maps
+CID 0, the second line CID 1, etc. File size is determined by size of
+the character collection. Only one file is allowed per character
+collection; the last specified file is used. There are no built-in
+cidToUnicode mappings.
+.TP
+.BI unicodeToUnicode " font\-name\-substring map\-file"
+This is used to work around PDF fonts which have incorrect Unicode
+information. It specifies a file which maps from the given
+(incorrect) Unicode indexes to the correct ones. The mapping will be
+used for any font whose name contains
+.IR font\-name\-substring .
+Each line of a unicodeToUnicode file represents one Unicode character:
+
+.RI " " in\-hex " " out\-hex1 " " out\-hex2 " ..."
+
+The
+.I in\-hex
+field is an input (incorrect) Unicode index, and the rest of the
+fields are one or more output (correct) Unicode indexes. Each
+occurrence of
+.I in\-hex
+will be converted to the specified output sequence.
+.TP
+.BI unicodeRemapping " remap\-file"
+Remap Unicode characters when doing text extraction. This specifies a
+file that maps from a particular Unicode index to zero or more
+replacement Unicode indexes. Each line of the remap file represents
+one Unicode character:
+
+.RI " " in\-hex " " out\-hex1 " " out\-hex2 " ..."
+
+Any Unicode characters not listed will be left unchanged. This
+function is typically used to remap things like non-breaking spaces,
+soft hyphens, ligatures, etc.
+.TP
+.BI unicodeMap " encoding\-name map\-file"
+Specifies the file with mapping from Unicode to
+.IR encoding\-name .
+These encodings are used for text output (see below). Each line of a
+unicodeMap file represents a range of one or more Unicode characters
+which maps linearly to a range in the output encoding:
+.nf
+
+.I " " in\-start\-hex in\-end\-hex out\-start\-hex
+
+.fi
+Entries for single characters can be abbreviated to:
+.nf
+
+.I " " in\-hex out\-hex
+
+.fi
+The
+.I in\-start\-hex
+and
+.I in\-end\-hex
+fields (or the single
+.I in\-hex
+field) specify the Unicode range. The
+.I out\-start\-hex
+field (or the
+.I out\-hex
+field) specifies the start of the output encoding range. The length
+of the
+.I out\-start\-hex
+(or
+.IR out\-hex )
+string determines the length of the output characters (e.g., UTF-8
+uses different numbers of bytes to represent characters in different
+ranges). Entries must be given in increasing Unicode order. Only one
+file is allowed per encoding; the last specified file is used. The
+.IR Latin1 ,
+.IR ASCII7 ,
+.IR Symbol ,
+.IR ZapfDingbats ,
+.IR UTF-8 ,
+and
+.I UCS-2
+encodings are predefined.
+.TP
+.BI cMapDir " registry\-ordering dir"
+Specifies a search directory,
+.IR dir ,
+for CMaps for the
+.I registry\-ordering
+character collection. There can be multiple directories for a
+particular collection. There are no default CMap directories.
+.TP
+.BI toUnicodeDir " dir"
+Specifies a search directory,
+.IR dir ,
+for ToUnicode CMaps. There can be multiple ToUnicode directories.
+There are no default ToUnicode directories.
+.TP
+.BI mapNumericCharNames " yes | no"
+If set to "yes", the Xpdf tools will attempt to map various numeric
+character names sometimes used in font subsets. In some cases this
+leads to usable text, and in other cases it leads to gibberish --
+there is no way for Xpdf to tell. This defaults to "yes".
+.TP
+.BI mapUnknownCharNames " yes | no"
+If set to "yes", and mapNumericCharNames is set to "no", the Xpdf
+tools will apply a simple pass-through mapping (Unicode index =
+character code) for all unrecognized glyph names. (For CID fonts,
+setting mapNumericCharNames to "no" is unnecessary.) In some cases,
+this leads to usable text, and in other cases it leads to gibberish --
+there is no way for Xpdf to tell. This defaults to "no".
+.TP
+.BI mapExtTrueTypeFontsViaUnicode " yes | no"
+When rasterizing text using an external TrueType font, there are two
+options for handling character codes. If
+mapExtTrueTypeFontsViaUnicode is set to "yes", Xpdf will use the font
+encoding/ToUnicode info to map character codes to Unicode, and then
+use the font's Unicode cmap to map Unicode to GIDs. If
+mapExtTrueTypeFontsViaUnicode is set to "no", Xpdf will assume the
+character codes are GIDs (i.e., use an identity mapping). This
+defaults to "yes".
+.TP
+.BI useTrueTypeUnicodeMapping " yes | no"
+If set to "yes", the Xpdf tools will use the Unicode encoding
+information in TrueType fonts (16-bit only), if avaiable, to override
+the PDF ToUnicode maps. Otherwise, the ToUnicode maps are always used
+when present. This defaults to "no".
+.TP
+.BI dropFont " font-name"
+Drop all text drawn in the specified font. To drop text drawn in
+unnamed fonts, use:
+.nf
+
+ dropFont ""
+
+.fi
+There can be any number of dropFont commands.
+.SH RASTERIZER SETTINGS
+.TP
+.BR enableFreeType " yes | no"
+Enables or disables use of FreeType (a TrueType / Type 1 font
+rasterizer). This is only relevant if the Xpdf tools were built with
+FreeType support. ("enableFreeType" replaces the old
+"freetypeControl" option.) This option defaults to "yes".
+.TP
+.BR disableFreeTypeHinting " yes | no"
+If this is set to "yes", FreeType hinting will be forced off. This
+option defaults to "no".
+.TP
+.BR antialias " yes | no"
+Enables or disables font anti-aliasing in the PDF rasterizer. This
+option affects all font rasterizers. ("antialias" replaces the
+anti-aliasing control provided by the old "t1libControl" and
+"freetypeControl" options.) This default to "yes".
+.TP
+.BR vectorAntialias " yes | no"
+Enables or disables anti-aliasing of vector graphics in the PDF
+rasterizer. This defaults to "yes".
+.TP
+.BR imageMaskAntialias " yes | no"
+Enables or disables anti-aliasing of image masks (when downsampling or
+upsampling) in the PDF rasterizer. This defaults to "yes".
+.TP
+.BR antialiasPrinting " yes | no"
+If this is "yes", bitmaps sent to the printer will be antialiased
+(according to the "antialias" and "vectorAntialias" settings). If
+this is "no", printed bitmaps will not be antialiased. This defaults
+to "no".
+.TP
+.BR strokeAdjust " yes | no | cad"
+Sets the stroke adjustment mode. If set to "no", no stroke adjustment
+will be done. If set to "yes", normal stroke adjustment will be done:
+horizontal and vertical lines will be moved by up to half a pixel to
+make them look cleaner when vector anti-aliasing is enabled. If set
+to "cad", a slightly different stroke adjustment algorithm will be
+used to ensure that lines of the same original width will always have
+the same adjusted width (at the expense of allowing gaps and overlaps
+between adjacent lines). This defaults to "yes".
+.TP
+.BR forceAccurateTiling " yes | no"
+If this is set to "yes", the TilingType is forced to 2 (no distortion)
+for all tiling patterns, regardless of the setting in the pattern
+dictionary. This defaults to "no".
+.TP
+.BR screenType " dispersed | clustered | stochasticClustered"
+Sets the halftone screen type, which will be used when generating a
+monochrome (1-bit) bitmap. The three options are dispersed-dot
+dithering, clustered-dot dithering (with a round dot and 45-degree
+screen angle), and stochastic clustered-dot dithering. By default,
+"stochasticClustered" is used for resolutions of 300 dpi and higher,
+and "dispersed" is used for resolutions lower then 300 dpi.
+.TP
+.BI screenSize " integer"
+Sets the size of the (square) halftone screen threshold matrix. By
+default, this is 4 for dispersed-dot dithering, 10 for clustered-dot
+dithering, and 100 for stochastic clustered-dot dithering.
+.TP
+.BI screenDotRadius " integer"
+Sets the halftone screen dot radius. This is only used when
+screenType is set to stochasticClustered, and it defaults to 2. In
+clustered-dot mode, the dot radius is half of the screen size.
+Dispersed-dot dithering doesn't have a dot radius.
+.TP
+.BI screenGamma " float"
+Sets the halftone screen gamma correction parameter. Gamma values
+greater than 1 make the output brighter; gamma values less than 1 make
+it darker. The default value is 1.
+.TP
+.BI screenBlackThreshold " float"
+When halftoning, all values below this threshold are forced to solid
+black. This parameter is a floating point value between 0 (black) and
+1 (white). The default value is 0.
+.TP
+.BI screenWhiteThreshold " float"
+When halftoning, all values above this threshold are forced to solid
+white. This parameter is a floating point value between 0 (black) and
+1 (white). The default value is 1.
+.TP
+.BI minLineWidth " float"
+Set the minimum line width, in device pixels. This affects the
+rasterizer only, not the PostScript converter (except when it uses
+rasterization to handle transparency). The default value is 0 (no
+minimum).
+.TP
+.BI enablePathSimplification " yes | no"
+If set to "yes", simplify paths by removing points where it won't make
+a significant difference to the shape. The default value is "no".
+.TP
+.BI overprintPreview " yes | no"
+If set to "yes", generate overprint preview output, honoring the
+OP/op/OPM settings in the PDF file. Ignored for non-CMYK output. The
+default value is "no".
+.SH VIEWER SETTINGS
+These settings only apply to the Xpdf GUI PDF viewer.
+.TP
+.BR initialZoom " \fIpercentage\fR | page | width"
+Sets the initial zoom factor. A number specifies a zoom percentage,
+where 100 means 72 dpi. You may also specify \'page', to fit the page
+to the window size, or \'width', to fit the page width to the window
+width.
+.TP
+.BI defaultFitZoom " percentage"
+If xpdf is started with fit-page or fit-width zoom and no window
+geometry, it will calculate a desired window size based on the PDF
+page size and this defaultFitZoom value. I.e., the window size will
+be chosen such that exactly one page will fit in the window at this
+zoom factor (which must be a percentage). The default value is
+based on the screen resolution.
+.TP
+.BR initialDisplayMode " single | continuous | sideBySideSingle | sideBySideContinuous | horizontalContinuous"
+Sets the initial display mode. The default setting is "continuous".
+.TP
+.BI initialToolbarState " yes | no"
+If set to "yes", xpdf opens with the toolbar visible. If set to "no",
+xpdf opens with the toolbar hidden. The default is "yes".
+.TP
+.BI initialSidebarState " yes | no"
+If set to "yes", xpdf opens with the sidebar (tabs, outline, etc.)
+visible. If set to "no", xpdf opens with the sidebar collapsed. The
+default is "yes".
+.TP
+.BI initialSidebarWidth " width"
+Sets the initial sidebar width, in pixels. This is only relevant if
+initialSidebarState is "yes". The default value is zero, which tells
+xpdf to use an internal default size.
+.TP
+.BR initialSelectMode " block | linear"
+Sets the initial selection mode. The default setting is "linear".
+.TP
+.BI paperColor " color"
+Set the "paper color", i.e., the background of the page display. The
+color can be #RRGGBB (hexadecimal) or a named color. This option will
+not work well with PDF files that do things like filling in white
+behind the text.
+.TP
+.BI matteColor " color"
+Set the matte color, i.e., the color used for background outside the
+actual page area. The color can be #RRGGBB (hexadecimal) or a named
+color.
+.TP
+.BI fullScreenMatteColor " color"
+Set the matte color for full-screen mode. The color can be #RRGGBB
+(hexadecimal) or a named color.
+.TP
+.BI selectionColor " color"
+Set the selection color. The color can be #RRGGBB (hexadecimal) or a
+named color.
+.TP
+.BI reverseVideoInvertImages " yes | no"
+If set to "no", xpdf's reverse-video mode inverts text and vector
+graphic content, but not images. If set to "yes", xpdf inverts images
+as well. The default is "no".
+.TP
+.BI popupMenuCmd " title command ..."
+Add a command to the popup menu.
+.I Title
+is the text to be displayed in the menu.
+.I Command
+is an Xpdf command (see the COMMANDS section of the
+.BR xpdf (1)
+man page for details). Multiple commands are separated by whitespace.
+.TP
+.BI maxTileWidth " pixels"
+Set the maximum width of tiles to be used by xpdf when rasterizing
+pages. This defaults to 1500.
+.TP
+.BI maxTileHeight " pixels"
+Set the maximum height of tiles to be used by xpdf when rasterizing
+pages. This defaults to 1500.
+.TP
+.BI tileCacheSize " tiles"
+Set the maximum number of tiles to be cached by xpdf when rasterizing
+pages. This defaults to 10.
+.TP
+.BI workerThreads " numThreads"
+Set the number of worker threads to be used by xpdf when rasterizing
+pages. This defaults to 1.
+.TP
+.BI launchCommand " command"
+Sets the command executed when you click on a "launch"-type link. The
+intent is for the command to be a program/script which determines the
+file type and runs the appropriate viewer. The command line will
+consist of the file to be launched, followed by any parameters
+specified with the link. Do not use "%s" in "command". By default,
+this is unset, and Xpdf will simply try to execute the file (after
+prompting the user).
+.TP
+.BI movieCommand " command"
+Sets the command executed when you click on a movie annotation. The
+string "%s" will be replaced with the movie file name. This has no
+default value.
+.TP
+.BI defaultPrinter " printer"
+Sets the default printer used in the viewer's print dialog.
+.TP
+.BI bind " modifiers-key context command ..."
+Add a key or mouse button binding.
+.I Modifiers
+can be zero or more of:
+.nf
+
+ shift-
+ ctrl-
+ alt-
+
+.fi
+.I Key
+can be a regular ASCII character, or any one of:
+.nf
+
+ space
+ tab
+ return
+ enter
+ backspace
+ esc
+ insert
+ delete
+ home
+ end
+ pgup
+ pgdn
+ left / right / up / down (arrow keys)
+ f1 .. f35 (function keys)
+ mousePress1 .. mousePress7 (mouse buttons)
+ mouseRelease1 .. mouseRelease7 (mouse buttons)
+ mouseClick1 .. mouseClick7 (mouse buttons)
+ mouseDoubleClick1 .. mouseDoubleClick7 (mouse buttons)
+ mouseTripleClick1 .. mouseTripleClick7 (mouse buttons)
+
+.fi
+.I Context
+is either "any" or a comma-separated combination of:
+.nf
+
+ fullScreen / window (full screen mode on/off)
+ continuous / singlePage (continuous mode on/off)
+ overLink / offLink (mouse over link or not)
+ scrLockOn / scrLockOff (scroll lock on/off)
+
+.fi
+The context string can include only one of each pair in the above
+list.
+
+.I Command
+is an Xpdf command (see the COMMANDS section of the
+.BR xpdf (1)
+man page for details). Multiple commands are separated by whitespace.
+
+The bind command replaces any existing binding, but only if it was
+defined for the exact same modifiers, key, and context. All tokens
+(modifiers, key, context, commands) are case-sensitive.
+
+Example key bindings:
+.nf
+
+ # bind ctrl-a in any context to the nextPage
+ # command
+ bind ctrl-a any nextPage
+
+ # bind uppercase B, when in continuous mode
+ # with scroll lock on, to the reload command
+ # followed by the prevPage command
+ bind B continuous,scrLockOn reload prevPage
+
+.fi
+See the
+.BR xpdf (1)
+man page for more examples.
+.TP
+.BI unbind " modifiers-key context"
+Removes a key binding established with the bind command. This is most
+useful to remove default key bindings before establishing new ones
+(e.g., if the default key binding is given for "any" context, and you
+want to create new key bindings for multiple contexts).
+.TP
+.BI tabStateFile " path"
+Sets the file used by the loadTabState and saveTabState commands (see
+the
+.BR xpdf (1)
+man page for more information).
+.SH MISCELLANEOUS SETTINGS
+.TP
+.BI drawAnnotations " yes | no"
+If set to "no", annotations will not be drawn or printed. The default
+value is "yes".
+.TP
+.BI drawFormFields " yes | no"
+If set to "no", form fields will not be drawn or printed. The default
+value is "yes".
+.TP
+.BI enableXFA " yes | no"
+If an XFA form is present, and this option is set to "yes", Xpdf will
+parse the XFA form and use certain XFA information to override
+AcroForm information. If set to "no", the XFA form will not be read.
+The default value is "yes".
+.TP
+.BI savePageNumbers " yes | no"
+If set to "yes", xpdf will save the current page numbers of all open
+files in ~/.xpdf.pages when the files are closed (or when quitting
+xpdf). Next time the file is opened, the last-viewed page number will
+be restored. The default value is "yes".
+.TP
+.BI printCommands " yes | no"
+If set to "yes", drawing commands are printed as they're executed
+(useful for debugging). This defaults to "no".
+.TP
+.BI printStatusInfo
+If set to "yes", print a status message (to stdout) before each page
+is processed. This defaults to "no".
+.TP
+.BI errQuiet " yes | no"
+If set to "yes", this suppresses all error and warning messages from
+all of the Xpdf tools. This defaults to "no".
+.SH EXAMPLES
+The following is a sample xpdfrc file.
+.nf
+
+# from the Thai support package
+nameToUnicode /usr/local/share/xpdf/Thai.nameToUnicode
+
+# from the Japanese support package
+cidToUnicode Adobe-Japan1 /usr/local/share/xpdf/Adobe-Japan1.cidToUnicode
+unicodeMap JISX0208 /usr/local/share/xpdf/JISX0208.unicodeMap
+cMapDir Adobe-Japan1 /usr/local/share/xpdf/cmap/Adobe-Japan1
+
+# use the Base-14 Type 1 fonts from ghostscript
+fontFile Times-Roman /usr/local/share/ghostscript/fonts/n021003l.pfb
+fontFile Times-Italic /usr/local/share/ghostscript/fonts/n021023l.pfb
+fontFile Times-Bold /usr/local/share/ghostscript/fonts/n021004l.pfb
+fontFile Times-BoldItalic /usr/local/share/ghostscript/fonts/n021024l.pfb
+fontFile Helvetica /usr/local/share/ghostscript/fonts/n019003l.pfb
+fontFile Helvetica-Oblique /usr/local/share/ghostscript/fonts/n019023l.pfb
+fontFile Helvetica-Bold /usr/local/share/ghostscript/fonts/n019004l.pfb
+fontFile Helvetica-BoldOblique /usr/local/share/ghostscript/fonts/n019024l.pfb
+fontFile Courier /usr/local/share/ghostscript/fonts/n022003l.pfb
+fontFile Courier-Oblique /usr/local/share/ghostscript/fonts/n022023l.pfb
+fontFile Courier-Bold /usr/local/share/ghostscript/fonts/n022004l.pfb
+fontFile Courier-BoldOblique /usr/local/share/ghostscript/fonts/n022024l.pfb
+fontFile Symbol /usr/local/share/ghostscript/fonts/s050000l.pfb
+fontFile ZapfDingbats /usr/local/share/ghostscript/fonts/d050000l.pfb
+
+# use the Bakoma Type 1 fonts
+# (this assumes they happen to be installed in /usr/local/fonts/bakoma)
+fontDir /usr/local/fonts/bakoma
+
+# set some PostScript options
+psPaperSize letter
+psDuplex no
+psLevel level2
+psEmbedType1Fonts yes
+psEmbedTrueTypeFonts yes
+
+# assume that the PostScript printer has the Univers and
+# Univers-Bold fonts
+psResidentFont Univers Univers
+psResidentFont Univers-Bold Univers-Bold
+
+# set the text output options
+textEncoding UTF-8
+textEOL unix
+
+# misc options
+enableFreeType yes
+launchCommand viewer-script
+
+.fi
+.SH FILES
+.TP
+.B /etc/xpdfrc
+This is the default location for the system-wide configuration file.
+Depending on build options, it may be placed elsewhere.
+.TP
+.B $HOME/.xpdfrc
+This is the user's configuration file. If it exists, it will be read
+in place of the system-wide file.
+.SH AUTHOR
+The Xpdf software and documentation are copyright 1996-2022 Glyph &
+Cog, LLC.
+.SH "SEE ALSO"
+.BR xpdf (1),
+.BR pdftops (1),
+.BR pdftotext (1),
+.BR pdftohtml (1),
+.BR pdfinfo (1),
+.BR pdffonts (1),
+.BR pdfdetach (1),
+.BR pdftoppm (1),
+.BR pdftopng (1),
+.BR pdfimages (1)
+.br
+.B http://www.xpdfreader.com/
diff --git a/doc/xpdfrc.cat b/doc/xpdfrc.cat
new file mode 100644
index 0000000..c38791e
--- /dev/null
+++ b/doc/xpdfrc.cat
@@ -0,0 +1,786 @@
+xpdfrc(5) File Formats Manual xpdfrc(5)
+
+
+
+NAME
+ xpdfrc - configuration file for Xpdf tools (version 4.04)
+
+DESCRIPTION
+ All of the Xpdf tools read a single configuration file.
+
+ On Linux/Unix/MacOS: if you have a .xpdfrc file in your home directory,
+ it will be read. Otherwise, a system-wide configuration file will be
+ read from /etc/xpdfrc, if it exists. (This is its default location;
+ depending on build options, it may be placed elsewhere.)
+
+ On Windows: the file must be named xpdfrc (no leading dot, no exten-
+ sion), and must be placed in the same directory as the executable
+ (pdftotext.exe, xpdf.exe, etc.)
+
+ The xpdfrc file consists of a series of configuration options, one per
+ line. Blank lines and lines starting with a '#' (comments) are
+ ignored.
+
+ Arguments can be single-quoted or double-quoted, e.g., for file names
+ that contain spaces ("aaa bbb", 'aaa bbb'). This quoting does not pro-
+ vide any escaping, so there's no way to include a double quote in a
+ double-quoted argument or a single quote in a single-quoted argument.
+
+ Arguments can also be at-quoted: @"aaa bbb". At-quoted strings allow
+ use of the DATADIR variable, which is set to the 'data' subdirectory in
+ the xpdf install directory. The percent sign (%) is an escape charac-
+ ter: a percent sign followed by any other character is replaced with
+ that character.
+
+ @"abc %"def%" ghi" --> abc "def" ghi
+ @"${DATADIR}/foo" --> ...install-dir.../data/foo
+ @"%${DATADIR}/foo" --> ${DATADIR}/foo
+
+ The following sections list all of the configuration options, sorted
+ into functional groups. There is an examples section at the end.
+
+INCLUDE FILES
+ include config-file
+ Includes the specified config file. The effect of this is
+ equivalent to inserting the contents of config-file directly
+ into the parent config file in place of the include command.
+ Config files can be nested arbitrarily deeply.
+
+GENERAL FONT CONFIGURATION
+ fontFile PDF-font-name font-file
+ Maps a PDF font, PDF-font-name, to a font for display or Post-
+ Script output. The font file, font-file, can be any type
+ allowed in a PDF file. This command can be used for 8-bit or
+ 16-bit (CID) fonts.
+
+ fontDir dir
+ Specifies a search directory for font files. There can be mul-
+ tiple fontDir commands; all of the specified directories will be
+ searched in order. The font files can be Type 1 (.pfa or .pfb)
+ or TrueType (.ttf or .ttc); other files in the directory will be
+ ignored. The font file name (not including the extension) must
+ exactly match the PDF font name. This search is performed if
+ the font name doesn't match any of the fonts declared with the
+ fontFile command. There are no default fontDir directories.
+
+ fontFileCC registry-ordering font-file
+ Maps the registry-ordering character collection to a font for
+ display or PostScript output. This mapping is used if the font
+ name doesn't match any of the fonts declared with the fontFile,
+ fontDir, psResidentFont16, or psResidentFontCC commands.
+
+POSTSCRIPT FONT CONFIGURATION
+ psFontPassthrough yes | no
+ If set to "yes", pass 8-bit font names through to the PostScript
+ output without substitution. Fonts which are not embedded in
+ the PDF file are expected to be available on the printer. This
+ defaults to "no".
+
+ psResidentFont PDF-font-name PS-font-name
+ When the 8-bit font PDF-font-name is used (without embedding) in
+ a PDF file, it will be translated to the PostScript font
+ PS-font-name, which is assumed to be resident in the printer.
+ Typically, PDF-font-name and PS-font-name are the same. By
+ default, only the Base-14 fonts are assumed to be resident.
+
+ psResidentFont16 PDF-font-name wMode PS-font-name encoding
+ When the 16-bit (CID) font PDF-font-name with writing mode wMode
+ is used (without embedding) in a PDF file, it will be translated
+ to the PostScript font PS-font-name, which is assumed to be res-
+ ident in the printer. The writing mode must be either 'H' for
+ horizontal or 'V' for vertical. The resident font is assumed to
+ use the specified encoding (which must have been defined with
+ the unicodeMap command).
+
+ psResidentFontCC registry-ordering wMode PS-font-name encoding
+ When a 16-bit (CID) font using the registry-ordering character
+ collection and wMode writing mode is used (without embedding) in
+ a PDF file, the PostScript font, PS-font-name, is substituted
+ for it. The substituted font is assumed to be resident in the
+ printer. The writing mode must be either 'H' for horizontal or
+ 'V' for vertical. The resident font is assumed to use the spec-
+ ified encoding (which must have been defined with the unicodeMap
+ command).
+
+ psEmbedType1Fonts yes | no
+ If set to "no", prevents embedding of Type 1 fonts in generated
+ PostScript. This defaults to "yes".
+
+ psEmbedTrueTypeFonts yes | no
+ If set to "no", prevents embedding of TrueType fonts in gener-
+ ated PostScript. This defaults to "yes".
+
+ psEmbedCIDTrueTypeFonts yes | no
+ If set to "no", prevents embedding of CID TrueType fonts in gen-
+ erated PostScript. For Level 3 PostScript, this generates a CID
+ font, for lower levels it generates a non-CID composite font.
+ This defaults to "yes".
+
+ psEmbedCIDPostScriptFonts yes | no
+ If set to "no", prevents embedding of CID PostScript fonts in
+ generated PostScript. For Level 3 PostScript, this generates a
+ CID font, for lower levels it generates a non-CID composite
+ font. This defaults to "yes".
+
+POSTSCRIPT CONTROL
+ psPaperSize width(pts) height(pts)
+ Sets the paper size for PostScript output. The width and height
+ parameters give the paper size in PostScript points (1 point =
+ 1/72 inch).
+
+ psPaperSize letter | legal | A4 | A3 | match
+ Sets the paper size for PostScript output to a standard size.
+ The default paper size is set when xpdf and pdftops are built,
+ typically to "letter" or "A4". This can also be set to "match",
+ which will set the paper size to match the size specified in the
+ PDF file.
+
+ psImageableArea llx lly urx ury
+ Sets the imageable area for PostScript output. The four inte-
+ gers are the coordinates of the lower-left and upper-right cor-
+ ners of the imageable region, specified in points (with the ori-
+ gin being the lower-left corner of the paper). This defaults to
+ the full paper size; the psPaperSize option will reset the
+ imageable area coordinates.
+
+ psCrop yes | no
+ If set to "yes", PostScript output is cropped to the CropBox
+ specified in the PDF file; otherwise no cropping is done. This
+ defaults to "yes".
+
+ psUseCropBoxAsPage yes | no
+ If set to "yes", PostScript output treats the CropBox as the
+ page size. By default, this is "no", and the MediaBox is used
+ as the page size.
+
+ psExpandSmaller yes | no
+ If set to "yes", PDF pages smaller than the PostScript imageable
+ area are expanded to fill the imageable area. Otherwise, no
+ scaling is done on smaller pages. This defaults to "no".
+
+ psShrinkLarger yes | no
+ If set to yes, PDF pages larger than the PostScript imageable
+ area are shrunk to fit the imageable area. Otherwise, no scal-
+ ing is done on larger pages. This defaults to "yes".
+
+ psCenter yes | no
+ If set to yes, PDF pages smaller than the PostScript imageable
+ area (after any scaling) are centered in the imageable area.
+ Otherwise, they are aligned at the lower-left corner of the
+ imageable area. This defaults to "yes".
+
+ psDuplex yes | no
+ If set to "yes", the generated PostScript will set the "Duplex"
+ pagedevice entry. This tells duplex-capable printers to enable
+ duplexing. This defaults to "no".
+
+ psLevel level1 | level1sep | level2 | level2gray | level2sep | level3 |
+ level3gray | level3Sep
+ Sets the PostScript level to generate. This defaults to
+ "level2".
+
+ psPreload yes | no
+ If set to "yes", PDF forms are converted to PS procedures, and
+ image data is preloaded. This uses more memory in the Post-
+ Script interpreter, but generates significantly smaller PS files
+ in situations where, e.g., the same image is drawn on every page
+ of a long document. This defaults to "no".
+
+ psOPI yes | no
+ If set to "yes", generates PostScript OPI comments for all
+ images and forms which have OPI information. This option is
+ only available if the Xpdf tools were compiled with OPI support.
+ This defaults to "no".
+
+ psASCIIHex yes | no
+ If set to "yes", the ASCIIHexEncode filter will be used instead
+ of ASCII85Encode for binary data. This defaults to "no".
+
+ psLZW yes | no
+ If set to "yes", the LZWEncode filter will be used for lossless
+ compression in PostScript output; if set to "no", the RunLength-
+ Encode filter will be used instead. LZW generates better com-
+ pression (smaller PS files), but may not be supported by some
+ printers. This defaults to "yes".
+
+ psUncompressPreloadedImages yes | no
+ If set to "yes", all preloaded images in PS files will uncom-
+ pressed. If set to "no", the original compressed images will be
+ used when possible. The "yes" setting is useful to work around
+ certain buggy PostScript interpreters. This defaults to "no".
+
+ psMinLineWidth float
+ Set the minimum line width, in points, for PostScript output.
+ The default value is 0 (no minimum).
+
+ psRasterResolution float
+ Set the resolution (in dpi) for rasterized pages in PostScript
+ output. (Pdftops will rasterize pages which use transparency.)
+ This defaults to 300.
+
+ psRasterMono yes | no
+ If set to "yes", rasterized pages in PS files will be monochrome
+ (8-bit gray) instead of color. This defaults to "no".
+
+ psRasterSliceSize pixels
+ When rasterizing pages, pdftops splits the page into horizontal
+ "slices", to limit memory usage. This option sets the maximum
+ slice size, in pixels. This defaults to 20000000 (20 million).
+
+ psAlwaysRasterize yes | no
+ If set to "yes", all PostScript output will be rasterized. This
+ defaults to "no".
+
+ psNeverRasterize yes | no
+ Pdftops rasterizes an pages that use transparency (because Post-
+ Script doesn't support transparency). If psNeverRasterize is
+ set to "yes", rasterization is disabled: pages will never be
+ rasterized, even if they contain transparency. This will likely
+ result in incorrect output for PDF files that use transparency,
+ and a warning message to that effect will be printed. This
+ defaults to "no".
+
+ fontDir dir
+ See the description above, in the DISPLAY FONTS section.
+
+TEXT CONTROL AND CHARACTER MAPPING
+ textEncoding encoding-name
+ Sets the encoding to use for text output. (This can be overrid-
+ den with the "-enc" switch on the command line.) The encod-
+ ing-name must be defined with the unicodeMap command (see
+ above). This defaults to "Latin1".
+
+ textEOL unix | dos | mac
+ Sets the end-of-line convention to use for text output. The
+ options are:
+
+ unix = LF
+ dos = CR+LF
+ mac = CR
+
+ (This can be overridden with the "-eol" switch on the command
+ line.) The default value is based on the OS where xpdf and
+ pdftotext were built.
+
+ textPageBreaks yes | no
+ If set to "yes", text extraction will insert page breaks (form
+ feed characters) between pages. This defaults to "yes".
+
+ textKeepTinyChars yes | no
+ If set to "yes", text extraction will keep all characters. If
+ set to "no", text extraction will discard tiny (smaller than 3
+ point) characters after the first 50000 per page, avoiding
+ extremely slow run times for PDF files that use special fonts to
+ do shading or cross-hatching. This defaults to "yes".
+
+ nameToUnicode map-file
+ Specifies a file with the mapping from character names to Uni-
+ code. This is used to handle PDF fonts that have valid encod-
+ ings but no ToUnicode entry. Each line of a nameToUnicode file
+ looks like this:
+
+ hex-string name
+
+ The hex-string is the Unicode (UCS-2) character index, and name
+ is the corresponding character name. Multiple nameToUnicode
+ files can be used; if a character name is given more than once,
+ the code in the last specified file is used. There is a built-
+ in default nameToUnicode table with all of Adobe's standard
+ character names.
+
+ cidToUnicode registry-ordering map-file
+ Specifies the file with the mapping from character collection to
+ Unicode. Each line of a cidToUnicode file represents one char-
+ acter:
+
+ hex-string
+
+ The hex-string is the Unicode (UCS-2) index for that character.
+ The first line maps CID 0, the second line CID 1, etc. File
+ size is determined by size of the character collection. Only
+ one file is allowed per character collection; the last specified
+ file is used. There are no built-in cidToUnicode mappings.
+
+ unicodeToUnicode font-name-substring map-file
+ This is used to work around PDF fonts which have incorrect Uni-
+ code information. It specifies a file which maps from the given
+ (incorrect) Unicode indexes to the correct ones. The mapping
+ will be used for any font whose name contains font-name-sub-
+ string. Each line of a unicodeToUnicode file represents one
+ Unicode character:
+
+ in-hex out-hex1 out-hex2 ...
+
+ The in-hex field is an input (incorrect) Unicode index, and the
+ rest of the fields are one or more output (correct) Unicode
+ indexes. Each occurrence of in-hex will be converted to the
+ specified output sequence.
+
+ unicodeRemapping remap-file
+ Remap Unicode characters when doing text extraction. This spec-
+ ifies a file that maps from a particular Unicode index to zero
+ or more replacement Unicode indexes. Each line of the remap
+ file represents one Unicode character:
+
+ in-hex out-hex1 out-hex2 ...
+
+ Any Unicode characters not listed will be left unchanged. This
+ function is typically used to remap things like non-breaking
+ spaces, soft hyphens, ligatures, etc.
+
+ unicodeMap encoding-name map-file
+ Specifies the file with mapping from Unicode to encoding-name.
+ These encodings are used for text output (see below). Each line
+ of a unicodeMap file represents a range of one or more Unicode
+ characters which maps linearly to a range in the output encod-
+ ing:
+
+ in-start-hex in-end-hex out-start-hex
+
+ Entries for single characters can be abbreviated to:
+
+ in-hex out-hex
+
+ The in-start-hex and in-end-hex fields (or the single in-hex
+ field) specify the Unicode range. The out-start-hex field (or
+ the out-hex field) specifies the start of the output encoding
+ range. The length of the out-start-hex (or out-hex) string
+ determines the length of the output characters (e.g., UTF-8 uses
+ different numbers of bytes to represent characters in different
+ ranges). Entries must be given in increasing Unicode order.
+ Only one file is allowed per encoding; the last specified file
+ is used. The Latin1, ASCII7, Symbol, ZapfDingbats, UTF-8, and
+ UCS-2 encodings are predefined.
+
+ cMapDir registry-ordering dir
+ Specifies a search directory, dir, for CMaps for the reg-
+ istry-ordering character collection. There can be multiple
+ directories for a particular collection. There are no default
+ CMap directories.
+
+ toUnicodeDir dir
+ Specifies a search directory, dir, for ToUnicode CMaps. There
+ can be multiple ToUnicode directories. There are no default
+ ToUnicode directories.
+
+ mapNumericCharNames yes | no
+ If set to "yes", the Xpdf tools will attempt to map various
+ numeric character names sometimes used in font subsets. In some
+ cases this leads to usable text, and in other cases it leads to
+ gibberish -- there is no way for Xpdf to tell. This defaults to
+ "yes".
+
+ mapUnknownCharNames yes | no
+ If set to "yes", and mapNumericCharNames is set to "no", the
+ Xpdf tools will apply a simple pass-through mapping (Unicode
+ index = character code) for all unrecognized glyph names. (For
+ CID fonts, setting mapNumericCharNames to "no" is unnecessary.)
+ In some cases, this leads to usable text, and in other cases it
+ leads to gibberish -- there is no way for Xpdf to tell. This
+ defaults to "no".
+
+ mapExtTrueTypeFontsViaUnicode yes | no
+ When rasterizing text using an external TrueType font, there are
+ two options for handling character codes. If mapExtTrueType-
+ FontsViaUnicode is set to "yes", Xpdf will use the font encod-
+ ing/ToUnicode info to map character codes to Unicode, and then
+ use the font's Unicode cmap to map Unicode to GIDs. If mapExt-
+ TrueTypeFontsViaUnicode is set to "no", Xpdf will assume the
+ character codes are GIDs (i.e., use an identity mapping). This
+ defaults to "yes".
+
+ useTrueTypeUnicodeMapping yes | no
+ If set to "yes", the Xpdf tools will use the Unicode encoding
+ information in TrueType fonts (16-bit only), if avaiable, to
+ override the PDF ToUnicode maps. Otherwise, the ToUnicode maps
+ are always used when present. This defaults to "no".
+
+ dropFont font-name
+ Drop all text drawn in the specified font. To drop text drawn
+ in unnamed fonts, use:
+
+ dropFont ""
+
+ There can be any number of dropFont commands.
+
+RASTERIZER SETTINGS
+ enableFreeType yes | no
+ Enables or disables use of FreeType (a TrueType / Type 1 font
+ rasterizer). This is only relevant if the Xpdf tools were built
+ with FreeType support. ("enableFreeType" replaces the old
+ "freetypeControl" option.) This option defaults to "yes".
+
+ disableFreeTypeHinting yes | no
+ If this is set to "yes", FreeType hinting will be forced off.
+ This option defaults to "no".
+
+ antialias yes | no
+ Enables or disables font anti-aliasing in the PDF rasterizer.
+ This option affects all font rasterizers. ("antialias" replaces
+ the anti-aliasing control provided by the old "t1libControl" and
+ "freetypeControl" options.) This default to "yes".
+
+ vectorAntialias yes | no
+ Enables or disables anti-aliasing of vector graphics in the PDF
+ rasterizer. This defaults to "yes".
+
+ imageMaskAntialias yes | no
+ Enables or disables anti-aliasing of image masks (when downsam-
+ pling or upsampling) in the PDF rasterizer. This defaults to
+ "yes".
+
+ antialiasPrinting yes | no
+ If this is "yes", bitmaps sent to the printer will be
+ antialiased (according to the "antialias" and "vectorAntialias"
+ settings). If this is "no", printed bitmaps will not be
+ antialiased. This defaults to "no".
+
+ strokeAdjust yes | no | cad
+ Sets the stroke adjustment mode. If set to "no", no stroke
+ adjustment will be done. If set to "yes", normal stroke adjust-
+ ment will be done: horizontal and vertical lines will be moved
+ by up to half a pixel to make them look cleaner when vector
+ anti-aliasing is enabled. If set to "cad", a slightly different
+ stroke adjustment algorithm will be used to ensure that lines of
+ the same original width will always have the same adjusted width
+ (at the expense of allowing gaps and overlaps between adjacent
+ lines). This defaults to "yes".
+
+ forceAccurateTiling yes | no
+ If this is set to "yes", the TilingType is forced to 2 (no dis-
+ tortion) for all tiling patterns, regardless of the setting in
+ the pattern dictionary. This defaults to "no".
+
+ screenType dispersed | clustered | stochasticClustered
+ Sets the halftone screen type, which will be used when generat-
+ ing a monochrome (1-bit) bitmap. The three options are dis-
+ persed-dot dithering, clustered-dot dithering (with a round dot
+ and 45-degree screen angle), and stochastic clustered-dot
+ dithering. By default, "stochasticClustered" is used for reso-
+ lutions of 300 dpi and higher, and "dispersed" is used for reso-
+ lutions lower then 300 dpi.
+
+ screenSize integer
+ Sets the size of the (square) halftone screen threshold matrix.
+ By default, this is 4 for dispersed-dot dithering, 10 for clus-
+ tered-dot dithering, and 100 for stochastic clustered-dot
+ dithering.
+
+ screenDotRadius integer
+ Sets the halftone screen dot radius. This is only used when
+ screenType is set to stochasticClustered, and it defaults to 2.
+ In clustered-dot mode, the dot radius is half of the screen
+ size. Dispersed-dot dithering doesn't have a dot radius.
+
+ screenGamma float
+ Sets the halftone screen gamma correction parameter. Gamma val-
+ ues greater than 1 make the output brighter; gamma values less
+ than 1 make it darker. The default value is 1.
+
+ screenBlackThreshold float
+ When halftoning, all values below this threshold are forced to
+ solid black. This parameter is a floating point value between 0
+ (black) and 1 (white). The default value is 0.
+
+ screenWhiteThreshold float
+ When halftoning, all values above this threshold are forced to
+ solid white. This parameter is a floating point value between 0
+ (black) and 1 (white). The default value is 1.
+
+ minLineWidth float
+ Set the minimum line width, in device pixels. This affects the
+ rasterizer only, not the PostScript converter (except when it
+ uses rasterization to handle transparency). The default value
+ is 0 (no minimum).
+
+ enablePathSimplification yes | no
+ If set to "yes", simplify paths by removing points where it
+ won't make a significant difference to the shape. The default
+ value is "no".
+
+ overprintPreview yes | no
+ If set to "yes", generate overprint preview output, honoring the
+ OP/op/OPM settings in the PDF file. Ignored for non-CMYK out-
+ put. The default value is "no".
+
+VIEWER SETTINGS
+ These settings only apply to the Xpdf GUI PDF viewer.
+
+ initialZoom percentage | page | width
+ Sets the initial zoom factor. A number specifies a zoom per-
+ centage, where 100 means 72 dpi. You may also specify 'page',
+ to fit the page to the window size, or 'width', to fit the page
+ width to the window width.
+
+ defaultFitZoom percentage
+ If xpdf is started with fit-page or fit-width zoom and no window
+ geometry, it will calculate a desired window size based on the
+ PDF page size and this defaultFitZoom value. I.e., the window
+ size will be chosen such that exactly one page will fit in the
+ window at this zoom factor (which must be a percentage). The
+ default value is based on the screen resolution.
+
+ initialDisplayMode single | continuous | sideBySideSingle | sideBySide-
+ Continuous | horizontalContinuous
+ Sets the initial display mode. The default setting is "continu-
+ ous".
+
+ initialToolbarState yes | no
+ If set to "yes", xpdf opens with the toolbar visible. If set to
+ "no", xpdf opens with the toolbar hidden. The default is "yes".
+
+ initialSidebarState yes | no
+ If set to "yes", xpdf opens with the sidebar (tabs, outline,
+ etc.) visible. If set to "no", xpdf opens with the sidebar
+ collapsed. The default is "yes".
+
+ initialSidebarWidth width
+ Sets the initial sidebar width, in pixels. This is only rele-
+ vant if initialSidebarState is "yes". The default value is
+ zero, which tells xpdf to use an internal default size.
+
+ initialSelectMode block | linear
+ Sets the initial selection mode. The default setting is "lin-
+ ear".
+
+ paperColor color
+ Set the "paper color", i.e., the background of the page display.
+ The color can be #RRGGBB (hexadecimal) or a named color. This
+ option will not work well with PDF files that do things like
+ filling in white behind the text.
+
+ matteColor color
+ Set the matte color, i.e., the color used for background outside
+ the actual page area. The color can be #RRGGBB (hexadecimal) or
+ a named color.
+
+ fullScreenMatteColor color
+ Set the matte color for full-screen mode. The color can be
+ #RRGGBB (hexadecimal) or a named color.
+
+ selectionColor color
+ Set the selection color. The color can be #RRGGBB (hexadecimal)
+ or a named color.
+
+ reverseVideoInvertImages yes | no
+ If set to "no", xpdf's reverse-video mode inverts text and vec-
+ tor graphic content, but not images. If set to "yes", xpdf
+ inverts images as well. The default is "no".
+
+ popupMenuCmd title command ...
+ Add a command to the popup menu. Title is the text to be dis-
+ played in the menu. Command is an Xpdf command (see the COM-
+ MANDS section of the xpdf(1) man page for details). Multiple
+ commands are separated by whitespace.
+
+ maxTileWidth pixels
+ Set the maximum width of tiles to be used by xpdf when rasteriz-
+ ing pages. This defaults to 1500.
+
+ maxTileHeight pixels
+ Set the maximum height of tiles to be used by xpdf when raster-
+ izing pages. This defaults to 1500.
+
+ tileCacheSize tiles
+ Set the maximum number of tiles to be cached by xpdf when ras-
+ terizing pages. This defaults to 10.
+
+ workerThreads numThreads
+ Set the number of worker threads to be used by xpdf when raster-
+ izing pages. This defaults to 1.
+
+ launchCommand command
+ Sets the command executed when you click on a "launch"-type
+ link. The intent is for the command to be a program/script
+ which determines the file type and runs the appropriate viewer.
+ The command line will consist of the file to be launched, fol-
+ lowed by any parameters specified with the link. Do not use
+ "%s" in "command". By default, this is unset, and Xpdf will
+ simply try to execute the file (after prompting the user).
+
+ movieCommand command
+ Sets the command executed when you click on a movie annotation.
+ The string "%s" will be replaced with the movie file name. This
+ has no default value.
+
+ defaultPrinter printer
+ Sets the default printer used in the viewer's print dialog.
+
+ bind modifiers-key context command ...
+ Add a key or mouse button binding. Modifiers can be zero or
+ more of:
+
+ shift-
+ ctrl-
+ alt-
+
+ Key can be a regular ASCII character, or any one of:
+
+ space
+ tab
+ return
+ enter
+ backspace
+ esc
+ insert
+ delete
+ home
+ end
+ pgup
+ pgdn
+ left / right / up / down (arrow keys)
+ f1 .. f35 (function keys)
+ mousePress1 .. mousePress7 (mouse buttons)
+ mouseRelease1 .. mouseRelease7 (mouse buttons)
+ mouseClick1 .. mouseClick7 (mouse buttons)
+ mouseDoubleClick1 .. mouseDoubleClick7 (mouse buttons)
+ mouseTripleClick1 .. mouseTripleClick7 (mouse buttons)
+
+ Context is either "any" or a comma-separated combination of:
+
+ fullScreen / window (full screen mode on/off)
+ continuous / singlePage (continuous mode on/off)
+ overLink / offLink (mouse over link or not)
+ scrLockOn / scrLockOff (scroll lock on/off)
+
+ The context string can include only one of each pair in the
+ above list.
+
+ Command is an Xpdf command (see the COMMANDS section of the
+ xpdf(1) man page for details). Multiple commands are separated
+ by whitespace.
+
+ The bind command replaces any existing binding, but only if it
+ was defined for the exact same modifiers, key, and context. All
+ tokens (modifiers, key, context, commands) are case-sensitive.
+
+ Example key bindings:
+
+ # bind ctrl-a in any context to the nextPage
+ # command
+ bind ctrl-a any nextPage
+
+ # bind uppercase B, when in continuous mode
+ # with scroll lock on, to the reload command
+ # followed by the prevPage command
+ bind B continuous,scrLockOn reload prevPage
+
+ See the xpdf(1) man page for more examples.
+
+ unbind modifiers-key context
+ Removes a key binding established with the bind command. This
+ is most useful to remove default key bindings before establish-
+ ing new ones (e.g., if the default key binding is given for
+ "any" context, and you want to create new key bindings for mul-
+ tiple contexts).
+
+ tabStateFile path
+ Sets the file used by the loadTabState and saveTabState commands
+ (see the xpdf(1) man page for more information).
+
+MISCELLANEOUS SETTINGS
+ drawAnnotations yes | no
+ If set to "no", annotations will not be drawn or printed. The
+ default value is "yes".
+
+ drawFormFields yes | no
+ If set to "no", form fields will not be drawn or printed. The
+ default value is "yes".
+
+ enableXFA yes | no
+ If an XFA form is present, and this option is set to "yes", Xpdf
+ will parse the XFA form and use certain XFA information to over-
+ ride AcroForm information. If set to "no", the XFA form will
+ not be read. The default value is "yes".
+
+ savePageNumbers yes | no
+ If set to "yes", xpdf will save the current page numbers of all
+ open files in ~/.xpdf.pages when the files are closed (or when
+ quitting xpdf). Next time the file is opened, the last-viewed
+ page number will be restored. The default value is "yes".
+
+ printCommands yes | no
+ If set to "yes", drawing commands are printed as they're exe-
+ cuted (useful for debugging). This defaults to "no".
+
+ printStatusInfo
+ If set to "yes", print a status message (to stdout) before each
+ page is processed. This defaults to "no".
+
+ errQuiet yes | no
+ If set to "yes", this suppresses all error and warning messages
+ from all of the Xpdf tools. This defaults to "no".
+
+EXAMPLES
+ The following is a sample xpdfrc file.
+
+ # from the Thai support package
+ nameToUnicode /usr/local/share/xpdf/Thai.nameToUnicode
+
+ # from the Japanese support package
+ cidToUnicode Adobe-Japan1 /usr/local/share/xpdf/Adobe-Japan1.cidToUnicode
+ unicodeMap JISX0208 /usr/local/share/xpdf/JISX0208.unicodeMap
+ cMapDir Adobe-Japan1 /usr/local/share/xpdf/cmap/Adobe-Japan1
+
+ # use the Base-14 Type 1 fonts from ghostscript
+ fontFile Times-Roman /usr/local/share/ghostscript/fonts/n021003l.pfb
+ fontFile Times-Italic /usr/local/share/ghostscript/fonts/n021023l.pfb
+ fontFile Times-Bold /usr/local/share/ghostscript/fonts/n021004l.pfb
+ fontFile Times-BoldItalic /usr/local/share/ghostscript/fonts/n021024l.pfb
+ fontFile Helvetica /usr/local/share/ghostscript/fonts/n019003l.pfb
+ fontFile Helvetica-Oblique /usr/local/share/ghostscript/fonts/n019023l.pfb
+ fontFile Helvetica-Bold /usr/local/share/ghostscript/fonts/n019004l.pfb
+ fontFile Helvetica-BoldOblique /usr/local/share/ghostscript/fonts/n019024l.pfb
+ fontFile Courier /usr/local/share/ghostscript/fonts/n022003l.pfb
+ fontFile Courier-Oblique /usr/local/share/ghostscript/fonts/n022023l.pfb
+ fontFile Courier-Bold /usr/local/share/ghostscript/fonts/n022004l.pfb
+ fontFile Courier-BoldOblique /usr/local/share/ghostscript/fonts/n022024l.pfb
+ fontFile Symbol /usr/local/share/ghostscript/fonts/s050000l.pfb
+ fontFile ZapfDingbats /usr/local/share/ghostscript/fonts/d050000l.pfb
+
+ # use the Bakoma Type 1 fonts
+ # (this assumes they happen to be installed in /usr/local/fonts/bakoma)
+ fontDir /usr/local/fonts/bakoma
+
+ # set some PostScript options
+ psPaperSize letter
+ psDuplex no
+ psLevel level2
+ psEmbedType1Fonts yes
+ psEmbedTrueTypeFonts yes
+
+ # assume that the PostScript printer has the Univers and
+ # Univers-Bold fonts
+ psResidentFont Univers Univers
+ psResidentFont Univers-Bold Univers-Bold
+
+ # set the text output options
+ textEncoding UTF-8
+ textEOL unix
+
+ # misc options
+ enableFreeType yes
+ launchCommand viewer-script
+
+
+FILES
+ /etc/xpdfrc
+ This is the default location for the system-wide configuration
+ file. Depending on build options, it may be placed elsewhere.
+
+ $HOME/.xpdfrc
+ This is the user's configuration file. If it exists, it will be
+ read in place of the system-wide file.
+
+AUTHOR
+ The Xpdf software and documentation are copyright 1996-2022 Glyph &
+ Cog, LLC.
+
+SEE ALSO
+ xpdf(1), pdftops(1), pdftotext(1), pdftohtml(1), pdfinfo(1), pdf-
+ fonts(1), pdfdetach(1), pdftoppm(1), pdftopng(1), pdfimages(1)
+ http://www.xpdfreader.com/
+
+
+
+ 18 Apr 202 xpdfrc(5)
diff --git a/fofi/CMakeFiles/CMakeDirectoryInformation.cmake b/fofi/CMakeFiles/CMakeDirectoryInformation.cmake
new file mode 100644
index 0000000..aef4d6c
--- /dev/null
+++ b/fofi/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/fofi/CMakeFiles/fofi.dir/DependInfo.cmake b/fofi/CMakeFiles/fofi.dir/DependInfo.cmake
new file mode 100644
index 0000000..19fab21
--- /dev/null
+++ b/fofi/CMakeFiles/fofi.dir/DependInfo.cmake
@@ -0,0 +1,11 @@
+# The set of languages for which implicit dependencies are needed:
+set(CMAKE_DEPENDS_LANGUAGES
+ )
+# The set of files for implicit dependencies of each language:
+
+# 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/fofi/CMakeFiles/fofi.dir/build.make b/fofi/CMakeFiles/fofi.dir/build.make
new file mode 100644
index 0000000..088891c
--- /dev/null
+++ b/fofi/CMakeFiles/fofi.dir/build.make
@@ -0,0 +1,115 @@
+# 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 fofi/CMakeFiles/fofi.dir/depend.make
+
+# Include the progress variables for this target.
+include fofi/CMakeFiles/fofi.dir/progress.make
+
+# Include the compile flags for this target's objects.
+include fofi/CMakeFiles/fofi.dir/flags.make
+
+# Object files for target fofi
+fofi_OBJECTS =
+
+# External object files for target fofi
+fofi_EXTERNAL_OBJECTS = \
+"/home/calvin/src/xpdf-4.04/fofi/CMakeFiles/fofi_objs.dir/FoFiBase.cc.o" \
+"/home/calvin/src/xpdf-4.04/fofi/CMakeFiles/fofi_objs.dir/FoFiEncodings.cc.o" \
+"/home/calvin/src/xpdf-4.04/fofi/CMakeFiles/fofi_objs.dir/FoFiIdentifier.cc.o" \
+"/home/calvin/src/xpdf-4.04/fofi/CMakeFiles/fofi_objs.dir/FoFiTrueType.cc.o" \
+"/home/calvin/src/xpdf-4.04/fofi/CMakeFiles/fofi_objs.dir/FoFiType1.cc.o" \
+"/home/calvin/src/xpdf-4.04/fofi/CMakeFiles/fofi_objs.dir/FoFiType1C.cc.o"
+
+fofi/libfofi.a: fofi/CMakeFiles/fofi_objs.dir/FoFiBase.cc.o
+fofi/libfofi.a: fofi/CMakeFiles/fofi_objs.dir/FoFiEncodings.cc.o
+fofi/libfofi.a: fofi/CMakeFiles/fofi_objs.dir/FoFiIdentifier.cc.o
+fofi/libfofi.a: fofi/CMakeFiles/fofi_objs.dir/FoFiTrueType.cc.o
+fofi/libfofi.a: fofi/CMakeFiles/fofi_objs.dir/FoFiType1.cc.o
+fofi/libfofi.a: fofi/CMakeFiles/fofi_objs.dir/FoFiType1C.cc.o
+fofi/libfofi.a: fofi/CMakeFiles/fofi.dir/build.make
+fofi/libfofi.a: fofi/CMakeFiles/fofi.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_1) "Linking CXX static library libfofi.a"
+ cd /home/calvin/src/xpdf-4.04/fofi && $(CMAKE_COMMAND) -P CMakeFiles/fofi.dir/cmake_clean_target.cmake
+ cd /home/calvin/src/xpdf-4.04/fofi && $(CMAKE_COMMAND) -E cmake_link_script CMakeFiles/fofi.dir/link.txt --verbose=$(VERBOSE)
+
+# Rule to build all files generated by this target.
+fofi/CMakeFiles/fofi.dir/build: fofi/libfofi.a
+
+.PHONY : fofi/CMakeFiles/fofi.dir/build
+
+fofi/CMakeFiles/fofi.dir/clean:
+ cd /home/calvin/src/xpdf-4.04/fofi && $(CMAKE_COMMAND) -P CMakeFiles/fofi.dir/cmake_clean.cmake
+.PHONY : fofi/CMakeFiles/fofi.dir/clean
+
+fofi/CMakeFiles/fofi.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/fofi /home/calvin/src/xpdf-4.04 /home/calvin/src/xpdf-4.04/fofi /home/calvin/src/xpdf-4.04/fofi/CMakeFiles/fofi.dir/DependInfo.cmake --color=$(COLOR)
+.PHONY : fofi/CMakeFiles/fofi.dir/depend
+
diff --git a/fofi/CMakeFiles/fofi.dir/cmake_clean.cmake b/fofi/CMakeFiles/fofi.dir/cmake_clean.cmake
new file mode 100644
index 0000000..fcbacc2
--- /dev/null
+++ b/fofi/CMakeFiles/fofi.dir/cmake_clean.cmake
@@ -0,0 +1,9 @@
+file(REMOVE_RECURSE
+ "libfofi.a"
+ "libfofi.pdb"
+)
+
+# Per-language clean rules from dependency scanning.
+foreach(lang CXX)
+ include(CMakeFiles/fofi.dir/cmake_clean_${lang}.cmake OPTIONAL)
+endforeach()
diff --git a/fofi/CMakeFiles/fofi.dir/cmake_clean_target.cmake b/fofi/CMakeFiles/fofi.dir/cmake_clean_target.cmake
new file mode 100644
index 0000000..71175d3
--- /dev/null
+++ b/fofi/CMakeFiles/fofi.dir/cmake_clean_target.cmake
@@ -0,0 +1,3 @@
+file(REMOVE_RECURSE
+ "libfofi.a"
+)
diff --git a/fofi/CMakeFiles/fofi.dir/depend.internal b/fofi/CMakeFiles/fofi.dir/depend.internal
new file mode 100644
index 0000000..756f521
--- /dev/null
+++ b/fofi/CMakeFiles/fofi.dir/depend.internal
@@ -0,0 +1,3 @@
+# CMAKE generated file: DO NOT EDIT!
+# Generated by "Unix Makefiles" Generator, CMake Version 3.18
+
diff --git a/fofi/CMakeFiles/fofi.dir/depend.make b/fofi/CMakeFiles/fofi.dir/depend.make
new file mode 100644
index 0000000..756f521
--- /dev/null
+++ b/fofi/CMakeFiles/fofi.dir/depend.make
@@ -0,0 +1,3 @@
+# CMAKE generated file: DO NOT EDIT!
+# Generated by "Unix Makefiles" Generator, CMake Version 3.18
+
diff --git a/fofi/CMakeFiles/fofi.dir/flags.make b/fofi/CMakeFiles/fofi.dir/flags.make
new file mode 100644
index 0000000..b3b8b67
--- /dev/null
+++ b/fofi/CMakeFiles/fofi.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
+
+CXX_FLAGS =
+
diff --git a/fofi/CMakeFiles/fofi.dir/link.txt b/fofi/CMakeFiles/fofi.dir/link.txt
new file mode 100644
index 0000000..98a9ca1
--- /dev/null
+++ b/fofi/CMakeFiles/fofi.dir/link.txt
@@ -0,0 +1,2 @@
+/usr/bin/ar qc libfofi.a CMakeFiles/fofi_objs.dir/FoFiBase.cc.o CMakeFiles/fofi_objs.dir/FoFiEncodings.cc.o CMakeFiles/fofi_objs.dir/FoFiIdentifier.cc.o CMakeFiles/fofi_objs.dir/FoFiTrueType.cc.o CMakeFiles/fofi_objs.dir/FoFiType1.cc.o CMakeFiles/fofi_objs.dir/FoFiType1C.cc.o
+/usr/bin/ranlib libfofi.a
diff --git a/fofi/CMakeFiles/fofi.dir/progress.make b/fofi/CMakeFiles/fofi.dir/progress.make
new file mode 100644
index 0000000..225de34
--- /dev/null
+++ b/fofi/CMakeFiles/fofi.dir/progress.make
@@ -0,0 +1,2 @@
+CMAKE_PROGRESS_1 =
+
diff --git a/fofi/CMakeFiles/fofi_objs.dir/CXX.includecache b/fofi/CMakeFiles/fofi_objs.dir/CXX.includecache
new file mode 100644
index 0000000..432133e
--- /dev/null
+++ b/fofi/CMakeFiles/fofi_objs.dir/CXX.includecache
@@ -0,0 +1,198 @@
+#IncludeRegexLine: ^[ ]*[#%][ ]*(include|import)[ ]*[<"]([^">]+)([">])
+
+#IncludeRegexScan: ^.*$
+
+#IncludeRegexComplain: ^$
+
+#IncludeRegexTransform:
+
+/home/calvin/src/xpdf-4.04/fofi/FoFiBase.cc
+aconf.h
+-
+stdio.h
+-
+limits.h
+-
+gmem.h
+/home/calvin/src/xpdf-4.04/fofi/gmem.h
+gmempp.h
+/home/calvin/src/xpdf-4.04/fofi/gmempp.h
+FoFiBase.h
+/home/calvin/src/xpdf-4.04/fofi/FoFiBase.h
+
+/home/calvin/src/xpdf-4.04/fofi/FoFiBase.h
+aconf.h
+-
+gtypes.h
+/home/calvin/src/xpdf-4.04/fofi/gtypes.h
+
+/home/calvin/src/xpdf-4.04/fofi/FoFiEncodings.cc
+aconf.h
+-
+stdlib.h
+-
+gmempp.h
+/home/calvin/src/xpdf-4.04/fofi/gmempp.h
+FoFiEncodings.h
+/home/calvin/src/xpdf-4.04/fofi/FoFiEncodings.h
+
+/home/calvin/src/xpdf-4.04/fofi/FoFiEncodings.h
+aconf.h
+-
+gtypes.h
+/home/calvin/src/xpdf-4.04/fofi/gtypes.h
+
+/home/calvin/src/xpdf-4.04/fofi/FoFiIdentifier.cc
+aconf.h
+-
+stdio.h
+-
+string.h
+-
+limits.h
+-
+gtypes.h
+/home/calvin/src/xpdf-4.04/fofi/gtypes.h
+gmem.h
+/home/calvin/src/xpdf-4.04/fofi/gmem.h
+gmempp.h
+/home/calvin/src/xpdf-4.04/fofi/gmempp.h
+GString.h
+/home/calvin/src/xpdf-4.04/fofi/GString.h
+GList.h
+/home/calvin/src/xpdf-4.04/fofi/GList.h
+FoFiIdentifier.h
+/home/calvin/src/xpdf-4.04/fofi/FoFiIdentifier.h
+
+/home/calvin/src/xpdf-4.04/fofi/FoFiIdentifier.h
+aconf.h
+-
+
+/home/calvin/src/xpdf-4.04/fofi/FoFiTrueType.cc
+aconf.h
+-
+stdlib.h
+-
+string.h
+-
+algorithm
+-
+gtypes.h
+/home/calvin/src/xpdf-4.04/fofi/gtypes.h
+gmem.h
+/home/calvin/src/xpdf-4.04/fofi/gmem.h
+gmempp.h
+/home/calvin/src/xpdf-4.04/fofi/gmempp.h
+GString.h
+/home/calvin/src/xpdf-4.04/fofi/GString.h
+GHash.h
+/home/calvin/src/xpdf-4.04/fofi/GHash.h
+FoFiType1C.h
+/home/calvin/src/xpdf-4.04/fofi/FoFiType1C.h
+FoFiTrueType.h
+/home/calvin/src/xpdf-4.04/fofi/FoFiTrueType.h
+
+/home/calvin/src/xpdf-4.04/fofi/FoFiTrueType.h
+aconf.h
+-
+gtypes.h
+/home/calvin/src/xpdf-4.04/fofi/gtypes.h
+FoFiBase.h
+/home/calvin/src/xpdf-4.04/fofi/FoFiBase.h
+
+/home/calvin/src/xpdf-4.04/fofi/FoFiType1.cc
+aconf.h
+-
+stdlib.h
+-
+string.h
+-
+gmem.h
+/home/calvin/src/xpdf-4.04/fofi/gmem.h
+gmempp.h
+/home/calvin/src/xpdf-4.04/fofi/gmempp.h
+FoFiEncodings.h
+/home/calvin/src/xpdf-4.04/fofi/FoFiEncodings.h
+FoFiType1.h
+/home/calvin/src/xpdf-4.04/fofi/FoFiType1.h
+
+/home/calvin/src/xpdf-4.04/fofi/FoFiType1.h
+aconf.h
+-
+gtypes.h
+/home/calvin/src/xpdf-4.04/fofi/gtypes.h
+FoFiBase.h
+/home/calvin/src/xpdf-4.04/fofi/FoFiBase.h
+
+/home/calvin/src/xpdf-4.04/fofi/FoFiType1C.cc
+aconf.h
+-
+stdlib.h
+-
+string.h
+-
+math.h
+-
+gmem.h
+/home/calvin/src/xpdf-4.04/fofi/gmem.h
+gmempp.h
+/home/calvin/src/xpdf-4.04/fofi/gmempp.h
+GString.h
+/home/calvin/src/xpdf-4.04/fofi/GString.h
+GHash.h
+/home/calvin/src/xpdf-4.04/fofi/GHash.h
+FoFiEncodings.h
+/home/calvin/src/xpdf-4.04/fofi/FoFiEncodings.h
+FoFiType1C.h
+/home/calvin/src/xpdf-4.04/fofi/FoFiType1C.h
+
+/home/calvin/src/xpdf-4.04/fofi/FoFiType1C.h
+aconf.h
+-
+gtypes.h
+/home/calvin/src/xpdf-4.04/fofi/gtypes.h
+FoFiBase.h
+/home/calvin/src/xpdf-4.04/fofi/FoFiBase.h
+
+aconf.h
+aconf2.h
+-
+
+aconf2.h
+AvailabilityMacros.h
+-
+
+goo/GHash.h
+aconf.h
+-
+gtypes.h
+goo/gtypes.h
+
+goo/GList.h
+aconf.h
+-
+gtypes.h
+goo/gtypes.h
+
+goo/GString.h
+aconf.h
+-
+limits.h
+-
+stdarg.h
+-
+gtypes.h
+goo/gtypes.h
+
+goo/gmem.h
+stdio.h
+-
+aconf.h
+-
+
+goo/gmempp.h
+stdlib.h
+-
+
+goo/gtypes.h
+
diff --git a/fofi/CMakeFiles/fofi_objs.dir/DependInfo.cmake b/fofi/CMakeFiles/fofi_objs.dir/DependInfo.cmake
new file mode 100644
index 0000000..fe7f765
--- /dev/null
+++ b/fofi/CMakeFiles/fofi_objs.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/fofi/FoFiBase.cc" "/home/calvin/src/xpdf-4.04/fofi/CMakeFiles/fofi_objs.dir/FoFiBase.cc.o"
+ "/home/calvin/src/xpdf-4.04/fofi/FoFiEncodings.cc" "/home/calvin/src/xpdf-4.04/fofi/CMakeFiles/fofi_objs.dir/FoFiEncodings.cc.o"
+ "/home/calvin/src/xpdf-4.04/fofi/FoFiIdentifier.cc" "/home/calvin/src/xpdf-4.04/fofi/CMakeFiles/fofi_objs.dir/FoFiIdentifier.cc.o"
+ "/home/calvin/src/xpdf-4.04/fofi/FoFiTrueType.cc" "/home/calvin/src/xpdf-4.04/fofi/CMakeFiles/fofi_objs.dir/FoFiTrueType.cc.o"
+ "/home/calvin/src/xpdf-4.04/fofi/FoFiType1.cc" "/home/calvin/src/xpdf-4.04/fofi/CMakeFiles/fofi_objs.dir/FoFiType1.cc.o"
+ "/home/calvin/src/xpdf-4.04/fofi/FoFiType1C.cc" "/home/calvin/src/xpdf-4.04/fofi/CMakeFiles/fofi_objs.dir/FoFiType1C.cc.o"
+ )
+set(CMAKE_CXX_COMPILER_ID "GNU")
+
+# The include file search paths:
+set(CMAKE_CXX_TARGET_INCLUDE_PATH
+ "."
+ "goo"
+ )
+
+# 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/fofi/CMakeFiles/fofi_objs.dir/FoFiBase.cc.o b/fofi/CMakeFiles/fofi_objs.dir/FoFiBase.cc.o
new file mode 100644
index 0000000..c5393e6
--- /dev/null
+++ b/fofi/CMakeFiles/fofi_objs.dir/FoFiBase.cc.o
Binary files differ
diff --git a/fofi/CMakeFiles/fofi_objs.dir/FoFiEncodings.cc.o b/fofi/CMakeFiles/fofi_objs.dir/FoFiEncodings.cc.o
new file mode 100644
index 0000000..e7ce97f
--- /dev/null
+++ b/fofi/CMakeFiles/fofi_objs.dir/FoFiEncodings.cc.o
Binary files differ
diff --git a/fofi/CMakeFiles/fofi_objs.dir/FoFiIdentifier.cc.o b/fofi/CMakeFiles/fofi_objs.dir/FoFiIdentifier.cc.o
new file mode 100644
index 0000000..89e1f3e
--- /dev/null
+++ b/fofi/CMakeFiles/fofi_objs.dir/FoFiIdentifier.cc.o
Binary files differ
diff --git a/fofi/CMakeFiles/fofi_objs.dir/FoFiTrueType.cc.o b/fofi/CMakeFiles/fofi_objs.dir/FoFiTrueType.cc.o
new file mode 100644
index 0000000..2dca8ab
--- /dev/null
+++ b/fofi/CMakeFiles/fofi_objs.dir/FoFiTrueType.cc.o
Binary files differ
diff --git a/fofi/CMakeFiles/fofi_objs.dir/FoFiType1.cc.o b/fofi/CMakeFiles/fofi_objs.dir/FoFiType1.cc.o
new file mode 100644
index 0000000..d9d0fc3
--- /dev/null
+++ b/fofi/CMakeFiles/fofi_objs.dir/FoFiType1.cc.o
Binary files differ
diff --git a/fofi/CMakeFiles/fofi_objs.dir/FoFiType1C.cc.o b/fofi/CMakeFiles/fofi_objs.dir/FoFiType1C.cc.o
new file mode 100644
index 0000000..3943e20
--- /dev/null
+++ b/fofi/CMakeFiles/fofi_objs.dir/FoFiType1C.cc.o
Binary files differ
diff --git a/fofi/CMakeFiles/fofi_objs.dir/build.make b/fofi/CMakeFiles/fofi_objs.dir/build.make
new file mode 100644
index 0000000..f830d62
--- /dev/null
+++ b/fofi/CMakeFiles/fofi_objs.dir/build.make
@@ -0,0 +1,179 @@
+# 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 fofi/CMakeFiles/fofi_objs.dir/depend.make
+
+# Include the progress variables for this target.
+include fofi/CMakeFiles/fofi_objs.dir/progress.make
+
+# Include the compile flags for this target's objects.
+include fofi/CMakeFiles/fofi_objs.dir/flags.make
+
+fofi/CMakeFiles/fofi_objs.dir/FoFiBase.cc.o: fofi/CMakeFiles/fofi_objs.dir/flags.make
+fofi/CMakeFiles/fofi_objs.dir/FoFiBase.cc.o: fofi/FoFiBase.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 fofi/CMakeFiles/fofi_objs.dir/FoFiBase.cc.o"
+ cd /home/calvin/src/xpdf-4.04/fofi && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/fofi_objs.dir/FoFiBase.cc.o -c /home/calvin/src/xpdf-4.04/fofi/FoFiBase.cc
+
+fofi/CMakeFiles/fofi_objs.dir/FoFiBase.cc.i: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/fofi_objs.dir/FoFiBase.cc.i"
+ cd /home/calvin/src/xpdf-4.04/fofi && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/fofi/FoFiBase.cc > CMakeFiles/fofi_objs.dir/FoFiBase.cc.i
+
+fofi/CMakeFiles/fofi_objs.dir/FoFiBase.cc.s: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/fofi_objs.dir/FoFiBase.cc.s"
+ cd /home/calvin/src/xpdf-4.04/fofi && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/fofi/FoFiBase.cc -o CMakeFiles/fofi_objs.dir/FoFiBase.cc.s
+
+fofi/CMakeFiles/fofi_objs.dir/FoFiEncodings.cc.o: fofi/CMakeFiles/fofi_objs.dir/flags.make
+fofi/CMakeFiles/fofi_objs.dir/FoFiEncodings.cc.o: fofi/FoFiEncodings.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 fofi/CMakeFiles/fofi_objs.dir/FoFiEncodings.cc.o"
+ cd /home/calvin/src/xpdf-4.04/fofi && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/fofi_objs.dir/FoFiEncodings.cc.o -c /home/calvin/src/xpdf-4.04/fofi/FoFiEncodings.cc
+
+fofi/CMakeFiles/fofi_objs.dir/FoFiEncodings.cc.i: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/fofi_objs.dir/FoFiEncodings.cc.i"
+ cd /home/calvin/src/xpdf-4.04/fofi && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/fofi/FoFiEncodings.cc > CMakeFiles/fofi_objs.dir/FoFiEncodings.cc.i
+
+fofi/CMakeFiles/fofi_objs.dir/FoFiEncodings.cc.s: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/fofi_objs.dir/FoFiEncodings.cc.s"
+ cd /home/calvin/src/xpdf-4.04/fofi && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/fofi/FoFiEncodings.cc -o CMakeFiles/fofi_objs.dir/FoFiEncodings.cc.s
+
+fofi/CMakeFiles/fofi_objs.dir/FoFiIdentifier.cc.o: fofi/CMakeFiles/fofi_objs.dir/flags.make
+fofi/CMakeFiles/fofi_objs.dir/FoFiIdentifier.cc.o: fofi/FoFiIdentifier.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 fofi/CMakeFiles/fofi_objs.dir/FoFiIdentifier.cc.o"
+ cd /home/calvin/src/xpdf-4.04/fofi && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/fofi_objs.dir/FoFiIdentifier.cc.o -c /home/calvin/src/xpdf-4.04/fofi/FoFiIdentifier.cc
+
+fofi/CMakeFiles/fofi_objs.dir/FoFiIdentifier.cc.i: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/fofi_objs.dir/FoFiIdentifier.cc.i"
+ cd /home/calvin/src/xpdf-4.04/fofi && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/fofi/FoFiIdentifier.cc > CMakeFiles/fofi_objs.dir/FoFiIdentifier.cc.i
+
+fofi/CMakeFiles/fofi_objs.dir/FoFiIdentifier.cc.s: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/fofi_objs.dir/FoFiIdentifier.cc.s"
+ cd /home/calvin/src/xpdf-4.04/fofi && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/fofi/FoFiIdentifier.cc -o CMakeFiles/fofi_objs.dir/FoFiIdentifier.cc.s
+
+fofi/CMakeFiles/fofi_objs.dir/FoFiTrueType.cc.o: fofi/CMakeFiles/fofi_objs.dir/flags.make
+fofi/CMakeFiles/fofi_objs.dir/FoFiTrueType.cc.o: fofi/FoFiTrueType.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 fofi/CMakeFiles/fofi_objs.dir/FoFiTrueType.cc.o"
+ cd /home/calvin/src/xpdf-4.04/fofi && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/fofi_objs.dir/FoFiTrueType.cc.o -c /home/calvin/src/xpdf-4.04/fofi/FoFiTrueType.cc
+
+fofi/CMakeFiles/fofi_objs.dir/FoFiTrueType.cc.i: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/fofi_objs.dir/FoFiTrueType.cc.i"
+ cd /home/calvin/src/xpdf-4.04/fofi && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/fofi/FoFiTrueType.cc > CMakeFiles/fofi_objs.dir/FoFiTrueType.cc.i
+
+fofi/CMakeFiles/fofi_objs.dir/FoFiTrueType.cc.s: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/fofi_objs.dir/FoFiTrueType.cc.s"
+ cd /home/calvin/src/xpdf-4.04/fofi && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/fofi/FoFiTrueType.cc -o CMakeFiles/fofi_objs.dir/FoFiTrueType.cc.s
+
+fofi/CMakeFiles/fofi_objs.dir/FoFiType1.cc.o: fofi/CMakeFiles/fofi_objs.dir/flags.make
+fofi/CMakeFiles/fofi_objs.dir/FoFiType1.cc.o: fofi/FoFiType1.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 fofi/CMakeFiles/fofi_objs.dir/FoFiType1.cc.o"
+ cd /home/calvin/src/xpdf-4.04/fofi && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/fofi_objs.dir/FoFiType1.cc.o -c /home/calvin/src/xpdf-4.04/fofi/FoFiType1.cc
+
+fofi/CMakeFiles/fofi_objs.dir/FoFiType1.cc.i: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/fofi_objs.dir/FoFiType1.cc.i"
+ cd /home/calvin/src/xpdf-4.04/fofi && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/fofi/FoFiType1.cc > CMakeFiles/fofi_objs.dir/FoFiType1.cc.i
+
+fofi/CMakeFiles/fofi_objs.dir/FoFiType1.cc.s: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/fofi_objs.dir/FoFiType1.cc.s"
+ cd /home/calvin/src/xpdf-4.04/fofi && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/fofi/FoFiType1.cc -o CMakeFiles/fofi_objs.dir/FoFiType1.cc.s
+
+fofi/CMakeFiles/fofi_objs.dir/FoFiType1C.cc.o: fofi/CMakeFiles/fofi_objs.dir/flags.make
+fofi/CMakeFiles/fofi_objs.dir/FoFiType1C.cc.o: fofi/FoFiType1C.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 fofi/CMakeFiles/fofi_objs.dir/FoFiType1C.cc.o"
+ cd /home/calvin/src/xpdf-4.04/fofi && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/fofi_objs.dir/FoFiType1C.cc.o -c /home/calvin/src/xpdf-4.04/fofi/FoFiType1C.cc
+
+fofi/CMakeFiles/fofi_objs.dir/FoFiType1C.cc.i: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/fofi_objs.dir/FoFiType1C.cc.i"
+ cd /home/calvin/src/xpdf-4.04/fofi && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/fofi/FoFiType1C.cc > CMakeFiles/fofi_objs.dir/FoFiType1C.cc.i
+
+fofi/CMakeFiles/fofi_objs.dir/FoFiType1C.cc.s: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/fofi_objs.dir/FoFiType1C.cc.s"
+ cd /home/calvin/src/xpdf-4.04/fofi && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/fofi/FoFiType1C.cc -o CMakeFiles/fofi_objs.dir/FoFiType1C.cc.s
+
+fofi_objs: fofi/CMakeFiles/fofi_objs.dir/FoFiBase.cc.o
+fofi_objs: fofi/CMakeFiles/fofi_objs.dir/FoFiEncodings.cc.o
+fofi_objs: fofi/CMakeFiles/fofi_objs.dir/FoFiIdentifier.cc.o
+fofi_objs: fofi/CMakeFiles/fofi_objs.dir/FoFiTrueType.cc.o
+fofi_objs: fofi/CMakeFiles/fofi_objs.dir/FoFiType1.cc.o
+fofi_objs: fofi/CMakeFiles/fofi_objs.dir/FoFiType1C.cc.o
+fofi_objs: fofi/CMakeFiles/fofi_objs.dir/build.make
+
+.PHONY : fofi_objs
+
+# Rule to build all files generated by this target.
+fofi/CMakeFiles/fofi_objs.dir/build: fofi_objs
+
+.PHONY : fofi/CMakeFiles/fofi_objs.dir/build
+
+fofi/CMakeFiles/fofi_objs.dir/clean:
+ cd /home/calvin/src/xpdf-4.04/fofi && $(CMAKE_COMMAND) -P CMakeFiles/fofi_objs.dir/cmake_clean.cmake
+.PHONY : fofi/CMakeFiles/fofi_objs.dir/clean
+
+fofi/CMakeFiles/fofi_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/fofi /home/calvin/src/xpdf-4.04 /home/calvin/src/xpdf-4.04/fofi /home/calvin/src/xpdf-4.04/fofi/CMakeFiles/fofi_objs.dir/DependInfo.cmake --color=$(COLOR)
+.PHONY : fofi/CMakeFiles/fofi_objs.dir/depend
+
diff --git a/fofi/CMakeFiles/fofi_objs.dir/cmake_clean.cmake b/fofi/CMakeFiles/fofi_objs.dir/cmake_clean.cmake
new file mode 100644
index 0000000..a41cbd8
--- /dev/null
+++ b/fofi/CMakeFiles/fofi_objs.dir/cmake_clean.cmake
@@ -0,0 +1,13 @@
+file(REMOVE_RECURSE
+ "CMakeFiles/fofi_objs.dir/FoFiBase.cc.o"
+ "CMakeFiles/fofi_objs.dir/FoFiEncodings.cc.o"
+ "CMakeFiles/fofi_objs.dir/FoFiIdentifier.cc.o"
+ "CMakeFiles/fofi_objs.dir/FoFiTrueType.cc.o"
+ "CMakeFiles/fofi_objs.dir/FoFiType1.cc.o"
+ "CMakeFiles/fofi_objs.dir/FoFiType1C.cc.o"
+)
+
+# Per-language clean rules from dependency scanning.
+foreach(lang CXX)
+ include(CMakeFiles/fofi_objs.dir/cmake_clean_${lang}.cmake OPTIONAL)
+endforeach()
diff --git a/fofi/CMakeFiles/fofi_objs.dir/depend.internal b/fofi/CMakeFiles/fofi_objs.dir/depend.internal
new file mode 100644
index 0000000..2c61253
--- /dev/null
+++ b/fofi/CMakeFiles/fofi_objs.dir/depend.internal
@@ -0,0 +1,62 @@
+# CMAKE generated file: DO NOT EDIT!
+# Generated by "Unix Makefiles" Generator, CMake Version 3.18
+
+fofi/CMakeFiles/fofi_objs.dir/FoFiBase.cc.o
+ /home/calvin/src/xpdf-4.04/fofi/FoFiBase.cc
+ /home/calvin/src/xpdf-4.04/fofi/FoFiBase.h
+ aconf.h
+ aconf2.h
+ goo/gmem.h
+ goo/gmempp.h
+ goo/gtypes.h
+fofi/CMakeFiles/fofi_objs.dir/FoFiEncodings.cc.o
+ /home/calvin/src/xpdf-4.04/fofi/FoFiEncodings.cc
+ /home/calvin/src/xpdf-4.04/fofi/FoFiEncodings.h
+ aconf.h
+ aconf2.h
+ goo/gmempp.h
+ goo/gtypes.h
+fofi/CMakeFiles/fofi_objs.dir/FoFiIdentifier.cc.o
+ /home/calvin/src/xpdf-4.04/fofi/FoFiIdentifier.cc
+ /home/calvin/src/xpdf-4.04/fofi/FoFiIdentifier.h
+ aconf.h
+ aconf2.h
+ goo/GList.h
+ goo/GString.h
+ goo/gmem.h
+ goo/gmempp.h
+ goo/gtypes.h
+fofi/CMakeFiles/fofi_objs.dir/FoFiTrueType.cc.o
+ /home/calvin/src/xpdf-4.04/fofi/FoFiBase.h
+ /home/calvin/src/xpdf-4.04/fofi/FoFiTrueType.cc
+ /home/calvin/src/xpdf-4.04/fofi/FoFiTrueType.h
+ /home/calvin/src/xpdf-4.04/fofi/FoFiType1C.h
+ aconf.h
+ aconf2.h
+ goo/GHash.h
+ goo/GString.h
+ goo/gmem.h
+ goo/gmempp.h
+ goo/gtypes.h
+fofi/CMakeFiles/fofi_objs.dir/FoFiType1.cc.o
+ /home/calvin/src/xpdf-4.04/fofi/FoFiBase.h
+ /home/calvin/src/xpdf-4.04/fofi/FoFiEncodings.h
+ /home/calvin/src/xpdf-4.04/fofi/FoFiType1.cc
+ /home/calvin/src/xpdf-4.04/fofi/FoFiType1.h
+ aconf.h
+ aconf2.h
+ goo/gmem.h
+ goo/gmempp.h
+ goo/gtypes.h
+fofi/CMakeFiles/fofi_objs.dir/FoFiType1C.cc.o
+ /home/calvin/src/xpdf-4.04/fofi/FoFiBase.h
+ /home/calvin/src/xpdf-4.04/fofi/FoFiEncodings.h
+ /home/calvin/src/xpdf-4.04/fofi/FoFiType1C.cc
+ /home/calvin/src/xpdf-4.04/fofi/FoFiType1C.h
+ aconf.h
+ aconf2.h
+ goo/GHash.h
+ goo/GString.h
+ goo/gmem.h
+ goo/gmempp.h
+ goo/gtypes.h
diff --git a/fofi/CMakeFiles/fofi_objs.dir/depend.make b/fofi/CMakeFiles/fofi_objs.dir/depend.make
new file mode 100644
index 0000000..cc496ef
--- /dev/null
+++ b/fofi/CMakeFiles/fofi_objs.dir/depend.make
@@ -0,0 +1,62 @@
+# CMAKE generated file: DO NOT EDIT!
+# Generated by "Unix Makefiles" Generator, CMake Version 3.18
+
+fofi/CMakeFiles/fofi_objs.dir/FoFiBase.cc.o: fofi/FoFiBase.cc
+fofi/CMakeFiles/fofi_objs.dir/FoFiBase.cc.o: fofi/FoFiBase.h
+fofi/CMakeFiles/fofi_objs.dir/FoFiBase.cc.o: aconf.h
+fofi/CMakeFiles/fofi_objs.dir/FoFiBase.cc.o: aconf2.h
+fofi/CMakeFiles/fofi_objs.dir/FoFiBase.cc.o: goo/gmem.h
+fofi/CMakeFiles/fofi_objs.dir/FoFiBase.cc.o: goo/gmempp.h
+fofi/CMakeFiles/fofi_objs.dir/FoFiBase.cc.o: goo/gtypes.h
+
+fofi/CMakeFiles/fofi_objs.dir/FoFiEncodings.cc.o: fofi/FoFiEncodings.cc
+fofi/CMakeFiles/fofi_objs.dir/FoFiEncodings.cc.o: fofi/FoFiEncodings.h
+fofi/CMakeFiles/fofi_objs.dir/FoFiEncodings.cc.o: aconf.h
+fofi/CMakeFiles/fofi_objs.dir/FoFiEncodings.cc.o: aconf2.h
+fofi/CMakeFiles/fofi_objs.dir/FoFiEncodings.cc.o: goo/gmempp.h
+fofi/CMakeFiles/fofi_objs.dir/FoFiEncodings.cc.o: goo/gtypes.h
+
+fofi/CMakeFiles/fofi_objs.dir/FoFiIdentifier.cc.o: fofi/FoFiIdentifier.cc
+fofi/CMakeFiles/fofi_objs.dir/FoFiIdentifier.cc.o: fofi/FoFiIdentifier.h
+fofi/CMakeFiles/fofi_objs.dir/FoFiIdentifier.cc.o: aconf.h
+fofi/CMakeFiles/fofi_objs.dir/FoFiIdentifier.cc.o: aconf2.h
+fofi/CMakeFiles/fofi_objs.dir/FoFiIdentifier.cc.o: goo/GList.h
+fofi/CMakeFiles/fofi_objs.dir/FoFiIdentifier.cc.o: goo/GString.h
+fofi/CMakeFiles/fofi_objs.dir/FoFiIdentifier.cc.o: goo/gmem.h
+fofi/CMakeFiles/fofi_objs.dir/FoFiIdentifier.cc.o: goo/gmempp.h
+fofi/CMakeFiles/fofi_objs.dir/FoFiIdentifier.cc.o: goo/gtypes.h
+
+fofi/CMakeFiles/fofi_objs.dir/FoFiTrueType.cc.o: fofi/FoFiBase.h
+fofi/CMakeFiles/fofi_objs.dir/FoFiTrueType.cc.o: fofi/FoFiTrueType.cc
+fofi/CMakeFiles/fofi_objs.dir/FoFiTrueType.cc.o: fofi/FoFiTrueType.h
+fofi/CMakeFiles/fofi_objs.dir/FoFiTrueType.cc.o: fofi/FoFiType1C.h
+fofi/CMakeFiles/fofi_objs.dir/FoFiTrueType.cc.o: aconf.h
+fofi/CMakeFiles/fofi_objs.dir/FoFiTrueType.cc.o: aconf2.h
+fofi/CMakeFiles/fofi_objs.dir/FoFiTrueType.cc.o: goo/GHash.h
+fofi/CMakeFiles/fofi_objs.dir/FoFiTrueType.cc.o: goo/GString.h
+fofi/CMakeFiles/fofi_objs.dir/FoFiTrueType.cc.o: goo/gmem.h
+fofi/CMakeFiles/fofi_objs.dir/FoFiTrueType.cc.o: goo/gmempp.h
+fofi/CMakeFiles/fofi_objs.dir/FoFiTrueType.cc.o: goo/gtypes.h
+
+fofi/CMakeFiles/fofi_objs.dir/FoFiType1.cc.o: fofi/FoFiBase.h
+fofi/CMakeFiles/fofi_objs.dir/FoFiType1.cc.o: fofi/FoFiEncodings.h
+fofi/CMakeFiles/fofi_objs.dir/FoFiType1.cc.o: fofi/FoFiType1.cc
+fofi/CMakeFiles/fofi_objs.dir/FoFiType1.cc.o: fofi/FoFiType1.h
+fofi/CMakeFiles/fofi_objs.dir/FoFiType1.cc.o: aconf.h
+fofi/CMakeFiles/fofi_objs.dir/FoFiType1.cc.o: aconf2.h
+fofi/CMakeFiles/fofi_objs.dir/FoFiType1.cc.o: goo/gmem.h
+fofi/CMakeFiles/fofi_objs.dir/FoFiType1.cc.o: goo/gmempp.h
+fofi/CMakeFiles/fofi_objs.dir/FoFiType1.cc.o: goo/gtypes.h
+
+fofi/CMakeFiles/fofi_objs.dir/FoFiType1C.cc.o: fofi/FoFiBase.h
+fofi/CMakeFiles/fofi_objs.dir/FoFiType1C.cc.o: fofi/FoFiEncodings.h
+fofi/CMakeFiles/fofi_objs.dir/FoFiType1C.cc.o: fofi/FoFiType1C.cc
+fofi/CMakeFiles/fofi_objs.dir/FoFiType1C.cc.o: fofi/FoFiType1C.h
+fofi/CMakeFiles/fofi_objs.dir/FoFiType1C.cc.o: aconf.h
+fofi/CMakeFiles/fofi_objs.dir/FoFiType1C.cc.o: aconf2.h
+fofi/CMakeFiles/fofi_objs.dir/FoFiType1C.cc.o: goo/GHash.h
+fofi/CMakeFiles/fofi_objs.dir/FoFiType1C.cc.o: goo/GString.h
+fofi/CMakeFiles/fofi_objs.dir/FoFiType1C.cc.o: goo/gmem.h
+fofi/CMakeFiles/fofi_objs.dir/FoFiType1C.cc.o: goo/gmempp.h
+fofi/CMakeFiles/fofi_objs.dir/FoFiType1C.cc.o: goo/gtypes.h
+
diff --git a/fofi/CMakeFiles/fofi_objs.dir/flags.make b/fofi/CMakeFiles/fofi_objs.dir/flags.make
new file mode 100644
index 0000000..8695794
--- /dev/null
+++ b/fofi/CMakeFiles/fofi_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
+
+CXX_FLAGS = -fPIC
+
diff --git a/fofi/CMakeFiles/fofi_objs.dir/progress.make b/fofi/CMakeFiles/fofi_objs.dir/progress.make
new file mode 100644
index 0000000..392d5e4
--- /dev/null
+++ b/fofi/CMakeFiles/fofi_objs.dir/progress.make
@@ -0,0 +1,7 @@
+CMAKE_PROGRESS_1 = 1
+CMAKE_PROGRESS_2 = 2
+CMAKE_PROGRESS_3 =
+CMAKE_PROGRESS_4 = 3
+CMAKE_PROGRESS_5 = 4
+CMAKE_PROGRESS_6 = 5
+
diff --git a/fofi/CMakeFiles/progress.marks b/fofi/CMakeFiles/progress.marks
new file mode 100644
index 0000000..7ed6ff8
--- /dev/null
+++ b/fofi/CMakeFiles/progress.marks
@@ -0,0 +1 @@
+5
diff --git a/fofi/CMakeLists.txt b/fofi/CMakeLists.txt
new file mode 100644
index 0000000..fd61b25
--- /dev/null
+++ b/fofi/CMakeLists.txt
@@ -0,0 +1,28 @@
+#========================================================================
+#
+# fofi/CMakeLists.txt
+#
+# CMake script for the fofi library.
+#
+# Copyright 2015 Glyph & Cog, LLC
+#
+#========================================================================
+
+include_directories("${PROJECT_SOURCE_DIR}")
+include_directories("${PROJECT_BINARY_DIR}")
+include_directories("${PROJECT_SOURCE_DIR}/goo")
+
+add_library(fofi_objs OBJECT
+ FoFiBase.cc
+ FoFiEncodings.cc
+ FoFiIdentifier.cc
+ FoFiTrueType.cc
+ FoFiType1.cc
+ FoFiType1C.cc
+)
+set_property(TARGET fofi_objs
+ PROPERTY POSITION_INDEPENDENT_CODE True)
+
+add_library(fofi
+ $<TARGET_OBJECTS:fofi_objs>
+)
diff --git a/fofi/FoFiBase.cc b/fofi/FoFiBase.cc
new file mode 100644
index 0000000..e1951b0
--- /dev/null
+++ b/fofi/FoFiBase.cc
@@ -0,0 +1,177 @@
+//========================================================================
+//
+// FoFiBase.cc
+//
+// Copyright 1999-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stdio.h>
+#include <limits.h>
+#include "gmem.h"
+#include "gmempp.h"
+#include "FoFiBase.h"
+
+//------------------------------------------------------------------------
+// FoFiBase
+//------------------------------------------------------------------------
+
+FoFiBase::FoFiBase(char *fileA, int lenA, GBool freeFileDataA) {
+ fileData = file = (Guchar *)fileA;
+ len = lenA;
+ freeFileData = freeFileDataA;
+}
+
+FoFiBase::~FoFiBase() {
+ if (freeFileData) {
+ gfree(fileData);
+ }
+}
+
+char *FoFiBase::readFile(char *fileName, int *fileLen) {
+ FILE *f;
+ char *buf;
+ int n;
+
+ if (!(f = fopen(fileName, "rb"))) {
+ return NULL;
+ }
+ fseek(f, 0, SEEK_END);
+ n = (int)ftell(f);
+ if (n < 0) {
+ fclose(f);
+ return NULL;
+ }
+ fseek(f, 0, SEEK_SET);
+ buf = (char *)gmalloc(n);
+ if ((int)fread(buf, 1, n, f) != n) {
+ gfree(buf);
+ fclose(f);
+ return NULL;
+ }
+ fclose(f);
+ *fileLen = n;
+ return buf;
+}
+
+int FoFiBase::getS8(int pos, GBool *ok) {
+ int x;
+
+ if (pos < 0 || pos >= len) {
+ *ok = gFalse;
+ return 0;
+ }
+ x = file[pos];
+ if (x & 0x80) {
+ x |= ~0xff;
+ }
+ return x;
+}
+
+int FoFiBase::getU8(int pos, GBool *ok) {
+ if (pos < 0 || pos >= len) {
+ *ok = gFalse;
+ return 0;
+ }
+ return file[pos];
+}
+
+int FoFiBase::getS16BE(int pos, GBool *ok) {
+ int x;
+
+ if (pos < 0 || pos > INT_MAX - 1 || pos+1 >= len) {
+ *ok = gFalse;
+ return 0;
+ }
+ x = file[pos];
+ x = (x << 8) + file[pos+1];
+ if (x & 0x8000) {
+ x |= ~0xffff;
+ }
+ return x;
+}
+
+int FoFiBase::getU16BE(int pos, GBool *ok) {
+ int x;
+
+ if (pos < 0 || pos > INT_MAX - 1 || pos+1 >= len) {
+ *ok = gFalse;
+ return 0;
+ }
+ x = file[pos];
+ x = (x << 8) + file[pos+1];
+ return x;
+}
+
+int FoFiBase::getS32BE(int pos, GBool *ok) {
+ int x;
+
+ if (pos < 0 || pos > INT_MAX - 3 || pos+3 >= len) {
+ *ok = gFalse;
+ return 0;
+ }
+ x = file[pos];
+ x = (x << 8) + file[pos+1];
+ x = (x << 8) + file[pos+2];
+ x = (x << 8) + file[pos+3];
+ if (x & 0x80000000) {
+ x |= ~0xffffffff;
+ }
+ return x;
+}
+
+Guint FoFiBase::getU32BE(int pos, GBool *ok) {
+ Guint x;
+
+ if (pos < 0 || pos > INT_MAX - 3 || pos+3 >= len) {
+ *ok = gFalse;
+ return 0;
+ }
+ x = file[pos];
+ x = (x << 8) + file[pos+1];
+ x = (x << 8) + file[pos+2];
+ x = (x << 8) + file[pos+3];
+ return x;
+}
+
+Guint FoFiBase::getU32LE(int pos, GBool *ok) {
+ Guint x;
+
+ if (pos < 0 || pos > INT_MAX - 3 || pos+3 >= len) {
+ *ok = gFalse;
+ return 0;
+ }
+ x = file[pos+3];
+ x = (x << 8) + file[pos+2];
+ x = (x << 8) + file[pos+1];
+ x = (x << 8) + file[pos];
+ return x;
+}
+
+Guint FoFiBase::getUVarBE(int pos, int size, GBool *ok) {
+ Guint x;
+ int i;
+
+ if (pos < 0 || pos > INT_MAX - size || pos + size > len) {
+ *ok = gFalse;
+ return 0;
+ }
+ x = 0;
+ for (i = 0; i < size; ++i) {
+ x = (x << 8) + file[pos + i];
+ }
+ return x;
+}
+
+GBool FoFiBase::checkRegion(int pos, int size) {
+ return pos >= 0 &&
+ size >= 0 &&
+ size <= INT_MAX - pos &&
+ pos + size <= len;
+}
diff --git a/fofi/FoFiBase.h b/fofi/FoFiBase.h
new file mode 100644
index 0000000..c9f93eb
--- /dev/null
+++ b/fofi/FoFiBase.h
@@ -0,0 +1,58 @@
+//========================================================================
+//
+// FoFiBase.h
+//
+// Copyright 1999-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef FOFIBASE_H
+#define FOFIBASE_H
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include "gtypes.h"
+
+//------------------------------------------------------------------------
+
+typedef void (*FoFiOutputFunc)(void *stream, const char *data, int len);
+
+//------------------------------------------------------------------------
+// FoFiBase
+//------------------------------------------------------------------------
+
+class FoFiBase {
+public:
+
+ virtual ~FoFiBase();
+
+protected:
+
+ FoFiBase(char *fileA, int lenA, GBool freeFileDataA);
+ static char *readFile(char *fileName, int *fileLen);
+
+ // S = signed / U = unsigned
+ // 8/16/32/Var = word length, in bytes
+ // BE = big endian
+ int getS8(int pos, GBool *ok);
+ int getU8(int pos, GBool *ok);
+ int getS16BE(int pos, GBool *ok);
+ int getU16BE(int pos, GBool *ok);
+ int getS32BE(int pos, GBool *ok);
+ Guint getU32BE(int pos, GBool *ok);
+ Guint getU32LE(int pos, GBool *ok);
+ Guint getUVarBE(int pos, int size, GBool *ok);
+
+ GBool checkRegion(int pos, int size);
+
+ Guchar *fileData;
+ Guchar *file;
+ int len;
+ GBool freeFileData;
+};
+
+#endif
diff --git a/fofi/FoFiEncodings.cc b/fofi/FoFiEncodings.cc
new file mode 100644
index 0000000..6b3debb
--- /dev/null
+++ b/fofi/FoFiEncodings.cc
@@ -0,0 +1,995 @@
+//========================================================================
+//
+// FoFiEncodings.cc
+//
+// Copyright 1999-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stdlib.h>
+#include "gmempp.h"
+#include "FoFiEncodings.h"
+
+//------------------------------------------------------------------------
+// Type 1 and 1C font data
+//------------------------------------------------------------------------
+
+const char *fofiType1StandardEncoding[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 *fofiType1ExpertEncoding[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"
+};
+
+//------------------------------------------------------------------------
+// Type 1C font data
+//------------------------------------------------------------------------
+
+const char *fofiType1CStdStrings[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"
+};
+
+Gushort fofiType1CISOAdobeCharset[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
+};
+
+Gushort fofiType1CExpertCharset[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
+};
+
+Gushort fofiType1CExpertSubsetCharset[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
+};
diff --git a/fofi/FoFiEncodings.h b/fofi/FoFiEncodings.h
new file mode 100644
index 0000000..dd85458
--- /dev/null
+++ b/fofi/FoFiEncodings.h
@@ -0,0 +1,36 @@
+//========================================================================
+//
+// FoFiEncodings.h
+//
+// Copyright 1999-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef FOFIENCODINGS_H
+#define FOFIENCODINGS_H
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include "gtypes.h"
+
+//------------------------------------------------------------------------
+// Type 1 and 1C font data
+//------------------------------------------------------------------------
+
+extern const char *fofiType1StandardEncoding[256];
+extern const char *fofiType1ExpertEncoding[256];
+
+//------------------------------------------------------------------------
+// Type 1C font data
+//------------------------------------------------------------------------
+
+extern const char *fofiType1CStdStrings[391];
+extern Gushort fofiType1CISOAdobeCharset[229];
+extern Gushort fofiType1CExpertCharset[166];
+extern Gushort fofiType1CExpertSubsetCharset[87];
+
+#endif
diff --git a/fofi/FoFiIdentifier.cc b/fofi/FoFiIdentifier.cc
new file mode 100644
index 0000000..4c6797b
--- /dev/null
+++ b/fofi/FoFiIdentifier.cc
@@ -0,0 +1,887 @@
+//========================================================================
+//
+// FoFiIdentifier.cc
+//
+// Copyright 2009 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <limits.h>
+#include "gtypes.h"
+#include "gmem.h"
+#include "gmempp.h"
+#include "GString.h"
+#include "GList.h"
+#include "FoFiIdentifier.h"
+
+//------------------------------------------------------------------------
+
+class Reader {
+public:
+
+ virtual ~Reader() {}
+
+ // Read one byte. Returns -1 if past EOF.
+ virtual int getByte(int pos) = 0;
+
+ // Read a big-endian unsigned 16-bit integer. Fills in *val and
+ // returns true if successful.
+ virtual GBool getU16BE(int pos, int *val) = 0;
+
+ // Read a big-endian unsigned 32-bit integer. Fills in *val and
+ // returns true if successful.
+ virtual GBool getU32BE(int pos, Guint *val) = 0;
+
+ // Read a little-endian unsigned 32-bit integer. Fills in *val and
+ // returns true if successful.
+ virtual GBool getU32LE(int pos, Guint *val) = 0;
+
+ // Read a big-endian unsigned <size>-byte integer, where 1 <= size
+ // <= 4. Fills in *val and returns true if successful.
+ virtual GBool getUVarBE(int pos, int size, Guint *val) = 0;
+
+ // Compare against a string. Returns true if equal.
+ virtual GBool cmp(int pos, const char *s) = 0;
+
+};
+
+//------------------------------------------------------------------------
+
+class MemReader: public Reader {
+public:
+
+ static MemReader *make(char *bufA, int lenA);
+ virtual ~MemReader();
+ virtual int getByte(int pos);
+ virtual GBool getU16BE(int pos, int *val);
+ virtual GBool getU32BE(int pos, Guint *val);
+ virtual GBool getU32LE(int pos, Guint *val);
+ virtual GBool getUVarBE(int pos, int size, Guint *val);
+ virtual GBool cmp(int pos, const char *s);
+
+private:
+
+ MemReader(char *bufA, int lenA);
+
+ char *buf;
+ int len;
+};
+
+MemReader *MemReader::make(char *bufA, int lenA) {
+ return new MemReader(bufA, lenA);
+}
+
+MemReader::MemReader(char *bufA, int lenA) {
+ buf = bufA;
+ len = lenA;
+}
+
+MemReader::~MemReader() {
+}
+
+int MemReader::getByte(int pos) {
+ if (pos < 0 || pos >= len) {
+ return -1;
+ }
+ return buf[pos] & 0xff;
+}
+
+GBool MemReader::getU16BE(int pos, int *val) {
+ if (pos < 0 || pos > len - 2) {
+ return gFalse;
+ }
+ *val = ((buf[pos] & 0xff) << 8) +
+ (buf[pos+1] & 0xff);
+ return gTrue;
+}
+
+GBool MemReader::getU32BE(int pos, Guint *val) {
+ if (pos < 0 || pos > len - 4) {
+ return gFalse;
+ }
+ *val = ((buf[pos] & 0xff) << 24) +
+ ((buf[pos+1] & 0xff) << 16) +
+ ((buf[pos+2] & 0xff) << 8) +
+ (buf[pos+3] & 0xff);
+ return gTrue;
+}
+
+GBool MemReader::getU32LE(int pos, Guint *val) {
+ if (pos < 0 || pos > len - 4) {
+ return gFalse;
+ }
+ *val = (buf[pos] & 0xff) +
+ ((buf[pos+1] & 0xff) << 8) +
+ ((buf[pos+2] & 0xff) << 16) +
+ ((buf[pos+3] & 0xff) << 24);
+ return gTrue;
+}
+
+GBool MemReader::getUVarBE(int pos, int size, Guint *val) {
+ int i;
+
+ if (size < 1 || size > 4 || pos < 0 || pos > len - size) {
+ return gFalse;
+ }
+ *val = 0;
+ for (i = 0; i < size; ++i) {
+ *val = (*val << 8) + (buf[pos + i] & 0xff);
+ }
+ return gTrue;
+}
+
+GBool MemReader::cmp(int pos, const char *s) {
+ int n;
+
+ n = (int)strlen(s);
+ if (pos < 0 || len < n || pos > len - n) {
+ return gFalse;
+ }
+ return !memcmp(buf + pos, s, n);
+}
+
+//------------------------------------------------------------------------
+
+class FileReader: public Reader {
+public:
+
+ static FileReader *make(char *fileName);
+ virtual ~FileReader();
+ virtual int getByte(int pos);
+ virtual GBool getU16BE(int pos, int *val);
+ virtual GBool getU32BE(int pos, Guint *val);
+ virtual GBool getU32LE(int pos, Guint *val);
+ virtual GBool getUVarBE(int pos, int size, Guint *val);
+ virtual GBool cmp(int pos, const char *s);
+
+private:
+
+ FileReader(FILE *fA);
+ GBool fillBuf(int pos, int len);
+
+ FILE *f;
+ char buf[1024];
+ int bufPos, bufLen;
+};
+
+FileReader *FileReader::make(char *fileName) {
+ FILE *fA;
+
+ if (!(fA = fopen(fileName, "rb"))) {
+ return NULL;
+ }
+ return new FileReader(fA);
+}
+
+FileReader::FileReader(FILE *fA) {
+ f = fA;
+ bufPos = 0;
+ bufLen = 0;
+}
+
+FileReader::~FileReader() {
+ fclose(f);
+}
+
+int FileReader::getByte(int pos) {
+ if (!fillBuf(pos, 1)) {
+ return -1;
+ }
+ return buf[pos - bufPos] & 0xff;
+}
+
+GBool FileReader::getU16BE(int pos, int *val) {
+ if (!fillBuf(pos, 2)) {
+ return gFalse;
+ }
+ *val = ((buf[pos - bufPos] & 0xff) << 8) +
+ (buf[pos - bufPos + 1] & 0xff);
+ return gTrue;
+}
+
+GBool FileReader::getU32BE(int pos, Guint *val) {
+ if (!fillBuf(pos, 4)) {
+ return gFalse;
+ }
+ *val = ((buf[pos - bufPos] & 0xff) << 24) +
+ ((buf[pos - bufPos + 1] & 0xff) << 16) +
+ ((buf[pos - bufPos + 2] & 0xff) << 8) +
+ (buf[pos - bufPos + 3] & 0xff);
+ return gTrue;
+}
+
+GBool FileReader::getU32LE(int pos, Guint *val) {
+ if (!fillBuf(pos, 4)) {
+ return gFalse;
+ }
+ *val = (buf[pos - bufPos] & 0xff) +
+ ((buf[pos - bufPos + 1] & 0xff) << 8) +
+ ((buf[pos - bufPos + 2] & 0xff) << 16) +
+ ((buf[pos - bufPos + 3] & 0xff) << 24);
+ return gTrue;
+}
+
+GBool FileReader::getUVarBE(int pos, int size, Guint *val) {
+ int i;
+
+ if (size < 1 || size > 4 || !fillBuf(pos, size)) {
+ return gFalse;
+ }
+ *val = 0;
+ for (i = 0; i < size; ++i) {
+ *val = (*val << 8) + (buf[pos - bufPos + i] & 0xff);
+ }
+ return gTrue;
+}
+
+GBool FileReader::cmp(int pos, const char *s) {
+ int n;
+
+ n = (int)strlen(s);
+ if (!fillBuf(pos, n)) {
+ return gFalse;
+ }
+ return !memcmp(buf - bufPos + pos, s, n);
+}
+
+GBool FileReader::fillBuf(int pos, int len) {
+ if (pos < 0 || len < 0 || len > (int)sizeof(buf) ||
+ pos > INT_MAX - (int)sizeof(buf)) {
+ return gFalse;
+ }
+ if (pos >= bufPos && pos + len <= bufPos + bufLen) {
+ return gTrue;
+ }
+ if (fseek(f, pos, SEEK_SET)) {
+ return gFalse;
+ }
+ bufPos = pos;
+ bufLen = (int)fread(buf, 1, sizeof(buf), f);
+ if (bufLen < len) {
+ return gFalse;
+ }
+ return gTrue;
+}
+
+//------------------------------------------------------------------------
+
+class StreamReader: public Reader {
+public:
+
+ static StreamReader *make(int (*getCharA)(void *data), void *dataA);
+ virtual ~StreamReader();
+ virtual int getByte(int pos);
+ virtual GBool getU16BE(int pos, int *val);
+ virtual GBool getU32BE(int pos, Guint *val);
+ virtual GBool getU32LE(int pos, Guint *val);
+ virtual GBool getUVarBE(int pos, int size, Guint *val);
+ virtual GBool cmp(int pos, const char *s);
+
+private:
+
+ StreamReader(int (*getCharA)(void *data), void *dataA);
+ GBool fillBuf(int pos, int len);
+
+ int (*getChar)(void *data);
+ void *data;
+ int streamPos;
+ char buf[1024];
+ int bufPos, bufLen;
+};
+
+StreamReader *StreamReader::make(int (*getCharA)(void *data), void *dataA) {
+ return new StreamReader(getCharA, dataA);
+}
+
+StreamReader::StreamReader(int (*getCharA)(void *data), void *dataA) {
+ getChar = getCharA;
+ data = dataA;
+ streamPos = 0;
+ bufPos = 0;
+ bufLen = 0;
+}
+
+StreamReader::~StreamReader() {
+}
+
+int StreamReader::getByte(int pos) {
+ if (!fillBuf(pos, 1)) {
+ return -1;
+ }
+ return buf[pos - bufPos] & 0xff;
+}
+
+GBool StreamReader::getU16BE(int pos, int *val) {
+ if (!fillBuf(pos, 2)) {
+ return gFalse;
+ }
+ *val = ((buf[pos - bufPos] & 0xff) << 8) +
+ (buf[pos - bufPos + 1] & 0xff);
+ return gTrue;
+}
+
+GBool StreamReader::getU32BE(int pos, Guint *val) {
+ if (!fillBuf(pos, 4)) {
+ return gFalse;
+ }
+ *val = ((buf[pos - bufPos] & 0xff) << 24) +
+ ((buf[pos - bufPos + 1] & 0xff) << 16) +
+ ((buf[pos - bufPos + 2] & 0xff) << 8) +
+ (buf[pos - bufPos + 3] & 0xff);
+ return gTrue;
+}
+
+GBool StreamReader::getU32LE(int pos, Guint *val) {
+ if (!fillBuf(pos, 4)) {
+ return gFalse;
+ }
+ *val = (buf[pos - bufPos] & 0xff) +
+ ((buf[pos - bufPos + 1] & 0xff) << 8) +
+ ((buf[pos - bufPos + 2] & 0xff) << 16) +
+ ((buf[pos - bufPos + 3] & 0xff) << 24);
+ return gTrue;
+}
+
+GBool StreamReader::getUVarBE(int pos, int size, Guint *val) {
+ int i;
+
+ if (size < 1 || size > 4 || !fillBuf(pos, size)) {
+ return gFalse;
+ }
+ *val = 0;
+ for (i = 0; i < size; ++i) {
+ *val = (*val << 8) + (buf[pos - bufPos + i] & 0xff);
+ }
+ return gTrue;
+}
+
+GBool StreamReader::cmp(int pos, const char *s) {
+ int n;
+
+ n = (int)strlen(s);
+ if (!fillBuf(pos, n)) {
+ return gFalse;
+ }
+ return !memcmp(buf - bufPos + pos, s, n);
+}
+
+GBool StreamReader::fillBuf(int pos, int len) {
+ int c;
+
+ if (pos < 0 || len < 0 || len > (int)sizeof(buf) ||
+ pos > INT_MAX - (int)sizeof(buf)) {
+ return gFalse;
+ }
+ if (pos < bufPos) {
+ return gFalse;
+ }
+
+ // if requested region will not fit in the current buffer...
+ if (pos + len > bufPos + (int)sizeof(buf)) {
+
+ // if the start of the requested data is already in the buffer, move
+ // it to the start of the buffer
+ if (pos < bufPos + bufLen) {
+ bufLen -= pos - bufPos;
+ memmove(buf, buf + (pos - bufPos), bufLen);
+ bufPos = pos;
+
+ // otherwise discard data from the
+ // stream until we get to the requested position
+ } else {
+ bufPos += bufLen;
+ bufLen = 0;
+ while (bufPos < pos) {
+ if ((c = (*getChar)(data)) < 0) {
+ return gFalse;
+ }
+ ++bufPos;
+ }
+ }
+ }
+
+ // read the rest of the requested data
+ while (bufPos + bufLen < pos + len) {
+ if ((c = (*getChar)(data)) < 0) {
+ return gFalse;
+ }
+ buf[bufLen++] = (char)c;
+ }
+
+ return gTrue;
+}
+
+//------------------------------------------------------------------------
+
+static FoFiIdentifierType identify(Reader *reader);
+static FoFiIdentifierType identifyOpenType(Reader *reader);
+static FoFiIdentifierType identifyCFF(Reader *reader, int start);
+
+FoFiIdentifierType FoFiIdentifier::identifyMem(char *file, int len) {
+ MemReader *reader;
+ FoFiIdentifierType type;
+
+ if (!(reader = MemReader::make(file, len))) {
+ return fofiIdError;
+ }
+ type = identify(reader);
+ delete reader;
+ return type;
+}
+
+FoFiIdentifierType FoFiIdentifier::identifyFile(char *fileName) {
+ FileReader *reader;
+ FoFiIdentifierType type;
+ int n;
+
+ if (!(reader = FileReader::make(fileName))) {
+ return fofiIdError;
+ }
+ type = identify(reader);
+ delete reader;
+
+ // Mac OS X dfont files don't have any sort of header or magic number,
+ // so look at the file name extension
+ if (type == fofiIdUnknown) {
+ n = (int)strlen(fileName);
+ if (n >= 6 && !strcmp(fileName + n - 6, ".dfont")) {
+ type = fofiIdDfont;
+ }
+ }
+
+ return type;
+}
+
+FoFiIdentifierType FoFiIdentifier::identifyStream(int (*getChar)(void *data),
+ void *data) {
+ StreamReader *reader;
+ FoFiIdentifierType type;
+
+ if (!(reader = StreamReader::make(getChar, data))) {
+ return fofiIdError;
+ }
+ type = identify(reader);
+ delete reader;
+ return type;
+}
+
+static FoFiIdentifierType identify(Reader *reader) {
+ Guint n;
+
+ //----- PFA
+ if (reader->cmp(0, "%!PS-AdobeFont-1") ||
+ reader->cmp(0, "%!FontType1")) {
+ return fofiIdType1PFA;
+ }
+
+ //----- PFB
+ if (reader->getByte(0) == 0x80 &&
+ reader->getByte(1) == 0x01 &&
+ reader->getU32LE(2, &n)) {
+ if ((n >= 16 && reader->cmp(6, "%!PS-AdobeFont-1")) ||
+ (n >= 11 && reader->cmp(6, "%!FontType1"))) {
+ return fofiIdType1PFB;
+ }
+ }
+
+ //----- TrueType
+ if ((reader->getByte(0) == 0x00 &&
+ reader->getByte(1) == 0x01 &&
+ reader->getByte(2) == 0x00 &&
+ reader->getByte(3) == 0x00) ||
+ (reader->getByte(0) == 0x74 && // 'true'
+ reader->getByte(1) == 0x72 &&
+ reader->getByte(2) == 0x75 &&
+ reader->getByte(3) == 0x65)) {
+ return fofiIdTrueType;
+ }
+ if (reader->getByte(0) == 0x74 && // 'ttcf'
+ reader->getByte(1) == 0x74 &&
+ reader->getByte(2) == 0x63 &&
+ reader->getByte(3) == 0x66) {
+ return fofiIdTrueTypeCollection;
+ }
+
+ //----- OpenType
+ if (reader->getByte(0) == 0x4f && // 'OTTO
+ reader->getByte(1) == 0x54 &&
+ reader->getByte(2) == 0x54 &&
+ reader->getByte(3) == 0x4f) {
+ return identifyOpenType(reader);
+ }
+
+ //----- CFF
+ if (reader->getByte(0) == 0x01 &&
+ reader->getByte(1) == 0x00) {
+ return identifyCFF(reader, 0);
+ }
+ // some tools embed CFF fonts with an extra whitespace char at the
+ // beginning
+ if (reader->getByte(1) == 0x01 &&
+ reader->getByte(2) == 0x00) {
+ return identifyCFF(reader, 1);
+ }
+
+ return fofiIdUnknown;
+}
+
+static FoFiIdentifierType identifyOpenType(Reader *reader) {
+ FoFiIdentifierType type;
+ Guint offset;
+ int nTables, i;
+
+ if (!reader->getU16BE(4, &nTables)) {
+ return fofiIdUnknown;
+ }
+ for (i = 0; i < nTables; ++i) {
+ if (reader->cmp(12 + i*16, "CFF ")) {
+ if (reader->getU32BE(12 + i*16 + 8, &offset) &&
+ offset < (Guint)INT_MAX) {
+ type = identifyCFF(reader, (int)offset);
+ if (type == fofiIdCFF8Bit) {
+ type = fofiIdOpenTypeCFF8Bit;
+ } else if (type == fofiIdCFFCID) {
+ type = fofiIdOpenTypeCFFCID;
+ }
+ return type;
+ }
+ return fofiIdUnknown;
+ }
+ }
+ return fofiIdUnknown;
+}
+
+static FoFiIdentifierType identifyCFF(Reader *reader, int start) {
+ Guint offset0, offset1;
+ int hdrSize, offSize0, offSize1, pos, endPos, b0, n;
+
+ //----- read the header
+ if (reader->getByte(start) != 0x01 ||
+ reader->getByte(start + 1) != 0x00) {
+ return fofiIdUnknown;
+ }
+ if ((hdrSize = reader->getByte(start + 2)) < 0) {
+ return fofiIdUnknown;
+ }
+ if ((offSize0 = reader->getByte(start + 3)) < 1 || offSize0 > 4) {
+ return fofiIdUnknown;
+ }
+ pos = start + hdrSize;
+ if (pos < 0) {
+ return fofiIdUnknown;
+ }
+
+ //----- skip the name index
+ if (!reader->getU16BE(pos, &n)) {
+ return fofiIdUnknown;
+ }
+ if (n == 0) {
+ pos += 2;
+ } else {
+ if ((offSize1 = reader->getByte(pos + 2)) < 1 || offSize1 > 4) {
+ return fofiIdUnknown;
+ }
+ if (!reader->getUVarBE(pos + 3 + n * offSize1, offSize1, &offset1) ||
+ offset1 > (Guint)INT_MAX) {
+ return fofiIdUnknown;
+ }
+ pos += 3 + (n + 1) * offSize1 + (int)offset1 - 1;
+ }
+ if (pos < 0) {
+ return fofiIdUnknown;
+ }
+
+ //----- parse the top dict index
+ if (!reader->getU16BE(pos, &n) || n < 1) {
+ return fofiIdUnknown;
+ }
+ if ((offSize1 = reader->getByte(pos + 2)) < 1 || offSize1 > 4) {
+ return fofiIdUnknown;
+ }
+ if (!reader->getUVarBE(pos + 3, offSize1, &offset0) ||
+ offset0 > (Guint)INT_MAX ||
+ !reader->getUVarBE(pos + 3 + offSize1, offSize1, &offset1) ||
+ offset1 > (Guint)INT_MAX ||
+ offset0 > offset1) {
+ return fofiIdUnknown;
+ }
+ pos = pos + 3 + (n + 1) * offSize1 + (int)offset0 - 1;
+ endPos = pos + 3 + (n + 1) * offSize1 + (int)offset1 - 1;
+ if (pos < 0 || endPos < 0 || pos > endPos) {
+ return fofiIdUnknown;
+ }
+
+ //----- parse the top dict, look for ROS as first entry
+ // for a CID font, the top dict starts with:
+ // <int> <int> <int> ROS
+ while (pos >= 0 && pos < endPos) {
+ b0 = reader->getByte(pos);
+ if (b0 == 0x1c) {
+ pos += 3;
+ } else if (b0 == 0x1d) {
+ pos += 5;
+ } else if (b0 >= 0xf7 && b0 <= 0xfe) {
+ pos += 2;
+ } else if (b0 >= 0x20 && b0 <= 0xf6) {
+ pos += 1;
+ } else {
+ break;
+ }
+ }
+ if (pos + 1 < endPos &&
+ reader->getByte(pos) == 12 &&
+ reader->getByte(pos + 1) == 30) {
+ return fofiIdCFFCID;
+ } else {
+ return fofiIdCFF8Bit;
+ }
+}
+
+//------------------------------------------------------------------------
+
+static GList *getTTCFontList(FILE *f);
+static GList *getDfontFontList(FILE *f);
+
+GList *FoFiIdentifier::getFontList(char *fileName) {
+ FILE *f;
+ char buf[4];
+ GList *ret;
+
+ if (!(f = fopen(fileName, "rb"))) {
+ return NULL;
+ }
+ if (fread(buf, 1, 4, f) == 4 &&
+ buf[0] == 0x74 && // 'ttcf'
+ buf[1] == 0x74 &&
+ buf[2] == 0x63 &&
+ buf[3] == 0x66) {
+ ret = getTTCFontList(f);
+ } else {
+ ret = getDfontFontList(f);
+ }
+ fclose(f);
+ return ret;
+}
+
+static GList *getTTCFontList(FILE *f) {
+ Guchar buf[12];
+ Guchar *buf2;
+ int fileLength, nFonts;
+ int tabDirOffset, nTables, nameTabOffset, nNames, stringsOffset;
+ int stringPlatform, stringLength, stringOffset;
+ GBool stringUnicode;
+ int i, j;
+ GList *ret;
+
+ fseek(f, 0, SEEK_END);
+ fileLength = (int)ftell(f);
+ if (fileLength < 0) {
+ goto err1;
+ }
+ fseek(f, 8, SEEK_SET);
+ if (fread(buf, 1, 4, f) != 4) {
+ goto err1;
+ }
+ nFonts = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
+ if (nFonts < 0 ||
+ 12 + 4 * nFonts > fileLength) {
+ goto err1;
+ }
+ ret = new GList();
+ for (i = 0; i < nFonts; ++i) {
+ fseek(f, 12 + 4 * i, SEEK_SET);
+ if (fread(buf, 1, 4, f) != 4) {
+ goto err2;
+ }
+ tabDirOffset = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
+ if (tabDirOffset < 0 ||
+ tabDirOffset + 12 < 0 ||
+ tabDirOffset + 12 > fileLength) {
+ goto err2;
+ }
+ fseek(f, tabDirOffset, SEEK_SET);
+ if (fread(buf, 1, 12, f) != 12) {
+ goto err2;
+ }
+ nTables = (buf[4] << 8) | buf[5];
+ if (tabDirOffset + 12 + 16 * nTables < 0 ||
+ tabDirOffset + 12 + 16 * nTables > fileLength) {
+ goto err2;
+ }
+ buf2 = (Guchar *)gmallocn(nTables, 16);
+ if ((int)fread(buf2, 1, 16 * nTables, f) != 16 * nTables) {
+ goto err3;
+ }
+ nameTabOffset = 0; // make gcc happy
+ for (j = 0; j < nTables; ++j) {
+ if (buf2[16*j + 0] == 'n' &&
+ buf2[16*j + 1] == 'a' &&
+ buf2[16*j + 2] == 'm' &&
+ buf2[16*j + 3] == 'e') {
+ nameTabOffset = (buf2[16*j + 8] << 24) | (buf2[16*j + 9] << 16) |
+ (buf2[16*j + 10] << 8) | buf2[16*j + 11];
+ break;
+ }
+ }
+ gfree(buf2);
+ if (j >= nTables) {
+ goto err2;
+ }
+ if (nameTabOffset < 0 ||
+ nameTabOffset + 6 < 0 ||
+ nameTabOffset + 6 > fileLength) {
+ goto err2;
+ }
+ fseek(f, nameTabOffset, SEEK_SET);
+ if (fread(buf, 1, 6, f) != 6) {
+ goto err2;
+ }
+ nNames = (buf[2] << 8) | buf[3];
+ stringsOffset = (buf[4] << 8) | buf[5];
+ if (nameTabOffset + 6 + 12 * nNames < 0 ||
+ nameTabOffset + 6 + 12 * nNames > fileLength ||
+ nameTabOffset + stringsOffset < 0) {
+ goto err2;
+ }
+ buf2 = (Guchar *)gmallocn(nNames, 12);
+ if ((int)fread(buf2, 1, 12 * nNames, f) != 12 * nNames) {
+ goto err3;
+ }
+ for (j = 0; j < nNames; ++j) {
+ if (buf2[12*j + 6] == 0 && // 0x0004 = full name
+ buf2[12*j + 7] == 4) {
+ break;
+ }
+ }
+ if (j >= nNames) {
+ goto err3;
+ }
+ stringPlatform = (buf2[12*j] << 8) | buf2[12*j + 1];
+ // stringEncoding = (buf2[12*j + 2] << 8) | buf2[12*j + 3];
+ stringUnicode = stringPlatform == 0 || stringPlatform == 3;
+ stringLength = (buf2[12*j + 8] << 8) | buf2[12*j + 9];
+ stringOffset = nameTabOffset + stringsOffset +
+ ((buf2[12*j + 10] << 8) | buf2[12*j + 11]);
+ gfree(buf2);
+ if (stringOffset < 0 ||
+ stringOffset + stringLength < 0 ||
+ stringOffset + stringLength > fileLength) {
+ goto err2;
+ }
+ buf2 = (Guchar *)gmalloc(stringLength);
+ fseek(f, stringOffset, SEEK_SET);
+ if ((int)fread(buf2, 1, stringLength, f) != stringLength) {
+ goto err3;
+ }
+ if (stringUnicode) {
+ stringLength /= 2;
+ for (j = 0; j < stringLength; ++j) {
+ buf2[j] = buf2[2*j + 1];
+ }
+ }
+ ret->append(new GString((char *)buf2, stringLength));
+ gfree(buf2);
+ }
+ return ret;
+
+ err3:
+ gfree(buf2);
+ err2:
+ deleteGList(ret, GString);
+ err1:
+ return NULL;
+}
+
+static GList *getDfontFontList(FILE *f) {
+ Guchar buf[16];
+ Guchar *resMap;
+ int fileLength, resMapOffset, resMapLength;
+ int resTypeListOffset, resNameListOffset, nTypes;
+ int refListOffset, nFonts, nameOffset, nameLen;
+ int offset, i;
+ GList *ret;
+
+ fseek(f, 0, SEEK_END);
+ fileLength = (int)ftell(f);
+ if (fileLength < 0) {
+ goto err1;
+ }
+ fseek(f, 0, SEEK_SET);
+ if (fread((char *)buf, 1, 16, f) != 16) {
+ goto err1;
+ }
+ resMapOffset = (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7];
+ resMapLength = (buf[12] << 24) | (buf[13] << 16) | (buf[14] << 8) | buf[15];
+ if (resMapOffset < 0 ||
+ resMapOffset >= fileLength ||
+ resMapLength < 0 ||
+ resMapOffset + resMapLength > fileLength ||
+ resMapOffset + resMapLength < 0) {
+ goto err1;
+ }
+ if (resMapLength > 32768) {
+ // sanity check - this probably isn't a dfont file
+ goto err1;
+ }
+ resMap = (Guchar *)gmalloc(resMapLength);
+ fseek(f, resMapOffset, SEEK_SET);
+ if ((int)fread((char *)resMap, 1, resMapLength, f) != resMapLength) {
+ goto err2;
+ }
+ resTypeListOffset = (resMap[24] << 8) | resMap[25];
+ resNameListOffset = (resMap[26] << 8) | resMap[27];
+ nTypes = ((resMap[28] << 8) | resMap[29]) + 1;
+ if (resTypeListOffset + 2 + nTypes * 8 > resMapLength ||
+ resNameListOffset >= resMapLength) {
+ goto err2;
+ }
+ for (i = 0; i < nTypes; ++i) {
+ offset = resTypeListOffset + 2 + 8 * i;
+ if (resMap[offset] == 0x73 && // 'sfnt'
+ resMap[offset+1] == 0x66 &&
+ resMap[offset+2] == 0x6e &&
+ resMap[offset+3] == 0x74) {
+ nFonts = ((resMap[offset+4] << 8) | resMap[offset+5]) + 1;
+ refListOffset = (resMap[offset+6] << 8) | resMap[offset+7];
+ break;
+ }
+ }
+ if (i >= nTypes) {
+ goto err2;
+ }
+ if (resTypeListOffset + refListOffset >= resMapLength ||
+ resTypeListOffset + refListOffset + nFonts * 12 > resMapLength) {
+ goto err2;
+ }
+ ret = new GList();
+ for (i = 0; i < nFonts; ++i) {
+ offset = resTypeListOffset + refListOffset + 12 * i;
+ nameOffset = (resMap[offset+2] << 8) | resMap[offset+3];
+ offset = resNameListOffset + nameOffset;
+ if (offset >= resMapLength) {
+ goto err3;
+ }
+ nameLen = resMap[offset];
+ if (offset + 1 + nameLen > resMapLength) {
+ goto err3;
+ }
+ ret->append(new GString((char *)resMap + offset + 1, nameLen));
+ }
+ gfree(resMap);
+ return ret;
+
+ err3:
+ deleteGList(ret, GString);
+ err2:
+ gfree(resMap);
+ err1:
+ return NULL;
+}
diff --git a/fofi/FoFiIdentifier.h b/fofi/FoFiIdentifier.h
new file mode 100644
index 0000000..b0307a0
--- /dev/null
+++ b/fofi/FoFiIdentifier.h
@@ -0,0 +1,55 @@
+//========================================================================
+//
+// FoFiIdentifier.h
+//
+// Copyright 2009 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef FOFIIDENTIFIER_H
+#define FOFIIDENTIFIER_H
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+class GList;
+
+//------------------------------------------------------------------------
+// FoFiIdentifier
+//------------------------------------------------------------------------
+
+enum FoFiIdentifierType {
+ fofiIdType1PFA, // Type 1 font in PFA format
+ fofiIdType1PFB, // Type 1 font in PFB format
+ fofiIdCFF8Bit, // 8-bit CFF font
+ fofiIdCFFCID, // CID CFF font
+ fofiIdTrueType, // TrueType font
+ fofiIdTrueTypeCollection, // TrueType collection
+ fofiIdOpenTypeCFF8Bit, // OpenType wrapper with 8-bit CFF font
+ fofiIdOpenTypeCFFCID, // OpenType wrapper with CID CFF font
+ fofiIdDfont, // Mac OS X dfont
+ fofiIdUnknown, // unknown type
+ fofiIdError // error in reading the file
+};
+
+class FoFiIdentifier {
+public:
+
+ // Identify a font file.
+ static FoFiIdentifierType identifyMem(char *file, int len);
+ static FoFiIdentifierType identifyFile(char *fileName);
+ static FoFiIdentifierType identifyStream(int (*getChar)(void *data),
+ void *data);
+
+ // Return a list of font names (GString *) in a font collection
+ // file. Indexes into the returned list are indexes into the
+ // collection. This function is only useful with TrueType
+ // collections and Mac dfont files. Returns NULL on error
+ // (including invalid font type).
+ static GList *getFontList(char *fileName);
+};
+
+#endif
diff --git a/fofi/FoFiTrueType.cc b/fofi/FoFiTrueType.cc
new file mode 100644
index 0000000..57b12b1
--- /dev/null
+++ b/fofi/FoFiTrueType.cc
@@ -0,0 +1,2461 @@
+//========================================================================
+//
+// FoFiTrueType.cc
+//
+// Copyright 1999-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#if HAVE_STD_SORT
+#include <algorithm>
+#endif
+#include "gtypes.h"
+#include "gmem.h"
+#include "gmempp.h"
+#include "GString.h"
+#include "GHash.h"
+#include "FoFiType1C.h"
+#include "FoFiTrueType.h"
+
+//
+// Terminology
+// -----------
+//
+// character code = number used as an element of a text string
+//
+// character name = glyph name = name for a particular glyph within a
+// font
+//
+// glyph index = GID = position (within some internal table in the font)
+// where the instructions to draw a particular glyph are
+// stored
+//
+// Type 1 fonts
+// ------------
+//
+// Type 1 fonts contain:
+//
+// Encoding: array of glyph names, maps char codes to glyph names
+//
+// Encoding[charCode] = charName
+//
+// CharStrings: dictionary of instructions, keyed by character names,
+// maps character name to glyph data
+//
+// CharStrings[charName] = glyphData
+//
+// TrueType fonts
+// --------------
+//
+// TrueType fonts contain:
+//
+// 'cmap' table: mapping from character code to glyph index; there may
+// be multiple cmaps in a TrueType font
+//
+// cmap[charCode] = gid
+//
+// 'post' table: mapping from glyph index to glyph name
+//
+// post[gid] = glyphName
+//
+// Type 42 fonts
+// -------------
+//
+// Type 42 fonts contain:
+//
+// Encoding: array of glyph names, maps char codes to glyph names
+//
+// Encoding[charCode] = charName
+//
+// CharStrings: dictionary of glyph indexes, keyed by character names,
+// maps character name to glyph index
+//
+// CharStrings[charName] = gid
+//
+
+//------------------------------------------------------------------------
+
+#define ttcfTag 0x74746366
+
+//------------------------------------------------------------------------
+
+struct TrueTypeTable {
+ Guint tag;
+ Guint checksum;
+ int offset;
+ int origOffset;
+ int len;
+};
+
+struct TrueTypeCmap {
+ int platform;
+ int encoding;
+ int offset;
+ int len;
+ int fmt;
+};
+
+struct TrueTypeLoca {
+ int idx;
+ int origOffset;
+ int newOffset;
+ int len;
+};
+
+#define cmapTag 0x636d6170
+#define glyfTag 0x676c7966
+#define headTag 0x68656164
+#define hheaTag 0x68686561
+#define hmtxTag 0x686d7478
+#define locaTag 0x6c6f6361
+#define nameTag 0x6e616d65
+#define os2Tag 0x4f532f32
+#define postTag 0x706f7374
+
+#if HAVE_STD_SORT
+
+struct cmpTrueTypeLocaOffsetFunctor {
+ bool operator()(const TrueTypeLoca &loca1, const TrueTypeLoca &loca2) {
+ if (loca1.origOffset == loca2.origOffset) {
+ return loca1.idx < loca2.idx;
+ }
+ return loca1.origOffset < loca2.origOffset;
+ }
+};
+
+struct cmpTrueTypeLocaIdxFunctor {
+ bool operator()(const TrueTypeLoca &loca1, const TrueTypeLoca &loca2) {
+ return loca1.idx < loca2.idx;
+ }
+};
+
+struct cmpTrueTypeTableTagFunctor {
+ bool operator()(const TrueTypeTable &tab1, const TrueTypeTable &tab2) {
+ return tab1.tag < tab2.tag;
+ }
+};
+
+#else // HAVE_STD_SORT
+
+static int cmpTrueTypeLocaOffset(const void *p1, const void *p2) {
+ TrueTypeLoca *loca1 = (TrueTypeLoca *)p1;
+ TrueTypeLoca *loca2 = (TrueTypeLoca *)p2;
+
+ if (loca1->origOffset == loca2->origOffset) {
+ return loca1->idx - loca2->idx;
+ }
+ return loca1->origOffset - loca2->origOffset;
+}
+
+static int cmpTrueTypeLocaIdx(const void *p1, const void *p2) {
+ TrueTypeLoca *loca1 = (TrueTypeLoca *)p1;
+ TrueTypeLoca *loca2 = (TrueTypeLoca *)p2;
+
+ return loca1->idx - loca2->idx;
+}
+
+static int cmpTrueTypeTableTag(const void *p1, const void *p2) {
+ TrueTypeTable *tab1 = (TrueTypeTable *)p1;
+ TrueTypeTable *tab2 = (TrueTypeTable *)p2;
+
+ return (int)tab1->tag - (int)tab2->tag;
+}
+
+#endif // HAVE_STD_SORT
+
+//------------------------------------------------------------------------
+
+struct T42Table {
+ const char *tag; // 4-byte tag
+ GBool required; // required by the TrueType spec?
+};
+
+// TrueType tables to be embedded in Type 42 fonts.
+// NB: the table names must be in alphabetical order here.
+#define nT42Tables 11
+static T42Table t42Tables[nT42Tables] = {
+ { "cvt ", gTrue },
+ { "fpgm", gTrue },
+ { "glyf", gTrue },
+ { "head", gTrue },
+ { "hhea", gTrue },
+ { "hmtx", gTrue },
+ { "loca", gTrue },
+ { "maxp", gTrue },
+ { "prep", gTrue },
+ { "vhea", gFalse },
+ { "vmtx", gFalse }
+};
+#define t42HeadTable 3
+#define t42LocaTable 6
+#define t42GlyfTable 2
+#define t42VheaTable 9
+#define t42VmtxTable 10
+
+//------------------------------------------------------------------------
+
+// Glyph names in some arbitrary standard order that Apple uses for
+// their TrueType fonts.
+static const char *macGlyphNames[258] = {
+ ".notdef", "null", "CR", "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", "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", "mu1",
+ "partialdiff", "summation", "product", "pi",
+ "integral", "ordfeminine", "ordmasculine", "Ohm",
+ "ae", "oslash", "questiondown", "exclamdown",
+ "logicalnot", "radical", "florin", "approxequal",
+ "increment", "guillemotleft", "guillemotright", "ellipsis",
+ "nbspace", "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", "applelogo", "Ograve",
+ "Uacute", "Ucircumflex", "Ugrave", "dotlessi",
+ "circumflex", "tilde", "overscore", "breve",
+ "dotaccent", "ring", "cedilla", "hungarumlaut",
+ "ogonek", "caron", "Lslash", "lslash",
+ "Scaron", "scaron", "Zcaron", "zcaron",
+ "brokenbar", "Eth", "eth", "Yacute",
+ "yacute", "Thorn", "thorn", "minus",
+ "multiply", "onesuperior", "twosuperior", "threesuperior",
+ "onehalf", "onequarter", "threequarters", "franc",
+ "Gbreve", "gbreve", "Idot", "Scedilla",
+ "scedilla", "Cacute", "cacute", "Ccaron",
+ "ccaron", "dmacron"
+};
+
+//------------------------------------------------------------------------
+// FoFiTrueType
+//------------------------------------------------------------------------
+
+FoFiTrueType *FoFiTrueType::make(char *fileA, int lenA, int fontNum,
+ GBool allowHeadlessCFF) {
+ FoFiTrueType *ff;
+
+ ff = new FoFiTrueType(fileA, lenA, gFalse, fontNum, gFalse, allowHeadlessCFF);
+ if (!ff->parsedOk) {
+ delete ff;
+ return NULL;
+ }
+ return ff;
+}
+
+FoFiTrueType *FoFiTrueType::load(char *fileName, int fontNum,
+ GBool allowHeadlessCFF) {
+ FoFiTrueType *ff;
+ char *fileA;
+ int lenA, n;
+ GBool isDfontA;
+
+ if (!(fileA = FoFiBase::readFile(fileName, &lenA))) {
+ return NULL;
+ }
+ n = (int)strlen(fileName);
+ isDfontA = n >= 6 && !strcmp(fileName + n - 6, ".dfont");
+ ff = new FoFiTrueType(fileA, lenA, gTrue, fontNum, isDfontA,
+ allowHeadlessCFF);
+ if (!ff->parsedOk) {
+ delete ff;
+ return NULL;
+ }
+ return ff;
+}
+
+FoFiTrueType::FoFiTrueType(char *fileA, int lenA, GBool freeFileDataA,
+ int fontNum, GBool isDfontA,
+ GBool allowHeadlessCFF):
+ FoFiBase(fileA, lenA, freeFileDataA)
+{
+ tables = NULL;
+ nTables = 0;
+ cmaps = NULL;
+ nCmaps = 0;
+ nameToGID = NULL;
+ isDfont = isDfontA;
+ isTTC = gFalse;
+ parsedOk = gFalse;
+
+ parse(fontNum, allowHeadlessCFF);
+}
+
+FoFiTrueType::~FoFiTrueType() {
+ gfree(tables);
+ gfree(cmaps);
+ if (nameToGID) {
+ delete nameToGID;
+ }
+}
+
+int FoFiTrueType::getNumCmaps() {
+ return nCmaps;
+}
+
+int FoFiTrueType::getCmapPlatform(int i) {
+ return cmaps[i].platform;
+}
+
+int FoFiTrueType::getCmapEncoding(int i) {
+ return cmaps[i].encoding;
+}
+
+int FoFiTrueType::findCmap(int platform, int encoding) {
+ int i;
+
+ for (i = 0; i < nCmaps; ++i) {
+ if (cmaps[i].platform == platform && cmaps[i].encoding == encoding) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+int FoFiTrueType::mapCodeToGID(int i, int c) {
+ int gid;
+ int segCnt, segEnd, segStart, segDelta, segOffset;
+ int cmapFirst, cmapLen;
+ int pos, a, b, m;
+ GBool ok;
+
+ if (i < 0 || i >= nCmaps) {
+ return 0;
+ }
+ ok = gTrue;
+ pos = cmaps[i].offset;
+ switch (cmaps[i].fmt) {
+ case 0:
+ if (c < 0 || c >= cmaps[i].len - 6) {
+ return 0;
+ }
+ gid = getU8(pos + 6 + c, &ok);
+ break;
+ case 2:
+ // this only handles single-byte codes
+ if (c < 0 || c > 0xff) {
+ return 0;
+ }
+ // check that: subHeaderKeys[0] = 0
+ // subHeaders[0].firstCode = 0
+ // subHeaders[0].entryCount = 256
+ // subHeaders[0].idDelta = 0
+ if (getU16BE(pos + 6, &ok) != 0 ||
+ getU16BE(pos + 518 + 0, &ok) != 0 ||
+ getU16BE(pos + 518 + 2, &ok) != 256 ||
+ getU16BE(pos + 518 + 4, &ok) != 0) {
+ return 0;
+ }
+ // subHeaders[0].idRangeOffset is a byte offset from itself
+ pos = pos + 518 + 6 + getU16BE(pos + 518 + 6, &ok);
+ gid = getU16BE(pos + 2 * c, &ok);
+ break;
+ case 4:
+ segCnt = getU16BE(pos + 6, &ok) / 2;
+ a = -1;
+ b = segCnt - 1;
+ segEnd = getU16BE(pos + 14 + 2*b, &ok);
+ if (c > segEnd) {
+ // malformed font -- the TrueType spec requires the last segEnd
+ // to be 0xffff
+ return 0;
+ }
+ // invariant: seg[a].end < code <= seg[b].end
+ while (b - a > 1 && ok) {
+ m = (a + b) / 2;
+ segEnd = getU16BE(pos + 14 + 2*m, &ok);
+ if (segEnd < c) {
+ a = m;
+ } else {
+ b = m;
+ }
+ }
+ segStart = getU16BE(pos + 16 + 2*segCnt + 2*b, &ok);
+ segDelta = getU16BE(pos + 16 + 4*segCnt + 2*b, &ok);
+ segOffset = getU16BE(pos + 16 + 6*segCnt + 2*b, &ok);
+ if (c < segStart) {
+ return 0;
+ }
+ if (segOffset == 0) {
+ gid = (c + segDelta) & 0xffff;
+ } else {
+ gid = getU16BE(pos + 16 + 6*segCnt + 2*b +
+ segOffset + 2 * (c - segStart), &ok);
+ if (gid != 0) {
+ gid = (gid + segDelta) & 0xffff;
+ }
+ }
+ break;
+ case 6:
+ cmapFirst = getU16BE(pos + 6, &ok);
+ cmapLen = getU16BE(pos + 8, &ok);
+ if (c < cmapFirst || c >= cmapFirst + cmapLen) {
+ return 0;
+ }
+ gid = getU16BE(pos + 10 + 2 * (c - cmapFirst), &ok);
+ break;
+ default:
+ return 0;
+ }
+ if (!ok) {
+ return 0;
+ }
+ return gid;
+}
+
+int FoFiTrueType::mapNameToGID(char *name) {
+ if (!nameToGID) {
+ return 0;
+ }
+ return nameToGID->lookupInt(name);
+}
+
+GBool FoFiTrueType::getCFFBlock(char **start, int *length) {
+ int i;
+
+ if (!openTypeCFF) {
+ return gFalse;
+ }
+ i = seekTable("CFF ");
+ if (!checkRegion(tables[i].offset, tables[i].len)) {
+ return gFalse;
+ }
+ *start = (char *)file + tables[i].offset;
+ *length = tables[i].len;
+ return gTrue;
+}
+
+int *FoFiTrueType::getCIDToGIDMap(int *nCIDs) {
+ char *start;
+ int length;
+ FoFiType1C *ff;
+ int *map;
+
+ *nCIDs = 0;
+ if (!getCFFBlock(&start, &length)) {
+ return NULL;
+ }
+ if (!(ff = FoFiType1C::make(start, length))) {
+ return NULL;
+ }
+ map = ff->getCIDToGIDMap(nCIDs);
+ delete ff;
+ return map;
+}
+
+int FoFiTrueType::getEmbeddingRights() {
+ int i, fsType;
+ GBool ok;
+
+ if ((i = seekTable("OS/2")) < 0) {
+ return 4;
+ }
+ ok = gTrue;
+ fsType = getU16BE(tables[i].offset + 8, &ok);
+ if (!ok) {
+ return 4;
+ }
+ if (fsType & 0x0008) {
+ return 2;
+ }
+ if (fsType & 0x0004) {
+ return 1;
+ }
+ if (fsType & 0x0002) {
+ return 0;
+ }
+ return 3;
+}
+
+void FoFiTrueType::getFontMatrix(double *mat) {
+ char *start;
+ int length;
+ FoFiType1C *ff;
+
+ if (!getCFFBlock(&start, &length)) {
+ return;
+ }
+ if (!(ff = FoFiType1C::make(start, length))) {
+ return;
+ }
+ ff->getFontMatrix(mat);
+ delete ff;
+}
+
+struct FoFiTrueTypeTrickyFont {
+ int cvtLen;
+ Guint cvtChecksum;
+ int fpgmLen;
+ Guint fpgmChecksum;
+ int prepLen;
+ Guint prepChecksum;
+};
+
+// This data was taken from the FreeType project.
+static FoFiTrueTypeTrickyFont trickyFonts[] = {
+ { 0x000002e4, 0x05bcf058, // MingLiU 1995
+ 0x000087c4, 0x28233bf1,
+ 0x000001e1, 0xa344a1ea },
+ { 0x000002e4, 0x05bcf058, // MingLiU 1996-
+ 0x000087c4, 0x28233bf1,
+ 0x000001e1, 0xa344a1eb },
+ { 0x00000350, 0x12c3ebb2, // DFGothic-EB
+ 0x000087a7, 0xb680ee64,
+ 0x00000758, 0xce939563 },
+ { 0x00000350, 0x11e5ead4, // DFGyoSho-Lt
+ 0x0000bc85, 0xce5956e9,
+ 0x00000045, 0x8272f416 },
+ { 0x00000350, 0x1262eb4e, // DFHSGothic-W5
+ 0x00007940, 0xe86a5d64,
+ 0x000005ff, 0x7850f729 },
+ { 0x00000350, 0x122deb0a, // DFHSMincho-W3
+ 0x0000859b, 0x3d16328a,
+ 0x000002cb, 0xa93fc33b },
+ { 0x00000350, 0x125feb26, // DFHSMincho-W7
+ 0x00007ee1, 0xa5acc982,
+ 0x0000041f, 0x90999196 },
+ { 0x00000350, 0x11e5ead4, // DFKaiShu
+ 0x00009063, 0x5a30ca3b,
+ 0x0000007e, 0x13a42602 },
+ { 0x00000350, 0x11e5ead4, // DFKaiShu2
+ 0x00008998, 0xa6e78c01,
+ 0x0000007e, 0x13a42602 },
+ { 0x00000008, 0xfffbfffc, // HuaTianKaiTi
+ 0x0000bea2, 0x9c9e48b8,
+ 0x00000008, 0x70020112 },
+ { 0x00000008, 0xfffbfffc, // HuaTianSongTi
+ 0x00017c39, 0x0a5a0483,
+ 0x00000008, 0x70020112 },
+ { 0x00000000, 0x00000000, // NEC fadpop7.ttf
+ 0x000000e5, 0x40c92555,
+ 0x0000117c, 0xa39b58e3 },
+ { 0x00000000, 0x00000000, // NEC fadrei5.ttf
+ 0x000000e5, 0x33c41652,
+ 0x00000f6a, 0x26d6c52a },
+ { 0x00000000, 0x00000000, // NEC fangot7.ttf
+ 0x0000019d, 0x6db1651d,
+ 0x00002492, 0x6c6e4b03 },
+ { 0x00000000, 0x00000000, // NEC fangyo5.ttf
+ 0x000000e5, 0x40c92555,
+ 0x0000117c, 0xde51fad0 },
+ { 0x00000000, 0x00000000, // NEC fankyo5.ttf
+ 0x000000e5, 0x85e47664,
+ 0x00001caa, 0xa6c62831 },
+ { 0x00000000, 0x00000000, // NEC fanrgo5.ttf
+ 0x0000019d, 0x2d891cfd,
+ 0x00001de8, 0xa0604633 },
+ { 0x00000000, 0x00000000, // NEC fangot5.ttc
+ 0x000001cb, 0x40aa774c,
+ 0x00001f9a, 0x9b5caa96 },
+ { 0x00000000, 0x00000000, // NEC fanmin3.ttc
+ 0x00000141, 0x0d3de9cb,
+ 0x00002280, 0xd4127766 },
+ { 0x00000000, 0x00000000, // NEC FA-Gothic, 1996
+ 0x000001f0, 0x4a692698,
+ 0x00001fca, 0x340d4346 },
+ { 0x00000000, 0x00000000, // NEC FA-Minchou, 1996
+ 0x00000166, 0xcd34c604,
+ 0x000022b0, 0x6cf31046 },
+ { 0x00000000, 0x00000000, // NEC FA-RoundGothicB, 1996
+ 0x0000019d, 0x5da75315,
+ 0x000022e0, 0x40745a5f },
+ { 0x00000000, 0x00000000, // NEC FA-RoundGothicM, 1996
+ 0x000001c2, 0xf055fc48,
+ 0x00001e18, 0x3900ded3 },
+ { 0x00000060, 0x00170003, // MINGLI, 1992
+ 0x000058aa, 0xdbb4306e,
+ 0x00000035, 0xd643482a }
+};
+
+#define nTrickyFonts ((int)(sizeof(trickyFonts) / sizeof(FoFiTrueTypeTrickyFont)))
+
+// This looks at the length and checksum values for the cvt, fpgm, and
+// prep tables. The theory is that those tables will be the same,
+// even if the font is renamed and/or subsetted.
+GBool FoFiTrueType::checkForTrickyCJK() {
+ int cvtIdx, fpgmIdx, prepIdx;
+ int cvtLen, fpgmLen, prepLen;
+ Guint cvtChecksum, fpgmChecksum, prepChecksum;
+ int i;
+
+ if ((cvtIdx = seekTable("cvt ")) >= 0) {
+ cvtLen = tables[cvtIdx].len;
+ cvtChecksum = tables[cvtIdx].checksum;
+ } else {
+ cvtLen = 0;
+ cvtChecksum = 0;
+ }
+ if ((fpgmIdx = seekTable("fpgm")) >= 0) {
+ fpgmLen = tables[fpgmIdx].len;
+ fpgmChecksum = tables[fpgmIdx].checksum;
+ } else {
+ fpgmLen = 0;
+ fpgmChecksum = 0;
+ }
+ if ((prepIdx = seekTable("prep")) >= 0) {
+ prepLen = tables[prepIdx].len;
+ prepChecksum = tables[prepIdx].checksum;
+ } else {
+ prepLen = 0;
+ prepChecksum = 0;
+ }
+
+ for (i = 0; i < nTrickyFonts; ++i) {
+ if (cvtLen == trickyFonts[i].cvtLen &&
+ cvtChecksum == trickyFonts[i].cvtChecksum &&
+ fpgmLen == trickyFonts[i].fpgmLen &&
+ fpgmChecksum == trickyFonts[i].fpgmChecksum &&
+ prepLen == trickyFonts[i].prepLen &&
+ prepChecksum == trickyFonts[i].prepChecksum) {
+ return gTrue;
+ }
+ }
+ return gFalse;
+}
+
+void FoFiTrueType::convertToType42(char *psName, char **encoding,
+ int *codeToGID,
+ FoFiOutputFunc outputFunc,
+ void *outputStream) {
+ GString *buf;
+ int maxUsedGlyph;
+ GBool ok;
+
+ if (openTypeCFF) {
+ return;
+ }
+
+ // write the header
+ ok = gTrue;
+ buf = GString::format("%!PS-TrueTypeFont-{0:2g}\n",
+ (double)getS32BE(0, &ok) / 65536.0);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+
+ // begin the font dictionary
+ (*outputFunc)(outputStream, "10 dict begin\n", 14);
+ (*outputFunc)(outputStream, "/FontName /", 11);
+ (*outputFunc)(outputStream, psName, (int)strlen(psName));
+ (*outputFunc)(outputStream, " def\n", 5);
+ (*outputFunc)(outputStream, "/FontType 42 def\n", 17);
+ (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
+ buf = GString::format("/FontBBox [{0:d} {1:d} {2:d} {3:d}] def\n",
+ bbox[0], bbox[1], bbox[2], bbox[3]);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ (*outputFunc)(outputStream, "/PaintType 0 def\n", 17);
+
+ // write the guts of the dictionary
+ cvtEncoding(encoding, outputFunc, outputStream);
+ cvtCharStrings(encoding, codeToGID, outputFunc, outputStream);
+ cvtSfnts(outputFunc, outputStream, NULL, gFalse, &maxUsedGlyph);
+
+ // end the dictionary and define the font
+ (*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40);
+}
+
+void FoFiTrueType::convertToType1(char *psName, const char **newEncoding,
+ GBool ascii, FoFiOutputFunc outputFunc,
+ void *outputStream) {
+ char *start;
+ int length;
+ FoFiType1C *ff;
+
+ if (!getCFFBlock(&start, &length)) {
+ return;
+ }
+ if (!(ff = FoFiType1C::make(start, length))) {
+ return;
+ }
+ ff->convertToType1(psName, newEncoding, ascii, outputFunc, outputStream);
+ delete ff;
+}
+
+void FoFiTrueType::convertToCIDType2(char *psName,
+ int *cidMap, int nCIDs,
+ GBool needVerticalMetrics,
+ FoFiOutputFunc outputFunc,
+ void *outputStream) {
+ GString *buf;
+ int cid, maxUsedGlyph;
+ GBool ok;
+ int i, j, k;
+
+ if (openTypeCFF) {
+ return;
+ }
+
+ // write the header
+ ok = gTrue;
+ buf = GString::format("%!PS-TrueTypeFont-{0:2g}\n",
+ (double)getS32BE(0, &ok) / 65536.0);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+
+ // begin the font dictionary
+ (*outputFunc)(outputStream, "20 dict begin\n", 14);
+ (*outputFunc)(outputStream, "/CIDFontName /", 14);
+ (*outputFunc)(outputStream, psName, (int)strlen(psName));
+ (*outputFunc)(outputStream, " def\n", 5);
+ (*outputFunc)(outputStream, "/CIDFontType 2 def\n", 19);
+ (*outputFunc)(outputStream, "/FontType 42 def\n", 17);
+ (*outputFunc)(outputStream, "/CIDSystemInfo 3 dict dup begin\n", 32);
+ (*outputFunc)(outputStream, " /Registry (Adobe) def\n", 24);
+ (*outputFunc)(outputStream, " /Ordering (Identity) def\n", 27);
+ (*outputFunc)(outputStream, " /Supplement 0 def\n", 20);
+ (*outputFunc)(outputStream, " end def\n", 10);
+ (*outputFunc)(outputStream, "/GDBytes 2 def\n", 15);
+ if (cidMap) {
+ buf = GString::format("/CIDCount {0:d} def\n", nCIDs);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ if (nCIDs > 32767) {
+ (*outputFunc)(outputStream, "/CIDMap [", 9);
+ for (i = 0; i < nCIDs; i += 32768 - 16) {
+ (*outputFunc)(outputStream, "<\n", 2);
+ for (j = 0; j < 32768 - 16 && i+j < nCIDs; j += 16) {
+ (*outputFunc)(outputStream, " ", 2);
+ for (k = 0; k < 16 && i+j+k < nCIDs; ++k) {
+ cid = cidMap[i+j+k];
+ buf = GString::format("{0:02x}{1:02x}",
+ (cid >> 8) & 0xff, cid & 0xff);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ }
+ (*outputFunc)(outputStream, "\n", 1);
+ }
+ (*outputFunc)(outputStream, " >", 3);
+ }
+ (*outputFunc)(outputStream, "\n", 1);
+ (*outputFunc)(outputStream, "] def\n", 6);
+ } else {
+ (*outputFunc)(outputStream, "/CIDMap <\n", 10);
+ for (i = 0; i < nCIDs; i += 16) {
+ (*outputFunc)(outputStream, " ", 2);
+ for (j = 0; j < 16 && i+j < nCIDs; ++j) {
+ cid = cidMap[i+j];
+ buf = GString::format("{0:02x}{1:02x}",
+ (cid >> 8) & 0xff, cid & 0xff);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ }
+ (*outputFunc)(outputStream, "\n", 1);
+ }
+ (*outputFunc)(outputStream, "> def\n", 6);
+ }
+ } else {
+ // direct mapping - just fill the string(s) with s[i]=i
+ buf = GString::format("/CIDCount {0:d} def\n", nGlyphs);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ if (nGlyphs > 32767) {
+ (*outputFunc)(outputStream, "/CIDMap [\n", 10);
+ for (i = 0; i < nGlyphs; i += 32767) {
+ j = nGlyphs - i < 32767 ? nGlyphs - i : 32767;
+ buf = GString::format(" {0:d} string 0 1 {1:d} {{\n", 2 * j, j - 1);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ buf = GString::format(" 2 copy dup 2 mul exch {0:d} add -8 bitshift put\n",
+ i);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ buf = GString::format(" 1 index exch dup 2 mul 1 add exch {0:d} add"
+ " 255 and put\n", i);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ (*outputFunc)(outputStream, " } for\n", 8);
+ }
+ (*outputFunc)(outputStream, "] def\n", 6);
+ } else {
+ buf = GString::format("/CIDMap {0:d} string\n", 2 * nGlyphs);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ buf = GString::format(" 0 1 {0:d} {{\n", nGlyphs - 1);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ (*outputFunc)(outputStream,
+ " 2 copy dup 2 mul exch -8 bitshift put\n", 42);
+ (*outputFunc)(outputStream,
+ " 1 index exch dup 2 mul 1 add exch 255 and put\n", 50);
+ (*outputFunc)(outputStream, " } for\n", 8);
+ (*outputFunc)(outputStream, "def\n", 4);
+ }
+ }
+ (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
+ buf = GString::format("/FontBBox [{0:d} {1:d} {2:d} {3:d}] def\n",
+ bbox[0], bbox[1], bbox[2], bbox[3]);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ (*outputFunc)(outputStream, "/PaintType 0 def\n", 17);
+ (*outputFunc)(outputStream, "/Encoding [] readonly def\n", 26);
+ (*outputFunc)(outputStream, "/CharStrings 1 dict dup begin\n", 30);
+ (*outputFunc)(outputStream, " /.notdef 0 def\n", 17);
+ (*outputFunc)(outputStream, " end readonly def\n", 19);
+
+ // write the guts of the dictionary
+ cvtSfnts(outputFunc, outputStream, NULL, needVerticalMetrics, &maxUsedGlyph);
+
+ // end the dictionary and define the font
+ (*outputFunc)(outputStream,
+ "CIDFontName currentdict end /CIDFont defineresource pop\n",
+ 56);
+}
+
+void FoFiTrueType::convertToCIDType0(char *psName, int *cidMap, int nCIDs,
+ FoFiOutputFunc outputFunc,
+ void *outputStream) {
+ char *start;
+ int length;
+ FoFiType1C *ff;
+
+ if (!getCFFBlock(&start, &length)) {
+ return;
+ }
+ if (!(ff = FoFiType1C::make(start, length))) {
+ return;
+ }
+ ff->convertToCIDType0(psName, cidMap, nCIDs, outputFunc, outputStream);
+ delete ff;
+}
+
+void FoFiTrueType::convertToType0(char *psName, int *cidMap, int nCIDs,
+ GBool needVerticalMetrics,
+ FoFiOutputFunc outputFunc,
+ void *outputStream) {
+ GString *buf;
+ GString *sfntsName;
+ int maxUsedGlyph, n, i, j;
+
+ if (openTypeCFF) {
+ return;
+ }
+
+ // write the Type 42 sfnts array
+ sfntsName = (new GString(psName))->append("_sfnts");
+ cvtSfnts(outputFunc, outputStream, sfntsName, needVerticalMetrics,
+ &maxUsedGlyph);
+ delete sfntsName;
+
+ // write the descendant Type 42 fonts
+ // (The following is a kludge: nGlyphs is the glyph count from the
+ // maxp table; maxUsedGlyph is the max glyph number that has a
+ // non-zero-length description, from the loca table. The problem is
+ // that some TrueType font subsets fail to change the glyph count,
+ // i.e., nGlyphs is much larger than maxUsedGlyph+1, which results
+ // in an unnecessarily huge Type 0 font. But some other PDF files
+ // have fonts with only zero or one used glyph, and a content stream
+ // that refers to one of the unused glyphs -- this results in PS
+ // errors if we simply use maxUsedGlyph+1 for the Type 0 font. So
+ // we compromise by always defining at least 256 glyphs.)
+ if (cidMap) {
+ n = nCIDs;
+ } else if (nGlyphs > maxUsedGlyph + 256) {
+ if (maxUsedGlyph <= 255) {
+ n = 256;
+ } else {
+ n = maxUsedGlyph + 1;
+ }
+ } else {
+ n = nGlyphs;
+ }
+ for (i = 0; i < n; i += 256) {
+ (*outputFunc)(outputStream, "10 dict begin\n", 14);
+ (*outputFunc)(outputStream, "/FontName /", 11);
+ (*outputFunc)(outputStream, psName, (int)strlen(psName));
+ buf = GString::format("_{0:02x} def\n", i >> 8);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ (*outputFunc)(outputStream, "/FontType 42 def\n", 17);
+ (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
+ buf = GString::format("/FontBBox [{0:d} {1:d} {2:d} {3:d}] def\n",
+ bbox[0], bbox[1], bbox[2], bbox[3]);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ (*outputFunc)(outputStream, "/PaintType 0 def\n", 17);
+ (*outputFunc)(outputStream, "/sfnts ", 7);
+ (*outputFunc)(outputStream, psName, (int)strlen(psName));
+ (*outputFunc)(outputStream, "_sfnts def\n", 11);
+ (*outputFunc)(outputStream, "/Encoding 256 array\n", 20);
+ for (j = 0; j < 256 && i+j < n; ++j) {
+ buf = GString::format("dup {0:d} /c{1:02x} put\n", j, j);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ }
+ (*outputFunc)(outputStream, "readonly def\n", 13);
+ (*outputFunc)(outputStream, "/CharStrings 257 dict dup begin\n", 32);
+ (*outputFunc)(outputStream, "/.notdef 0 def\n", 15);
+ for (j = 0; j < 256 && i+j < n; ++j) {
+ buf = GString::format("/c{0:02x} {1:d} def\n",
+ j, cidMap ? cidMap[i+j] : i+j);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ }
+ (*outputFunc)(outputStream, "end readonly def\n", 17);
+ (*outputFunc)(outputStream,
+ "FontName currentdict end definefont pop\n", 40);
+ }
+
+ // write the Type 0 parent font
+ (*outputFunc)(outputStream, "16 dict begin\n", 14);
+ (*outputFunc)(outputStream, "/FontName /", 11);
+ (*outputFunc)(outputStream, psName, (int)strlen(psName));
+ (*outputFunc)(outputStream, " def\n", 5);
+ (*outputFunc)(outputStream, "/FontType 0 def\n", 16);
+ (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
+ (*outputFunc)(outputStream, "/FMapType 2 def\n", 16);
+ (*outputFunc)(outputStream, "/Encoding [\n", 12);
+ for (i = 0; i < n; i += 256) {
+ buf = GString::format("{0:d}\n", i >> 8);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ }
+ (*outputFunc)(outputStream, "] def\n", 6);
+ (*outputFunc)(outputStream, "/FDepVector [\n", 14);
+ for (i = 0; i < n; i += 256) {
+ (*outputFunc)(outputStream, "/", 1);
+ (*outputFunc)(outputStream, psName, (int)strlen(psName));
+ buf = GString::format("_{0:02x} findfont\n", i >> 8);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ }
+ (*outputFunc)(outputStream, "] def\n", 6);
+ (*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40);
+}
+
+void FoFiTrueType::convertToType0(char *psName, int *cidMap, int nCIDs,
+ FoFiOutputFunc outputFunc,
+ void *outputStream) {
+ char *start;
+ int length;
+ FoFiType1C *ff;
+
+ if (!getCFFBlock(&start, &length)) {
+ return;
+ }
+ if (!(ff = FoFiType1C::make(start, length))) {
+ return;
+ }
+ ff->convertToType0(psName, cidMap, nCIDs, outputFunc, outputStream);
+ delete ff;
+}
+
+GBool FoFiTrueType::writeTTF(FoFiOutputFunc outputFunc,
+ void *outputStream, char *name,
+ int *codeToGID, Guchar *replacementCmapTable,
+ int replacementCmapTableLen) {
+ // this substitute cmap table maps char code ffff to glyph 0,
+ // with tables for MacRoman and MS Unicode
+ static char cmapTab[44] = {
+ 0, 0, // table version number
+ 0, 2, // number of encoding tables
+ 0, 1, // platform ID
+ 0, 0, // encoding ID
+ 0, 0, 0, 20, // offset of subtable
+ 0, 3, // platform ID
+ 0, 1, // encoding ID
+ 0, 0, 0, 20, // offset of subtable
+ 0, 4, // subtable format
+ 0, 24, // subtable length
+ 0, 0, // subtable version
+ 0, 2, // segment count * 2
+ 0, 2, // 2 * 2 ^ floor(log2(segCount))
+ 0, 0, // floor(log2(segCount))
+ 0, 0, // 2*segCount - 2*2^floor(log2(segCount))
+ (char)0xff, (char)0xff, // endCount[0]
+ 0, 0, // reserved
+ (char)0xff, (char)0xff, // startCount[0]
+ 0, 1, // idDelta[0]
+ 0, 0 // idRangeOffset[0]
+ };
+ static char nameTab[8] = {
+ 0, 0, // format
+ 0, 0, // number of name records
+ 0, 6, // offset to start of string storage
+ 0, 0 // pad to multiple of four bytes
+ };
+ static char postTab[32] = {
+ 0, 1, 0, 0, // format
+ 0, 0, 0, 0, // italic angle
+ 0, 0, // underline position
+ 0, 0, // underline thickness
+ 0, 0, 0, 0, // fixed pitch
+ 0, 0, 0, 0, // min Type 42 memory
+ 0, 0, 0, 0, // max Type 42 memory
+ 0, 0, 0, 0, // min Type 1 memory
+ 0, 0, 0, 0 // max Type 1 memory
+ };
+ static char os2Tab[86] = {
+ 0, 1, // version
+ 0, 1, // xAvgCharWidth
+ 0x01, (char)0x90, // usWeightClass
+ 0, 5, // usWidthClass
+ 0, 0, // fsType
+ 0, 0, // ySubscriptXSize
+ 0, 0, // ySubscriptYSize
+ 0, 0, // ySubscriptXOffset
+ 0, 0, // ySubscriptYOffset
+ 0, 0, // ySuperscriptXSize
+ 0, 0, // ySuperscriptYSize
+ 0, 0, // ySuperscriptXOffset
+ 0, 0, // ySuperscriptYOffset
+ 0, 0, // yStrikeoutSize
+ 0, 0, // yStrikeoutPosition
+ 0, 0, // sFamilyClass
+ 0, 0, 0, 0, 0, // panose
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, // ulUnicodeRange1
+ 0, 0, 0, 0, // ulUnicodeRange2
+ 0, 0, 0, 0, // ulUnicodeRange3
+ 0, 0, 0, 0, // ulUnicodeRange4
+ 0, 0, 0, 0, // achVendID
+ 0, 0, // fsSelection
+ 0, 0, // usFirstCharIndex
+ 0, 0, // usLastCharIndex
+ 0, 0, // sTypoAscender
+ 0, 0, // sTypoDescender
+ 0, 0, // sTypoLineGap
+ 0x20, 0x00, // usWinAscent
+ 0x20, 0x00, // usWinDescent
+ 0, 0, 0, 1, // ulCodePageRange1
+ 0, 0, 0, 0 // ulCodePageRange2
+ };
+ GBool missingCmap, missingName, missingPost, missingOS2;
+ GBool unsortedLoca, emptyCmap, badCmapLen, abbrevHMTX;
+ int nZeroLengthTables, nBogusTables;
+ int nHMetrics, advWidth, lsb;
+ TrueTypeLoca *locaTable;
+ TrueTypeTable *newTables;
+ char *newNameTab, *newCmapTab, *newHHEATab, *newHMTXTab;
+ int nNewTables, cmapIdx, cmapLen, glyfLen, newNameLen, newCmapLen, next;
+ int newHHEALen, newHMTXLen;
+ Guint locaChecksum, glyfChecksum, fileChecksum;
+ char *tableDir;
+ char locaBuf[4], checksumBuf[4];
+ GBool ok;
+ Guint t;
+ int pos, i, j, k, n;
+
+ if (openTypeCFF) {
+ return gFalse;
+ }
+
+ // check for missing tables
+ // (Note: if the OS/2 table is missing, the Microsoft PCL5 driver
+ // will embed a PCL TrueType font with the pitch field set to zero,
+ // which apparently causes divide-by-zero errors. As far as I can
+ // tell, the only important field in the OS/2 table is
+ // xAvgCharWidth.)
+ missingCmap = (cmapIdx = seekTable("cmap")) < 0;
+ missingName = seekTable("name") < 0;
+ missingPost = seekTable("post") < 0;
+ missingOS2 = seekTable("OS/2") < 0;
+
+ // read the loca table, check to see if it's sorted
+ locaTable = (TrueTypeLoca *)gmallocn(nGlyphs + 1, sizeof(TrueTypeLoca));
+ unsortedLoca = gFalse;
+ i = seekTable("loca");
+ pos = tables[i].offset;
+ glyfLen = tables[seekTable("glyf")].len;
+ ok = gTrue;
+ for (i = 0; i <= nGlyphs; ++i) {
+ if (locaFmt) {
+ locaTable[i].origOffset = (int)getU32BE(pos + i*4, &ok);
+ } else {
+ locaTable[i].origOffset = 2 * getU16BE(pos + i*2, &ok);
+ }
+ if (locaTable[i].origOffset < 0 ||
+ locaTable[i].origOffset > glyfLen) {
+ locaTable[i].origOffset = glyfLen;
+ unsortedLoca = gTrue;
+ }
+ if (i > 0 && locaTable[i].origOffset < locaTable[i-1].origOffset) {
+ unsortedLoca = gTrue;
+ }
+ // glyph descriptions must be at least 12 bytes long (nContours,
+ // xMin, yMin, xMax, yMax, instructionLength - two bytes each);
+ // invalid glyph descriptions (even if they're never used) make
+ // Windows choke, so we work around that problem here (ideally,
+ // this would parse the glyph descriptions in the glyf table and
+ // remove any that were invalid, but this quick test is a decent
+ // start)
+ if (i > 0 &&
+ locaTable[i].origOffset - locaTable[i-1].origOffset > 0 &&
+ locaTable[i].origOffset - locaTable[i-1].origOffset < 12) {
+ locaTable[i-1].origOffset = locaTable[i].origOffset;
+ unsortedLoca = gTrue;
+ }
+ locaTable[i].idx = i;
+ }
+
+ // check for zero-length tables and bogus tags
+ nZeroLengthTables = nBogusTables = 0;
+ for (i = 0; i < nTables; ++i) {
+ if (tables[i].len == 0) {
+ ++nZeroLengthTables;
+ if (tables[i].tag == cmapTag) {
+ missingCmap = gTrue;
+ } else if (tables[i].tag == nameTag) {
+ missingName = gTrue;
+ } else if (tables[i].tag == postTag) {
+ missingPost = gTrue;
+ } else if (tables[i].tag == os2Tag) {
+ missingOS2 = gTrue;
+ }
+ } else if (!(tables[i].tag & 0xe0000000) ||
+ !(tables[i].tag & 0x00e00000) ||
+ !(tables[i].tag & 0x0000e000) ||
+ !(tables[i].tag & 0x000000e0)) {
+ // tags where any of the bytes are < 0x20 are probably bogus
+ // (the TrueType spec uses ASCII sequences for tags) -- this
+ // catches problems where the number of tables given in the
+ // header is too large, and so gibberish data is read at the end
+ // of the table directory
+ ++nBogusTables;
+ }
+ }
+
+ // check for an empty cmap table or an incorrect cmap table length
+ emptyCmap = badCmapLen = gFalse;
+ cmapLen = 0; // make gcc happy
+ if (!missingCmap) {
+ if (nCmaps == 0) {
+ emptyCmap = gTrue;
+ } else {
+ cmapLen = cmaps[0].offset + cmaps[0].len;
+ for (i = 1; i < nCmaps; ++i) {
+ if (cmaps[i].offset + cmaps[i].len > cmapLen) {
+ cmapLen = cmaps[i].offset + cmaps[i].len;
+ }
+ }
+ cmapLen -= tables[cmapIdx].offset;
+ if (cmapLen > tables[cmapIdx].len) {
+ badCmapLen = gTrue;
+ }
+ }
+ }
+
+ // check for an abbreviated hmtx table (this is completely legal,
+ // but confuses the Microsoft PCL5 printer driver, which generates
+ // embedded fonts with the pitch field set to zero)
+ i = seekTable("hhea");
+ nHMetrics = getU16BE(tables[i].offset + 34, &ok);
+ abbrevHMTX = nHMetrics < nGlyphs;
+
+ // if nothing is broken, just write the TTF file as is
+ if (!missingCmap && !missingName && !missingPost && !missingOS2 &&
+ !unsortedLoca && !emptyCmap && !badCmapLen && !abbrevHMTX &&
+ nZeroLengthTables == 0 && nBogusTables == 0 &&
+ !name && !codeToGID && !replacementCmapTable && !isDfont && !isTTC) {
+ (*outputFunc)(outputStream, (char *)file, len);
+ gfree(locaTable);
+ return gFalse;
+ }
+
+ // sort the 'loca' table: some (non-compliant) fonts have
+ // out-of-order loca tables; in order to correctly handle the case
+ // where (compliant) fonts have empty entries in the middle of the
+ // table, cmpTrueTypeLocaOffset uses offset as its primary sort key,
+ // and idx as its secondary key (ensuring that adjacent entries with
+ // the same pos value remain in the same order)
+ glyfLen = 0; // make gcc happy
+ if (unsortedLoca) {
+#if HAVE_STD_SORT
+ std::sort(locaTable, locaTable + nGlyphs + 1,
+ cmpTrueTypeLocaOffsetFunctor());
+#else
+ qsort(locaTable, nGlyphs + 1, sizeof(TrueTypeLoca),
+ &cmpTrueTypeLocaOffset);
+#endif
+ for (i = 0; i < nGlyphs; ++i) {
+ locaTable[i].len = locaTable[i+1].origOffset - locaTable[i].origOffset;
+ }
+ locaTable[nGlyphs].len = 0;
+#if HAVE_STD_SORT
+ std::sort(locaTable, locaTable + nGlyphs + 1, cmpTrueTypeLocaIdxFunctor());
+#else
+ qsort(locaTable, nGlyphs + 1, sizeof(TrueTypeLoca),
+ &cmpTrueTypeLocaIdx);
+#endif
+ // if the last entry in the loca is not the max offset (size of
+ // the glyf table), something is wrong -- work around the problem
+ // by forcing the last sorted entry to have a zero length
+ locaTable[nGlyphs].len = 0;
+ pos = 0;
+ for (i = 0; i <= nGlyphs; ++i) {
+ locaTable[i].newOffset = pos;
+ pos += locaTable[i].len;
+ if (pos & 3) {
+ pos += 4 - (pos & 3);
+ }
+ }
+ glyfLen = pos;
+ }
+
+ // compute checksums for the loca and glyf tables
+ locaChecksum = glyfChecksum = 0;
+ if (unsortedLoca) {
+ if (locaFmt) {
+ for (j = 0; j <= nGlyphs; ++j) {
+ locaChecksum += locaTable[j].newOffset;
+ }
+ } else {
+ for (j = 0; j <= nGlyphs; j += 2) {
+ locaChecksum += locaTable[j].newOffset << 16;
+ if (j + 1 <= nGlyphs) {
+ locaChecksum += locaTable[j+1].newOffset;
+ }
+ }
+ }
+ pos = tables[seekTable("glyf")].offset;
+ for (j = 0; j < nGlyphs; ++j) {
+ n = locaTable[j].len;
+ if (n > 0) {
+ k = locaTable[j].origOffset;
+ if (checkRegion(pos + k, n)) {
+ glyfChecksum += computeTableChecksum(file + pos + k, n);
+ }
+ }
+ }
+ }
+
+ // construct the new name table
+ if (name) {
+ n = (int)strlen(name);
+ newNameLen = (6 + 4*12 + 2 * (3*n + 7) + 3) & ~3;
+ newNameTab = (char *)gmalloc(newNameLen);
+ memset(newNameTab, 0, newNameLen);
+ newNameTab[0] = 0; // format selector
+ newNameTab[1] = 0;
+ newNameTab[2] = 0; // number of name records
+ newNameTab[3] = 4;
+ newNameTab[4] = 0; // offset to start of string storage
+ newNameTab[5] = 6 + 4*12;
+ next = 0;
+ for (i = 0; i < 4; ++i) {
+ newNameTab[6 + i*12 + 0] = 0; // platform ID = Microsoft
+ newNameTab[6 + i*12 + 1] = 3;
+ newNameTab[6 + i*12 + 2] = 0; // encoding ID = Unicode
+ newNameTab[6 + i*12 + 3] = 1;
+ newNameTab[6 + i*12 + 4] = 0x04; // language ID = American English
+ newNameTab[6 + i*12 + 5] = 0x09;
+ newNameTab[6 + i*12 + 6] = 0; // name ID
+ newNameTab[6 + i*12 + 7] = (char)(i + 1);
+ // string length
+ newNameTab[6 + i*12 + 8] = (char)(i+1 == 2 ? 0 : ((2*n) >> 8));
+ newNameTab[6 + i*12 + 9] = (char)(i+1 == 2 ? 14 : ((2*n) & 0xff));
+ // string offset
+ newNameTab[6 + i*12 + 10] = (char)(next >> 8);
+ newNameTab[6 + i*12 + 11] = (char)(next & 0xff);
+ if (i+1 == 2) {
+ memcpy(newNameTab + 6 + 4*12 + next, "\0R\0e\0g\0u\0l\0a\0r", 14);
+ next += 14;
+ } else {
+ for (j = 0; j < n; ++j) {
+ newNameTab[6 + 4*12 + next + 2*j] = 0;
+ newNameTab[6 + 4*12 + next + 2*j + 1] = name[j];
+ }
+ next += 2*n;
+ }
+ }
+ } else {
+ newNameLen = 0;
+ newNameTab = NULL;
+ }
+
+ // construct the new cmap table
+ if (codeToGID && !replacementCmapTable) {
+ newCmapLen = 44 + 256 * 2;
+ newCmapTab = (char *)gmalloc(newCmapLen);
+ newCmapTab[0] = 0; // table version number = 0
+ newCmapTab[1] = 0;
+ newCmapTab[2] = 0; // number of encoding tables = 1
+ newCmapTab[3] = 1;
+ newCmapTab[4] = 0; // platform ID = Microsoft
+ newCmapTab[5] = 3;
+ newCmapTab[6] = 0; // encoding ID = Unicode
+ newCmapTab[7] = 1;
+ newCmapTab[8] = 0; // offset of subtable
+ newCmapTab[9] = 0;
+ newCmapTab[10] = 0;
+ newCmapTab[11] = 12;
+ newCmapTab[12] = 0; // subtable format = 4
+ newCmapTab[13] = 4;
+ newCmapTab[14] = 0x02; // subtable length
+ newCmapTab[15] = 0x20;
+ newCmapTab[16] = 0; // subtable version = 0
+ newCmapTab[17] = 0;
+ newCmapTab[18] = 0; // segment count * 2
+ newCmapTab[19] = 4;
+ newCmapTab[20] = 0; // 2 * 2 ^ floor(log2(segCount))
+ newCmapTab[21] = 4;
+ newCmapTab[22] = 0; // floor(log2(segCount))
+ newCmapTab[23] = 1;
+ newCmapTab[24] = 0; // 2*segCount - 2*2^floor(log2(segCount))
+ newCmapTab[25] = 0;
+ newCmapTab[26] = 0x00; // endCount[0]
+ newCmapTab[27] = (char)0xff;
+ newCmapTab[28] = (char)0xff; // endCount[1]
+ newCmapTab[29] = (char)0xff;
+ newCmapTab[30] = 0; // reserved
+ newCmapTab[31] = 0;
+ newCmapTab[32] = 0x00; // startCount[0]
+ newCmapTab[33] = 0x00;
+ newCmapTab[34] = (char)0xff; // startCount[1]
+ newCmapTab[35] = (char)0xff;
+ newCmapTab[36] = 0; // idDelta[0]
+ newCmapTab[37] = 0;
+ newCmapTab[38] = 0; // idDelta[1]
+ newCmapTab[39] = 1;
+ newCmapTab[40] = 0; // idRangeOffset[0]
+ newCmapTab[41] = 4;
+ newCmapTab[42] = 0; // idRangeOffset[1]
+ newCmapTab[43] = 0;
+ for (i = 0; i < 256; ++i) {
+ if (codeToGID[i] < 0) {
+ //~ this may not be correct - we want this character to never be
+ //~ displayed, but mapping it to the notdef glyph may result in
+ //~ little boxes being displayed
+ newCmapTab[44 + 2*i] = 0;
+ newCmapTab[44 + 2*i + 1] = 0;
+ } else {
+ newCmapTab[44 + 2*i] = (char)(codeToGID[i] >> 8);
+ newCmapTab[44 + 2*i + 1] = (char)(codeToGID[i] & 0xff);
+ }
+ }
+ } else {
+ newCmapLen = 0;
+ newCmapTab = NULL;
+ }
+
+ // generate the new hmtx table and the updated hhea table
+ if (abbrevHMTX) {
+ i = seekTable("hhea");
+ pos = tables[i].offset;
+ newHHEALen = 36;
+ newHHEATab = (char *)gmalloc(newHHEALen);
+ for (i = 0; i < newHHEALen; ++i) {
+ newHHEATab[i] = (char)getU8(pos++, &ok);
+ }
+ newHHEATab[34] = (char)(nGlyphs >> 8);
+ newHHEATab[35] = (char)(nGlyphs & 0xff);
+ i = seekTable("hmtx");
+ pos = tables[i].offset;
+ newHMTXLen = 4 * nGlyphs;
+ newHMTXTab = (char *)gmalloc(newHMTXLen);
+ advWidth = 0;
+ for (i = 0; i < nHMetrics; ++i) {
+ advWidth = getU16BE(pos, &ok);
+ lsb = getU16BE(pos + 2, &ok);
+ pos += 4;
+ newHMTXTab[4*i ] = (char)(advWidth >> 8);
+ newHMTXTab[4*i + 1] = (char)(advWidth & 0xff);
+ newHMTXTab[4*i + 2] = (char)(lsb >> 8);
+ newHMTXTab[4*i + 3] = (char)(lsb & 0xff);
+ }
+ for (; i < nGlyphs; ++i) {
+ lsb = getU16BE(pos, &ok);
+ pos += 2;
+ newHMTXTab[4*i ] = (char)(advWidth >> 8);
+ newHMTXTab[4*i + 1] = (char)(advWidth & 0xff);
+ newHMTXTab[4*i + 2] = (char)(lsb >> 8);
+ newHMTXTab[4*i + 3] = (char)(lsb & 0xff);
+ }
+ } else {
+ newHHEATab = newHMTXTab = NULL;
+ newHHEALen = newHMTXLen = 0; // make gcc happy
+ }
+
+ // construct the new table directory:
+ // - keep all original tables with non-zero length
+ // - fix the cmap table's length, if necessary
+ // - add missing tables
+ // - sort the table by tag
+ // - compute new table positions, including 4-byte alignment
+ // - (re)compute table checksums
+ nNewTables = nTables - nZeroLengthTables - nBogusTables +
+ (missingCmap ? 1 : 0) + (missingName ? 1 : 0) +
+ (missingPost ? 1 : 0) + (missingOS2 ? 1 : 0);
+ newTables = (TrueTypeTable *)gmallocn(nNewTables, sizeof(TrueTypeTable));
+ j = 0;
+ for (i = 0; i < nTables; ++i) {
+ if (tables[i].len > 0 &&
+ (tables[i].tag & 0xe0000000) &&
+ (tables[i].tag & 0x00e00000) &&
+ (tables[i].tag & 0x0000e000) &&
+ (tables[i].tag & 0x000000e0)) {
+ newTables[j] = tables[i];
+ newTables[j].origOffset = tables[i].offset;
+ if (checkRegion(tables[i].offset, tables[i].len)) {
+ newTables[j].checksum =
+ computeTableChecksum(file + tables[i].offset, tables[i].len);
+ if (tables[i].tag == headTag) {
+ // don't include the file checksum
+ newTables[j].checksum -= getU32BE(tables[i].offset + 8, &ok);
+ }
+ } else {
+ // we'll write four zero bytes for this table
+ newTables[j].len = 4;
+ }
+ if (newTables[j].tag == cmapTag && replacementCmapTable) {
+ newTables[j].len = replacementCmapTableLen;
+ newTables[j].checksum = computeTableChecksum(replacementCmapTable,
+ replacementCmapTableLen);
+ } else if (newTables[j].tag == cmapTag && codeToGID) {
+ newTables[j].len = newCmapLen;
+ newTables[j].checksum = computeTableChecksum((Guchar *)newCmapTab,
+ newCmapLen);
+ } else if (newTables[j].tag == cmapTag && emptyCmap) {
+ newTables[j].checksum = computeTableChecksum((Guchar *)cmapTab,
+ sizeof(cmapTab));
+ newTables[j].len = sizeof(cmapTab);
+ } else if (newTables[j].tag == cmapTag && badCmapLen) {
+ newTables[j].len = cmapLen;
+ } else if (newTables[j].tag == locaTag && unsortedLoca) {
+ newTables[j].len = (nGlyphs + 1) * (locaFmt ? 4 : 2);
+ newTables[j].checksum = locaChecksum;
+ } else if (newTables[j].tag == glyfTag && unsortedLoca) {
+ newTables[j].len = glyfLen;
+ newTables[j].checksum = glyfChecksum;
+ } else if (newTables[j].tag == nameTag && name) {
+ newTables[j].len = newNameLen;
+ newTables[j].checksum = computeTableChecksum((Guchar *)newNameTab,
+ newNameLen);
+ } else if (newTables[j].tag == hheaTag && abbrevHMTX) {
+ newTables[j].len = newHHEALen;
+ newTables[j].checksum = computeTableChecksum((Guchar *)newHHEATab,
+ newHHEALen);
+ } else if (newTables[j].tag == hmtxTag && abbrevHMTX) {
+ newTables[j].len = newHMTXLen;
+ newTables[j].checksum = computeTableChecksum((Guchar *)newHMTXTab,
+ newHMTXLen);
+ }
+ ++j;
+ }
+ }
+ if (missingCmap) {
+ newTables[j].tag = cmapTag;
+ if (replacementCmapTable) {
+ newTables[j].checksum = computeTableChecksum(replacementCmapTable,
+ replacementCmapTableLen);
+ newTables[j].len = replacementCmapTableLen;
+ } else if (codeToGID) {
+ newTables[j].checksum = computeTableChecksum((Guchar *)newCmapTab,
+ newCmapLen);
+ newTables[j].len = newCmapLen;
+ } else {
+ newTables[j].checksum = computeTableChecksum((Guchar *)cmapTab,
+ sizeof(cmapTab));
+ newTables[j].len = sizeof(cmapTab);
+ }
+ ++j;
+ }
+ if (missingName) {
+ newTables[j].tag = nameTag;
+ if (name) {
+ newTables[j].checksum = computeTableChecksum((Guchar *)newNameTab,
+ newNameLen);
+ newTables[j].len = newNameLen;
+ } else {
+ newTables[j].checksum = computeTableChecksum((Guchar *)nameTab,
+ sizeof(nameTab));
+ newTables[j].len = sizeof(nameTab);
+ }
+ ++j;
+ }
+ if (missingPost) {
+ newTables[j].tag = postTag;
+ newTables[j].checksum = computeTableChecksum((Guchar *)postTab,
+ sizeof(postTab));
+ newTables[j].len = sizeof(postTab);
+ ++j;
+ }
+ if (missingOS2) {
+ newTables[j].tag = os2Tag;
+ newTables[j].checksum = computeTableChecksum((Guchar *)os2Tab,
+ sizeof(os2Tab));
+ newTables[j].len = sizeof(os2Tab);
+ ++j;
+ }
+#if HAVE_STD_SORT
+ std::sort(newTables, newTables + nNewTables, cmpTrueTypeTableTagFunctor());
+#else
+ qsort(newTables, nNewTables, sizeof(TrueTypeTable),
+ &cmpTrueTypeTableTag);
+#endif
+ pos = 12 + nNewTables * 16;
+ for (i = 0; i < nNewTables; ++i) {
+ newTables[i].offset = pos;
+ pos += newTables[i].len;
+ if (pos & 3) {
+ pos += 4 - (pos & 3);
+ }
+ }
+
+ // write the table directory
+ tableDir = (char *)gmalloc(12 + nNewTables * 16);
+ tableDir[0] = 0x00; // sfnt version
+ tableDir[1] = 0x01;
+ tableDir[2] = 0x00;
+ tableDir[3] = 0x00;
+ tableDir[4] = (char)((nNewTables >> 8) & 0xff); // numTables
+ tableDir[5] = (char)(nNewTables & 0xff);
+ for (i = -1, t = (Guint)nNewTables; t; ++i, t >>= 1) ;
+ t = 1 << (4 + i);
+ tableDir[6] = (char)((t >> 8) & 0xff); // searchRange
+ tableDir[7] = (char)(t & 0xff);
+ tableDir[8] = (char)((i >> 8) & 0xff); // entrySelector
+ tableDir[9] = (char)(i & 0xff);
+ t = nNewTables * 16 - t;
+ tableDir[10] = (char)((t >> 8) & 0xff); // rangeShift
+ tableDir[11] = (char)(t & 0xff);
+ pos = 12;
+ for (i = 0; i < nNewTables; ++i) {
+ tableDir[pos ] = (char)(newTables[i].tag >> 24);
+ tableDir[pos+ 1] = (char)(newTables[i].tag >> 16);
+ tableDir[pos+ 2] = (char)(newTables[i].tag >> 8);
+ tableDir[pos+ 3] = (char) newTables[i].tag;
+ tableDir[pos+ 4] = (char)(newTables[i].checksum >> 24);
+ tableDir[pos+ 5] = (char)(newTables[i].checksum >> 16);
+ tableDir[pos+ 6] = (char)(newTables[i].checksum >> 8);
+ tableDir[pos+ 7] = (char) newTables[i].checksum;
+ tableDir[pos+ 8] = (char)(newTables[i].offset >> 24);
+ tableDir[pos+ 9] = (char)(newTables[i].offset >> 16);
+ tableDir[pos+10] = (char)(newTables[i].offset >> 8);
+ tableDir[pos+11] = (char) newTables[i].offset;
+ tableDir[pos+12] = (char)(newTables[i].len >> 24);
+ tableDir[pos+13] = (char)(newTables[i].len >> 16);
+ tableDir[pos+14] = (char)(newTables[i].len >> 8);
+ tableDir[pos+15] = (char) newTables[i].len;
+ pos += 16;
+ }
+ (*outputFunc)(outputStream, tableDir, 12 + nNewTables * 16);
+
+ // compute the file checksum
+ fileChecksum = computeTableChecksum((Guchar *)tableDir,
+ 12 + nNewTables * 16);
+ for (i = 0; i < nNewTables; ++i) {
+ fileChecksum += newTables[i].checksum;
+ }
+ fileChecksum = 0xb1b0afba - fileChecksum;
+
+ // write the tables
+ for (i = 0; i < nNewTables; ++i) {
+ if (newTables[i].tag == headTag) {
+ if (checkRegion(newTables[i].origOffset, newTables[i].len)) {
+ (*outputFunc)(outputStream, (char *)file + newTables[i].origOffset, 8);
+ checksumBuf[0] = (char)(fileChecksum >> 24);
+ checksumBuf[1] = (char)(fileChecksum >> 16);
+ checksumBuf[2] = (char)(fileChecksum >> 8);
+ checksumBuf[3] = (char)fileChecksum;
+ (*outputFunc)(outputStream, checksumBuf, 4);
+ (*outputFunc)(outputStream,
+ (char *)file + newTables[i].origOffset + 12,
+ newTables[i].len - 12);
+ } else {
+ for (j = 0; j < newTables[i].len; ++j) {
+ (*outputFunc)(outputStream, "\0", 1);
+ }
+ }
+ } else if (newTables[i].tag == cmapTag && replacementCmapTable) {
+ (*outputFunc)(outputStream, (char *)replacementCmapTable,
+ newTables[i].len);
+ } else if (newTables[i].tag == cmapTag && codeToGID) {
+ (*outputFunc)(outputStream, newCmapTab, newTables[i].len);
+ } else if (newTables[i].tag == cmapTag && missingCmap) {
+ (*outputFunc)(outputStream, cmapTab, newTables[i].len);
+ } else if (newTables[i].tag == nameTag && name) {
+ (*outputFunc)(outputStream, newNameTab, newTables[i].len);
+ } else if (newTables[i].tag == nameTag && missingName) {
+ (*outputFunc)(outputStream, nameTab, newTables[i].len);
+ } else if (newTables[i].tag == postTag && missingPost) {
+ (*outputFunc)(outputStream, postTab, newTables[i].len);
+ } else if (newTables[i].tag == os2Tag && missingOS2) {
+ (*outputFunc)(outputStream, os2Tab, newTables[i].len);
+ } else if (newTables[i].tag == hheaTag && abbrevHMTX) {
+ (*outputFunc)(outputStream, newHHEATab, newTables[i].len);
+ } else if (newTables[i].tag == hmtxTag && abbrevHMTX) {
+ (*outputFunc)(outputStream, newHMTXTab, newTables[i].len);
+ } else if (newTables[i].tag == locaTag && unsortedLoca) {
+ for (j = 0; j <= nGlyphs; ++j) {
+ if (locaFmt) {
+ locaBuf[0] = (char)(locaTable[j].newOffset >> 24);
+ locaBuf[1] = (char)(locaTable[j].newOffset >> 16);
+ locaBuf[2] = (char)(locaTable[j].newOffset >> 8);
+ locaBuf[3] = (char) locaTable[j].newOffset;
+ (*outputFunc)(outputStream, locaBuf, 4);
+ } else {
+ locaBuf[0] = (char)(locaTable[j].newOffset >> 9);
+ locaBuf[1] = (char)(locaTable[j].newOffset >> 1);
+ (*outputFunc)(outputStream, locaBuf, 2);
+ }
+ }
+ } else if (newTables[i].tag == glyfTag && unsortedLoca) {
+ pos = tables[seekTable("glyf")].offset;
+ for (j = 0; j < nGlyphs; ++j) {
+ n = locaTable[j].len;
+ if (n > 0) {
+ k = locaTable[j].origOffset;
+ if (checkRegion(pos + k, n)) {
+ (*outputFunc)(outputStream, (char *)file + pos + k, n);
+ } else {
+ for (k = 0; k < n; ++k) {
+ (*outputFunc)(outputStream, "\0", 1);
+ }
+ }
+ if ((k = locaTable[j].len & 3)) {
+ (*outputFunc)(outputStream, "\0\0\0\0", 4 - k);
+ }
+ }
+ }
+ } else {
+ if (checkRegion(newTables[i].origOffset, newTables[i].len)) {
+ (*outputFunc)(outputStream, (char *)file + newTables[i].origOffset,
+ newTables[i].len);
+ } else {
+ for (j = 0; j < newTables[i].len; ++j) {
+ (*outputFunc)(outputStream, "\0", 1);
+ }
+ }
+ }
+ if (newTables[i].len & 3) {
+ (*outputFunc)(outputStream, "\0\0\0", 4 - (newTables[i].len & 3));
+ }
+ }
+
+ gfree(newHMTXTab);
+ gfree(newHHEATab);
+ gfree(newCmapTab);
+ gfree(newNameTab);
+ gfree(tableDir);
+ gfree(newTables);
+ gfree(locaTable);
+ return gTrue;
+}
+
+void FoFiTrueType::cvtEncoding(char **encoding,
+ FoFiOutputFunc outputFunc,
+ void *outputStream) {
+ const char *name;
+ GString *buf;
+ int i;
+
+ (*outputFunc)(outputStream, "/Encoding 256 array\n", 20);
+ if (encoding) {
+ for (i = 0; i < 256; ++i) {
+ if (!(name = encoding[i])) {
+ name = ".notdef";
+ }
+ buf = GString::format("dup {0:d} /", i);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ (*outputFunc)(outputStream, name, (int)strlen(name));
+ (*outputFunc)(outputStream, " put\n", 5);
+ }
+ } else {
+ for (i = 0; i < 256; ++i) {
+ buf = GString::format("dup {0:d} /c{1:02x} put\n", i, i);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ }
+ }
+ (*outputFunc)(outputStream, "readonly def\n", 13);
+}
+
+void FoFiTrueType::cvtCharStrings(char **encoding,
+ int *codeToGID,
+ FoFiOutputFunc outputFunc,
+ void *outputStream) {
+ char *name;
+ GString *buf;
+ char buf2[16];
+ int i, k;
+
+ // always define '.notdef'
+ (*outputFunc)(outputStream, "/CharStrings 256 dict dup begin\n", 32);
+ (*outputFunc)(outputStream, "/.notdef 0 def\n", 15);
+
+ // map char name to glyph index:
+ // 1. use encoding to map name to char code
+ // 2. use codeToGID to map char code to glyph index
+ // N.B. We do this in reverse order because font subsets can have
+ // weird encodings that use the same character name twice, and
+ // the first definition is probably the one we want.
+ k = 0; // make gcc happy
+ for (i = 255; i >= 0; --i) {
+ if (encoding) {
+ name = encoding[i];
+ } else {
+ snprintf(buf2, sizeof(buf2), "c%02x", i);
+ name = buf2;
+ }
+ if (name && strcmp(name, ".notdef")) {
+ k = codeToGID[i];
+ // note: Distiller (maybe Adobe's PS interpreter in general)
+ // doesn't like TrueType fonts that have CharStrings entries
+ // which point to nonexistent glyphs, hence the (k < nGlyphs)
+ // test
+ if (k > 0 && k < nGlyphs) {
+ (*outputFunc)(outputStream, "/", 1);
+ (*outputFunc)(outputStream, name, (int)strlen(name));
+ buf = GString::format(" {0:d} def\n", k);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ }
+ }
+ }
+
+ (*outputFunc)(outputStream, "end readonly def\n", 17);
+}
+
+void FoFiTrueType::cvtSfnts(FoFiOutputFunc outputFunc,
+ void *outputStream, GString *name,
+ GBool needVerticalMetrics,
+ int *maxUsedGlyph) {
+ Guchar headData[54];
+ TrueTypeLoca *locaTable;
+ Guchar *locaData;
+ TrueTypeTable newTables[nT42Tables];
+ Guchar tableDir[12 + nT42Tables*16];
+ GBool ok;
+ Guint checksum;
+ int nNewTables;
+ int glyfTableLen, length, pos, glyfPos, i, j, k;
+ Guchar vheaTab[36] = {
+ 0, 1, 0, 0, // table version number
+ 0, 0, // ascent
+ 0, 0, // descent
+ 0, 0, // reserved
+ 0, 0, // max advance height
+ 0, 0, // min top side bearing
+ 0, 0, // min bottom side bearing
+ 0, 0, // y max extent
+ 0, 0, // caret slope rise
+ 0, 1, // caret slope run
+ 0, 0, // caret offset
+ 0, 0, // reserved
+ 0, 0, // reserved
+ 0, 0, // reserved
+ 0, 0, // reserved
+ 0, 0, // metric data format
+ 0, 1 // number of advance heights in vmtx table
+ };
+ Guchar *vmtxTab;
+ GBool needVhea, needVmtx;
+ int advance;
+
+ // construct the 'head' table, zero out the font checksum
+ i = seekTable("head");
+ pos = tables[i].offset;
+ if (!checkRegion(pos, 54)) {
+ return;
+ }
+ memcpy(headData, file + pos, 54);
+ headData[8] = headData[9] = headData[10] = headData[11] = (Guchar)0;
+
+ // check for a bogus loca format field in the 'head' table
+ // (I've encountered fonts with loca format set to 0x0100 instead of 0x0001)
+ if (locaFmt != 0 && locaFmt != 1) {
+ headData[50] = 0;
+ headData[51] = 1;
+ }
+
+ // read the original 'loca' table, pad entries out to 4 bytes, and
+ // sort it into proper order -- some (non-compliant) fonts have
+ // out-of-order loca tables; in order to correctly handle the case
+ // where (compliant) fonts have empty entries in the middle of the
+ // table, cmpTrueTypeLocaOffset uses offset as its primary sort key,
+ // and idx as its secondary key (ensuring that adjacent entries with
+ // the same pos value remain in the same order)
+ //
+ // NB: a glyph description containing 12 zero bytes should be a
+ // valid empty glyph (from my reading of the TrueType spec), but
+ // Acrobat chokes on this (which is an issue when an Xpdf-generated
+ // PS file is converted back to PDF - with Ghostscript or
+ // Distiller), so we drop any glyph descriptions of 12 or fewer
+ // bytes -- an empty glyph description generates an empty glyph with
+ // no errors
+ locaTable = (TrueTypeLoca *)gmallocn(nGlyphs + 1, sizeof(TrueTypeLoca));
+ i = seekTable("loca");
+ pos = tables[i].offset;
+ i = seekTable("glyf");
+ glyfTableLen = tables[i].len;
+ ok = gTrue;
+ for (i = 0; i <= nGlyphs; ++i) {
+ locaTable[i].idx = i;
+ if (locaFmt) {
+ locaTable[i].origOffset = (int)getU32BE(pos + i*4, &ok);
+ } else {
+ locaTable[i].origOffset = 2 * getU16BE(pos + i*2, &ok);
+ }
+ if (locaTable[i].origOffset < 0 ||
+ locaTable[i].origOffset > glyfTableLen) {
+ locaTable[i].origOffset = glyfTableLen;
+ }
+ }
+#if HAVE_STD_SORT
+ std::sort(locaTable, locaTable + nGlyphs + 1,
+ cmpTrueTypeLocaOffsetFunctor());
+#else
+ qsort(locaTable, nGlyphs + 1, sizeof(TrueTypeLoca),
+ &cmpTrueTypeLocaOffset);
+#endif
+ for (i = 0; i < nGlyphs; ++i) {
+ locaTable[i].len = locaTable[i+1].origOffset - locaTable[i].origOffset;
+ }
+ locaTable[nGlyphs].len = 0;
+#if HAVE_STD_SORT
+ std::sort(locaTable, locaTable + nGlyphs + 1, cmpTrueTypeLocaIdxFunctor());
+#else
+ qsort(locaTable, nGlyphs + 1, sizeof(TrueTypeLoca),
+ &cmpTrueTypeLocaIdx);
+#endif
+ pos = 0;
+ *maxUsedGlyph = -1;
+ for (i = 0; i <= nGlyphs; ++i) {
+ locaTable[i].newOffset = pos;
+ if (locaTable[i].len > 12) {
+ pos += locaTable[i].len;
+ if (pos & 3) {
+ pos += 4 - (pos & 3);
+ }
+ *maxUsedGlyph = i;
+ }
+ }
+
+ // construct the new 'loca' table
+ locaData = (Guchar *)gmallocn(nGlyphs + 1, (locaFmt ? 4 : 2));
+ for (i = 0; i <= nGlyphs; ++i) {
+ pos = locaTable[i].newOffset;
+ if (locaFmt) {
+ locaData[4*i ] = (Guchar)(pos >> 24);
+ locaData[4*i+1] = (Guchar)(pos >> 16);
+ locaData[4*i+2] = (Guchar)(pos >> 8);
+ locaData[4*i+3] = (Guchar) pos;
+ } else {
+ locaData[2*i ] = (Guchar)(pos >> 9);
+ locaData[2*i+1] = (Guchar)(pos >> 1);
+ }
+ }
+
+ // count the number of tables
+ nNewTables = 0;
+ for (i = 0; i < nT42Tables; ++i) {
+ if (t42Tables[i].required ||
+ seekTable(t42Tables[i].tag) >= 0) {
+ ++nNewTables;
+ }
+ }
+ vmtxTab = NULL; // make gcc happy
+ advance = 0; // make gcc happy
+ if (needVerticalMetrics) {
+ needVhea = seekTable("vhea") < 0;
+ needVmtx = seekTable("vmtx") < 0;
+ if (needVhea || needVmtx) {
+ i = seekTable("head");
+ advance = getU16BE(tables[i].offset + 18, &ok); // units per em
+ if (needVhea) {
+ ++nNewTables;
+ }
+ if (needVmtx) {
+ ++nNewTables;
+ }
+ }
+ }
+
+ // construct the new table headers, including table checksums
+ // (pad each table out to a multiple of 4 bytes)
+ pos = 12 + nNewTables*16;
+ k = 0;
+ for (i = 0; i < nT42Tables; ++i) {
+ length = -1;
+ checksum = 0; // make gcc happy
+ if (i == t42HeadTable) {
+ length = 54;
+ checksum = computeTableChecksum(headData, 54);
+ } else if (i == t42LocaTable) {
+ length = (nGlyphs + 1) * (locaFmt ? 4 : 2);
+ checksum = computeTableChecksum(locaData, length);
+ } else if (i == t42GlyfTable) {
+ length = 0;
+ checksum = 0;
+ glyfPos = tables[seekTable("glyf")].offset;
+ for (j = 0; j < nGlyphs; ++j) {
+ if (locaTable[j].len > 12) {
+ length += locaTable[j].len;
+ if (length & 3) {
+ length += 4 - (length & 3);
+ }
+ if (checkRegion(glyfPos + locaTable[j].origOffset,
+ locaTable[j].len)) {
+ checksum +=
+ computeTableChecksum(file + glyfPos + locaTable[j].origOffset,
+ locaTable[j].len);
+ }
+ }
+ }
+ } else {
+ if ((j = seekTable(t42Tables[i].tag)) >= 0) {
+ length = tables[j].len;
+ if (checkRegion(tables[j].offset, length)) {
+ checksum = computeTableChecksum(file + tables[j].offset, length);
+ }
+ } else if (needVerticalMetrics && i == t42VheaTable) {
+ vheaTab[10] = (Guchar)(advance / 256); // max advance height
+ vheaTab[11] = (Guchar)(advance % 256);
+ length = sizeof(vheaTab);
+ checksum = computeTableChecksum(vheaTab, length);
+ } else if (needVerticalMetrics && i == t42VmtxTable) {
+ length = 4 + (nGlyphs - 1) * 2;
+ vmtxTab = (Guchar *)gmalloc(length);
+ vmtxTab[0] = (Guchar)(advance / 256);
+ vmtxTab[1] = (Guchar)(advance % 256);
+ for (j = 2; j < length; j += 2) {
+ vmtxTab[j] = 0;
+ vmtxTab[j+1] = 0;
+ }
+ checksum = computeTableChecksum(vmtxTab, length);
+ } else if (t42Tables[i].required) {
+ //~ error(-1, "Embedded TrueType font is missing a required table ('%s')",
+ //~ t42Tables[i].tag);
+ length = 0;
+ checksum = 0;
+ }
+ }
+ if (length >= 0) {
+ newTables[k].tag = ((t42Tables[i].tag[0] & 0xff) << 24) |
+ ((t42Tables[i].tag[1] & 0xff) << 16) |
+ ((t42Tables[i].tag[2] & 0xff) << 8) |
+ (t42Tables[i].tag[3] & 0xff);
+ newTables[k].checksum = checksum;
+ newTables[k].offset = pos;
+ newTables[k].len = length;
+ pos += length;
+ if (pos & 3) {
+ pos += 4 - (length & 3);
+ }
+ ++k;
+ }
+ }
+
+ // construct the table directory
+ tableDir[0] = 0x00; // sfnt version
+ tableDir[1] = 0x01;
+ tableDir[2] = 0x00;
+ tableDir[3] = 0x00;
+ tableDir[4] = 0; // numTables
+ tableDir[5] = (Guchar)nNewTables;
+ tableDir[6] = 0; // searchRange
+ tableDir[7] = (Guchar)128;
+ tableDir[8] = 0; // entrySelector
+ tableDir[9] = 3;
+ tableDir[10] = 0; // rangeShift
+ tableDir[11] = (Guchar)(16 * nNewTables - 128);
+ pos = 12;
+ for (i = 0; i < nNewTables; ++i) {
+ tableDir[pos ] = (Guchar)(newTables[i].tag >> 24);
+ tableDir[pos+ 1] = (Guchar)(newTables[i].tag >> 16);
+ tableDir[pos+ 2] = (Guchar)(newTables[i].tag >> 8);
+ tableDir[pos+ 3] = (Guchar) newTables[i].tag;
+ tableDir[pos+ 4] = (Guchar)(newTables[i].checksum >> 24);
+ tableDir[pos+ 5] = (Guchar)(newTables[i].checksum >> 16);
+ tableDir[pos+ 6] = (Guchar)(newTables[i].checksum >> 8);
+ tableDir[pos+ 7] = (Guchar) newTables[i].checksum;
+ tableDir[pos+ 8] = (Guchar)(newTables[i].offset >> 24);
+ tableDir[pos+ 9] = (Guchar)(newTables[i].offset >> 16);
+ tableDir[pos+10] = (Guchar)(newTables[i].offset >> 8);
+ tableDir[pos+11] = (Guchar) newTables[i].offset;
+ tableDir[pos+12] = (Guchar)(newTables[i].len >> 24);
+ tableDir[pos+13] = (Guchar)(newTables[i].len >> 16);
+ tableDir[pos+14] = (Guchar)(newTables[i].len >> 8);
+ tableDir[pos+15] = (Guchar) newTables[i].len;
+ pos += 16;
+ }
+
+ // compute the font checksum and store it in the head table
+ checksum = computeTableChecksum(tableDir, 12 + nNewTables*16);
+ for (i = 0; i < nNewTables; ++i) {
+ checksum += newTables[i].checksum;
+ }
+ checksum = 0xb1b0afba - checksum; // because the TrueType spec says so
+ headData[ 8] = (Guchar)(checksum >> 24);
+ headData[ 9] = (Guchar)(checksum >> 16);
+ headData[10] = (Guchar)(checksum >> 8);
+ headData[11] = (Guchar) checksum;
+
+ // start the sfnts array
+ if (name) {
+ (*outputFunc)(outputStream, "/", 1);
+ (*outputFunc)(outputStream, name->getCString(), name->getLength());
+ (*outputFunc)(outputStream, " [\n", 3);
+ } else {
+ (*outputFunc)(outputStream, "/sfnts [\n", 9);
+ }
+
+ // write the table directory
+ dumpString(tableDir, 12 + nNewTables*16, outputFunc, outputStream);
+
+ // write the tables
+ for (i = 0; i < nNewTables; ++i) {
+ if (i == t42HeadTable) {
+ dumpString(headData, 54, outputFunc, outputStream);
+ } else if (i == t42LocaTable) {
+ length = (nGlyphs + 1) * (locaFmt ? 4 : 2);
+ dumpString(locaData, length, outputFunc, outputStream);
+ } else if (i == t42GlyfTable) {
+ glyfPos = tables[seekTable("glyf")].offset;
+ for (j = 0; j < nGlyphs; ++j) {
+ if (locaTable[j].len > 12 &&
+ checkRegion(glyfPos + locaTable[j].origOffset, locaTable[j].len)) {
+ dumpString(file + glyfPos + locaTable[j].origOffset,
+ locaTable[j].len, outputFunc, outputStream);
+ }
+ }
+ } else {
+ // length == 0 means the table is missing and the error was
+ // already reported during the construction of the table
+ // headers
+ if ((length = newTables[i].len) > 0) {
+ if ((j = seekTable(t42Tables[i].tag)) >= 0 &&
+ checkRegion(tables[j].offset, tables[j].len)) {
+ dumpString(file + tables[j].offset, tables[j].len,
+ outputFunc, outputStream);
+ } else if (needVerticalMetrics && i == t42VheaTable) {
+ dumpString(vheaTab, length, outputFunc, outputStream);
+ } else if (needVerticalMetrics && i == t42VmtxTable) {
+ dumpString(vmtxTab, length, outputFunc, outputStream);
+ }
+ }
+ }
+ }
+
+ // end the sfnts array
+ (*outputFunc)(outputStream, "] def\n", 6);
+
+ gfree(locaData);
+ gfree(locaTable);
+ if (vmtxTab) {
+ gfree(vmtxTab);
+ }
+}
+
+void FoFiTrueType::dumpString(Guchar *s, int length,
+ FoFiOutputFunc outputFunc,
+ void *outputStream) {
+ GString *buf;
+ int pad, i, j;
+
+ (*outputFunc)(outputStream, "<", 1);
+ for (i = 0; i < length; i += 32) {
+ for (j = 0; j < 32 && i+j < length; ++j) {
+ buf = GString::format("{0:02x}", s[i+j] & 0xff);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ }
+ if (i % (65536 - 32) == 65536 - 64) {
+ (*outputFunc)(outputStream, ">\n<", 3);
+ } else if (i+32 < length) {
+ (*outputFunc)(outputStream, "\n", 1);
+ }
+ }
+ if (length & 3) {
+ pad = 4 - (length & 3);
+ for (i = 0; i < pad; ++i) {
+ (*outputFunc)(outputStream, "00", 2);
+ }
+ }
+ // add an extra zero byte because the Adobe Type 42 spec says so
+ (*outputFunc)(outputStream, "00>\n", 4);
+}
+
+Guint FoFiTrueType::computeTableChecksum(Guchar *data, int length) {
+ Guint checksum, word;
+ int i;
+
+ checksum = 0;
+ for (i = 0; i+3 < length; i += 4) {
+ word = ((data[i ] & 0xff) << 24) +
+ ((data[i+1] & 0xff) << 16) +
+ ((data[i+2] & 0xff) << 8) +
+ (data[i+3] & 0xff);
+ checksum += word;
+ }
+ if (length & 3) {
+ word = 0;
+ i = length & ~3;
+ switch (length & 3) {
+ case 3:
+ word |= (data[i+2] & 0xff) << 8;
+ case 2:
+ word |= (data[i+1] & 0xff) << 16;
+ case 1:
+ word |= (data[i ] & 0xff) << 24;
+ break;
+ }
+ checksum += word;
+ }
+ return checksum;
+}
+
+void FoFiTrueType::parse(int fontNum, GBool allowHeadlessCFF) {
+ Guint topTag;
+ int offset, pos, ver, i, j, k;
+
+ parsedOk = gTrue;
+
+ // check for a dfont or TrueType collection (TTC)
+ // offset = start of actual TrueType font file (table positions are
+ // relative to this
+ // pos = position of table directory (relative to offset)
+ if (isDfont) {
+ parseDfont(fontNum, &offset, &pos);
+ } else {
+ offset = 0;
+ topTag = getU32BE(0, &parsedOk);
+ if (!parsedOk) {
+ return;
+ }
+ if (topTag == ttcfTag) {
+ parseTTC(fontNum, &pos);
+ } else {
+ pos = 0;
+ }
+ }
+ if (!parsedOk) {
+ return;
+ }
+
+ // check the sfnt version
+ ver = getU32BE(offset + pos, &parsedOk);
+ if (!parsedOk) {
+ return;
+ }
+ openTypeCFF = ver == 0x4f54544f; // 'OTTO'
+
+ // read the table directory
+ nTables = getU16BE(offset + pos + 4, &parsedOk);
+ if (!parsedOk) {
+ return;
+ }
+ tables = (TrueTypeTable *)gmallocn(nTables, sizeof(TrueTypeTable));
+ pos += 12;
+ j = 0;
+ for (i = 0; i < nTables; ++i) {
+ tables[j].tag = getU32BE(offset + pos, &parsedOk);
+ tables[j].checksum = getU32BE(offset + pos + 4, &parsedOk);
+ tables[j].offset = offset + (int)getU32BE(offset + pos + 8, &parsedOk);
+ tables[j].len = (int)getU32BE(offset + pos + 12, &parsedOk);
+ if (tables[j].offset >= 0 &&
+ tables[j].len >= 0 &&
+ tables[j].offset + tables[j].len >= tables[j].offset &&
+ tables[j].offset + tables[j].len <= len) {
+ // ignore any bogus entries in the table directory
+ ++j;
+ }
+ pos += 16;
+ }
+ nTables = j;
+ if (!parsedOk) {
+ return;
+ }
+
+ // check for the head table; allow for a head-less OpenType CFF font
+ headlessCFF = gFalse;
+ if (seekTable("head") < 0) {
+ if (openTypeCFF && allowHeadlessCFF && seekTable("CFF ") >= 0) {
+ headlessCFF = gTrue;
+ nGlyphs = 0;
+ bbox[0] = bbox[1] = bbox[2] = bbox[3] = 0;
+ locaFmt = 0;
+ return;
+ }
+ parsedOk = gFalse;
+ return;
+ }
+
+ // check for other tables that are required by both the TrueType
+ // spec and the Type 42 spec
+ if (seekTable("hhea") < 0 ||
+ seekTable("maxp") < 0 ||
+ seekTable("hmtx") < 0 ||
+ (!openTypeCFF && seekTable("loca") < 0) ||
+ (!openTypeCFF && seekTable("glyf") < 0) ||
+ (openTypeCFF && seekTable("CFF ") < 0)) {
+ parsedOk = gFalse;
+ return;
+ }
+
+ // read the cmaps
+ if ((i = seekTable("cmap")) >= 0 && tables[i].len >= 4) {
+ pos = tables[i].offset + 2;
+ nCmaps = getU16BE(pos, &parsedOk);
+ pos += 2;
+ if (!parsedOk) {
+ return;
+ }
+ cmaps = (TrueTypeCmap *)gmallocn(nCmaps, sizeof(TrueTypeCmap));
+ k = 0;
+ for (j = 0; j < nCmaps; ++j) {
+ cmaps[k].platform = getU16BE(pos, &parsedOk);
+ cmaps[k].encoding = getU16BE(pos + 2, &parsedOk);
+ cmaps[k].offset = getU32BE(pos + 4, &parsedOk);
+ pos += 8;
+ if (cmaps[k].offset >= tables[i].len) {
+ // skip any invalid subtables
+ continue;
+ }
+ cmaps[k].offset += tables[i].offset;
+ cmaps[k].fmt = getU16BE(cmaps[k].offset, &parsedOk);
+ cmaps[k].len = getU16BE(cmaps[k].offset + 2, &parsedOk);
+ ++k;
+ }
+ nCmaps = k;
+ if (!parsedOk) {
+ return;
+ }
+ }
+
+ // get the number of glyphs from the maxp table
+ i = seekTable("maxp");
+ nGlyphs = getU16BE(tables[i].offset + 4, &parsedOk);
+ if (!parsedOk) {
+ return;
+ }
+
+ // get the bbox and loca table format from the head table
+ i = seekTable("head");
+ bbox[0] = getS16BE(tables[i].offset + 36, &parsedOk);
+ bbox[1] = getS16BE(tables[i].offset + 38, &parsedOk);
+ bbox[2] = getS16BE(tables[i].offset + 40, &parsedOk);
+ bbox[3] = getS16BE(tables[i].offset + 42, &parsedOk);
+ locaFmt = getS16BE(tables[i].offset + 50, &parsedOk);
+ if (!parsedOk) {
+ return;
+ }
+
+ // make sure the loca table is sane (correct length)
+ // NB: out-of-bounds entries are handled in writeTTF()
+ if (!openTypeCFF) {
+ i = seekTable("loca");
+ if (tables[i].len < (locaFmt ? 4 : 2)) {
+ parsedOk = gFalse;
+ return;
+ }
+ if (tables[i].len < (nGlyphs + 1) * (locaFmt ? 4 : 2)) {
+ nGlyphs = tables[i].len / (locaFmt ? 4 : 2) - 1;
+ }
+ if (!parsedOk) {
+ return;
+ }
+ }
+
+ // read the post table
+ readPostTable();
+}
+
+// Get the table directory position
+void FoFiTrueType::parseTTC(int fontNum, int *pos) {
+ int nFonts;
+
+ isTTC = gTrue;
+ nFonts = getU32BE(8, &parsedOk);
+ if (!parsedOk) {
+ return;
+ }
+ if (fontNum < 0 || fontNum >= nFonts) {
+ parsedOk = gFalse;
+ return;
+ }
+ *pos = getU32BE(12 + 4 * fontNum, &parsedOk);
+}
+
+void FoFiTrueType::parseDfont(int fontNum, int *offset, int *startPos) {
+ int resMapOffset, resDataOffset;
+ int resTypeListOffset, nTypes, typeTag;
+ int nFonts, refListOffset, dataOffset;
+ int pos, i;
+
+ resDataOffset = getU32BE(0, &parsedOk);
+ resMapOffset = getU32BE(4, &parsedOk);
+ if (!parsedOk) {
+ return;
+ }
+
+ resTypeListOffset = getU16BE(resMapOffset + 24, &parsedOk);
+ // resNameListOffset = getU16BE(resMapOffset + 26, &parsedOk);
+ nTypes = getU16BE(resMapOffset + 28, &parsedOk) + 1;
+ if (!parsedOk) {
+ return;
+ }
+
+ pos = 0; // make gcc happy
+ for (i = 0; i < nTypes; ++i) {
+ pos = resMapOffset + resTypeListOffset + 2 + 8*i;
+ typeTag = getU32BE(pos, &parsedOk);
+ if (!parsedOk) {
+ return;
+ }
+ if (typeTag == 0x73666e74) { // 'sfnt'
+ break;
+ }
+ }
+ if (i >= nTypes) {
+ parsedOk = gFalse;
+ return;
+ }
+ nFonts = getU16BE(pos + 4, &parsedOk) + 1;
+ refListOffset = getU16BE(pos + 6, &parsedOk);
+ if (!parsedOk) {
+ return;
+ }
+ if (fontNum < 0 || fontNum >= nFonts) {
+ parsedOk = gFalse;
+ return;
+ }
+ pos = resMapOffset + resTypeListOffset + refListOffset + 12 * fontNum;
+ dataOffset = getU32BE(pos + 4, &parsedOk) & 0x00ffffff;
+ if (!parsedOk) {
+ return;
+ }
+ // the data offset points to a 4-byte length field, which we skip over
+ *offset = resDataOffset + dataOffset + 4;
+ *startPos = 0;
+}
+
+void FoFiTrueType::readPostTable() {
+ GString *name;
+ int tablePos, postFmt, stringIdx, stringPos;
+ GBool ok;
+ int i, j, n, m;
+
+ ok = gTrue;
+ if ((i = seekTable("post")) < 0) {
+ return;
+ }
+ tablePos = tables[i].offset;
+ postFmt = getU32BE(tablePos, &ok);
+ if (!ok) {
+ goto err;
+ }
+ if (postFmt == 0x00010000) {
+ nameToGID = new GHash(gTrue);
+ for (i = 0; i < 258; ++i) {
+ nameToGID->add(new GString(macGlyphNames[i]), i);
+ }
+ } else if (postFmt == 0x00020000) {
+ nameToGID = new GHash(gTrue);
+ n = getU16BE(tablePos + 32, &ok);
+ if (!ok) {
+ goto err;
+ }
+ stringIdx = 0;
+ stringPos = tablePos + 34 + 2*n;
+ for (i = 0; i < n && i < nGlyphs; ++i) {
+ ok = gTrue;
+ j = getU16BE(tablePos + 34 + 2*i, &ok);
+ if (j < 258) {
+ nameToGID->removeInt(macGlyphNames[j]);
+ nameToGID->add(new GString(macGlyphNames[j]), i);
+ } else {
+ j -= 258;
+ if (j != stringIdx) {
+ for (stringIdx = 0, stringPos = tablePos + 34 + 2*n;
+ stringIdx < j;
+ ++stringIdx, stringPos += 1 + getU8(stringPos, &ok)) ;
+ if (!ok) {
+ continue;
+ }
+ }
+ m = getU8(stringPos, &ok);
+ if (!ok || !checkRegion(stringPos + 1, m)) {
+ continue;
+ }
+ name = new GString((char *)&file[stringPos + 1], m);
+ nameToGID->removeInt(name);
+ nameToGID->add(name, i);
+ ++stringIdx;
+ stringPos += 1 + m;
+ }
+ }
+ } else if (postFmt == 0x00028000) {
+ nameToGID = new GHash(gTrue);
+ for (i = 0; i < nGlyphs; ++i) {
+ j = getU8(tablePos + 32 + i, &ok);
+ if (!ok) {
+ continue;
+ }
+ if (j < 258) {
+ nameToGID->removeInt(macGlyphNames[j]);
+ nameToGID->add(new GString(macGlyphNames[j]), i);
+ }
+ }
+ }
+
+ return;
+
+ err:
+ if (nameToGID) {
+ delete nameToGID;
+ nameToGID = NULL;
+ }
+}
+
+int FoFiTrueType::seekTable(const char *tag) {
+ Guint tagI;
+ int i;
+
+ tagI = ((tag[0] & 0xff) << 24) |
+ ((tag[1] & 0xff) << 16) |
+ ((tag[2] & 0xff) << 8) |
+ (tag[3] & 0xff);
+ for (i = 0; i < nTables; ++i) {
+ if (tables[i].tag == tagI) {
+ return i;
+ }
+ }
+ return -1;
+}
diff --git a/fofi/FoFiTrueType.h b/fofi/FoFiTrueType.h
new file mode 100644
index 0000000..619e1bd
--- /dev/null
+++ b/fofi/FoFiTrueType.h
@@ -0,0 +1,216 @@
+//========================================================================
+//
+// FoFiTrueType.h
+//
+// Copyright 1999-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef FOFITRUETYPE_H
+#define FOFITRUETYPE_H
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include "gtypes.h"
+#include "FoFiBase.h"
+
+class GString;
+class GHash;
+struct TrueTypeTable;
+struct TrueTypeCmap;
+
+//------------------------------------------------------------------------
+// FoFiTrueType
+//------------------------------------------------------------------------
+
+class FoFiTrueType: public FoFiBase {
+public:
+
+ // Create a FoFiTrueType object from a memory buffer. If
+ // <allowHeadlessCFF> is true, OpenType CFF fonts without the 'head'
+ // table are permitted -- this is useful when calling the convert*
+ // functions.
+ static FoFiTrueType *make(char *fileA, int lenA, int fontNum,
+ GBool allowHeadlessCFF = gFalse);
+
+ // Create a FoFiTrueType object from a file on disk. If
+ // <allowHeadlessCFF> is true, OpenType CFF fonts without the 'head'
+ // table are permitted -- this is useful when calling the convert*
+ // functions.
+ static FoFiTrueType *load(char *fileName, int fontNum,
+ GBool allowHeadlessCFF = gFalse);
+
+ virtual ~FoFiTrueType();
+
+ // Returns true if this an OpenType font containing CFF data, false
+ // if it's a TrueType font (or OpenType font with TrueType data).
+ GBool isOpenTypeCFF() { return openTypeCFF; }
+
+ // Returns true if this is an OpenType CFF font that is missing the
+ // 'head' table. This is a violation of the OpenType spec, but the
+ // embedded CFF font can be usable for some purposes (e.g., the
+ // convert* functions).
+ GBool isHeadlessCFF() { return headlessCFF; }
+
+ // Return the number of cmaps defined by this font.
+ int getNumCmaps();
+
+ // Return the platform ID of the <i>th cmap.
+ int getCmapPlatform(int i);
+
+ // Return the encoding ID of the <i>th cmap.
+ int getCmapEncoding(int i);
+
+ // Return the index of the cmap for <platform>, <encoding>. Returns
+ // -1 if there is no corresponding cmap.
+ int findCmap(int platform, int encoding);
+
+ // Return the GID corresponding to <c> according to the <i>th cmap.
+ int mapCodeToGID(int i, int c);
+
+ // Returns the GID corresponding to <name> according to the post
+ // table. Returns 0 if there is no mapping for <name> or if the
+ // font does not have a post table.
+ int mapNameToGID(char *name);
+
+ // Return the mapping from CIDs to GIDs, and return the number of
+ // CIDs in *<nCIDs>. This is only useful for CID fonts. (Only
+ // useful for OpenType CFF fonts.)
+ int *getCIDToGIDMap(int *nCIDs);
+
+ // Returns the least restrictive embedding licensing right (as
+ // defined by the TrueType spec):
+ // * 4: OS/2 table is missing or invalid
+ // * 3: installable embedding
+ // * 2: editable embedding
+ // * 1: preview & print embedding
+ // * 0: restricted license embedding
+ int getEmbeddingRights();
+
+ // Return the font matrix as an array of six numbers. (Only useful
+ // for OpenType CFF fonts.)
+ void getFontMatrix(double *mat);
+
+ // Return the number of glyphs in the font.
+ int getNumGlyphs() { return nGlyphs; }
+
+ // Returns true if this looks like a CJK font that uses bytecode
+ // instructions to assemble glyphs.
+ GBool checkForTrickyCJK();
+
+ // Convert to a Type 42 font, suitable for embedding in a PostScript
+ // file. <psName> will be used as the PostScript font name (so we
+ // don't need to depend on the 'name' table in the font). The
+ // <encoding> array specifies the mapping from char codes to names.
+ // If <encoding> is NULL, the encoding is unknown or undefined. The
+ // <codeToGID> array specifies the mapping from char codes to GIDs.
+ // (Not useful for OpenType CFF fonts.)
+ void convertToType42(char *psName, char **encoding,
+ int *codeToGID,
+ FoFiOutputFunc outputFunc, void *outputStream);
+
+ // Convert to a Type 1 font, suitable for embedding in a PostScript
+ // file. This is only useful with 8-bit fonts. If <newEncoding> is
+ // not NULL, it will be used in place of the encoding in the Type 1C
+ // font. If <ascii> is true the eexec section will be hex-encoded,
+ // otherwise it will be left as binary data. If <psName> is
+ // non-NULL, it will be used as the PostScript font name. (Only
+ // useful for OpenType CFF fonts.)
+ void convertToType1(char *psName, const char **newEncoding, GBool ascii,
+ FoFiOutputFunc outputFunc, void *outputStream);
+
+ // Convert to a Type 2 CIDFont, suitable for embedding in a
+ // PostScript file. <psName> will be used as the PostScript font
+ // name (so we don't need to depend on the 'name' table in the
+ // font). The <cidMap> array maps CIDs to GIDs; it has <nCIDs>
+ // entries. (Not useful for OpenType CFF fonts.)
+ void convertToCIDType2(char *psName, int *cidMap, int nCIDs,
+ GBool needVerticalMetrics,
+ FoFiOutputFunc outputFunc, void *outputStream);
+
+ // Convert to a Type 0 CIDFont, suitable for embedding in a
+ // PostScript file. <psName> will be used as the PostScript font
+ // name. (Only useful for OpenType CFF fonts.)
+ void convertToCIDType0(char *psName, int *cidMap, int nCIDs,
+ FoFiOutputFunc outputFunc, void *outputStream);
+
+ // Convert to a Type 0 (but non-CID) composite font, suitable for
+ // embedding in a PostScript file. <psName> will be used as the
+ // PostScript font name (so we don't need to depend on the 'name'
+ // table in the font). The <cidMap> array maps CIDs to GIDs; it has
+ // <nCIDs> entries. (Not useful for OpenType CFF fonts.)
+ void convertToType0(char *psName, int *cidMap, int nCIDs,
+ GBool needVerticalMetrics,
+ FoFiOutputFunc outputFunc, void *outputStream);
+
+ // Convert to a Type 0 (but non-CID) composite font, suitable for
+ // embedding in a PostScript file. <psName> will be used as the
+ // PostScript font name. (Only useful for OpenType CFF fonts.)
+ void convertToType0(char *psName, int *cidMap, int nCIDs,
+ FoFiOutputFunc outputFunc, void *outputStream);
+
+ // Write a clean TTF file, filling in missing tables and correcting
+ // various other errors. If <name> is non-NULL, the font is renamed
+ // to <name>. If <codeToGID> is non-NULL, the font is re-encoded,
+ // using a Windows Unicode cmap. If <name> is NULL and the font is
+ // complete and correct, it will be written unmodified. If
+ // <replacementCmapTable> is non-NULL it will be used as the cmap
+ // table in the written font (overriding any existing cmap table
+ // and/or the codeToGID arg). (Not useful for OpenType CFF fonts.)
+ // Returns true if the font was modified.
+ GBool writeTTF(FoFiOutputFunc outputFunc, void *outputStream,
+ char *name = NULL, int *codeToGID = NULL,
+ Guchar *replacementCmapTable = NULL,
+ int replacementCmapTableLen = 0);
+
+ // Returns a pointer to the CFF font embedded in this OpenType font.
+ // If successful, sets *<start> and *<length>, and returns true.
+ // Otherwise returns false. (Only useful for OpenType CFF fonts).
+ GBool getCFFBlock(char **start, int *length);
+
+private:
+
+ FoFiTrueType(char *fileA, int lenA, GBool freeFileDataA,
+ int fontNum, GBool isDfont, GBool allowHeadlessCFF);
+ void cvtEncoding(char **encoding,
+ FoFiOutputFunc outputFunc,
+ void *outputStream);
+ void cvtCharStrings(char **encoding,
+ int *codeToGID,
+ FoFiOutputFunc outputFunc,
+ void *outputStream);
+ void cvtSfnts(FoFiOutputFunc outputFunc,
+ void *outputStream, GString *name,
+ GBool needVerticalMetrics,
+ int *maxUsedGlyph);
+ void dumpString(Guchar *s, int length,
+ FoFiOutputFunc outputFunc,
+ void *outputStream);
+ Guint computeTableChecksum(Guchar *data, int length);
+ void parse(int fontNum, GBool allowHeadlessCFF);
+ void parseTTC(int fontNum, int *pos);
+ void parseDfont(int fontNum, int *offset, int *pos);
+ void readPostTable();
+ int seekTable(const char *tag);
+
+ TrueTypeTable *tables;
+ int nTables;
+ TrueTypeCmap *cmaps;
+ int nCmaps;
+ int nGlyphs;
+ int locaFmt;
+ int bbox[4];
+ GHash *nameToGID;
+ GBool openTypeCFF;
+ GBool headlessCFF;
+ GBool isDfont;
+ GBool isTTC;
+
+ GBool parsedOk;
+};
+
+#endif
diff --git a/fofi/FoFiType1.cc b/fofi/FoFiType1.cc
new file mode 100644
index 0000000..83ec53e
--- /dev/null
+++ b/fofi/FoFiType1.cc
@@ -0,0 +1,359 @@
+//========================================================================
+//
+// FoFiType1.cc
+//
+// Copyright 1999-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include "gmem.h"
+#include "gmempp.h"
+#include "FoFiEncodings.h"
+#include "FoFiType1.h"
+
+//------------------------------------------------------------------------
+// FoFiType1
+//------------------------------------------------------------------------
+
+FoFiType1 *FoFiType1::make(char *fileA, int lenA) {
+ return new FoFiType1(fileA, lenA, gFalse);
+}
+
+FoFiType1 *FoFiType1::load(char *fileName) {
+ char *fileA;
+ int lenA;
+
+ if (!(fileA = FoFiBase::readFile(fileName, &lenA))) {
+ return NULL;
+ }
+ return new FoFiType1(fileA, lenA, gTrue);
+}
+
+FoFiType1::FoFiType1(char *fileA, int lenA, GBool freeFileDataA):
+ FoFiBase(fileA, lenA, freeFileDataA)
+{
+ name = NULL;
+ encoding = NULL;
+ fontMatrix[0] = 0.001;
+ fontMatrix[1] = 0;
+ fontMatrix[2] = 0;
+ fontMatrix[3] = 0.001;
+ fontMatrix[4] = 0;
+ fontMatrix[5] = 0;
+ parsed = gFalse;
+ undoPFB();
+}
+
+FoFiType1::~FoFiType1() {
+ int i;
+
+ if (name) {
+ gfree(name);
+ }
+ if (encoding && encoding != (char **)fofiType1StandardEncoding) {
+ for (i = 0; i < 256; ++i) {
+ gfree(encoding[i]);
+ }
+ gfree(encoding);
+ }
+}
+
+char *FoFiType1::getName() {
+ if (!parsed) {
+ parse();
+ }
+ return name;
+}
+
+char **FoFiType1::getEncoding() {
+ if (!parsed) {
+ parse();
+ }
+ return encoding;
+}
+
+void FoFiType1::getFontMatrix(double *mat) {
+ int i;
+
+ if (!parsed) {
+ parse();
+ }
+ for (i = 0; i < 6; ++i) {
+ mat[i] = fontMatrix[i];
+ }
+}
+
+void FoFiType1::writeEncoded(const char **newEncoding,
+ FoFiOutputFunc outputFunc, void *outputStream) {
+ char buf[512];
+ char *line, *line2, *p;
+ int i;
+
+ // copy everything up to the encoding
+ for (line = (char *)file;
+ line && line + 9 <= (char *)file + len && strncmp(line, "/Encoding", 9);
+ line = getNextLine(line)) ;
+ if (!line) {
+ // no encoding - just copy the whole font file
+ (*outputFunc)(outputStream, (char *)file, len);
+ return;
+ }
+ (*outputFunc)(outputStream, (char *)file, (int)(line - (char *)file));
+
+ // write the new encoding
+ (*outputFunc)(outputStream, "/Encoding 256 array\n", 20);
+ (*outputFunc)(outputStream,
+ "0 1 255 {1 index exch /.notdef put} for\n", 40);
+ for (i = 0; i < 256; ++i) {
+ if (newEncoding[i]) {
+ snprintf(buf, sizeof(buf), "dup %d /%s put\n", i, newEncoding[i]);
+ (*outputFunc)(outputStream, buf, (int)strlen(buf));
+ }
+ }
+ (*outputFunc)(outputStream, "readonly def\n", 13);
+
+ // find the end of the encoding data
+ //~ this ought to parse PostScript tokens
+ if (line + 30 <= (char *)file + len &&
+ !strncmp(line, "/Encoding StandardEncoding def", 30)) {
+ line = getNextLine(line);
+ } else {
+ // skip "/Encoding" + one whitespace char,
+ // then look for 'def' preceded by PostScript whitespace
+ p = line + 10;
+ line = NULL;
+ for (; p < (char *)file + len; ++p) {
+ if ((*p == ' ' || *p == '\t' || *p == '\x0a' ||
+ *p == '\x0d' || *p == '\x0c' || *p == '\0') &&
+ p + 4 <= (char *)file + len &&
+ !strncmp(p + 1, "def", 3)) {
+ line = p + 4;
+ break;
+ }
+ }
+ }
+
+ // some fonts have two /Encoding entries in their dictionary, so we
+ // check for a second one here
+ if (line) {
+ for (line2 = line, i = 0;
+ i < 20 && line2 && line2 + 9 <= (char *)file + len &&
+ strncmp(line2, "/Encoding", 9);
+ line2 = getNextLine(line2), ++i) ;
+ if (i < 20 && line2) {
+ (*outputFunc)(outputStream, line, (int)(line2 - line));
+ if (line2 + 30 <= (char *)file + len &&
+ !strncmp(line2, "/Encoding StandardEncoding def", 30)) {
+ line = getNextLine(line2);
+ } else {
+ // skip "/Encoding",
+ // then look for 'def' preceded by PostScript whitespace
+ p = line2 + 9;
+ line = NULL;
+ for (; p < (char *)file + len; ++p) {
+ if ((*p == ' ' || *p == '\t' || *p == '\x0a' ||
+ *p == '\x0d' || *p == '\x0c' || *p == '\0') &&
+ p + 4 <= (char *)file + len &&
+ !strncmp(p + 1, "def", 3)) {
+ line = p + 4;
+ break;
+ }
+ }
+ }
+ }
+
+ // copy everything after the encoding
+ if (line) {
+ (*outputFunc)(outputStream, line, (int)(((char *)file + len) - line));
+ }
+ }
+}
+
+char *FoFiType1::getNextLine(char *line) {
+ while (line < (char *)file + len && *line != '\x0a' && *line != '\x0d') {
+ ++line;
+ }
+ if (line < (char *)file + len && *line == '\x0d') {
+ ++line;
+ }
+ if (line < (char *)file + len && *line == '\x0a') {
+ ++line;
+ }
+ if (line >= (char *)file + len) {
+ return NULL;
+ }
+ return line;
+}
+
+void FoFiType1::parse() {
+ char *line, *line1, *p, *p2;
+ char buf[256];
+ char c;
+ int n, code, base, i, j;
+ GBool gotMatrix, startsWithDup, endsWithDup;
+
+ gotMatrix = gFalse;
+ for (i = 1, line = (char *)file;
+ i <= 100 && line && (!name || !encoding || !gotMatrix);
+ ++i) {
+
+ // get font name
+ if (!name && line + 9 <= (char *)file + len &&
+ !strncmp(line, "/FontName", 9)) {
+ n = 255;
+ if (line + n > (char *)file + len) {
+ n = (int)(((char *)file + len) - line);
+ }
+ strncpy(buf, line, n);
+ buf[n] = '\0';
+ if ((p = strchr(buf+9, '/')) &&
+ (p = strtok(p+1, " \t\n\r"))) {
+ name = copyString(p);
+ }
+ line = getNextLine(line);
+
+ // get encoding
+ } else if (!encoding && line + 30 <= (char *)file + len &&
+ !strncmp(line, "/Encoding StandardEncoding def", 30)) {
+ encoding = (char **)fofiType1StandardEncoding;
+ } else if (!encoding && line + 19 <= (char *)file + len &&
+ !strncmp(line, "/Encoding 256 array", 19)) {
+ encoding = (char **)gmallocn(256, sizeof(char *));
+ for (j = 0; j < 256; ++j) {
+ encoding[j] = NULL;
+ }
+ for (j = 0, line = getNextLine(line);
+ j < 300 && line && (line1 = getNextLine(line));
+ ++j, line = line1) {
+ if ((n = (int)(line1 - line)) > 255) {
+ n = 255;
+ }
+ strncpy(buf, line, n);
+ buf[n] = '\0';
+ for (p = buf; *p == ' ' || *p == '\t'; ++p) ;
+ endsWithDup = !strncmp(line - 4, "dup\x0a", 4) ||
+ !strncmp(line - 5, "dup\x0d", 4);
+ startsWithDup = !strncmp(p, "dup", 3);
+ if (endsWithDup || startsWithDup) {
+ if (startsWithDup) {
+ p += 3;
+ }
+ while (1) {
+ for (; *p == ' ' || *p == '\t'; ++p) ;
+ code = 0;
+ if (*p == '8' && p[1] == '#') {
+ base = 8;
+ p += 2;
+ } else if (*p >= '0' && *p <= '9') {
+ base = 10;
+ } else {
+ break;
+ }
+ for (; *p >= '0' && *p < '0' + base; ++p) {
+ code = code * base + (*p - '0');
+ }
+ for (; *p == ' ' || *p == '\t'; ++p) ;
+ if (*p != '/') {
+ break;
+ }
+ ++p;
+ for (p2 = p; *p2 && *p2 != ' ' && *p2 != '\t'; ++p2) ;
+ if (code >= 0 && code < 256) {
+ c = *p2;
+ *p2 = '\0';
+ gfree(encoding[code]);
+ encoding[code] = copyString(p);
+ *p2 = c;
+ }
+ for (p = p2; *p == ' ' || *p == '\t'; ++p) ;
+ if (strncmp(p, "put", 3)) {
+ break;
+ }
+ for (p += 3; *p == ' ' || *p == '\t'; ++p) ;
+ if (strncmp(p, "dup", 3)) {
+ break;
+ }
+ p += 3;
+ }
+ } else {
+ if (strtok(buf, " \t") &&
+ (p = strtok(NULL, " \t\n\r")) && !strcmp(p, "def")) {
+ break;
+ }
+ }
+ }
+ //~ check for getinterval/putinterval junk
+
+ } else if (!gotMatrix && line + 11 <= (char *)file + len &&
+ !strncmp(line, "/FontMatrix", 11)) {
+ n = 255;
+ if (line + 11 + n > (char *)file + len) {
+ n = (int)(((char *)file + len) - (line + 11));
+ }
+ strncpy(buf, line + 11, n);
+ buf[n] = '\0';
+ if ((p = strchr(buf, '['))) {
+ ++p;
+ if ((p2 = strchr(p, ']'))) {
+ *p2 = '\0';
+ for (j = 0; j < 6; ++j) {
+ if ((p = strtok(j == 0 ? p : (char *)NULL, " \t\n\r"))) {
+ fontMatrix[j] = atof(p);
+ } else {
+ break;
+ }
+ }
+ }
+ }
+ gotMatrix = gTrue;
+
+ } else {
+ line = getNextLine(line);
+ }
+ }
+
+ parsed = gTrue;
+}
+
+// Undo the PFB encoding, i.e., remove the PFB headers.
+void FoFiType1::undoPFB() {
+ GBool ok;
+ Guchar *file2;
+ int pos1, pos2, type;
+ Guint segLen;
+
+ ok = gTrue;
+ if (getU8(0, &ok) != 0x80 || !ok) {
+ return;
+ }
+ file2 = (Guchar *)gmalloc(len);
+ pos1 = pos2 = 0;
+ while (getU8(pos1, &ok) == 0x80 && ok) {
+ type = getU8(pos1 + 1, &ok);
+ if (type < 1 || type > 2 || !ok) {
+ break;
+ }
+ segLen = getU32LE(pos1 + 2, &ok);
+ pos1 += 6;
+ if (!ok || !checkRegion(pos1, segLen)) {
+ break;
+ }
+ memcpy(file2 + pos2, file + pos1, segLen);
+ pos1 += segLen;
+ pos2 += segLen;
+ }
+ if (freeFileData) {
+ gfree(fileData);
+ }
+ file = fileData = file2;
+ freeFileData = gTrue;
+ len = pos2;
+}
diff --git a/fofi/FoFiType1.h b/fofi/FoFiType1.h
new file mode 100644
index 0000000..4a64f24
--- /dev/null
+++ b/fofi/FoFiType1.h
@@ -0,0 +1,64 @@
+//========================================================================
+//
+// FoFiType1.h
+//
+// Copyright 1999-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef FOFITYPE1_H
+#define FOFITYPE1_H
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include "gtypes.h"
+#include "FoFiBase.h"
+
+//------------------------------------------------------------------------
+// FoFiType1
+//------------------------------------------------------------------------
+
+class FoFiType1: public FoFiBase {
+public:
+
+ // Create a FoFiType1 object from a memory buffer.
+ static FoFiType1 *make(char *fileA, int lenA);
+
+ // Create a FoFiType1 object from a file on disk.
+ static FoFiType1 *load(char *fileName);
+
+ virtual ~FoFiType1();
+
+ // Return the font name.
+ char *getName();
+
+ // Return the encoding, as an array of 256 names (any of which may
+ // be NULL).
+ char **getEncoding();
+
+ // Return the font matrix as an array of six numbers.
+ void getFontMatrix(double *mat);
+
+ // Write a version of the Type 1 font file with a new encoding.
+ void writeEncoded(const char **newEncoding,
+ FoFiOutputFunc outputFunc, void *outputStream);
+
+private:
+
+ FoFiType1(char *fileA, int lenA, GBool freeFileDataA);
+
+ char *getNextLine(char *line);
+ void parse();
+ void undoPFB();
+
+ char *name;
+ char **encoding;
+ double fontMatrix[6];
+ GBool parsed;
+};
+
+#endif
diff --git a/fofi/FoFiType1C.cc b/fofi/FoFiType1C.cc
new file mode 100644
index 0000000..b6a1339
--- /dev/null
+++ b/fofi/FoFiType1C.cc
@@ -0,0 +1,3405 @@
+//========================================================================
+//
+// FoFiType1C.cc
+//
+// Copyright 1999-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include "gmem.h"
+#include "gmempp.h"
+#include "GString.h"
+#include "GHash.h"
+#include "FoFiEncodings.h"
+#include "FoFiType1C.h"
+
+//------------------------------------------------------------------------
+
+static char hexChars[17] = "0123456789ABCDEF";
+
+#define type1cSubrRecursionLimit 20
+
+//------------------------------------------------------------------------
+
+GBool Type1COp::isZero() {
+ switch (kind) {
+ case type1COpInteger: return intgr == 0;
+ case type1COpFloat: return flt == 0;
+ case type1COpRational: return rat.num == 0;
+ default: return gFalse; // shouldn't happen
+ }
+}
+
+GBool Type1COp::isNegative() {
+ switch (kind) {
+ case type1COpInteger:
+ return intgr < 0;
+ case type1COpFloat:
+ return flt < 0;
+ case type1COpRational:
+ return (rat.num < 0) != (rat.den < 0);
+ default:
+ // shouldn't happen
+ return gFalse;
+ }
+}
+
+int Type1COp::toInt() {
+ switch (kind) {
+ case type1COpInteger:
+ return intgr;
+ case type1COpFloat:
+ if (flt < -2e9 || flt > 2e9) {
+ return 0;
+ }
+ return (int)flt;
+ case type1COpRational:
+ if (rat.den == 0) {
+ return 0;
+ }
+ return rat.num / rat.den;
+ default:
+ // shouldn't happen
+ return 0;
+ }
+}
+
+double Type1COp::toFloat() {
+ switch (kind) {
+ case type1COpInteger:
+ return (double)intgr;
+ case type1COpFloat:
+ return flt;
+ case type1COpRational:
+ if (rat.den == 0) {
+ return 0;
+ }
+ return (double)rat.num / (double)rat.den;
+ default:
+ // shouldn't happen
+ return 0.0;
+ }
+}
+
+//------------------------------------------------------------------------
+// FoFiType1C
+//------------------------------------------------------------------------
+
+FoFiType1C *FoFiType1C::make(char *fileA, int lenA) {
+ FoFiType1C *ff;
+
+ ff = new FoFiType1C(fileA, lenA, gFalse);
+ if (!ff->parse()) {
+ delete ff;
+ return NULL;
+ }
+ return ff;
+}
+
+FoFiType1C *FoFiType1C::load(char *fileName) {
+ FoFiType1C *ff;
+ char *fileA;
+ int lenA;
+
+ if (!(fileA = FoFiBase::readFile(fileName, &lenA))) {
+ return NULL;
+ }
+ ff = new FoFiType1C(fileA, lenA, gTrue);
+ if (!ff->parse()) {
+ delete ff;
+ return NULL;
+ }
+ return ff;
+}
+
+FoFiType1C::FoFiType1C(char *fileA, int lenA, GBool freeFileDataA):
+ FoFiBase(fileA, lenA, freeFileDataA)
+{
+ name = NULL;
+ encoding = NULL;
+ privateDicts = NULL;
+ fdSelect = NULL;
+ charset = NULL;
+}
+
+FoFiType1C::~FoFiType1C() {
+ int i;
+
+ if (name) {
+ delete name;
+ }
+ if (encoding &&
+ encoding != (char **)fofiType1StandardEncoding &&
+ encoding != (char **)fofiType1ExpertEncoding) {
+ for (i = 0; i < 256; ++i) {
+ gfree(encoding[i]);
+ }
+ gfree(encoding);
+ }
+ if (privateDicts) {
+ gfree(privateDicts);
+ }
+ if (fdSelect) {
+ gfree(fdSelect);
+ }
+ if (charset &&
+ charset != fofiType1CISOAdobeCharset &&
+ charset != fofiType1CExpertCharset &&
+ charset != fofiType1CExpertSubsetCharset) {
+ gfree(charset);
+ }
+}
+
+char *FoFiType1C::getName() {
+ return name ? name->getCString() : (char *)NULL;
+}
+
+char **FoFiType1C::getEncoding() {
+ return encoding;
+}
+
+GString *FoFiType1C::getGlyphName(int gid) {
+ char buf[256];
+ GBool ok;
+
+ ok = gTrue;
+ getString(charset[gid], buf, &ok);
+ if (!ok) {
+ return NULL;
+ }
+ return new GString(buf);
+}
+
+GHash *FoFiType1C::getNameToGIDMap() {
+ GHash *map;
+ char name[256];
+ GBool ok;
+ int gid;
+
+ map = new GHash(gTrue);
+ for (gid = 0; gid < nGlyphs; ++gid) {
+ ok = gTrue;
+ getString(charset[gid], name, &ok);
+ if (ok) {
+ map->add(new GString(name), gid);
+ }
+ }
+ return map;
+}
+
+int *FoFiType1C::getCIDToGIDMap(int *nCIDs) {
+ int *map;
+ int n, i;
+
+ // a CID font's top dict has ROS as the first operator
+ if (topDict.firstOp != 0x0c1e) {
+ *nCIDs = 0;
+ return NULL;
+ }
+
+ // in a CID font, the charset data is the GID-to-CID mapping, so all
+ // we have to do is reverse it
+ n = 0;
+ for (i = 0; i < nGlyphs; ++i) {
+ if (charset[i] > n) {
+ n = charset[i];
+ }
+ }
+ ++n;
+ map = (int *)gmallocn(n, sizeof(int));
+ memset(map, 0, n * sizeof(int));
+ for (i = 0; i < nGlyphs; ++i) {
+ map[charset[i]] = i;
+ }
+ *nCIDs = n;
+ return map;
+}
+
+void FoFiType1C::getFontMatrix(double *mat) {
+ int i;
+
+ if (topDict.firstOp == 0x0c1e && privateDicts[0].hasFontMatrix) {
+ if (topDict.hasFontMatrix) {
+ mat[0] = topDict.fontMatrix[0] * privateDicts[0].fontMatrix[0] +
+ topDict.fontMatrix[1] * privateDicts[0].fontMatrix[2];
+ mat[1] = topDict.fontMatrix[0] * privateDicts[0].fontMatrix[1] +
+ topDict.fontMatrix[1] * privateDicts[0].fontMatrix[3];
+ mat[2] = topDict.fontMatrix[2] * privateDicts[0].fontMatrix[0] +
+ topDict.fontMatrix[3] * privateDicts[0].fontMatrix[2];
+ mat[3] = topDict.fontMatrix[2] * privateDicts[0].fontMatrix[1] +
+ topDict.fontMatrix[3] * privateDicts[0].fontMatrix[3];
+ mat[4] = topDict.fontMatrix[4] * privateDicts[0].fontMatrix[0] +
+ topDict.fontMatrix[5] * privateDicts[0].fontMatrix[2];
+ mat[5] = topDict.fontMatrix[4] * privateDicts[0].fontMatrix[1] +
+ topDict.fontMatrix[5] * privateDicts[0].fontMatrix[3];
+ } else {
+ for (i = 0; i < 6; ++i) {
+ mat[i] = privateDicts[0].fontMatrix[i];
+ }
+ }
+ } else {
+ for (i = 0; i < 6; ++i) {
+ mat[i] = topDict.fontMatrix[i];
+ }
+ }
+}
+
+void FoFiType1C::convertToType1(char *psName, const char **newEncoding,
+ GBool ascii, FoFiOutputFunc outputFunc,
+ void *outputStream) {
+ int psNameLen;
+ Type1CEexecBuf eb;
+ Type1CIndex subrIdx;
+ Type1CIndexVal val;
+ GString *buf;
+ char buf2[256];
+ const char **enc;
+ GBool ok;
+ int i;
+
+ if (psName) {
+ psNameLen = (int)strlen(psName);
+ } else {
+ psName = name->getCString();
+ psNameLen = name->getLength();
+ }
+
+ // write header and font dictionary, up to encoding
+ ok = gTrue;
+ (*outputFunc)(outputStream, "%!FontType1-1.0: ", 17);
+ (*outputFunc)(outputStream, psName, psNameLen);
+ if (topDict.versionSID != 0) {
+ getString(topDict.versionSID, buf2, &ok);
+ (*outputFunc)(outputStream, buf2, (int)strlen(buf2));
+ }
+ (*outputFunc)(outputStream, "\n", 1);
+ // the dictionary needs room for 12 entries: the following 9, plus
+ // Private and CharStrings (in the eexec section) and FID (which is
+ // added by definefont)
+ (*outputFunc)(outputStream, "12 dict begin\n", 14);
+ (*outputFunc)(outputStream, "/FontInfo 10 dict dup begin\n", 28);
+ if (topDict.versionSID != 0) {
+ (*outputFunc)(outputStream, "/version ", 9);
+ writePSString(buf2, outputFunc, outputStream);
+ (*outputFunc)(outputStream, " readonly def\n", 14);
+ }
+ if (topDict.noticeSID != 0) {
+ getString(topDict.noticeSID, buf2, &ok);
+ (*outputFunc)(outputStream, "/Notice ", 8);
+ writePSString(buf2, outputFunc, outputStream);
+ (*outputFunc)(outputStream, " readonly def\n", 14);
+ }
+ if (topDict.copyrightSID != 0) {
+ getString(topDict.copyrightSID, buf2, &ok);
+ (*outputFunc)(outputStream, "/Copyright ", 11);
+ writePSString(buf2, outputFunc, outputStream);
+ (*outputFunc)(outputStream, " readonly def\n", 14);
+ }
+ if (topDict.fullNameSID != 0) {
+ getString(topDict.fullNameSID, buf2, &ok);
+ (*outputFunc)(outputStream, "/FullName ", 10);
+ writePSString(buf2, outputFunc, outputStream);
+ (*outputFunc)(outputStream, " readonly def\n", 14);
+ }
+ if (topDict.familyNameSID != 0) {
+ getString(topDict.familyNameSID, buf2, &ok);
+ (*outputFunc)(outputStream, "/FamilyName ", 12);
+ writePSString(buf2, outputFunc, outputStream);
+ (*outputFunc)(outputStream, " readonly def\n", 14);
+ }
+ if (topDict.weightSID != 0) {
+ getString(topDict.weightSID, buf2, &ok);
+ (*outputFunc)(outputStream, "/Weight ", 8);
+ writePSString(buf2, outputFunc, outputStream);
+ (*outputFunc)(outputStream, " readonly def\n", 14);
+ }
+ if (topDict.isFixedPitch) {
+ (*outputFunc)(outputStream, "/isFixedPitch true def\n", 23);
+ } else {
+ (*outputFunc)(outputStream, "/isFixedPitch false def\n", 24);
+ }
+ buf = GString::format("/ItalicAngle {0:.4g} def\n", topDict.italicAngle);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ buf = GString::format("/UnderlinePosition {0:.4g} def\n",
+ topDict.underlinePosition);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ buf = GString::format("/UnderlineThickness {0:.4g} def\n",
+ topDict.underlineThickness);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ (*outputFunc)(outputStream, "end readonly def\n", 17);
+ (*outputFunc)(outputStream, "/FontName /", 11);
+ (*outputFunc)(outputStream, psName, psNameLen);
+ (*outputFunc)(outputStream, " def\n", 5);
+ buf = GString::format("/PaintType {0:d} def\n", topDict.paintType);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ (*outputFunc)(outputStream, "/FontType 1 def\n", 16);
+ buf = GString::format("/FontMatrix [{0:.8g} {1:.8g} {2:.8g} {3:.8g} {4:.8g} {5:.8g}] readonly def\n",
+ topDict.fontMatrix[0], topDict.fontMatrix[1],
+ topDict.fontMatrix[2], topDict.fontMatrix[3],
+ topDict.fontMatrix[4], topDict.fontMatrix[5]);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ buf = GString::format("/FontBBox [{0:.4g} {1:.4g} {2:.4g} {3:.4g}] readonly def\n",
+ topDict.fontBBox[0], topDict.fontBBox[1],
+ topDict.fontBBox[2], topDict.fontBBox[3]);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ buf = GString::format("/StrokeWidth {0:.4g} def\n", topDict.strokeWidth);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ if (topDict.uniqueID != 0) {
+ buf = GString::format("/UniqueID {0:d} def\n", topDict.uniqueID);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ }
+
+ // write the encoding
+ (*outputFunc)(outputStream, "/Encoding ", 10);
+ if (!newEncoding && encoding == (char **)fofiType1StandardEncoding) {
+ (*outputFunc)(outputStream, "StandardEncoding def\n", 21);
+ } else {
+ (*outputFunc)(outputStream, "256 array\n", 10);
+ (*outputFunc)(outputStream,
+ "0 1 255 {1 index exch /.notdef put} for\n", 40);
+ enc = newEncoding ? newEncoding : (const char **)encoding;
+ for (i = 0; i < 256; ++i) {
+ if (enc[i]) {
+ buf = GString::format("dup {0:d} /{1:s} put\n", i, enc[i]);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ }
+ }
+ (*outputFunc)(outputStream, "readonly def\n", 13);
+ }
+ (*outputFunc)(outputStream, "currentdict end\n", 16);
+
+ // start the binary section
+ (*outputFunc)(outputStream, "currentfile eexec\n", 18);
+ eb.outputFunc = outputFunc;
+ eb.outputStream = outputStream;
+ eb.ascii = ascii;
+ eb.r1 = 55665;
+ eb.line = 0;
+
+ // write the private dictionary
+ eexecWrite(&eb, "\x83\xca\x73\xd5");
+ eexecWrite(&eb, "dup /Private 32 dict dup begin\n");
+ eexecWrite(&eb, "/RD {string currentfile exch readstring pop}"
+ " executeonly def\n");
+ eexecWrite(&eb, "/ND {noaccess def} executeonly def\n");
+ eexecWrite(&eb, "/NP {noaccess put} executeonly def\n");
+ eexecWrite(&eb, "/MinFeature {16 16} def\n");
+ eexecWrite(&eb, "/password 5839 def\n");
+ if (privateDicts[0].nBlueValues) {
+ eexecWrite(&eb, "/BlueValues [");
+ // number of entries must be even
+ int n = privateDicts[0].nBlueValues & ~1;
+ for (i = 0; i < n; ++i) {
+ buf = GString::format("{0:s}{1:d}",
+ i > 0 ? " " : "", privateDicts[0].blueValues[i]);
+ eexecWrite(&eb, buf->getCString());
+ delete buf;
+ }
+ eexecWrite(&eb, "] def\n");
+ }
+ if (privateDicts[0].nOtherBlues) {
+ eexecWrite(&eb, "/OtherBlues [");
+ // number of entries must be even
+ int n = privateDicts[0].nOtherBlues & ~1;
+ for (i = 0; i < n; ++i) {
+ buf = GString::format("{0:s}{1:d}",
+ i > 0 ? " " : "", privateDicts[0].otherBlues[i]);
+ eexecWrite(&eb, buf->getCString());
+ delete buf;
+ }
+ eexecWrite(&eb, "] def\n");
+ }
+ if (privateDicts[0].nFamilyBlues) {
+ eexecWrite(&eb, "/FamilyBlues [");
+ // number of entries must be even
+ int n = privateDicts[0].nFamilyBlues & ~1;
+ for (i = 0; i < n; ++i) {
+ buf = GString::format("{0:s}{1:d}",
+ i > 0 ? " " : "", privateDicts[0].familyBlues[i]);
+ eexecWrite(&eb, buf->getCString());
+ delete buf;
+ }
+ eexecWrite(&eb, "] def\n");
+ }
+ if (privateDicts[0].nFamilyOtherBlues) {
+ eexecWrite(&eb, "/FamilyOtherBlues [");
+ // number of entries must be even
+ int n = privateDicts[0].nFamilyOtherBlues & ~1;
+ for (i = 0; i < n; ++i) {
+ buf = GString::format("{0:s}{1:d}", i > 0 ? " " : "",
+ privateDicts[0].familyOtherBlues[i]);
+ eexecWrite(&eb, buf->getCString());
+ delete buf;
+ }
+ eexecWrite(&eb, "] def\n");
+ }
+ if (privateDicts[0].blueScale != 0.039625) {
+ buf = GString::format("/BlueScale {0:.4g} def\n",
+ privateDicts[0].blueScale);
+ eexecWrite(&eb, buf->getCString());
+ delete buf;
+ }
+ if (privateDicts[0].blueShift != 7) {
+ buf = GString::format("/BlueShift {0:d} def\n", privateDicts[0].blueShift);
+ eexecWrite(&eb, buf->getCString());
+ delete buf;
+ }
+ if (privateDicts[0].blueFuzz != 1) {
+ buf = GString::format("/BlueFuzz {0:d} def\n", privateDicts[0].blueFuzz);
+ eexecWrite(&eb, buf->getCString());
+ delete buf;
+ }
+ if (privateDicts[0].hasStdHW) {
+ buf = GString::format("/StdHW [{0:.4g}] def\n", privateDicts[0].stdHW);
+ eexecWrite(&eb, buf->getCString());
+ delete buf;
+ }
+ if (privateDicts[0].hasStdVW) {
+ buf = GString::format("/StdVW [{0:.4g}] def\n", privateDicts[0].stdVW);
+ eexecWrite(&eb, buf->getCString());
+ delete buf;
+ }
+ if (privateDicts[0].nStemSnapH) {
+ // the StemSnapH array should be unique values in ascending order --
+ // if not, just skip it
+ for (i = 1; i < privateDicts[0].nStemSnapH; ++i) {
+ if (privateDicts[0].stemSnapH[i-1] >= privateDicts[0].stemSnapH[i]) {
+ break;
+ }
+ }
+ if (i == privateDicts[0].nStemSnapH) {
+ eexecWrite(&eb, "/StemSnapH [");
+ for (i = 0; i < privateDicts[0].nStemSnapH; ++i) {
+ buf = GString::format("{0:s}{1:.4g}",
+ i > 0 ? " " : "", privateDicts[0].stemSnapH[i]);
+ eexecWrite(&eb, buf->getCString());
+ delete buf;
+ }
+ eexecWrite(&eb, "] def\n");
+ }
+ }
+ if (privateDicts[0].nStemSnapV) {
+ // the StemSnapV array should be unique values in ascending order --
+ // if not, just skip it
+ for (i = 1; i < privateDicts[0].nStemSnapV; ++i) {
+ if (privateDicts[0].stemSnapV[i-1] >= privateDicts[0].stemSnapV[i]) {
+ break;
+ }
+ }
+ if (i == privateDicts[0].nStemSnapV) {
+ eexecWrite(&eb, "/StemSnapV [");
+ for (i = 0; i < privateDicts[0].nStemSnapV; ++i) {
+ buf = GString::format("{0:s}{1:.4g}",
+ i > 0 ? " " : "", privateDicts[0].stemSnapV[i]);
+ eexecWrite(&eb, buf->getCString());
+ delete buf;
+ }
+ eexecWrite(&eb, "] def\n");
+ }
+ }
+ if (privateDicts[0].hasForceBold) {
+ buf = GString::format("/ForceBold {0:s} def\n",
+ privateDicts[0].forceBold ? "true" : "false");
+ eexecWrite(&eb, buf->getCString());
+ delete buf;
+ }
+ if (privateDicts[0].forceBoldThreshold != 0) {
+ buf = GString::format("/ForceBoldThreshold {0:.4g} def\n",
+ privateDicts[0].forceBoldThreshold);
+ eexecWrite(&eb, buf->getCString());
+ delete buf;
+ }
+ if (privateDicts[0].languageGroup != 0) {
+ buf = GString::format("/LanguageGroup {0:d} def\n",
+ privateDicts[0].languageGroup);
+ eexecWrite(&eb, buf->getCString());
+ delete buf;
+ }
+ if (privateDicts[0].expansionFactor != 0.06) {
+ buf = GString::format("/ExpansionFactor {0:.4g} def\n",
+ privateDicts[0].expansionFactor);
+ eexecWrite(&eb, buf->getCString());
+ delete buf;
+ }
+
+ // set up subroutines
+ ok = gTrue;
+ getIndex(privateDicts[0].subrsOffset, &subrIdx, &ok);
+ if (!ok) {
+ subrIdx.pos = -1;
+ }
+
+ // write the CharStrings
+ buf = GString::format("2 index /CharStrings {0:d} dict dup begin\n",
+ nGlyphs);
+ eexecWrite(&eb, buf->getCString());
+ delete buf;
+ for (i = 0; i < nGlyphs; ++i) {
+ ok = gTrue;
+ getIndexVal(&charStringsIdx, i, &val, &ok);
+ if (ok) {
+ getString(charset[i], buf2, &ok);
+ if (ok) {
+ eexecCvtGlyph(&eb, buf2, val.pos, val.len, &subrIdx, &privateDicts[0]);
+ }
+ }
+ }
+ eexecWrite(&eb, "end\n");
+ eexecWrite(&eb, "end\n");
+ eexecWrite(&eb, "readonly put\n");
+ eexecWrite(&eb, "noaccess put\n");
+ eexecWrite(&eb, "dup /FontName get exch definefont pop\n");
+ eexecWrite(&eb, "mark currentfile closefile\n");
+
+ // trailer
+ if (ascii && eb.line > 0) {
+ (*outputFunc)(outputStream, "\n", 1);
+ }
+ for (i = 0; i < 8; ++i) {
+ (*outputFunc)(outputStream, "0000000000000000000000000000000000000000000000000000000000000000\n", 65);
+ }
+ (*outputFunc)(outputStream, "cleartomark\n", 12);
+}
+
+void FoFiType1C::convertToCIDType0(char *psName, int *codeMap, int nCodes,
+ FoFiOutputFunc outputFunc,
+ void *outputStream) {
+ int *cidMap;
+ GString *charStrings;
+ int *charStringOffsets;
+ Type1CIndex subrIdx;
+ Type1CIndexVal val;
+ int nCIDs, gdBytes;
+ GString *buf;
+ char buf2[256];
+ GBool ok;
+ int gid, offset, n, i, j, k;
+
+ // compute the CID count and build the CID-to-GID mapping
+ if (codeMap) {
+ nCIDs = nCodes;
+ cidMap = (int *)gmallocn(nCIDs, sizeof(int));
+ for (i = 0; i < nCodes; ++i) {
+ if (codeMap[i] >= 0 && codeMap[i] < nGlyphs) {
+ cidMap[i] = codeMap[i];
+ } else {
+ cidMap[i] = -1;
+ }
+ }
+ } else if (topDict.firstOp == 0x0c1e) {
+ nCIDs = 0;
+ for (i = 0; i < nGlyphs; ++i) {
+ if (charset[i] >= nCIDs) {
+ nCIDs = charset[i] + 1;
+ }
+ }
+ cidMap = (int *)gmallocn(nCIDs, sizeof(int));
+ for (i = 0; i < nCIDs; ++i) {
+ cidMap[i] = -1;
+ }
+ for (i = 0; i < nGlyphs; ++i) {
+ cidMap[charset[i]] = i;
+ }
+ } else {
+ nCIDs = nGlyphs;
+ cidMap = (int *)gmallocn(nCIDs, sizeof(int));
+ for (i = 0; i < nCIDs; ++i) {
+ cidMap[i] = i;
+ }
+ }
+
+ // build the charstrings
+ charStrings = new GString();
+ charStringOffsets = (int *)gmallocn(nCIDs + 1, sizeof(int));
+ for (i = 0; i < nCIDs; ++i) {
+ charStringOffsets[i] = charStrings->getLength();
+ if ((gid = cidMap[i]) >= 0) {
+ ok = gTrue;
+ getIndexVal(&charStringsIdx, gid, &val, &ok);
+ if (ok) {
+ getIndex(privateDicts[fdSelect ? fdSelect[gid] : 0].subrsOffset,
+ &subrIdx, &ok);
+ if (!ok) {
+ subrIdx.pos = -1;
+ }
+ cvtGlyph(val.pos, val.len, charStrings,
+ &subrIdx, &privateDicts[fdSelect ? fdSelect[gid] : 0],
+ gTrue, 0);
+ }
+ }
+ }
+ charStringOffsets[nCIDs] = charStrings->getLength();
+
+ // compute gdBytes = number of bytes needed for charstring offsets
+ // (offset size needs to account for the charstring offset table,
+ // with a worst case of five bytes per entry, plus the charstrings
+ // themselves)
+ i = (nCIDs + 1) * 5 + charStrings->getLength();
+ if (i < 0x100) {
+ gdBytes = 1;
+ } else if (i < 0x10000) {
+ gdBytes = 2;
+ } else if (i < 0x1000000) {
+ gdBytes = 3;
+ } else {
+ gdBytes = 4;
+ }
+
+ // begin the font dictionary
+ (*outputFunc)(outputStream, "/CIDInit /ProcSet findresource begin\n", 37);
+ (*outputFunc)(outputStream, "20 dict begin\n", 14);
+ (*outputFunc)(outputStream, "/CIDFontName /", 14);
+ (*outputFunc)(outputStream, psName, (int)strlen(psName));
+ (*outputFunc)(outputStream, " def\n", 5);
+ (*outputFunc)(outputStream, "/CIDFontType 0 def\n", 19);
+ (*outputFunc)(outputStream, "/CIDSystemInfo 3 dict dup begin\n", 32);
+ if (topDict.registrySID > 0 && topDict.orderingSID > 0) {
+ ok = gTrue;
+ getString(topDict.registrySID, buf2, &ok);
+ if (ok) {
+ (*outputFunc)(outputStream, " /Registry (", 13);
+ (*outputFunc)(outputStream, buf2, (int)strlen(buf2));
+ (*outputFunc)(outputStream, ") def\n", 6);
+ }
+ ok = gTrue;
+ getString(topDict.orderingSID, buf2, &ok);
+ if (ok) {
+ (*outputFunc)(outputStream, " /Ordering (", 13);
+ (*outputFunc)(outputStream, buf2, (int)strlen(buf2));
+ (*outputFunc)(outputStream, ") def\n", 6);
+ }
+ } else {
+ (*outputFunc)(outputStream, " /Registry (Adobe) def\n", 24);
+ (*outputFunc)(outputStream, " /Ordering (Identity) def\n", 27);
+ }
+ buf = GString::format(" /Supplement {0:d} def\n", topDict.supplement);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ (*outputFunc)(outputStream, "end def\n", 8);
+ if (topDict.hasFontMatrix) {
+ buf = GString::format("/FontMatrix [{0:.8g} {1:.8g} {2:.8g} {3:.8g} {4:.8g} {5:.8g}] def\n",
+ topDict.fontMatrix[0], topDict.fontMatrix[1],
+ topDict.fontMatrix[2], topDict.fontMatrix[3],
+ topDict.fontMatrix[4], topDict.fontMatrix[5]);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ } else if (privateDicts[0].hasFontMatrix) {
+ (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
+ } else {
+ (*outputFunc)(outputStream,
+ "/FontMatrix [0.001 0 0 0.001 0 0] def\n", 38);
+ }
+ buf = GString::format("/FontBBox [{0:.4g} {1:.4g} {2:.4g} {3:.4g}] def\n",
+ topDict.fontBBox[0], topDict.fontBBox[1],
+ topDict.fontBBox[2], topDict.fontBBox[3]);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ (*outputFunc)(outputStream, "/FontInfo 1 dict dup begin\n", 27);
+ (*outputFunc)(outputStream, " /FSType 8 def\n", 16);
+ (*outputFunc)(outputStream, "end def\n", 8);
+
+ // CIDFont-specific entries
+ buf = GString::format("/CIDCount {0:d} def\n", nCIDs);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ (*outputFunc)(outputStream, "/FDBytes 1 def\n", 15);
+ buf = GString::format("/GDBytes {0:d} def\n", gdBytes);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ (*outputFunc)(outputStream, "/CIDMapOffset 0 def\n", 20);
+ if (topDict.paintType != 0) {
+ buf = GString::format("/PaintType {0:d} def\n", topDict.paintType);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ buf = GString::format("/StrokeWidth {0:.4g} def\n", topDict.strokeWidth);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ }
+
+ // FDArray entry
+ buf = GString::format("/FDArray {0:d} array\n", nFDs);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ for (i = 0; i < nFDs; ++i) {
+ buf = GString::format("dup {0:d} 10 dict begin\n", i);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ (*outputFunc)(outputStream, "/FontType 1 def\n", 16);
+ if (privateDicts[i].hasFontMatrix) {
+ buf = GString::format("/FontMatrix [{0:.8g} {1:.8g} {2:.8g} {3:.8g} {4:.8g} {5:.8g}] def\n",
+ privateDicts[i].fontMatrix[0],
+ privateDicts[i].fontMatrix[1],
+ privateDicts[i].fontMatrix[2],
+ privateDicts[i].fontMatrix[3],
+ privateDicts[i].fontMatrix[4],
+ privateDicts[i].fontMatrix[5]);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ } else {
+ (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
+ }
+ buf = GString::format("/PaintType {0:d} def\n", topDict.paintType);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ (*outputFunc)(outputStream, "/Private 32 dict begin\n", 23);
+ if (privateDicts[i].nBlueValues) {
+ (*outputFunc)(outputStream, "/BlueValues [", 13);
+ for (j = 0; j < privateDicts[i].nBlueValues; ++j) {
+ buf = GString::format("{0:s}{1:d}",
+ j > 0 ? " " : "", privateDicts[i].blueValues[j]);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ }
+ (*outputFunc)(outputStream, "] def\n", 6);
+ }
+ if (privateDicts[i].nOtherBlues) {
+ (*outputFunc)(outputStream, "/OtherBlues [", 13);
+ for (j = 0; j < privateDicts[i].nOtherBlues; ++j) {
+ buf = GString::format("{0:s}{1:d}",
+ j > 0 ? " " : "", privateDicts[i].otherBlues[j]);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ }
+ (*outputFunc)(outputStream, "] def\n", 6);
+ }
+ if (privateDicts[i].nFamilyBlues) {
+ (*outputFunc)(outputStream, "/FamilyBlues [", 14);
+ for (j = 0; j < privateDicts[i].nFamilyBlues; ++j) {
+ buf = GString::format("{0:s}{1:d}",
+ j > 0 ? " " : "",
+ privateDicts[i].familyBlues[j]);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ }
+ (*outputFunc)(outputStream, "] def\n", 6);
+ }
+ if (privateDicts[i].nFamilyOtherBlues) {
+ (*outputFunc)(outputStream, "/FamilyOtherBlues [", 19);
+ for (j = 0; j < privateDicts[i].nFamilyOtherBlues; ++j) {
+ buf = GString::format("{0:s}{1:d}", j > 0 ? " " : "",
+ privateDicts[i].familyOtherBlues[j]);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ }
+ (*outputFunc)(outputStream, "] def\n", 6);
+ }
+ if (privateDicts[i].blueScale != 0.039625) {
+ buf = GString::format("/BlueScale {0:.4g} def\n",
+ privateDicts[i].blueScale);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ }
+ if (privateDicts[i].blueShift != 7) {
+ buf = GString::format("/BlueShift {0:d} def\n",
+ privateDicts[i].blueShift);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ }
+ if (privateDicts[i].blueFuzz != 1) {
+ buf = GString::format("/BlueFuzz {0:d} def\n", privateDicts[i].blueFuzz);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ }
+ if (privateDicts[i].hasStdHW) {
+ buf = GString::format("/StdHW [{0:.4g}] def\n", privateDicts[i].stdHW);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ }
+ if (privateDicts[i].hasStdVW) {
+ buf = GString::format("/StdVW [{0:.4g}] def\n", privateDicts[i].stdVW);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ }
+ if (privateDicts[i].nStemSnapH) {
+ // the StemSnapH array should be unique values in ascending order --
+ // if not, just skip it
+ for (j = 1; j < privateDicts[i].nStemSnapH; ++j) {
+ if (privateDicts[i].stemSnapH[j-1] >= privateDicts[i].stemSnapH[j]) {
+ break;
+ }
+ }
+ if (j == privateDicts[i].nStemSnapH) {
+ (*outputFunc)(outputStream, "/StemSnapH [", 12);
+ for (j = 0; j < privateDicts[i].nStemSnapH; ++j) {
+ buf = GString::format("{0:s}{1:.4g}",
+ j > 0 ? " " : "", privateDicts[i].stemSnapH[j]);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ }
+ (*outputFunc)(outputStream, "] def\n", 6);
+ }
+ }
+ if (privateDicts[i].nStemSnapV) {
+ // the StemSnapV array should be unique values in ascending order --
+ // if not, just skip it
+ for (j = 1; j < privateDicts[i].nStemSnapV; ++j) {
+ if (privateDicts[i].stemSnapV[j-1] >= privateDicts[i].stemSnapV[j]) {
+ break;
+ }
+ }
+ if (j == privateDicts[i].nStemSnapV) {
+ (*outputFunc)(outputStream, "/StemSnapV [", 12);
+ for (j = 0; j < privateDicts[i].nStemSnapV; ++j) {
+ buf = GString::format("{0:s}{1:.4g}",
+ j > 0 ? " " : "", privateDicts[i].stemSnapV[j]);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ }
+ (*outputFunc)(outputStream, "] def\n", 6);
+ }
+ }
+ if (privateDicts[i].hasForceBold) {
+ buf = GString::format("/ForceBold {0:s} def\n",
+ privateDicts[i].forceBold ? "true" : "false");
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ }
+ if (privateDicts[i].forceBoldThreshold != 0) {
+ buf = GString::format("/ForceBoldThreshold {0:.4g} def\n",
+ privateDicts[i].forceBoldThreshold);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ }
+ if (privateDicts[i].languageGroup != 0) {
+ buf = GString::format("/LanguageGroup {0:d} def\n",
+ privateDicts[i].languageGroup);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ }
+ if (privateDicts[i].expansionFactor != 0.06) {
+ buf = GString::format("/ExpansionFactor {0:.4g} def\n",
+ privateDicts[i].expansionFactor);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ }
+ (*outputFunc)(outputStream, "currentdict end def\n", 20);
+ (*outputFunc)(outputStream, "currentdict end put\n", 20);
+ }
+ (*outputFunc)(outputStream, "def\n", 4);
+
+ // start the binary section
+ offset = (nCIDs + 1) * (1 + gdBytes);
+ buf = GString::format("(Hex) {0:d} StartData\n",
+ offset + charStrings->getLength());
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+
+ // write the charstring offset (CIDMap) table
+ for (i = 0; i <= nCIDs; i += 6) {
+ for (j = 0; j < 6 && i+j <= nCIDs; ++j) {
+ if (i+j < nCIDs && cidMap[i+j] >= 0 && fdSelect) {
+ buf2[0] = (char)fdSelect[cidMap[i+j]];
+ } else {
+ buf2[0] = (char)0;
+ }
+ n = offset + charStringOffsets[i+j];
+ for (k = gdBytes; k >= 1; --k) {
+ buf2[k] = (char)(n & 0xff);
+ n >>= 8;
+ }
+ for (k = 0; k <= gdBytes; ++k) {
+ buf = GString::format("{0:02x}", buf2[k] & 0xff);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ }
+ }
+ (*outputFunc)(outputStream, "\n", 1);
+ }
+
+ // write the charstring data
+ n = charStrings->getLength();
+ for (i = 0; i < n; i += 32) {
+ for (j = 0; j < 32 && i+j < n; ++j) {
+ buf = GString::format("{0:02x}", charStrings->getChar(i+j) & 0xff);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ }
+ if (i + 32 >= n) {
+ (*outputFunc)(outputStream, ">", 1);
+ }
+ (*outputFunc)(outputStream, "\n", 1);
+ }
+
+ gfree(charStringOffsets);
+ delete charStrings;
+ gfree(cidMap);
+}
+
+void FoFiType1C::convertToType0(char *psName, int *codeMap, int nCodes,
+ FoFiOutputFunc outputFunc,
+ void *outputStream) {
+ int *cidMap;
+ Type1CIndex subrIdx;
+ Type1CIndexVal val;
+ int nCIDs;
+ GString *buf;
+ Type1CEexecBuf eb;
+ GBool ok;
+ int fd, i, j, k;
+
+ // compute the CID count and build the CID-to-GID mapping
+ if (codeMap) {
+ nCIDs = nCodes;
+ cidMap = (int *)gmallocn(nCIDs, sizeof(int));
+ for (i = 0; i < nCodes; ++i) {
+ if (codeMap[i] >= 0 && codeMap[i] < nGlyphs) {
+ cidMap[i] = codeMap[i];
+ } else {
+ cidMap[i] = -1;
+ }
+ }
+ } else if (topDict.firstOp == 0x0c1e) {
+ nCIDs = 0;
+ for (i = 0; i < nGlyphs; ++i) {
+ if (charset[i] >= nCIDs) {
+ nCIDs = charset[i] + 1;
+ }
+ }
+ cidMap = (int *)gmallocn(nCIDs, sizeof(int));
+ for (i = 0; i < nCIDs; ++i) {
+ cidMap[i] = -1;
+ }
+ for (i = 0; i < nGlyphs; ++i) {
+ cidMap[charset[i]] = i;
+ }
+ } else {
+ nCIDs = nGlyphs;
+ cidMap = (int *)gmallocn(nCIDs, sizeof(int));
+ for (i = 0; i < nCIDs; ++i) {
+ cidMap[i] = i;
+ }
+ }
+
+ // write the descendant Type 1 fonts
+ for (i = 0; i < nCIDs; i += 256) {
+
+ //~ this assumes that all CIDs in this block have the same FD --
+ //~ to handle multiple FDs correctly, need to somehow divide the
+ //~ font up by FD; as a kludge we ignore CID 0, which is .notdef
+ fd = 0;
+ // if fdSelect is NULL, we have an 8-bit font, so just leave fd=0
+ if (fdSelect) {
+ for (j = i==0 ? 1 : 0; j < 256 && i+j < nCIDs; ++j) {
+ if (cidMap[i+j] >= 0) {
+ fd = fdSelect[cidMap[i+j]];
+ break;
+ }
+ }
+ }
+ if (fd < 0 || fd >= nFDs) {
+ // this will only happen in a broken/damaged font
+ fd = 0;
+ }
+
+ // font dictionary (unencrypted section)
+ (*outputFunc)(outputStream, "16 dict begin\n", 14);
+ (*outputFunc)(outputStream, "/FontName /", 11);
+ (*outputFunc)(outputStream, psName, (int)strlen(psName));
+ buf = GString::format("_{0:02x} def\n", i >> 8);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ (*outputFunc)(outputStream, "/FontType 1 def\n", 16);
+ if (privateDicts[fd].hasFontMatrix) {
+ buf = GString::format("/FontMatrix [{0:.8g} {1:.8g} {2:.8g} {3:.8g} {4:.8g} {5:.8g}] def\n",
+ privateDicts[fd].fontMatrix[0],
+ privateDicts[fd].fontMatrix[1],
+ privateDicts[fd].fontMatrix[2],
+ privateDicts[fd].fontMatrix[3],
+ privateDicts[fd].fontMatrix[4],
+ privateDicts[fd].fontMatrix[5]);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ } else if (topDict.hasFontMatrix) {
+ (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
+ } else {
+ (*outputFunc)(outputStream,
+ "/FontMatrix [0.001 0 0 0.001 0 0] def\n", 38);
+ }
+ buf = GString::format("/FontBBox [{0:.4g} {1:.4g} {2:.4g} {3:.4g}] def\n",
+ topDict.fontBBox[0], topDict.fontBBox[1],
+ topDict.fontBBox[2], topDict.fontBBox[3]);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ buf = GString::format("/PaintType {0:d} def\n", topDict.paintType);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ if (topDict.paintType != 0) {
+ buf = GString::format("/StrokeWidth {0:.4g} def\n", topDict.strokeWidth);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ }
+ (*outputFunc)(outputStream, "/Encoding 256 array\n", 20);
+ for (j = 0; j < 256 && i+j < nCIDs; ++j) {
+ buf = GString::format("dup {0:d} /c{1:02x} put\n", j, j);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ }
+ if (j < 256) {
+ buf = GString::format("{0:d} 1 255 {{ 1 index exch /.notdef put }} for\n",
+ j);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ }
+ (*outputFunc)(outputStream, "readonly def\n", 13);
+ (*outputFunc)(outputStream, "currentdict end\n", 16);
+
+ // start the binary section
+ (*outputFunc)(outputStream, "currentfile eexec\n", 18);
+ eb.outputFunc = outputFunc;
+ eb.outputStream = outputStream;
+ eb.ascii = gTrue;
+ eb.r1 = 55665;
+ eb.line = 0;
+
+ // start the private dictionary
+ eexecWrite(&eb, "\x83\xca\x73\xd5");
+ eexecWrite(&eb, "dup /Private 32 dict dup begin\n");
+ eexecWrite(&eb, "/RD {string currentfile exch readstring pop}"
+ " executeonly def\n");
+ eexecWrite(&eb, "/ND {noaccess def} executeonly def\n");
+ eexecWrite(&eb, "/NP {noaccess put} executeonly def\n");
+ eexecWrite(&eb, "/MinFeature {16 16} def\n");
+ eexecWrite(&eb, "/password 5839 def\n");
+ if (privateDicts[fd].nBlueValues) {
+ eexecWrite(&eb, "/BlueValues [");
+ for (k = 0; k < privateDicts[fd].nBlueValues; ++k) {
+ buf = GString::format("{0:s}{1:d}",
+ k > 0 ? " " : "",
+ privateDicts[fd].blueValues[k]);
+ eexecWrite(&eb, buf->getCString());
+ delete buf;
+ }
+ eexecWrite(&eb, "] def\n");
+ }
+ if (privateDicts[fd].nOtherBlues) {
+ eexecWrite(&eb, "/OtherBlues [");
+ for (k = 0; k < privateDicts[fd].nOtherBlues; ++k) {
+ buf = GString::format("{0:s}{1:d}",
+ k > 0 ? " " : "",
+ privateDicts[fd].otherBlues[k]);
+ eexecWrite(&eb, buf->getCString());
+ delete buf;
+ }
+ eexecWrite(&eb, "] def\n");
+ }
+ if (privateDicts[fd].nFamilyBlues) {
+ eexecWrite(&eb, "/FamilyBlues [");
+ for (k = 0; k < privateDicts[fd].nFamilyBlues; ++k) {
+ buf = GString::format("{0:s}{1:d}", k > 0 ? " " : "",
+ privateDicts[fd].familyBlues[k]);
+ eexecWrite(&eb, buf->getCString());
+ delete buf;
+ }
+ eexecWrite(&eb, "] def\n");
+ }
+ if (privateDicts[fd].nFamilyOtherBlues) {
+ eexecWrite(&eb, "/FamilyOtherBlues [");
+ for (k = 0; k < privateDicts[fd].nFamilyOtherBlues; ++k) {
+ buf = GString::format("{0:s}{1:d}", k > 0 ? " " : "",
+ privateDicts[fd].familyOtherBlues[k]);
+ eexecWrite(&eb, buf->getCString());
+ delete buf;
+ }
+ eexecWrite(&eb, "] def\n");
+ }
+ if (privateDicts[fd].blueScale != 0.039625) {
+ buf = GString::format("/BlueScale {0:.4g} def\n",
+ privateDicts[fd].blueScale);
+ eexecWrite(&eb, buf->getCString());
+ delete buf;
+ }
+ if (privateDicts[fd].blueShift != 7) {
+ buf = GString::format("/BlueShift {0:d} def\n",
+ privateDicts[fd].blueShift);
+ eexecWrite(&eb, buf->getCString());
+ delete buf;
+ }
+ if (privateDicts[fd].blueFuzz != 1) {
+ buf = GString::format("/BlueFuzz {0:d} def\n",
+ privateDicts[fd].blueFuzz);
+ eexecWrite(&eb, buf->getCString());
+ delete buf;
+ }
+ if (privateDicts[fd].hasStdHW) {
+ buf = GString::format("/StdHW [{0:.4g}] def\n", privateDicts[fd].stdHW);
+ eexecWrite(&eb, buf->getCString());
+ delete buf;
+ }
+ if (privateDicts[fd].hasStdVW) {
+ buf = GString::format("/StdVW [{0:.4g}] def\n", privateDicts[fd].stdVW);
+ eexecWrite(&eb, buf->getCString());
+ delete buf;
+ }
+ if (privateDicts[fd].nStemSnapH) {
+ // the StemSnapH array should be unique values in ascending order --
+ // if not, just skip it
+ for (k = 1; k < privateDicts[fd].nStemSnapH; ++k) {
+ if (privateDicts[fd].stemSnapH[k-1] >= privateDicts[fd].stemSnapH[k]) {
+ break;
+ }
+ }
+ if (k == privateDicts[fd].nStemSnapH) {
+ eexecWrite(&eb, "/StemSnapH [");
+ for (k = 0; k < privateDicts[fd].nStemSnapH; ++k) {
+ buf = GString::format("{0:s}{1:.4g}",
+ k > 0 ? " " : "",
+ privateDicts[fd].stemSnapH[k]);
+ eexecWrite(&eb, buf->getCString());
+ delete buf;
+ }
+ eexecWrite(&eb, "] def\n");
+ }
+ }
+ if (privateDicts[fd].nStemSnapV) {
+ // the StemSnapV array should be unique values in ascending order --
+ // if not, just skip it
+ for (k = 1; k < privateDicts[fd].nStemSnapV; ++k) {
+ if (privateDicts[fd].stemSnapV[k-1] >= privateDicts[fd].stemSnapV[k]) {
+ break;
+ }
+ }
+ if (k == privateDicts[fd].nStemSnapV) {
+ eexecWrite(&eb, "/StemSnapV [");
+ for (k = 0; k < privateDicts[fd].nStemSnapV; ++k) {
+ buf = GString::format("{0:s}{1:.4g}",
+ k > 0 ? " " : "",
+ privateDicts[fd].stemSnapV[k]);
+ eexecWrite(&eb, buf->getCString());
+ delete buf;
+ }
+ eexecWrite(&eb, "] def\n");
+ }
+ }
+ if (privateDicts[fd].hasForceBold) {
+ buf = GString::format("/ForceBold {0:s} def\n",
+ privateDicts[fd].forceBold ? "true" : "false");
+ eexecWrite(&eb, buf->getCString());
+ delete buf;
+ }
+ if (privateDicts[fd].forceBoldThreshold != 0) {
+ buf = GString::format("/ForceBoldThreshold {0:.4g} def\n",
+ privateDicts[fd].forceBoldThreshold);
+ eexecWrite(&eb, buf->getCString());
+ delete buf;
+ }
+ if (privateDicts[fd].languageGroup != 0) {
+ buf = GString::format("/LanguageGroup {0:d} def\n",
+ privateDicts[fd].languageGroup);
+ eexecWrite(&eb, buf->getCString());
+ delete buf;
+ }
+ if (privateDicts[fd].expansionFactor != 0.06) {
+ buf = GString::format("/ExpansionFactor {0:.4g} def\n",
+ privateDicts[fd].expansionFactor);
+ eexecWrite(&eb, buf->getCString());
+ delete buf;
+ }
+
+ // set up the subroutines
+ ok = gTrue;
+ getIndex(privateDicts[fd].subrsOffset, &subrIdx, &ok);
+ if (!ok) {
+ subrIdx.pos = -1;
+ }
+
+ // start the CharStrings
+ eexecWrite(&eb, "2 index /CharStrings 256 dict dup begin\n");
+
+ // write the .notdef CharString
+ ok = gTrue;
+ getIndexVal(&charStringsIdx, 0, &val, &ok);
+ if (ok) {
+ eexecCvtGlyph(&eb, ".notdef", val.pos, val.len,
+ &subrIdx, &privateDicts[fd]);
+ }
+
+ // write the CharStrings
+ for (j = 0; j < 256 && i+j < nCIDs; ++j) {
+ if (cidMap[i+j] >= 0) {
+ ok = gTrue;
+ getIndexVal(&charStringsIdx, cidMap[i+j], &val, &ok);
+ if (ok) {
+ buf = GString::format("c{0:02x}", j);
+ eexecCvtGlyph(&eb, buf->getCString(), val.pos, val.len,
+ &subrIdx, &privateDicts[fd]);
+ delete buf;
+ }
+ }
+ }
+ eexecWrite(&eb, "end\n");
+ eexecWrite(&eb, "end\n");
+ eexecWrite(&eb, "readonly put\n");
+ eexecWrite(&eb, "noaccess put\n");
+ eexecWrite(&eb, "dup /FontName get exch definefont pop\n");
+ eexecWrite(&eb, "mark currentfile closefile\n");
+
+ // trailer
+ if (eb.line > 0) {
+ (*outputFunc)(outputStream, "\n", 1);
+ }
+ for (j = 0; j < 8; ++j) {
+ (*outputFunc)(outputStream, "0000000000000000000000000000000000000000000000000000000000000000\n", 65);
+ }
+ (*outputFunc)(outputStream, "cleartomark\n", 12);
+ }
+
+ // write the Type 0 parent font
+ (*outputFunc)(outputStream, "16 dict begin\n", 14);
+ (*outputFunc)(outputStream, "/FontName /", 11);
+ (*outputFunc)(outputStream, psName, (int)strlen(psName));
+ (*outputFunc)(outputStream, " def\n", 5);
+ (*outputFunc)(outputStream, "/FontType 0 def\n", 16);
+ if (topDict.hasFontMatrix) {
+ buf = GString::format("/FontMatrix [{0:.8g} {1:.8g} {2:.8g} {3:.8g} {4:.8g} {5:.8g}] def\n",
+ topDict.fontMatrix[0], topDict.fontMatrix[1],
+ topDict.fontMatrix[2], topDict.fontMatrix[3],
+ topDict.fontMatrix[4], topDict.fontMatrix[5]);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ } else {
+ (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
+ }
+ (*outputFunc)(outputStream, "/FMapType 2 def\n", 16);
+ (*outputFunc)(outputStream, "/Encoding [\n", 12);
+ for (i = 0; i < nCIDs; i += 256) {
+ buf = GString::format("{0:d}\n", i >> 8);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ }
+ (*outputFunc)(outputStream, "] def\n", 6);
+ (*outputFunc)(outputStream, "/FDepVector [\n", 14);
+ for (i = 0; i < nCIDs; i += 256) {
+ (*outputFunc)(outputStream, "/", 1);
+ (*outputFunc)(outputStream, psName, (int)strlen(psName));
+ buf = GString::format("_{0:02x} findfont\n", i >> 8);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ }
+ (*outputFunc)(outputStream, "] def\n", 6);
+ (*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40);
+
+ gfree(cidMap);
+}
+
+void FoFiType1C::eexecCvtGlyph(Type1CEexecBuf *eb, const char *glyphName,
+ int offset, int nBytes,
+ Type1CIndex *subrIdx,
+ Type1CPrivateDict *pDict) {
+ GString *buf;
+ GString *charBuf;
+
+ // generate the charstring
+ charBuf = new GString();
+ cvtGlyph(offset, nBytes, charBuf, subrIdx, pDict, gTrue, 0);
+
+ buf = GString::format("/{0:s} {1:d} RD ", glyphName, charBuf->getLength());
+ eexecWrite(eb, buf->getCString());
+ delete buf;
+ eexecWriteCharstring(eb, (Guchar *)charBuf->getCString(),
+ charBuf->getLength());
+ eexecWrite(eb, " ND\n");
+
+ delete charBuf;
+}
+
+void FoFiType1C::cvtGlyph(int offset, int nBytes, GString *charBuf,
+ Type1CIndex *subrIdx, Type1CPrivateDict *pDict,
+ GBool top, int recursion) {
+ Type1CIndexVal val;
+ Type1COp zero, tmp;
+ GBool ok, dInt;
+ double d, dx, dy;
+ Gushort r2;
+ Guchar byte;
+ int pos, subrBias, start, num, den, i, k;
+
+ if (recursion > type1cSubrRecursionLimit) {
+ //~ error(-1, "Recursive loop in Type1C glyph");
+ return;
+ }
+
+ start = charBuf->getLength();
+ if (top) {
+ charBuf->append((char)73);
+ charBuf->append((char)58);
+ charBuf->append((char)147);
+ charBuf->append((char)134);
+ nOps = 0;
+ nHints = 0;
+ firstOp = gTrue;
+ openPath = gFalse;
+ }
+
+ zero.kind = type1COpInteger;
+ zero.intgr = 0;
+
+ pos = offset;
+ while (pos < offset + nBytes) {
+ ok = gTrue;
+ pos = getOp(pos, gTrue, &ok);
+ if (!ok) {
+ break;
+ }
+ if (ops[nOps - 1].kind == type1COpOperator) {
+ --nOps; // drop the operator
+ switch (ops[nOps].op) {
+ case 0x0001: // hstem
+ if (firstOp) {
+ cvtGlyphWidth(nOps & 1, charBuf, pDict);
+ firstOp = gFalse;
+ }
+ if (nOps & 1) {
+ //~ error(-1, "Wrong number of args (%d) to Type 2 hstem", nOps);
+ }
+ d = 0;
+ dInt = gTrue;
+ for (k = 0; k+1 < nOps; k += 2) {
+ // convert Type 2 edge hints (-20 or -21) to Type 1 ghost hints
+ if (ops[k+1].isNegative()) {
+ d += ops[k].toFloat() + ops[k+1].toFloat();
+ dInt &= ops[k].kind == type1COpInteger;
+ dInt &= ops[k+1].kind == type1COpInteger;
+ if (dInt) {
+ tmp.kind = type1COpInteger;
+ tmp.intgr = (int)(d + 0.5);
+ } else {
+ tmp.kind = type1COpFloat;
+ tmp.flt = d;
+ }
+ cvtNum(tmp, charBuf);
+ if (ops[k+1].kind == type1COpInteger) {
+ tmp.kind = type1COpInteger;
+ tmp.intgr = -ops[k+1].intgr;
+ } else if (ops[k+1].kind == type1COpRational) {
+ tmp.kind = type1COpRational;
+ tmp.rat.num = -ops[k+1].rat.num;
+ tmp.rat.den = ops[k+1].rat.den;
+ } else {
+ tmp.kind = type1COpFloat;
+ tmp.flt = -ops[k+1].toFloat();
+ }
+ cvtNum(tmp, charBuf);
+ } else {
+ d += ops[k].toFloat();
+ dInt &= ops[k].kind == type1COpInteger;
+ if (dInt) {
+ tmp.kind = type1COpInteger;
+ tmp.intgr = (int)(d + 0.5);
+ } else {
+ tmp.kind = type1COpFloat;
+ tmp.flt = d;
+ }
+ cvtNum(tmp, charBuf);
+ cvtNum(ops[k+1], charBuf);
+ d += ops[k+1].toFloat();
+ dInt &= ops[k+1].kind == type1COpInteger;
+ }
+ charBuf->append((char)1);
+ }
+ nHints += nOps / 2;
+ nOps = 0;
+ break;
+ case 0x0003: // vstem
+ if (firstOp) {
+ cvtGlyphWidth(nOps & 1, charBuf, pDict);
+ firstOp = gFalse;
+ }
+ if (nOps & 1) {
+ //~ error(-1, "Wrong number of args (%d) to Type 2 vstem", nOps);
+ }
+ d = 0;
+ dInt = gTrue;
+ for (k = 0; k+1 < nOps; k += 2) {
+ // convert Type 2 edge hints (-20 or -21) to Type 1 ghost hints
+ if (ops[k+1].isNegative()) {
+ d += ops[k].toFloat() + ops[k+1].toFloat();
+ dInt &= ops[k].kind == type1COpInteger;
+ dInt &= ops[k+1].kind == type1COpInteger;
+ if (dInt) {
+ tmp.kind = type1COpInteger;
+ tmp.intgr = (int)(d + 0.5);
+ } else {
+ tmp.kind = type1COpFloat;
+ tmp.flt = d;
+ }
+ cvtNum(tmp, charBuf);
+ if (ops[k+1].kind == type1COpInteger) {
+ tmp.kind = type1COpInteger;
+ tmp.intgr = -ops[k+1].intgr;
+ } else if (ops[k+1].kind == type1COpRational) {
+ tmp.kind = type1COpRational;
+ tmp.rat.num = -ops[k+1].rat.num;
+ tmp.rat.den = ops[k+1].rat.den;
+ } else {
+ tmp.kind = type1COpFloat;
+ tmp.flt = -ops[k+1].toFloat();
+ }
+ cvtNum(tmp, charBuf);
+ } else {
+ d += ops[k].toFloat();
+ dInt &= ops[k].kind == type1COpInteger;
+ if (dInt) {
+ tmp.kind = type1COpInteger;
+ tmp.intgr = (int)(d + 0.5);
+ } else {
+ tmp.kind = type1COpFloat;
+ tmp.flt = d;
+ }
+ cvtNum(tmp, charBuf);
+ cvtNum(ops[k+1], charBuf);
+ d += ops[k+1].toFloat();
+ dInt &= ops[k+1].kind == type1COpInteger;
+ }
+ charBuf->append((char)3);
+ }
+ nHints += nOps / 2;
+ nOps = 0;
+ break;
+ case 0x0004: // vmoveto
+ if (firstOp) {
+ cvtGlyphWidth(nOps == 2, charBuf, pDict);
+ firstOp = gFalse;
+ }
+ if (openPath) {
+ charBuf->append((char)9);
+ openPath = gFalse;
+ }
+ if (nOps != 1) {
+ //~ error(-1, "Wrong number of args (%d) to Type 2 vmoveto", nOps);
+ }
+ cvtNum(ops[0], charBuf);
+ charBuf->append((char)4);
+ nOps = 0;
+ break;
+ case 0x0005: // rlineto
+ if (nOps < 2 || nOps % 2 != 0) {
+ //~ error(-1, "Wrong number of args (%d) to Type 2 rlineto", nOps);
+ }
+ for (k = 0; k+1 < nOps; k += 2) {
+ cvtNum(ops[k], charBuf);
+ cvtNum(ops[k+1], charBuf);
+ charBuf->append((char)5);
+ }
+ nOps = 0;
+ openPath = gTrue;
+ break;
+ case 0x0006: // hlineto
+ if (nOps < 1) {
+ //~ error(-1, "Wrong number of args (%d) to Type 2 hlineto", nOps);
+ }
+ for (k = 0; k < nOps; ++k) {
+ cvtNum(ops[k], charBuf);
+ charBuf->append((char)((k & 1) ? 7 : 6));
+ }
+ nOps = 0;
+ openPath = gTrue;
+ break;
+ case 0x0007: // vlineto
+ if (nOps < 1) {
+ //~ error(-1, "Wrong number of args (%d) to Type 2 vlineto", nOps);
+ }
+ for (k = 0; k < nOps; ++k) {
+ cvtNum(ops[k], charBuf);
+ charBuf->append((char)((k & 1) ? 6 : 7));
+ }
+ nOps = 0;
+ openPath = gTrue;
+ break;
+ case 0x0008: // rrcurveto
+ if (nOps < 6 || nOps % 6 != 0) {
+ //~ error(-1, "Wrong number of args (%d) to Type 2 rrcurveto", nOps);
+ }
+ for (k = 0; k < nOps; k += 6) {
+ cvtNum(ops[k], charBuf);
+ cvtNum(ops[k+1], charBuf);
+ cvtNum(ops[k+2], charBuf);
+ cvtNum(ops[k+3], charBuf);
+ cvtNum(ops[k+4], charBuf);
+ cvtNum(ops[k+5], charBuf);
+ charBuf->append((char)8);
+ }
+ nOps = 0;
+ openPath = gTrue;
+ break;
+ case 0x000a: // callsubr
+ if (nOps >= 1) {
+ subrBias = (subrIdx->len < 1240)
+ ? 107 : (subrIdx->len < 33900) ? 1131 : 32768;
+ k = subrBias + ops[nOps - 1].toInt();
+ --nOps;
+ ok = gTrue;
+ getIndexVal(subrIdx, k, &val, &ok);
+ if (ok) {
+ cvtGlyph(val.pos, val.len, charBuf, subrIdx, pDict, gFalse,
+ recursion + 1);
+ }
+ } else {
+ //~ error(-1, "Too few args to Type 2 callsubr");
+ }
+ // don't clear the stack
+ break;
+ case 0x000b: // return
+ // don't clear the stack
+ break;
+ case 0x000e: // endchar / seac
+ if (firstOp) {
+ cvtGlyphWidth(nOps == 1 || nOps == 5, charBuf, pDict);
+ firstOp = gFalse;
+ }
+ if (openPath) {
+ charBuf->append((char)9);
+ openPath = gFalse;
+ }
+ if (nOps == 4) {
+ cvtNum(zero, charBuf);
+ cvtNum(ops[0], charBuf);
+ cvtNum(ops[1], charBuf);
+ cvtNum(ops[2], charBuf);
+ cvtNum(ops[3], charBuf);
+ charBuf->append((char)12)->append((char)6);
+ } else if (nOps == 0) {
+ charBuf->append((char)14);
+ } else {
+ //~ error(-1, "Wrong number of args (%d) to Type 2 endchar", nOps);
+ }
+ nOps = 0;
+ break;
+ case 0x000f: // (obsolete)
+ // this op is ignored, but we need the glyph width
+ if (firstOp) {
+ cvtGlyphWidth(nOps > 0, charBuf, pDict);
+ firstOp = gFalse;
+ }
+ nOps = 0;
+ break;
+ case 0x0010: // blend
+ //~ error(-1, "Unimplemented Type 2 charstring op: %d", file[i]);
+ nOps = 0;
+ break;
+ case 0x0012: // hstemhm
+ // ignored
+ if (firstOp) {
+ cvtGlyphWidth(nOps & 1, charBuf, pDict);
+ firstOp = gFalse;
+ }
+ if (nOps & 1) {
+ //~ error(-1, "Wrong number of args (%d) to Type 2 hstemhm", nOps);
+ }
+ nHints += nOps / 2;
+ nOps = 0;
+ break;
+ case 0x0013: // hintmask
+ // ignored
+ if (firstOp) {
+ cvtGlyphWidth(nOps & 1, charBuf, pDict);
+ firstOp = gFalse;
+ }
+ if (nOps > 0) {
+ if (nOps & 1) {
+ //~ error(-1, "Wrong number of args (%d) to Type 2 hintmask/vstemhm",
+ //~ nOps);
+ }
+ nHints += nOps / 2;
+ }
+ pos += (nHints + 7) >> 3;
+ nOps = 0;
+ break;
+ case 0x0014: // cntrmask
+ // ignored
+ if (firstOp) {
+ cvtGlyphWidth(nOps & 1, charBuf, pDict);
+ firstOp = gFalse;
+ }
+ if (nOps > 0) {
+ if (nOps & 1) {
+ //~ error(-1, "Wrong number of args (%d) to Type 2 cntrmask/vstemhm",
+ //~ nOps);
+ }
+ nHints += nOps / 2;
+ }
+ pos += (nHints + 7) >> 3;
+ nOps = 0;
+ break;
+ case 0x0015: // rmoveto
+ if (firstOp) {
+ cvtGlyphWidth(nOps == 3, charBuf, pDict);
+ firstOp = gFalse;
+ }
+ if (openPath) {
+ charBuf->append((char)9);
+ openPath = gFalse;
+ }
+ if (nOps != 2) {
+ //~ error(-1, "Wrong number of args (%d) to Type 2 rmoveto", nOps);
+ }
+ cvtNum(ops[0], charBuf);
+ cvtNum(ops[1], charBuf);
+ charBuf->append((char)21);
+ nOps = 0;
+ break;
+ case 0x0016: // hmoveto
+ if (firstOp) {
+ cvtGlyphWidth(nOps == 2, charBuf, pDict);
+ firstOp = gFalse;
+ }
+ if (openPath) {
+ charBuf->append((char)9);
+ openPath = gFalse;
+ }
+ if (nOps != 1) {
+ //~ error(-1, "Wrong number of args (%d) to Type 2 hmoveto", nOps);
+ }
+ cvtNum(ops[0], charBuf);
+ charBuf->append((char)22);
+ nOps = 0;
+ break;
+ case 0x0017: // vstemhm
+ // ignored
+ if (firstOp) {
+ cvtGlyphWidth(nOps & 1, charBuf, pDict);
+ firstOp = gFalse;
+ }
+ if (nOps & 1) {
+ //~ error(-1, "Wrong number of args (%d) to Type 2 vstemhm", nOps);
+ }
+ nHints += nOps / 2;
+ nOps = 0;
+ break;
+ case 0x0018: // rcurveline
+ if (nOps < 8 || (nOps - 2) % 6 != 0) {
+ //~ error(-1, "Wrong number of args (%d) to Type 2 rcurveline", nOps);
+ }
+ for (k = 0; k <= nOps - 8; k += 6) {
+ cvtNum(ops[k], charBuf);
+ cvtNum(ops[k+1], charBuf);
+ cvtNum(ops[k+2], charBuf);
+ cvtNum(ops[k+3], charBuf);
+ cvtNum(ops[k+4], charBuf);
+ cvtNum(ops[k+5], charBuf);
+ charBuf->append((char)8);
+ }
+ cvtNum(ops[k], charBuf);
+ cvtNum(ops[k+1], charBuf);
+ charBuf->append((char)5);
+ nOps = 0;
+ openPath = gTrue;
+ break;
+ case 0x0019: // rlinecurve
+ if (nOps < 8 || (nOps - 6) % 2 != 0) {
+ //~ error(-1, "Wrong number of args (%d) to Type 2 rlinecurve", nOps);
+ }
+ for (k = 0; k <= nOps - 8; k += 2) {
+ cvtNum(ops[k], charBuf);
+ cvtNum(ops[k+1], charBuf);
+ charBuf->append((char)5);
+ }
+ cvtNum(ops[k], charBuf);
+ cvtNum(ops[k+1], charBuf);
+ cvtNum(ops[k+2], charBuf);
+ cvtNum(ops[k+3], charBuf);
+ cvtNum(ops[k+4], charBuf);
+ cvtNum(ops[k+5], charBuf);
+ charBuf->append((char)8);
+ nOps = 0;
+ openPath = gTrue;
+ break;
+ case 0x001a: // vvcurveto
+ if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
+ //~ error(-1, "Wrong number of args (%d) to Type 2 vvcurveto", nOps);
+ }
+ if (nOps % 2 == 1 && nOps >= 5) {
+ cvtNum(ops[0], charBuf);
+ cvtNum(ops[1], charBuf);
+ cvtNum(ops[2], charBuf);
+ cvtNum(ops[3], charBuf);
+ cvtNum(zero, charBuf);
+ cvtNum(ops[4], charBuf);
+ charBuf->append((char)8);
+ k = 5;
+ } else {
+ k = 0;
+ }
+ for (; k+3 < nOps; k += 4) {
+ cvtNum(zero, charBuf);
+ cvtNum(ops[k], charBuf);
+ cvtNum(ops[k+1], charBuf);
+ cvtNum(ops[k+2], charBuf);
+ cvtNum(zero, charBuf);
+ cvtNum(ops[k+3], charBuf);
+ charBuf->append((char)8);
+ }
+ nOps = 0;
+ openPath = gTrue;
+ break;
+ case 0x001b: // hhcurveto
+ if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
+ //~ error(-1, "Wrong number of args (%d) to Type 2 hhcurveto", nOps);
+ }
+ if (nOps % 2 == 1 && nOps >= 5) {
+ cvtNum(ops[1], charBuf);
+ cvtNum(ops[0], charBuf);
+ cvtNum(ops[2], charBuf);
+ cvtNum(ops[3], charBuf);
+ cvtNum(ops[4], charBuf);
+ cvtNum(zero, charBuf);
+ charBuf->append((char)8);
+ k = 5;
+ } else {
+ k = 0;
+ }
+ for (; k+3 < nOps; k += 4) {
+ cvtNum(ops[k], charBuf);
+ cvtNum(zero, charBuf);
+ cvtNum(ops[k+1], charBuf);
+ cvtNum(ops[k+2], charBuf);
+ cvtNum(ops[k+3], charBuf);
+ cvtNum(zero, charBuf);
+ charBuf->append((char)8);
+ }
+ nOps = 0;
+ openPath = gTrue;
+ break;
+ case 0x001d: // callgsubr
+ if (nOps >= 1) {
+ k = gsubrBias + ops[nOps - 1].toInt();
+ --nOps;
+ ok = gTrue;
+ getIndexVal(&gsubrIdx, k, &val, &ok);
+ if (ok) {
+ cvtGlyph(val.pos, val.len, charBuf, subrIdx, pDict, gFalse,
+ recursion + 1);
+ }
+ } else {
+ //~ error(-1, "Too few args to Type 2 callgsubr");
+ }
+ // don't clear the stack
+ break;
+ case 0x001e: // vhcurveto
+ if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
+ //~ error(-1, "Wrong number of args (%d) to Type 2 vhcurveto", nOps);
+ }
+ for (k = 0; k+3 < nOps && k != nOps-5; k += 4) {
+ if (k % 8 == 0) {
+ cvtNum(ops[k], charBuf);
+ cvtNum(ops[k+1], charBuf);
+ cvtNum(ops[k+2], charBuf);
+ cvtNum(ops[k+3], charBuf);
+ charBuf->append((char)30);
+ } else {
+ cvtNum(ops[k], charBuf);
+ cvtNum(ops[k+1], charBuf);
+ cvtNum(ops[k+2], charBuf);
+ cvtNum(ops[k+3], charBuf);
+ charBuf->append((char)31);
+ }
+ }
+ if (k == nOps-5) {
+ if (k % 8 == 0) {
+ cvtNum(zero, charBuf);
+ cvtNum(ops[k], charBuf);
+ cvtNum(ops[k+1], charBuf);
+ cvtNum(ops[k+2], charBuf);
+ cvtNum(ops[k+3], charBuf);
+ cvtNum(ops[k+4], charBuf);
+ } else {
+ cvtNum(ops[k], charBuf);
+ cvtNum(zero, charBuf);
+ cvtNum(ops[k+1], charBuf);
+ cvtNum(ops[k+2], charBuf);
+ cvtNum(ops[k+4], charBuf);
+ cvtNum(ops[k+3], charBuf);
+ }
+ charBuf->append((char)8);
+ }
+ nOps = 0;
+ openPath = gTrue;
+ break;
+ case 0x001f: // hvcurveto
+ if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
+ //~ error(-1, "Wrong number of args (%d) to Type 2 hvcurveto", nOps);
+ }
+ for (k = 0; k+3 < nOps && k != nOps-5; k += 4) {
+ if (k % 8 == 0) {
+ cvtNum(ops[k], charBuf);
+ cvtNum(ops[k+1], charBuf);
+ cvtNum(ops[k+2], charBuf);
+ cvtNum(ops[k+3], charBuf);
+ charBuf->append((char)31);
+ } else {
+ cvtNum(ops[k], charBuf);
+ cvtNum(ops[k+1], charBuf);
+ cvtNum(ops[k+2], charBuf);
+ cvtNum(ops[k+3], charBuf);
+ charBuf->append((char)30);
+ }
+ }
+ if (k == nOps-5) {
+ if (k % 8 == 0) {
+ cvtNum(ops[k], charBuf);
+ cvtNum(zero, charBuf);
+ cvtNum(ops[k+1], charBuf);
+ cvtNum(ops[k+2], charBuf);
+ cvtNum(ops[k+4], charBuf);
+ cvtNum(ops[k+3], charBuf);
+ } else {
+ cvtNum(zero, charBuf);
+ cvtNum(ops[k], charBuf);
+ cvtNum(ops[k+1], charBuf);
+ cvtNum(ops[k+2], charBuf);
+ cvtNum(ops[k+3], charBuf);
+ cvtNum(ops[k+4], charBuf);
+ }
+ charBuf->append((char)8);
+ }
+ nOps = 0;
+ openPath = gTrue;
+ break;
+ case 0x0c00: // dotsection (should be Type 1 only?)
+ // ignored
+ nOps = 0;
+ break;
+ case 0x0c0c: // div
+ if (nOps >= 2) {
+ num = ops[nOps-2].toInt();
+ den = ops[nOps-1].toInt();
+ --nOps;
+ ops[nOps-1].kind = type1COpRational;
+ ops[nOps-1].rat.num = num;
+ ops[nOps-1].rat.den = den;
+ } else {
+ //~ error(-1, "Wrong number of args (%d) to Type 2 div", nOps);
+ }
+ break;
+ case 0x0c03: // and
+ case 0x0c04: // or
+ case 0x0c05: // not
+ case 0x0c08: // store
+ case 0x0c09: // abs
+ case 0x0c0a: // add
+ case 0x0c0b: // sub
+ case 0x0c0d: // load
+ case 0x0c0e: // neg
+ case 0x0c0f: // eq
+ case 0x0c12: // drop
+ case 0x0c14: // put
+ case 0x0c15: // get
+ case 0x0c16: // ifelse
+ case 0x0c17: // random
+ case 0x0c18: // mul
+ case 0x0c1a: // sqrt
+ case 0x0c1b: // dup
+ case 0x0c1c: // exch
+ case 0x0c1d: // index
+ case 0x0c1e: // roll
+ //~ error(-1, "Unimplemented Type 2 charstring op: 12.%d", file[i+1]);
+ nOps = 0;
+ break;
+ case 0x0c22: // hflex
+ if (nOps == 7) {
+ cvtNum(ops[0], charBuf);
+ cvtNum(zero, charBuf);
+ cvtNum(ops[1], charBuf);
+ cvtNum(ops[2], charBuf);
+ cvtNum(ops[3], charBuf);
+ cvtNum(zero, charBuf);
+ charBuf->append((char)8);
+ cvtNum(ops[4], charBuf);
+ cvtNum(zero, charBuf);
+ cvtNum(ops[5], charBuf);
+ if (ops[2].kind == type1COpInteger) {
+ tmp.kind = type1COpInteger;
+ tmp.intgr = -ops[2].intgr;
+ } else if (ops[2].kind == type1COpRational) {
+ tmp.kind = type1COpRational;
+ tmp.rat.num = -ops[2].rat.num;
+ tmp.rat.den = ops[2].rat.den;
+ } else {
+ tmp.kind = type1COpFloat;
+ tmp.flt = -ops[2].toFloat();
+ }
+ cvtNum(tmp, charBuf);
+ cvtNum(ops[6], charBuf);
+ cvtNum(zero, charBuf);
+ charBuf->append((char)8);
+ } else {
+ //~ error(-1, "Wrong number of args (%d) to Type 2 hflex", nOps);
+ }
+ nOps = 0;
+ openPath = gTrue;
+ break;
+ case 0x0c23: // flex
+ if (nOps == 13) {
+ cvtNum(ops[0], charBuf);
+ cvtNum(ops[1], charBuf);
+ cvtNum(ops[2], charBuf);
+ cvtNum(ops[3], charBuf);
+ cvtNum(ops[4], charBuf);
+ cvtNum(ops[5], charBuf);
+ charBuf->append((char)8);
+ cvtNum(ops[6], charBuf);
+ cvtNum(ops[7], charBuf);
+ cvtNum(ops[8], charBuf);
+ cvtNum(ops[9], charBuf);
+ cvtNum(ops[10], charBuf);
+ cvtNum(ops[11], charBuf);
+ charBuf->append((char)8);
+ } else {
+ //~ error(-1, "Wrong number of args (%d) to Type 2 flex", nOps);
+ }
+ nOps = 0;
+ openPath = gTrue;
+ break;
+ case 0x0c24: // hflex1
+ if (nOps == 9) {
+ cvtNum(ops[0], charBuf);
+ cvtNum(ops[1], charBuf);
+ cvtNum(ops[2], charBuf);
+ cvtNum(ops[3], charBuf);
+ cvtNum(ops[4], charBuf);
+ cvtNum(zero, charBuf);
+ charBuf->append((char)8);
+ cvtNum(ops[5], charBuf);
+ cvtNum(zero, charBuf);
+ cvtNum(ops[6], charBuf);
+ cvtNum(ops[7], charBuf);
+ cvtNum(ops[8], charBuf);
+ if (ops[1].kind == type1COpInteger &&
+ ops[3].kind == type1COpInteger &&
+ ops[7].kind == type1COpInteger) {
+ tmp.kind = type1COpInteger;
+ tmp.intgr = -(ops[1].intgr + ops[3].intgr + ops[7].intgr);
+ } else {
+ tmp.kind = type1COpFloat;
+ tmp.flt = -(ops[1].toFloat() + ops[3].toFloat() + ops[7].toFloat());
+ }
+ cvtNum(tmp, charBuf);
+ charBuf->append((char)8);
+ } else {
+ //~ error(-1, "Wrong number of args (%d) to Type 2 hflex1", nOps);
+ }
+ nOps = 0;
+ openPath = gTrue;
+ break;
+ case 0x0c25: // flex1
+ if (nOps == 11) {
+ cvtNum(ops[0], charBuf);
+ cvtNum(ops[1], charBuf);
+ cvtNum(ops[2], charBuf);
+ cvtNum(ops[3], charBuf);
+ cvtNum(ops[4], charBuf);
+ cvtNum(ops[5], charBuf);
+ charBuf->append((char)8);
+ cvtNum(ops[6], charBuf);
+ cvtNum(ops[7], charBuf);
+ cvtNum(ops[8], charBuf);
+ cvtNum(ops[9], charBuf);
+ dx = ops[0].toFloat() + ops[2].toFloat() + ops[4].toFloat()
+ + ops[6].toFloat() + ops[8].toFloat();
+ dy = ops[1].toFloat() + ops[3].toFloat() + ops[5].toFloat()
+ + ops[7].toFloat() + ops[9].toFloat();
+ if (fabs(dx) > fabs(dy)) {
+ cvtNum(ops[10], charBuf);
+ if (ops[1].kind == type1COpInteger &&
+ ops[3].kind == type1COpInteger &&
+ ops[5].kind == type1COpInteger &&
+ ops[7].kind == type1COpInteger &&
+ ops[9].kind == type1COpInteger) {
+ tmp.kind = type1COpInteger;
+ tmp.intgr = -(int)dy;
+ } else {
+ tmp.kind = type1COpFloat;
+ tmp.flt = -dy;
+ }
+ cvtNum(tmp, charBuf);
+ } else {
+ if (ops[0].kind == type1COpInteger &&
+ ops[2].kind == type1COpInteger &&
+ ops[4].kind == type1COpInteger &&
+ ops[6].kind == type1COpInteger &&
+ ops[8].kind == type1COpInteger) {
+ tmp.kind = type1COpInteger;
+ tmp.intgr = -(int)dx;
+ } else {
+ tmp.kind = type1COpFloat;
+ tmp.flt = -dx;
+ }
+ cvtNum(tmp, charBuf);
+ cvtNum(ops[10], charBuf);
+ }
+ charBuf->append((char)8);
+ } else {
+ //~ error(-1, "Wrong number of args (%d) to Type 2 flex1", nOps);
+ }
+ nOps = 0;
+ openPath = gTrue;
+ break;
+ default:
+ //~ error(-1, "Illegal Type 2 charstring op: %04x",
+ //~ ops[nOps].op);
+ nOps = 0;
+ break;
+ }
+ }
+ }
+
+ // charstring encryption
+ if (top) {
+ r2 = 4330;
+ for (i = start; i < charBuf->getLength(); ++i) {
+ byte = (Guchar)(charBuf->getChar(i) ^ (r2 >> 8));
+ charBuf->setChar(i, byte);
+ r2 = (Gushort)((byte + r2) * 52845 + 22719);
+ }
+ }
+}
+
+void FoFiType1C::cvtGlyphWidth(GBool useOp, GString *charBuf,
+ Type1CPrivateDict *pDict) {
+ Type1COp zero, w;
+ int i;
+
+ if (useOp) {
+ if (pDict->nominalWidthXInt & (ops[0].kind == type1COpInteger)) {
+ w.kind = type1COpInteger;
+ w.intgr = (int)(pDict->nominalWidthX + ops[0].intgr);
+ } else {
+ w.kind = type1COpFloat;
+ w.flt = pDict->nominalWidthX + ops[0].toFloat();
+ }
+ for (i = 1; i < nOps; ++i) {
+ ops[i-1] = ops[i];
+ }
+ --nOps;
+ } else {
+ if (pDict->defaultWidthXInt) {
+ w.kind = type1COpInteger;
+ w.intgr = (int)pDict->defaultWidthX;
+ } else {
+ w.kind = type1COpFloat;
+ w.flt = pDict->defaultWidthX;
+ }
+ }
+ zero.kind = type1COpInteger;
+ zero.intgr = 0;
+ cvtNum(zero, charBuf);
+ cvtNum(w, charBuf);
+ charBuf->append((char)13);
+}
+
+void FoFiType1C::cvtNum(Type1COp op, GString *charBuf) {
+ Type1COp tmp;
+ Guchar buf[12];
+ int y, n;
+
+ n = 0;
+ switch (op.kind) {
+ case type1COpInteger:
+ y = op.intgr;
+ if (y >= -107 && y <= 107) {
+ buf[0] = (Guchar)(y + 139);
+ n = 1;
+ } else if (y > 107 && y <= 1131) {
+ y -= 108;
+ buf[0] = (Guchar)((y >> 8) + 247);
+ buf[1] = (Guchar)(y & 0xff);
+ n = 2;
+ } else if (y < -107 && y >= -1131) {
+ y = -y - 108;
+ buf[0] = (Guchar)((y >> 8) + 251);
+ buf[1] = (Guchar)(y & 0xff);
+ n = 2;
+ } else {
+ buf[0] = 255;
+ buf[1] = (Guchar)(y >> 24);
+ buf[2] = (Guchar)(y >> 16);
+ buf[3] = (Guchar)(y >> 8);
+ buf[4] = (Guchar)y;
+ n = 5;
+ }
+ break;
+ case type1COpFloat:
+ if (op.flt >= -32768 && op.flt < 32768) {
+ y = (int)(op.flt * 256.0);
+ buf[0] = 255;
+ buf[1] = (Guchar)(y >> 24);
+ buf[2] = (Guchar)(y >> 16);
+ buf[3] = (Guchar)(y >> 8);
+ buf[4] = (Guchar)y;
+ buf[5] = 255;
+ buf[6] = 0;
+ buf[7] = 0;
+ buf[8] = 1;
+ buf[9] = 0;
+ buf[10] = 12;
+ buf[11] = 12;
+ n = 12;
+ } else {
+ //~ error(-1, "Type 2 fixed point constant out of range");
+ }
+ break;
+ case type1COpRational:
+ tmp.kind = type1COpInteger;
+ tmp.intgr = op.rat.num;
+ cvtNum(tmp, charBuf);
+ tmp.intgr = op.rat.den;
+ cvtNum(tmp, charBuf);
+ buf[0] = 0x0c;
+ buf[1] = 0x0c;
+ n = 2;
+ break;
+ default: // shouldn't happen
+ break;
+ }
+ charBuf->append((char *)buf, n);
+}
+
+void FoFiType1C::eexecWrite(Type1CEexecBuf *eb, const char *s) {
+ Guchar *p;
+ Guchar x;
+
+ for (p = (Guchar *)s; *p; ++p) {
+ x = *p ^ (Guchar)(eb->r1 >> 8);
+ eb->r1 = (Gushort)((x + eb->r1) * 52845 + 22719);
+ if (eb->ascii) {
+ (*eb->outputFunc)(eb->outputStream, &hexChars[x >> 4], 1);
+ (*eb->outputFunc)(eb->outputStream, &hexChars[x & 0x0f], 1);
+ eb->line += 2;
+ if (eb->line == 64) {
+ (*eb->outputFunc)(eb->outputStream, "\n", 1);
+ eb->line = 0;
+ }
+ } else {
+ (*eb->outputFunc)(eb->outputStream, (char *)&x, 1);
+ }
+ }
+}
+
+void FoFiType1C::eexecWriteCharstring(Type1CEexecBuf *eb,
+ Guchar *s, int n) {
+ Guchar x;
+ int i;
+
+ // eexec encryption
+ for (i = 0; i < n; ++i) {
+ x = s[i] ^ (Guchar)(eb->r1 >> 8);
+ eb->r1 = (Gushort)((x + eb->r1) * 52845 + 22719);
+ if (eb->ascii) {
+ (*eb->outputFunc)(eb->outputStream, &hexChars[x >> 4], 1);
+ (*eb->outputFunc)(eb->outputStream, &hexChars[x & 0x0f], 1);
+ eb->line += 2;
+ if (eb->line == 64) {
+ (*eb->outputFunc)(eb->outputStream, "\n", 1);
+ eb->line = 0;
+ }
+ } else {
+ (*eb->outputFunc)(eb->outputStream, (char *)&x, 1);
+ }
+ }
+}
+
+void FoFiType1C::writePSString(char *s, FoFiOutputFunc outputFunc,
+ void *outputStream) {
+ char buf[80];
+ char *p;
+ int i, c;
+
+ i = 0;
+ buf[i++] = '(';
+ for (p = s; *p; ++p) {
+ c = *p & 0xff;
+ if (c == '(' || c == ')' || c == '\\') {
+ buf[i++] = '\\';
+ buf[i++] = (char)c;
+ } else if (c < 0x20 || c >= 0x80) {
+ buf[i++] = '\\';
+ buf[i++] = (char)('0' + ((c >> 6) & 7));
+ buf[i++] = (char)('0' + ((c >> 3) & 7));
+ buf[i++] = (char)('0' + (c & 7));
+ } else {
+ buf[i++] = (char)c;
+ }
+ if (i >= 64) {
+ buf[i++] = '\\';
+ buf[i++] = '\n';
+ (*outputFunc)(outputStream, buf, i);
+ i = 0;
+ }
+ }
+ buf[i++] = ')';
+ (*outputFunc)(outputStream, buf, i);
+}
+
+void FoFiType1C::convertToOpenType(FoFiOutputFunc outputFunc,
+ void *outputStream,
+ int nWidths, Gushort *widths,
+ Guchar *cmapTable, int cmapTableLen) {
+ // dummy OS/2 table (taken from FoFiTrueType::writeTTF)
+ static Guchar os2Tab[86] = {
+ 0, 1, // version
+ 0, 1, // xAvgCharWidth
+ 0x01, 0x90, // usWeightClass
+ 0, 5, // usWidthClass
+ 0, 0, // fsType
+ 0, 0, // ySubscriptXSize
+ 0, 0, // ySubscriptYSize
+ 0, 0, // ySubscriptXOffset
+ 0, 0, // ySubscriptYOffset
+ 0, 0, // ySuperscriptXSize
+ 0, 0, // ySuperscriptYSize
+ 0, 0, // ySuperscriptXOffset
+ 0, 0, // ySuperscriptYOffset
+ 0, 0, // yStrikeoutSize
+ 0, 0, // yStrikeoutPosition
+ 0, 0, // sFamilyClass
+ 0, 0, 0, 0, 0, // panose
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, // ulUnicodeRange1
+ 0, 0, 0, 0, // ulUnicodeRange2
+ 0, 0, 0, 0, // ulUnicodeRange3
+ 0, 0, 0, 0, // ulUnicodeRange4
+ 0, 0, 0, 0, // achVendID
+ 0, 0, // fsSelection
+ 0, 0, // usFirstCharIndex
+ 0, 0, // usLastCharIndex
+ 0, 0, // sTypoAscender
+ 0, 0, // sTypoDescender
+ 0, 0, // sTypoLineGap
+ 0x20, 0x00, // usWinAscent
+ 0x20, 0x00, // usWinDescent
+ 0, 0, 0, 1, // ulCodePageRange1
+ 0, 0, 0, 0 // ulCodePageRange2
+ };
+ Guchar headTable[54], hheaTable[36], maxpTable[6];
+ Guchar nameTable[26], postTable[32];
+ Guchar *hmtxTable;
+ static const char *tableTag[9] = {
+ "CFF ",
+ "OS/2",
+ "cmap",
+ "head",
+ "hhea",
+ "hmtx",
+ "maxp",
+ "name",
+ "post"
+ };
+ Guchar *tableData[9];
+ int tableLength[9];
+ Guchar header[12 + 9*16];
+ double mat[6];
+ Gushort maxWidth;
+ Guint checksum, fileChecksum;
+ int unitsPerEm, xMin, yMin, xMax, yMax, offset, i;
+
+ //--- CFF_ table
+ tableData[0] = file;
+ tableLength[0] = len;
+
+ //--- OS/2 table
+ tableData[1] = os2Tab;
+ tableLength[1] = 86;
+
+ //--- cmap table
+ tableData[2] = cmapTable;
+ tableLength[2] = cmapTableLen;
+
+ //--- head table
+ getFontMatrix(mat);
+ if (mat[0] == 0) {
+ unitsPerEm = 1000;
+ } else {
+ unitsPerEm = (int)(1 / mat[0] + 0.5);
+ }
+ xMin = (int)(topDict.fontBBox[0] + 0.5);
+ yMin = (int)(topDict.fontBBox[1] + 0.5);
+ xMax = (int)(topDict.fontBBox[2] + 0.5);
+ yMax = (int)(topDict.fontBBox[3] + 0.5);
+ headTable[ 0] = 0x00; // version
+ headTable[ 1] = 0x01;
+ headTable[ 2] = 0x00;
+ headTable[ 3] = 0x00;
+ headTable[ 4] = 0x00; // revision
+ headTable[ 5] = 0x00;
+ headTable[ 6] = 0x00;
+ headTable[ 7] = 0x00;
+ headTable[ 8] = 0x00; // checksumAdjustment
+ headTable[ 9] = 0x00; // (set later)
+ headTable[10] = 0x00;
+ headTable[11] = 0x00;
+ headTable[12] = 0x5f; // magicNumber
+ headTable[13] = 0x0f;
+ headTable[14] = 0x3c;
+ headTable[15] = 0xf5;
+ headTable[16] = 0x00; // flags
+ headTable[17] = 0x03;
+ headTable[18] = (Guchar)(unitsPerEm >> 8); // unitsPerEm
+ headTable[19] = (Guchar)unitsPerEm;
+ headTable[20] = 0x00; // created
+ headTable[21] = 0x00;
+ headTable[22] = 0x00;
+ headTable[23] = 0x00;
+ headTable[24] = 0x00;
+ headTable[25] = 0x00;
+ headTable[26] = 0x00;
+ headTable[27] = 0x00;
+ headTable[28] = 0x00; // modified
+ headTable[29] = 0x00;
+ headTable[30] = 0x00;
+ headTable[31] = 0x00;
+ headTable[32] = 0x00;
+ headTable[33] = 0x00;
+ headTable[34] = 0x00;
+ headTable[35] = 0x00;
+ headTable[36] = (Guchar)(xMin >> 8); // xMin
+ headTable[37] = (Guchar)xMin;
+ headTable[38] = (Guchar)(yMin >> 8); // yMin
+ headTable[39] = (Guchar)yMin;
+ headTable[40] = (Guchar)(xMax >> 8); // xMax
+ headTable[41] = (Guchar)xMax;
+ headTable[42] = (Guchar)(yMax >> 8); // yMax
+ headTable[43] = (Guchar)yMax;
+ headTable[44] = 0; // macStyle
+ headTable[45] = 0;
+ headTable[46] = 0; // lowestRecPPEM
+ headTable[47] = 3;
+ headTable[48] = 0; // fontDirectionHint
+ headTable[49] = 2; // (deprecated)
+ headTable[50] = 0; // indexToLocFormat
+ headTable[51] = 0; // (n/a to CFF fonts)
+ headTable[52] = 0; // glyphDataFormat
+ headTable[53] = 0; // (n/a to CFF fonts)
+ tableData[3] = headTable;
+ tableLength[3] = 54;
+
+ //--- hhea table
+ maxWidth = widths[0];
+ for (i = 1; i < nWidths; ++i) {
+ if (widths[i] > maxWidth) {
+ maxWidth = widths[i];
+ }
+ }
+ hheaTable[ 0] = 0x00; // version
+ hheaTable[ 1] = 0x01;
+ hheaTable[ 2] = 0x00;
+ hheaTable[ 3] = 0x00;
+ hheaTable[ 4] = (Guchar)(yMax >> 8); // ascender
+ hheaTable[ 5] = (Guchar)yMax;
+ hheaTable[ 6] = (Guchar)(yMin >> 8); // descender
+ hheaTable[ 7] = (Guchar)yMin;
+ hheaTable[ 8] = 0; // lineGap
+ hheaTable[ 9] = 0;
+ hheaTable[10] = (Guchar)(maxWidth >> 8); // advanceWidthMax
+ hheaTable[11] = (Guchar)maxWidth;
+ hheaTable[12] = 0; // minLeftSideBearing
+ hheaTable[13] = 0;
+ hheaTable[14] = 0; // minRightSideBearing
+ hheaTable[15] = 0;
+ hheaTable[16] = (Guchar)(maxWidth >> 8); // xMaxExtent
+ hheaTable[17] = (Guchar)maxWidth;
+ hheaTable[18] = 0; // caretSlopeRise
+ hheaTable[19] = 1;
+ hheaTable[20] = 0; // caretSlopeRun
+ hheaTable[21] = 0;
+ hheaTable[22] = 0; // caretOffset
+ hheaTable[23] = 0;
+ hheaTable[24] = 0; // reserved
+ hheaTable[25] = 0;
+ hheaTable[26] = 0; // reserved
+ hheaTable[27] = 0;
+ hheaTable[28] = 0; // reserved
+ hheaTable[29] = 0;
+ hheaTable[30] = 0; // reserved
+ hheaTable[31] = 0;
+ hheaTable[32] = 0; // metricDataFormat
+ hheaTable[33] = 0;
+ hheaTable[34] = (Guchar)(nWidths >> 8); // numberOfHMetrics
+ hheaTable[35] = (Guchar)nWidths;
+ tableData[4] = hheaTable;
+ tableLength[4] = 36;
+
+ //--- hmtx table
+ //~ this currently sets LSB to 0 for all glyphs
+ hmtxTable = (Guchar *)gmallocn(nWidths, 4);
+ for (i = 0; i < nWidths; ++i) {
+ hmtxTable[4*i ] = (Guchar)(widths[i] >> 8);
+ hmtxTable[4*i+1] = (Guchar)widths[i];
+ hmtxTable[4*i+2] = 0;
+ hmtxTable[4*i+3] = 0;
+ }
+ tableData[5] = hmtxTable;
+ tableLength[5] = 4 * nWidths;
+
+ //--- maxp table
+ maxpTable[0] = 0x00; // version = 0.5
+ maxpTable[1] = 0x00;
+ maxpTable[2] = 0x50;
+ maxpTable[3] = 0x00;
+ maxpTable[4] = (Guchar)(nGlyphs >> 8); // numGlyphs
+ maxpTable[5] = (Guchar)nGlyphs;
+ tableData[6] = maxpTable;
+ tableLength[6] = 6;
+
+ //--- name table
+ nameTable[ 0] = 0x00; // format
+ nameTable[ 1] = 0x00;
+ nameTable[ 2] = 0x00; // count
+ nameTable[ 3] = 0x01;
+ nameTable[ 4] = 0x00; // stringOffset
+ nameTable[ 5] = 0x12;
+ nameTable[ 6] = 0x00; // platformID
+ nameTable[ 7] = 0x00;
+ nameTable[ 8] = 0x00; // encodingID
+ nameTable[ 9] = 0x03;
+ nameTable[10] = 0x00; // languageID
+ nameTable[11] = 0x00;
+ nameTable[12] = 0x00; // nameID
+ nameTable[13] = 0x00;
+ nameTable[14] = 0x00; // length
+ nameTable[15] = 0x08;
+ nameTable[16] = 0x00; // offset
+ nameTable[17] = 0x00;
+ nameTable[18] = 0x00; // string data
+ nameTable[19] = (Guchar)'n';
+ nameTable[20] = 0x00;
+ nameTable[21] = (Guchar)'o';
+ nameTable[22] = 0x00;
+ nameTable[23] = (Guchar)'n';
+ nameTable[24] = 0x00;
+ nameTable[25] = (Guchar)'e';
+ tableData[7] = nameTable;
+ tableLength[7] = 26;
+
+ //--- post table
+ postTable[ 0] = 0x00; // version = 3.0
+ postTable[ 1] = 0x03;
+ postTable[ 2] = 0x00;
+ postTable[ 3] = 0x00;
+ postTable[ 4] = 0x00; // italicAngle
+ postTable[ 5] = 0x00;
+ postTable[ 6] = 0x00;
+ postTable[ 7] = 0x00;
+ postTable[ 8] = 0x00; // underlinePosition
+ postTable[ 9] = 0x00;
+ postTable[10] = 0x00; // underlineThickness
+ postTable[11] = 0x00;
+ postTable[12] = 0x00; // isFixedPitch
+ postTable[13] = 0x00;
+ postTable[14] = 0x00;
+ postTable[15] = 0x00;
+ postTable[16] = 0x00; // minMemType42
+ postTable[17] = 0x00;
+ postTable[18] = 0x00;
+ postTable[19] = 0x00;
+ postTable[20] = 0x00; // maxMemType42
+ postTable[21] = 0x00;
+ postTable[22] = 0x00;
+ postTable[23] = 0x00;
+ postTable[24] = 0x00; // minMemType1
+ postTable[25] = 0x00;
+ postTable[26] = 0x00;
+ postTable[27] = 0x00;
+ postTable[28] = 0x00; // maxMemType1
+ postTable[29] = 0x00;
+ postTable[30] = 0x00;
+ postTable[31] = 0x00;
+ tableData[8] = postTable;
+ tableLength[8] = 32;
+
+ //--- header and table directory
+ header[ 0] = 'O'; // sfnt version
+ header[ 1] = 'T';
+ header[ 2] = 'T';
+ header[ 3] = 'O';
+ header[ 4] = 0x00; // numTables
+ header[ 5] = 0x09;
+ header[ 6] = 0x00; // searchRange
+ header[ 7] = 0x80;
+ header[ 8] = 0x00; // entrySelector
+ header[ 9] = 0x03;
+ header[10] = 0x00; // rangeShift
+ header[11] = 0x10;
+ offset = 12 + 9*16;
+ fileChecksum = 0;
+ for (i = 0; i < 9; ++i) {
+ header[12 + i*16 + 0] = tableTag[i][0];
+ header[12 + i*16 + 1] = tableTag[i][1];
+ header[12 + i*16 + 2] = tableTag[i][2];
+ header[12 + i*16 + 3] = tableTag[i][3];
+ checksum = computeOpenTypeTableChecksum(tableData[i], tableLength[i]);
+ fileChecksum += checksum;
+ header[12 + i*16 + 4] = (Guchar)(checksum >> 24);
+ header[12 + i*16 + 5] = (Guchar)(checksum >> 16);
+ header[12 + i*16 + 6] = (Guchar)(checksum >> 8);
+ header[12 + i*16 + 7] = (Guchar)checksum;
+ header[12 + i*16 + 8] = (Guchar)(offset >> 24);
+ header[12 + i*16 + 9] = (Guchar)(offset >> 16);
+ header[12 + i*16 + 10] = (Guchar)(offset >> 8);
+ header[12 + i*16 + 11] = (Guchar)offset;
+ header[12 + i*16 + 12] = (Guchar)(tableLength[i] >> 24);
+ header[12 + i*16 + 13] = (Guchar)(tableLength[i] >> 16);
+ header[12 + i*16 + 14] = (Guchar)(tableLength[i] >> 8);
+ header[12 + i*16 + 15] = (Guchar)tableLength[i];
+ offset += tableLength[i];
+ if (tableLength[i] & 3) {
+ offset += 4 - (tableLength[i] & 3);
+ }
+ }
+
+ //--- file checksum
+ fileChecksum += computeOpenTypeTableChecksum(header, 12 + 9*16);
+ fileChecksum = 0xb1b0afba - fileChecksum;
+ headTable[ 8] = (Guchar)(fileChecksum >> 24);
+ headTable[ 9] = (Guchar)(fileChecksum >> 16);
+ headTable[10] = (Guchar)(fileChecksum >> 8);
+ headTable[11] = (Guchar)fileChecksum;
+
+ //--- write the OpenType font
+ (*outputFunc)(outputStream, (char *)header, 12 + 9*16);
+ for (i = 0; i < 9; ++i) {
+ (*outputFunc)(outputStream, (char *)tableData[i], tableLength[i]);
+ if (tableLength[i] & 3) {
+ (*outputFunc)(outputStream, "\0\0\0", 4 - (tableLength[i] & 3));
+ }
+ }
+
+ gfree(hmtxTable);
+}
+
+Guint FoFiType1C::computeOpenTypeTableChecksum(Guchar *data, int length) {
+ Guint checksum, word;
+ int i;
+
+ checksum = 0;
+ for (i = 0; i+3 < length; i += 4) {
+ word = ((data[i ] & 0xff) << 24) +
+ ((data[i+1] & 0xff) << 16) +
+ ((data[i+2] & 0xff) << 8) +
+ (data[i+3] & 0xff);
+ checksum += word;
+ }
+ if (length & 3) {
+ word = 0;
+ i = length & ~3;
+ switch (length & 3) {
+ case 3:
+ word |= (data[i+2] & 0xff) << 8;
+ case 2:
+ word |= (data[i+1] & 0xff) << 16;
+ case 1:
+ word |= (data[i ] & 0xff) << 24;
+ break;
+ }
+ checksum += word;
+ }
+ return checksum;
+}
+
+GBool FoFiType1C::parse() {
+ Type1CIndex fdIdx;
+ Type1CIndexVal val;
+ int i;
+
+ parsedOk = gTrue;
+
+ // some tools embed Type 1C fonts with an extra whitespace char at
+ // the beginning
+ if (len > 0 && file[0] != '\x01') {
+ ++file;
+ --len;
+ }
+
+ // find the indexes
+ getIndex(getU8(2, &parsedOk), &nameIdx, &parsedOk);
+ getIndex(nameIdx.endPos, &topDictIdx, &parsedOk);
+ getIndex(topDictIdx.endPos, &stringIdx, &parsedOk);
+ getIndex(stringIdx.endPos, &gsubrIdx, &parsedOk);
+ if (!parsedOk) {
+ return gFalse;
+ }
+ gsubrBias = (gsubrIdx.len < 1240) ? 107
+ : (gsubrIdx.len < 33900) ? 1131 : 32768;
+
+ // read the first font name
+ getIndexVal(&nameIdx, 0, &val, &parsedOk);
+ if (!parsedOk) {
+ return gFalse;
+ }
+ name = new GString((char *)&file[val.pos], val.len);
+
+ // read the top dict for the first font
+ readTopDict();
+
+ // for CID fonts: read the FDArray dicts and private dicts
+ if (topDict.firstOp == 0x0c1e) {
+ if (topDict.fdArrayOffset == 0) {
+ nFDs = 1;
+ privateDicts = (Type1CPrivateDict *)gmalloc(sizeof(Type1CPrivateDict));
+ readPrivateDict(0, 0, &privateDicts[0]);
+ } else {
+ getIndex(topDict.fdArrayOffset, &fdIdx, &parsedOk);
+ if (!parsedOk) {
+ return gFalse;
+ }
+ nFDs = fdIdx.len;
+ privateDicts = (Type1CPrivateDict *)
+ gmallocn(nFDs, sizeof(Type1CPrivateDict));
+ for (i = 0; i < nFDs; ++i) {
+ getIndexVal(&fdIdx, i, &val, &parsedOk);
+ if (!parsedOk) {
+ return gFalse;
+ }
+ readFD(val.pos, val.len, &privateDicts[i]);
+ }
+ }
+
+ // for 8-bit fonts: read the private dict
+ } else {
+ nFDs = 1;
+ privateDicts = (Type1CPrivateDict *)gmalloc(sizeof(Type1CPrivateDict));
+ readPrivateDict(topDict.privateOffset, topDict.privateSize,
+ &privateDicts[0]);
+ }
+
+ // check for parse errors in the private dict(s)
+ if (!parsedOk) {
+ return gFalse;
+ }
+
+ // get the charstrings index
+ if (topDict.charStringsOffset <= 0) {
+ parsedOk = gFalse;
+ return gFalse;
+ }
+ getIndex(topDict.charStringsOffset, &charStringsIdx, &parsedOk);
+ if (!parsedOk) {
+ return gFalse;
+ }
+ nGlyphs = charStringsIdx.len;
+
+ // for CID fonts: read the FDSelect table
+ if (topDict.firstOp == 0x0c1e) {
+ readFDSelect();
+ if (!parsedOk) {
+ return gFalse;
+ }
+ }
+
+ // read the charset
+ if (!readCharset()) {
+ parsedOk = gFalse;
+ return gFalse;
+ }
+
+ // for 8-bit fonts: build the encoding
+ if (topDict.firstOp != 0x0c14 && topDict.firstOp != 0x0c1e) {
+ buildEncoding();
+ if (!parsedOk) {
+ return gFalse;
+ }
+ }
+
+ return parsedOk;
+}
+
+void FoFiType1C::readTopDict() {
+ Type1CIndexVal topDictPtr;
+ int pos;
+
+ topDict.firstOp = -1;
+ topDict.versionSID = 0;
+ topDict.noticeSID = 0;
+ topDict.copyrightSID = 0;
+ topDict.fullNameSID = 0;
+ topDict.familyNameSID = 0;
+ topDict.weightSID = 0;
+ topDict.isFixedPitch = 0;
+ topDict.italicAngle = 0;
+ topDict.underlinePosition = -100;
+ topDict.underlineThickness = 50;
+ topDict.paintType = 0;
+ topDict.charstringType = 2;
+ topDict.fontMatrix[0] = 0.001;
+ topDict.fontMatrix[1] = 0;
+ topDict.fontMatrix[2] = 0;
+ topDict.fontMatrix[3] = 0.001;
+ topDict.fontMatrix[4] = 0;
+ topDict.fontMatrix[5] = 0;
+ topDict.hasFontMatrix = gFalse;
+ topDict.uniqueID = 0;
+ topDict.fontBBox[0] = 0;
+ topDict.fontBBox[1] = 0;
+ topDict.fontBBox[2] = 0;
+ topDict.fontBBox[3] = 0;
+ topDict.strokeWidth = 0;
+ topDict.charsetOffset = 0;
+ topDict.encodingOffset = 0;
+ topDict.charStringsOffset = 0;
+ topDict.privateSize = 0;
+ topDict.privateOffset = 0;
+ topDict.registrySID = 0;
+ topDict.orderingSID = 0;
+ topDict.supplement = 0;
+ topDict.fdArrayOffset = 0;
+ topDict.fdSelectOffset = 0;
+
+ getIndexVal(&topDictIdx, 0, &topDictPtr, &parsedOk);
+ pos = topDictPtr.pos;
+ nOps = 0;
+ while (pos < topDictPtr.pos + topDictPtr.len) {
+ pos = getOp(pos, gFalse, &parsedOk);
+ if (!parsedOk) {
+ break;
+ }
+ if (ops[nOps - 1].kind == type1COpOperator) {
+ --nOps; // drop the operator
+ if (topDict.firstOp < 0) {
+ topDict.firstOp = ops[nOps].op;
+ }
+ switch (ops[nOps].op) {
+ case 0x0000: topDict.versionSID = ops[0].toInt(); break;
+ case 0x0001: topDict.noticeSID = ops[0].toInt(); break;
+ case 0x0c00: topDict.copyrightSID = ops[0].toInt(); break;
+ case 0x0002: topDict.fullNameSID = ops[0].toInt(); break;
+ case 0x0003: topDict.familyNameSID = ops[0].toInt(); break;
+ case 0x0004: topDict.weightSID = ops[0].toInt(); break;
+ case 0x0c01: topDict.isFixedPitch = ops[0].toInt(); break;
+ case 0x0c02: topDict.italicAngle = ops[0].toFloat(); break;
+ case 0x0c03: topDict.underlinePosition = ops[0].toFloat(); break;
+ case 0x0c04: topDict.underlineThickness = ops[0].toFloat(); break;
+ case 0x0c05: topDict.paintType = ops[0].toInt(); break;
+ case 0x0c06: topDict.charstringType = ops[0].toInt(); break;
+ case 0x0c07: topDict.fontMatrix[0] = ops[0].toFloat();
+ topDict.fontMatrix[1] = ops[1].toFloat();
+ topDict.fontMatrix[2] = ops[2].toFloat();
+ topDict.fontMatrix[3] = ops[3].toFloat();
+ topDict.fontMatrix[4] = ops[4].toFloat();
+ topDict.fontMatrix[5] = ops[5].toFloat();
+ topDict.hasFontMatrix = gTrue;
+ break;
+ case 0x000d: topDict.uniqueID = ops[0].toInt(); break;
+ case 0x0005: topDict.fontBBox[0] = ops[0].toFloat();
+ topDict.fontBBox[1] = ops[1].toFloat();
+ topDict.fontBBox[2] = ops[2].toFloat();
+ topDict.fontBBox[3] = ops[3].toFloat();
+ break;
+ case 0x0c08: topDict.strokeWidth = ops[0].toFloat(); break;
+ case 0x000f: topDict.charsetOffset = ops[0].toInt(); break;
+ case 0x0010: topDict.encodingOffset = ops[0].toInt(); break;
+ case 0x0011: topDict.charStringsOffset = ops[0].toInt(); break;
+ case 0x0012: topDict.privateSize = ops[0].toInt();
+ topDict.privateOffset = ops[1].toInt();
+ break;
+ case 0x0c1e: topDict.registrySID = ops[0].toInt();
+ topDict.orderingSID = ops[1].toInt();
+ topDict.supplement = ops[2].toInt();
+ break;
+ case 0x0c24: topDict.fdArrayOffset = ops[0].toInt(); break;
+ case 0x0c25: topDict.fdSelectOffset = ops[0].toInt(); break;
+ }
+ nOps = 0;
+ }
+ }
+}
+
+// Read a CID font dict (FD) - this pulls out the private dict
+// pointer, and reads the private dict. It also pulls the FontMatrix
+// (if any) out of the FD.
+void FoFiType1C::readFD(int offset, int length, Type1CPrivateDict *pDict) {
+ int pos, pSize, pOffset;
+ double fontMatrix[6];
+ GBool hasFontMatrix;
+
+ hasFontMatrix = gFalse;
+ fontMatrix[0] = fontMatrix[1] = fontMatrix[2] = 0; // make gcc happy
+ fontMatrix[3] = fontMatrix[4] = fontMatrix[5] = 0;
+ pSize = pOffset = 0;
+ pos = offset;
+ nOps = 0;
+ while (pos < offset + length) {
+ pos = getOp(pos, gFalse, &parsedOk);
+ if (!parsedOk) {
+ return;
+ }
+ if (ops[nOps - 1].kind == type1COpOperator) {
+ if (ops[nOps - 1].op == 0x0012) {
+ if (nOps < 3) {
+ parsedOk = gFalse;
+ return;
+ }
+ pSize = ops[0].toInt();
+ pOffset = ops[1].toInt();
+ break;
+ } else if (ops[nOps - 1].op == 0x0c07) {
+ fontMatrix[0] = ops[0].toFloat();
+ fontMatrix[1] = ops[1].toFloat();
+ fontMatrix[2] = ops[2].toFloat();
+ fontMatrix[3] = ops[3].toFloat();
+ fontMatrix[4] = ops[4].toFloat();
+ fontMatrix[5] = ops[5].toFloat();
+ hasFontMatrix = gTrue;
+ }
+ nOps = 0;
+ }
+ }
+ readPrivateDict(pOffset, pSize, pDict);
+ if (hasFontMatrix) {
+ pDict->fontMatrix[0] = fontMatrix[0];
+ pDict->fontMatrix[1] = fontMatrix[1];
+ pDict->fontMatrix[2] = fontMatrix[2];
+ pDict->fontMatrix[3] = fontMatrix[3];
+ pDict->fontMatrix[4] = fontMatrix[4];
+ pDict->fontMatrix[5] = fontMatrix[5];
+ pDict->hasFontMatrix = gTrue;
+ }
+}
+
+void FoFiType1C::readPrivateDict(int offset, int length,
+ Type1CPrivateDict *pDict) {
+ int pos;
+
+ pDict->hasFontMatrix = gFalse;
+ pDict->nBlueValues = 0;
+ pDict->nOtherBlues = 0;
+ pDict->nFamilyBlues = 0;
+ pDict->nFamilyOtherBlues = 0;
+ pDict->blueScale = 0.039625;
+ pDict->blueShift = 7;
+ pDict->blueFuzz = 1;
+ pDict->hasStdHW = gFalse;
+ pDict->hasStdVW = gFalse;
+ pDict->nStemSnapH = 0;
+ pDict->nStemSnapV = 0;
+ pDict->hasForceBold = gFalse;
+ pDict->forceBoldThreshold = 0;
+ pDict->languageGroup = 0;
+ pDict->expansionFactor = 0.06;
+ pDict->initialRandomSeed = 0;
+ pDict->subrsOffset = 0;
+ pDict->defaultWidthX = 0;
+ pDict->defaultWidthXInt = gTrue;
+ pDict->nominalWidthX = 0;
+ pDict->nominalWidthXInt = gTrue;
+
+ // no dictionary
+ if (offset == 0 || length == 0) {
+ return;
+ }
+
+ pos = offset;
+ nOps = 0;
+ while (pos < offset + length) {
+ pos = getOp(pos, gFalse, &parsedOk);
+ if (!parsedOk) {
+ break;
+ }
+ if (ops[nOps - 1].kind == type1COpOperator) {
+ --nOps; // drop the operator
+ switch (ops[nOps].op) {
+ case 0x0006:
+ pDict->nBlueValues = getDeltaIntArray(pDict->blueValues,
+ type1CMaxBlueValues);
+ break;
+ case 0x0007:
+ pDict->nOtherBlues = getDeltaIntArray(pDict->otherBlues,
+ type1CMaxOtherBlues);
+ break;
+ case 0x0008:
+ pDict->nFamilyBlues = getDeltaIntArray(pDict->familyBlues,
+ type1CMaxBlueValues);
+ break;
+ case 0x0009:
+ pDict->nFamilyOtherBlues = getDeltaIntArray(pDict->familyOtherBlues,
+ type1CMaxOtherBlues);
+ break;
+ case 0x0c09:
+ pDict->blueScale = ops[0].toFloat();
+ break;
+ case 0x0c0a:
+ pDict->blueShift = ops[0].toInt();
+ break;
+ case 0x0c0b:
+ pDict->blueFuzz = ops[0].toInt();
+ break;
+ case 0x000a:
+ pDict->stdHW = ops[0].toFloat();
+ pDict->hasStdHW = gTrue;
+ break;
+ case 0x000b:
+ pDict->stdVW = ops[0].toFloat();
+ pDict->hasStdVW = gTrue;
+ break;
+ case 0x0c0c:
+ pDict->nStemSnapH = getDeltaFPArray(pDict->stemSnapH,
+ type1CMaxStemSnap);
+ break;
+ case 0x0c0d:
+ pDict->nStemSnapV = getDeltaFPArray(pDict->stemSnapV,
+ type1CMaxStemSnap);
+ break;
+ case 0x0c0e:
+ pDict->forceBold = !ops[0].isZero();
+ pDict->hasForceBold = gTrue;
+ break;
+ case 0x0c0f:
+ pDict->forceBoldThreshold = ops[0].toFloat();
+ break;
+ case 0x0c11:
+ pDict->languageGroup = ops[0].toInt();
+ break;
+ case 0x0c12:
+ pDict->expansionFactor = ops[0].toFloat();
+ break;
+ case 0x0c13:
+ pDict->initialRandomSeed = ops[0].toInt();
+ break;
+ case 0x0013:
+ pDict->subrsOffset = offset + ops[0].toInt();
+ break;
+ case 0x0014:
+ pDict->defaultWidthX = ops[0].toFloat();
+ pDict->defaultWidthXInt = ops[0].kind == type1COpInteger;
+ break;
+ case 0x0015:
+ pDict->nominalWidthX = ops[0].toFloat();
+ pDict->nominalWidthXInt = ops[0].kind == type1COpInteger;
+ break;
+ }
+ nOps = 0;
+ }
+ }
+}
+
+void FoFiType1C::readFDSelect() {
+ int fdSelectFmt, pos, nRanges, gid0, gid1, fd, i, j;
+
+ fdSelect = (Guchar *)gmalloc(nGlyphs);
+ for (i = 0; i < nGlyphs; ++i) {
+ fdSelect[i] = 0;
+ }
+ if (topDict.fdSelectOffset != 0) {
+ pos = topDict.fdSelectOffset;
+ fdSelectFmt = getU8(pos++, &parsedOk);
+ if (!parsedOk) {
+ return;
+ }
+ if (fdSelectFmt == 0) {
+ if (!checkRegion(pos, nGlyphs)) {
+ parsedOk = gFalse;
+ return;
+ }
+ for (gid0 = 0; gid0 < nGlyphs; ++gid0) {
+ if (file[pos + gid0] >= nFDs) {
+ //~ error(-1, "Bad FDSelect table in CID font");
+ parsedOk = gFalse;
+ return;
+ }
+ fdSelect[gid0] = file[pos + gid0];
+ }
+ } else if (fdSelectFmt == 3) {
+ nRanges = getU16BE(pos, &parsedOk);
+ pos += 2;
+ gid0 = getU16BE(pos, &parsedOk);
+ pos += 2;
+ for (i = 1; i <= nRanges; ++i) {
+ fd = getU8(pos++, &parsedOk);
+ gid1 = getU16BE(pos, &parsedOk);
+ if (!parsedOk) {
+ return;
+ }
+ pos += 2;
+ if (gid0 > gid1 || gid1 > nGlyphs || fd >= nFDs) {
+ //~ error(-1, "Bad FDSelect table in CID font");
+ parsedOk = gFalse;
+ return;
+ }
+ for (j = gid0; j < gid1; ++j) {
+ fdSelect[j] = (Guchar)fd;
+ }
+ gid0 = gid1;
+ }
+ } else {
+ //~ error(-1, "Unknown FDSelect table format in CID font");
+ }
+ }
+}
+
+void FoFiType1C::buildEncoding() {
+ char buf[256];
+ int nCodes, nRanges, encFormat;
+ int pos, c, sid, nLeft, nSups, i, j;
+
+ if (topDict.encodingOffset == 0) {
+ encoding = (char **)fofiType1StandardEncoding;
+
+ } else if (topDict.encodingOffset == 1) {
+ encoding = (char **)fofiType1ExpertEncoding;
+
+ } else {
+ encoding = (char **)gmallocn(256, sizeof(char *));
+ for (i = 0; i < 256; ++i) {
+ encoding[i] = NULL;
+ }
+ pos = topDict.encodingOffset;
+ encFormat = getU8(pos++, &parsedOk);
+ if (!parsedOk) {
+ return;
+ }
+ if ((encFormat & 0x7f) == 0) {
+ nCodes = 1 + getU8(pos++, &parsedOk);
+ if (!parsedOk) {
+ return;
+ }
+ if (nCodes > nGlyphs) {
+ nCodes = nGlyphs;
+ }
+ for (i = 1; i < nCodes; ++i) {
+ c = getU8(pos++, &parsedOk);
+ if (!parsedOk) {
+ return;
+ }
+ if (encoding[c]) {
+ gfree(encoding[c]);
+ }
+ encoding[c] = copyString(getString(charset[i], buf, &parsedOk));
+ }
+ } else if ((encFormat & 0x7f) == 1) {
+ nRanges = getU8(pos++, &parsedOk);
+ if (!parsedOk) {
+ return;
+ }
+ nCodes = 1;
+ for (i = 0; i < nRanges; ++i) {
+ c = getU8(pos++, &parsedOk);
+ nLeft = getU8(pos++, &parsedOk);
+ if (!parsedOk) {
+ return;
+ }
+ for (j = 0; j <= nLeft && nCodes < nGlyphs; ++j) {
+ if (c < 256) {
+ if (encoding[c]) {
+ gfree(encoding[c]);
+ }
+ encoding[c] = copyString(getString(charset[nCodes], buf,
+ &parsedOk));
+ }
+ ++nCodes;
+ ++c;
+ }
+ }
+ }
+ if (encFormat & 0x80) {
+ nSups = getU8(pos++, &parsedOk);
+ if (!parsedOk) {
+ return;
+ }
+ for (i = 0; i < nSups; ++i) {
+ c = getU8(pos++, &parsedOk);;
+ if (!parsedOk) {
+ return;;
+ }
+ sid = getU16BE(pos, &parsedOk);
+ pos += 2;
+ if (!parsedOk) {
+ return;
+ }
+ if (encoding[c]) {
+ gfree(encoding[c]);
+ }
+ encoding[c] = copyString(getString(sid, buf, &parsedOk));
+ }
+ }
+ }
+}
+
+GBool FoFiType1C::readCharset() {
+ int charsetFormat, c, pos;
+ int nLeft, i, j;
+
+ if (topDict.charsetOffset == 0) {
+ charset = fofiType1CISOAdobeCharset;
+ if (nGlyphs > 229) {
+ nGlyphs = 229;
+ }
+ } else if (topDict.charsetOffset == 1) {
+ charset = fofiType1CExpertCharset;
+ if (nGlyphs > 166) {
+ nGlyphs = 166;
+ }
+ } else if (topDict.charsetOffset == 2) {
+ charset = fofiType1CExpertSubsetCharset;
+ if (nGlyphs > 87) {
+ nGlyphs = 87;
+ }
+ } else {
+ charset = (Gushort *)gmallocn(nGlyphs, sizeof(Gushort));
+ for (i = 0; i < nGlyphs; ++i) {
+ charset[i] = 0;
+ }
+ pos = topDict.charsetOffset;
+ charsetFormat = getU8(pos++, &parsedOk);
+ if (charsetFormat == 0) {
+ for (i = 1; i < nGlyphs; ++i) {
+ charset[i] = (Gushort)getU16BE(pos, &parsedOk);
+ pos += 2;
+ if (!parsedOk) {
+ break;
+ }
+ }
+ } else if (charsetFormat == 1) {
+ i = 1;
+ while (i < nGlyphs) {
+ c = getU16BE(pos, &parsedOk);
+ pos += 2;
+ nLeft = getU8(pos++, &parsedOk);
+ if (!parsedOk) {
+ break;
+ }
+ for (j = 0; j <= nLeft && i < nGlyphs; ++j) {
+ charset[i++] = (Gushort)c++;
+ }
+ }
+ } else if (charsetFormat == 2) {
+ i = 1;
+ while (i < nGlyphs) {
+ c = getU16BE(pos, &parsedOk);
+ pos += 2;
+ nLeft = getU16BE(pos, &parsedOk);
+ pos += 2;
+ if (!parsedOk) {
+ break;
+ }
+ for (j = 0; j <= nLeft && i < nGlyphs; ++j) {
+ charset[i++] = (Gushort)c++;
+ }
+ }
+ }
+ if (!parsedOk) {
+ gfree(charset);
+ charset = NULL;
+ return gFalse;
+ }
+ }
+ return gTrue;
+}
+
+int FoFiType1C::getOp(int pos, GBool charstring, GBool *ok) {
+ static char nybChars[16] = "0123456789.ee -";
+ Type1COp op;
+ char buf[65];
+ int b0, b1, nyb0, nyb1, x, i;
+
+ b0 = getU8(pos++, ok);
+
+ if (b0 == 28) {
+ x = getU8(pos++, ok);
+ x = (x << 8) | getU8(pos++, ok);
+ if (x & 0x8000) {
+ x |= ~0xffff;
+ }
+ op.kind = type1COpInteger;
+ op.intgr = x;
+
+ } else if (!charstring && b0 == 29) {
+ x = getU8(pos++, ok);
+ x = (x << 8) | getU8(pos++, ok);
+ x = (x << 8) | getU8(pos++, ok);
+ x = (x << 8) | getU8(pos++, ok);
+ if (x & 0x80000000) {
+ x |= ~0xffffffff;
+ }
+ op.kind = type1COpInteger;
+ op.intgr = x;
+
+ } else if (!charstring && b0 == 30) {
+ i = 0;
+ do {
+ b1 = getU8(pos++, ok);
+ nyb0 = b1 >> 4;
+ nyb1 = b1 & 0x0f;
+ if (nyb0 == 0xf) {
+ break;
+ }
+ buf[i++] = nybChars[nyb0];
+ if (i == 64) {
+ break;
+ }
+ if (nyb0 == 0xc) {
+ buf[i++] = '-';
+ }
+ if (i == 64) {
+ break;
+ }
+ if (nyb1 == 0xf) {
+ break;
+ }
+ buf[i++] = nybChars[nyb1];
+ if (i == 64) {
+ break;
+ }
+ if (nyb1 == 0xc) {
+ buf[i++] = '-';
+ }
+ } while (i < 64);
+ buf[i] = '\0';
+ op.kind = type1COpFloat;
+ op.flt = atof(buf);
+
+ } else if (b0 >= 32 && b0 <= 246) {
+ op.kind = type1COpInteger;
+ op.intgr = b0 - 139;
+
+ } else if (b0 >= 247 && b0 <= 250) {
+ op.kind = type1COpInteger;
+ op.intgr = ((b0 - 247) << 8) + getU8(pos++, ok) + 108;
+
+ } else if (b0 >= 251 && b0 <= 254) {
+ op.kind = type1COpInteger;
+ op.intgr = -((b0 - 251) << 8) - getU8(pos++, ok) - 108;
+
+ } else if (charstring && b0 == 255) {
+ x = getU8(pos++, ok);
+ x = (x << 8) | getU8(pos++, ok);
+ x = (x << 8) | getU8(pos++, ok);
+ x = (x << 8) | getU8(pos++, ok);
+ if (x & 0x80000000) {
+ x |= ~0xffffffff;
+ }
+ op.kind = type1COpFloat;
+ op.flt = (double)x / 65536.0;
+
+ } else if (b0 == 12) {
+ op.kind = type1COpOperator;
+ op.op = 0x0c00 + getU8(pos++, ok);
+
+ } else {
+ op.kind = type1COpOperator;
+ op.op = b0;
+ }
+
+ if (nOps < 49) {
+ ops[nOps++] = op;
+ }
+
+ return pos;
+}
+
+// Convert the delta-encoded ops array to an array of ints.
+int FoFiType1C::getDeltaIntArray(int *arr, int maxLen) {
+ int x;
+ int n, i;
+
+ if ((n = nOps) > maxLen) {
+ n = maxLen;
+ }
+ x = 0;
+ for (i = 0; i < n; ++i) {
+ x += ops[i].toInt();
+ arr[i] = x;
+ }
+ return n;
+}
+
+// Convert the delta-encoded ops array to an array of doubles.
+int FoFiType1C::getDeltaFPArray(double *arr, int maxLen) {
+ double x;
+ int n, i;
+
+ if ((n = nOps) > maxLen) {
+ n = maxLen;
+ }
+ x = 0;
+ for (i = 0; i < n; ++i) {
+ x += ops[i].toFloat();
+ arr[i] = x;
+ }
+ return n;
+}
+
+void FoFiType1C::getIndex(int pos, Type1CIndex *idx, GBool *ok) {
+ idx->pos = pos;
+ idx->len = getU16BE(pos, ok);
+ if (idx->len == 0) {
+ // empty indexes are legal and contain just the length field
+ idx->offSize = 0;
+ idx->startPos = idx->endPos = pos + 2;
+ } else {
+ idx->offSize = getU8(pos + 2, ok);
+ if (idx->offSize < 1 || idx->offSize > 4) {
+ *ok = gFalse;
+ }
+ idx->startPos = pos + 3 + (idx->len + 1) * idx->offSize - 1;
+ if (idx->startPos < 0 || idx->startPos >= len) {
+ *ok = gFalse;
+ }
+ idx->endPos = idx->startPos + getUVarBE(pos + 3 + idx->len * idx->offSize,
+ idx->offSize, ok);
+ if (idx->endPos < idx->startPos || idx->endPos > len) {
+ *ok = gFalse;
+ }
+ }
+}
+
+void FoFiType1C::getIndexVal(Type1CIndex *idx, int i,
+ Type1CIndexVal *val, GBool *ok) {
+ int pos0, pos1;
+
+ if (i < 0 || i >= idx->len) {
+ val->pos = 0;
+ val->len = 0;
+ *ok = gFalse;
+ return;
+ }
+ pos0 = idx->startPos + getUVarBE(idx->pos + 3 + i * idx->offSize,
+ idx->offSize, ok);
+ pos1 = idx->startPos + getUVarBE(idx->pos + 3 + (i + 1) * idx->offSize,
+ idx->offSize, ok);
+ if (pos0 < idx->startPos || pos0 > idx->endPos ||
+ pos1 <= idx->startPos || pos1 > idx->endPos ||
+ pos1 < pos0) {
+ *ok = gFalse;
+ }
+ val->pos = pos0;
+ val->len = pos1 - pos0;
+}
+
+char *FoFiType1C::getString(int sid, char *buf, GBool *ok) {
+ Type1CIndexVal val;
+ int n;
+
+ if (sid < 0) {
+ buf[0] = '\0';
+ } else if (sid < 391) {
+ strcpy(buf, fofiType1CStdStrings[sid]);
+ } else {
+ sid -= 391;
+ getIndexVal(&stringIdx, sid, &val, ok);
+ if (*ok) {
+ if ((n = val.len) > 255) {
+ n = 255;
+ }
+ strncpy(buf, (char *)&file[val.pos], n);
+ buf[n] = '\0';
+ } else {
+ buf[0] = '\0';
+ }
+ }
+ return buf;
+}
diff --git a/fofi/FoFiType1C.h b/fofi/FoFiType1C.h
new file mode 100644
index 0000000..15a823c
--- /dev/null
+++ b/fofi/FoFiType1C.h
@@ -0,0 +1,281 @@
+//========================================================================
+//
+// FoFiType1C.h
+//
+// Copyright 1999-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef FOFITYPE1C_H
+#define FOFITYPE1C_H
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include "gtypes.h"
+#include "FoFiBase.h"
+
+class GHash;
+class GString;
+
+//------------------------------------------------------------------------
+
+struct Type1CIndex {
+ int pos; // absolute position in file
+ int len; // length (number of entries)
+ int offSize; // offset size
+ int startPos; // position of start of index data - 1
+ int endPos; // position one byte past end of the index
+};
+
+struct Type1CIndexVal {
+ int pos; // absolute position in file
+ int len; // length, in bytes
+};
+
+struct Type1CTopDict {
+ int firstOp;
+
+ int versionSID;
+ int noticeSID;
+ int copyrightSID;
+ int fullNameSID;
+ int familyNameSID;
+ int weightSID;
+ int isFixedPitch;
+ double italicAngle;
+ double underlinePosition;
+ double underlineThickness;
+ int paintType;
+ int charstringType;
+ double fontMatrix[6];
+ GBool hasFontMatrix; // CID fonts are allowed to put their
+ // FontMatrix in the FD instead of the
+ // top dict
+ int uniqueID;
+ double fontBBox[4];
+ double strokeWidth;
+ int charsetOffset;
+ int encodingOffset;
+ int charStringsOffset;
+ int privateSize;
+ int privateOffset;
+
+ // CIDFont entries
+ int registrySID;
+ int orderingSID;
+ int supplement;
+ int fdArrayOffset;
+ int fdSelectOffset;
+};
+
+#define type1CMaxBlueValues 14
+#define type1CMaxOtherBlues 10
+#define type1CMaxStemSnap 12
+
+struct Type1CPrivateDict {
+ double fontMatrix[6];
+ GBool hasFontMatrix;
+ int blueValues[type1CMaxBlueValues];
+ int nBlueValues;
+ int otherBlues[type1CMaxOtherBlues];
+ int nOtherBlues;
+ int familyBlues[type1CMaxBlueValues];
+ int nFamilyBlues;
+ int familyOtherBlues[type1CMaxOtherBlues];
+ int nFamilyOtherBlues;
+ double blueScale;
+ int blueShift;
+ int blueFuzz;
+ double stdHW;
+ GBool hasStdHW;
+ double stdVW;
+ GBool hasStdVW;
+ double stemSnapH[type1CMaxStemSnap];
+ int nStemSnapH;
+ double stemSnapV[type1CMaxStemSnap];
+ int nStemSnapV;
+ GBool forceBold;
+ GBool hasForceBold;
+ double forceBoldThreshold;
+ int languageGroup;
+ double expansionFactor;
+ int initialRandomSeed;
+ int subrsOffset;
+ double defaultWidthX;
+ GBool defaultWidthXInt;
+ double nominalWidthX;
+ GBool nominalWidthXInt;
+};
+
+// operand kind
+enum Type1COpKind {
+ type1COpOperator,
+ type1COpInteger,
+ type1COpFloat,
+ type1COpRational
+};
+
+// operand
+struct Type1COp {
+ Type1COpKind kind;
+ union {
+ int op; // type1COpOperator
+ int intgr; // type1COpInteger
+ double flt; // type1COpFloat
+ struct {
+ int num, den; // type1COpRational
+ } rat;
+ };
+ GBool isZero();
+ GBool isNegative();
+ int toInt();
+ double toFloat();
+};
+
+struct Type1CEexecBuf {
+ FoFiOutputFunc outputFunc;
+ void *outputStream;
+ GBool ascii; // ASCII encoding?
+ Gushort r1; // eexec encryption key
+ int line; // number of eexec chars left on current line
+};
+
+//------------------------------------------------------------------------
+// FoFiType1C
+//------------------------------------------------------------------------
+
+class FoFiType1C: public FoFiBase {
+public:
+
+ // Create a FoFiType1C object from a memory buffer.
+ static FoFiType1C *make(char *fileA, int lenA);
+
+ // Create a FoFiType1C object from a file on disk.
+ static FoFiType1C *load(char *fileName);
+
+ virtual ~FoFiType1C();
+
+ // Return the font name.
+ char *getName();
+
+ // Return the encoding, as an array of 256 names (any of which may
+ // be NULL). This is only useful with 8-bit fonts.
+ char **getEncoding();
+
+ // Get the glyph names.
+ int getNumGlyphs() { return nGlyphs; }
+ GString *getGlyphName(int gid);
+
+ // Returns a hash mapping glyph names to GIDs. This is only useful
+ // with 8-bit fonts.
+ GHash *getNameToGIDMap();
+
+ // Return the mapping from CIDs to GIDs, and return the number of
+ // CIDs in *<nCIDs>. This is only useful for CID fonts.
+ int *getCIDToGIDMap(int *nCIDs);
+
+ // Return the font matrix as an array of six numbers.
+ void getFontMatrix(double *mat);
+
+ // Convert to a Type 1 font, suitable for embedding in a PostScript
+ // file. This is only useful with 8-bit fonts. If <newEncoding> is
+ // not NULL, it will be used in place of the encoding in the Type 1C
+ // font. If <ascii> is true the eexec section will be hex-encoded,
+ // otherwise it will be left as binary data. If <psName> is non-NULL,
+ // it will be used as the PostScript font name.
+ void convertToType1(char *psName, const char **newEncoding, GBool ascii,
+ FoFiOutputFunc outputFunc, void *outputStream);
+
+ // Convert to a Type 0 CIDFont, suitable for embedding in a
+ // PostScript file. <psName> will be used as the PostScript font
+ // name. There are three cases for the CID-to-GID mapping:
+ // (1) if <codeMap> is non-NULL, then it is the CID-to-GID mapping
+ // (2) if <codeMap> is NULL and this is a CID CFF font, then the
+ // font's internal CID-to-GID mapping is used
+ // (3) is <codeMap> is NULL and this is an 8-bit CFF font, then
+ // the identity CID-to-GID mapping is used
+ void convertToCIDType0(char *psName, int *codeMap, int nCodes,
+ FoFiOutputFunc outputFunc, void *outputStream);
+
+ // Convert to a Type 0 (but non-CID) composite font, suitable for
+ // embedding in a PostScript file. <psName> will be used as the
+ // PostScript font name. There are three cases for the CID-to-GID
+ // mapping:
+ // (1) if <codeMap> is non-NULL, then it is the CID-to-GID mapping
+ // (2) if <codeMap> is NULL and this is a CID CFF font, then the
+ // font's internal CID-to-GID mapping is used
+ // (3) is <codeMap> is NULL and this is an 8-bit CFF font, then
+ // the identity CID-to-GID mapping is used
+ void convertToType0(char *psName, int *codeMap, int nCodes,
+ FoFiOutputFunc outputFunc, void *outputStream);
+
+ // Write an OpenType file, encapsulating the CFF font. <widths>
+ // provides the glyph widths (in design units) for <nWidths> glyphs.
+ // The cmap table must be supplied by the caller.
+ void convertToOpenType(FoFiOutputFunc outputFunc, void *outputStream,
+ int nWidths, Gushort *widths,
+ Guchar *cmapTable, int cmapTableLen);
+
+private:
+
+ FoFiType1C(char *fileA, int lenA, GBool freeFileDataA);
+ void eexecCvtGlyph(Type1CEexecBuf *eb, const char *glyphName,
+ int offset, int nBytes,
+ Type1CIndex *subrIdx,
+ Type1CPrivateDict *pDict);
+ void cvtGlyph(int offset, int nBytes, GString *charBuf,
+ Type1CIndex *subrIdx, Type1CPrivateDict *pDict,
+ GBool top, int recursion);
+ void cvtGlyphWidth(GBool useOp, GString *charBuf,
+ Type1CPrivateDict *pDict);
+ void cvtNum(Type1COp op, GString *charBuf);
+ void eexecWrite(Type1CEexecBuf *eb, const char *s);
+ void eexecWriteCharstring(Type1CEexecBuf *eb, Guchar *s, int n);
+ void writePSString(char *s, FoFiOutputFunc outputFunc, void *outputStream);
+ Guint computeOpenTypeTableChecksum(Guchar *data, int length);
+ GBool parse();
+ void readTopDict();
+ void readFD(int offset, int length, Type1CPrivateDict *pDict);
+ void readPrivateDict(int offset, int length, Type1CPrivateDict *pDict);
+ void readFDSelect();
+ void buildEncoding();
+ GBool readCharset();
+ int getOp(int pos, GBool charstring, GBool *ok);
+ int getDeltaIntArray(int *arr, int maxLen);
+ int getDeltaFPArray(double *arr, int maxLen);
+ void getIndex(int pos, Type1CIndex *idx, GBool *ok);
+ void getIndexVal(Type1CIndex *idx, int i, Type1CIndexVal *val, GBool *ok);
+ char *getString(int sid, char *buf, GBool *ok);
+
+ GString *name;
+ char **encoding;
+
+ Type1CIndex nameIdx;
+ Type1CIndex topDictIdx;
+ Type1CIndex stringIdx;
+ Type1CIndex gsubrIdx;
+ Type1CIndex charStringsIdx;
+
+ Type1CTopDict topDict;
+ Type1CPrivateDict *privateDicts;
+
+ int nGlyphs;
+ int nFDs;
+ Guchar *fdSelect;
+ Gushort *charset;
+ int gsubrBias;
+
+ GBool parsedOk;
+
+ Type1COp ops[49]; // operands and operator
+ int nOps; // number of operands
+ int nHints; // number of hints for the current glyph
+ GBool firstOp; // true if we haven't hit the first op yet
+ GBool openPath; // true if there is an unclosed path
+};
+
+#endif
diff --git a/fofi/Makefile b/fofi/Makefile
new file mode 100644
index 0000000..95b56dc
--- /dev/null
+++ b/fofi/Makefile
@@ -0,0 +1,415 @@
+# 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 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 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 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/fofi//CMakeFiles/progress.marks
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 fofi/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 fofi/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 fofi/preinstall
+.PHONY : preinstall
+
+# Prepare targets for installation.
+preinstall/fast:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 fofi/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.
+fofi/CMakeFiles/fofi.dir/rule:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 fofi/CMakeFiles/fofi.dir/rule
+.PHONY : fofi/CMakeFiles/fofi.dir/rule
+
+# Convenience name for target.
+fofi: fofi/CMakeFiles/fofi.dir/rule
+
+.PHONY : fofi
+
+# fast build rule for target.
+fofi/fast:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f fofi/CMakeFiles/fofi.dir/build.make fofi/CMakeFiles/fofi.dir/build
+.PHONY : fofi/fast
+
+# Convenience name for target.
+fofi/CMakeFiles/fofi_objs.dir/rule:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 fofi/CMakeFiles/fofi_objs.dir/rule
+.PHONY : fofi/CMakeFiles/fofi_objs.dir/rule
+
+# Convenience name for target.
+fofi_objs: fofi/CMakeFiles/fofi_objs.dir/rule
+
+.PHONY : fofi_objs
+
+# fast build rule for target.
+fofi_objs/fast:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f fofi/CMakeFiles/fofi_objs.dir/build.make fofi/CMakeFiles/fofi_objs.dir/build
+.PHONY : fofi_objs/fast
+
+FoFiBase.o: FoFiBase.cc.o
+
+.PHONY : FoFiBase.o
+
+# target to build an object file
+FoFiBase.cc.o:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f fofi/CMakeFiles/fofi_objs.dir/build.make fofi/CMakeFiles/fofi_objs.dir/FoFiBase.cc.o
+.PHONY : FoFiBase.cc.o
+
+FoFiBase.i: FoFiBase.cc.i
+
+.PHONY : FoFiBase.i
+
+# target to preprocess a source file
+FoFiBase.cc.i:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f fofi/CMakeFiles/fofi_objs.dir/build.make fofi/CMakeFiles/fofi_objs.dir/FoFiBase.cc.i
+.PHONY : FoFiBase.cc.i
+
+FoFiBase.s: FoFiBase.cc.s
+
+.PHONY : FoFiBase.s
+
+# target to generate assembly for a file
+FoFiBase.cc.s:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f fofi/CMakeFiles/fofi_objs.dir/build.make fofi/CMakeFiles/fofi_objs.dir/FoFiBase.cc.s
+.PHONY : FoFiBase.cc.s
+
+FoFiEncodings.o: FoFiEncodings.cc.o
+
+.PHONY : FoFiEncodings.o
+
+# target to build an object file
+FoFiEncodings.cc.o:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f fofi/CMakeFiles/fofi_objs.dir/build.make fofi/CMakeFiles/fofi_objs.dir/FoFiEncodings.cc.o
+.PHONY : FoFiEncodings.cc.o
+
+FoFiEncodings.i: FoFiEncodings.cc.i
+
+.PHONY : FoFiEncodings.i
+
+# target to preprocess a source file
+FoFiEncodings.cc.i:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f fofi/CMakeFiles/fofi_objs.dir/build.make fofi/CMakeFiles/fofi_objs.dir/FoFiEncodings.cc.i
+.PHONY : FoFiEncodings.cc.i
+
+FoFiEncodings.s: FoFiEncodings.cc.s
+
+.PHONY : FoFiEncodings.s
+
+# target to generate assembly for a file
+FoFiEncodings.cc.s:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f fofi/CMakeFiles/fofi_objs.dir/build.make fofi/CMakeFiles/fofi_objs.dir/FoFiEncodings.cc.s
+.PHONY : FoFiEncodings.cc.s
+
+FoFiIdentifier.o: FoFiIdentifier.cc.o
+
+.PHONY : FoFiIdentifier.o
+
+# target to build an object file
+FoFiIdentifier.cc.o:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f fofi/CMakeFiles/fofi_objs.dir/build.make fofi/CMakeFiles/fofi_objs.dir/FoFiIdentifier.cc.o
+.PHONY : FoFiIdentifier.cc.o
+
+FoFiIdentifier.i: FoFiIdentifier.cc.i
+
+.PHONY : FoFiIdentifier.i
+
+# target to preprocess a source file
+FoFiIdentifier.cc.i:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f fofi/CMakeFiles/fofi_objs.dir/build.make fofi/CMakeFiles/fofi_objs.dir/FoFiIdentifier.cc.i
+.PHONY : FoFiIdentifier.cc.i
+
+FoFiIdentifier.s: FoFiIdentifier.cc.s
+
+.PHONY : FoFiIdentifier.s
+
+# target to generate assembly for a file
+FoFiIdentifier.cc.s:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f fofi/CMakeFiles/fofi_objs.dir/build.make fofi/CMakeFiles/fofi_objs.dir/FoFiIdentifier.cc.s
+.PHONY : FoFiIdentifier.cc.s
+
+FoFiTrueType.o: FoFiTrueType.cc.o
+
+.PHONY : FoFiTrueType.o
+
+# target to build an object file
+FoFiTrueType.cc.o:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f fofi/CMakeFiles/fofi_objs.dir/build.make fofi/CMakeFiles/fofi_objs.dir/FoFiTrueType.cc.o
+.PHONY : FoFiTrueType.cc.o
+
+FoFiTrueType.i: FoFiTrueType.cc.i
+
+.PHONY : FoFiTrueType.i
+
+# target to preprocess a source file
+FoFiTrueType.cc.i:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f fofi/CMakeFiles/fofi_objs.dir/build.make fofi/CMakeFiles/fofi_objs.dir/FoFiTrueType.cc.i
+.PHONY : FoFiTrueType.cc.i
+
+FoFiTrueType.s: FoFiTrueType.cc.s
+
+.PHONY : FoFiTrueType.s
+
+# target to generate assembly for a file
+FoFiTrueType.cc.s:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f fofi/CMakeFiles/fofi_objs.dir/build.make fofi/CMakeFiles/fofi_objs.dir/FoFiTrueType.cc.s
+.PHONY : FoFiTrueType.cc.s
+
+FoFiType1.o: FoFiType1.cc.o
+
+.PHONY : FoFiType1.o
+
+# target to build an object file
+FoFiType1.cc.o:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f fofi/CMakeFiles/fofi_objs.dir/build.make fofi/CMakeFiles/fofi_objs.dir/FoFiType1.cc.o
+.PHONY : FoFiType1.cc.o
+
+FoFiType1.i: FoFiType1.cc.i
+
+.PHONY : FoFiType1.i
+
+# target to preprocess a source file
+FoFiType1.cc.i:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f fofi/CMakeFiles/fofi_objs.dir/build.make fofi/CMakeFiles/fofi_objs.dir/FoFiType1.cc.i
+.PHONY : FoFiType1.cc.i
+
+FoFiType1.s: FoFiType1.cc.s
+
+.PHONY : FoFiType1.s
+
+# target to generate assembly for a file
+FoFiType1.cc.s:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f fofi/CMakeFiles/fofi_objs.dir/build.make fofi/CMakeFiles/fofi_objs.dir/FoFiType1.cc.s
+.PHONY : FoFiType1.cc.s
+
+FoFiType1C.o: FoFiType1C.cc.o
+
+.PHONY : FoFiType1C.o
+
+# target to build an object file
+FoFiType1C.cc.o:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f fofi/CMakeFiles/fofi_objs.dir/build.make fofi/CMakeFiles/fofi_objs.dir/FoFiType1C.cc.o
+.PHONY : FoFiType1C.cc.o
+
+FoFiType1C.i: FoFiType1C.cc.i
+
+.PHONY : FoFiType1C.i
+
+# target to preprocess a source file
+FoFiType1C.cc.i:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f fofi/CMakeFiles/fofi_objs.dir/build.make fofi/CMakeFiles/fofi_objs.dir/FoFiType1C.cc.i
+.PHONY : FoFiType1C.cc.i
+
+FoFiType1C.s: FoFiType1C.cc.s
+
+.PHONY : FoFiType1C.s
+
+# target to generate assembly for a file
+FoFiType1C.cc.s:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f fofi/CMakeFiles/fofi_objs.dir/build.make fofi/CMakeFiles/fofi_objs.dir/FoFiType1C.cc.s
+.PHONY : FoFiType1C.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 "... fofi"
+ @echo "... fofi_objs"
+ @echo "... FoFiBase.o"
+ @echo "... FoFiBase.i"
+ @echo "... FoFiBase.s"
+ @echo "... FoFiEncodings.o"
+ @echo "... FoFiEncodings.i"
+ @echo "... FoFiEncodings.s"
+ @echo "... FoFiIdentifier.o"
+ @echo "... FoFiIdentifier.i"
+ @echo "... FoFiIdentifier.s"
+ @echo "... FoFiTrueType.o"
+ @echo "... FoFiTrueType.i"
+ @echo "... FoFiTrueType.s"
+ @echo "... FoFiType1.o"
+ @echo "... FoFiType1.i"
+ @echo "... FoFiType1.s"
+ @echo "... FoFiType1C.o"
+ @echo "... FoFiType1C.i"
+ @echo "... FoFiType1C.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/fofi/cmake_install.cmake b/fofi/cmake_install.cmake
new file mode 100644
index 0000000..99e1905
--- /dev/null
+++ b/fofi/cmake_install.cmake
@@ -0,0 +1,44 @@
+# Install script for directory: /home/calvin/src/xpdf-4.04/fofi
+
+# 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()
+
diff --git a/fofi/libfofi.a b/fofi/libfofi.a
new file mode 100644
index 0000000..0eb6473
--- /dev/null
+++ b/fofi/libfofi.a
Binary files differ
diff --git a/goo/CMakeFiles/CMakeDirectoryInformation.cmake b/goo/CMakeFiles/CMakeDirectoryInformation.cmake
new file mode 100644
index 0000000..aef4d6c
--- /dev/null
+++ b/goo/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/goo/CMakeFiles/goo.dir/DependInfo.cmake b/goo/CMakeFiles/goo.dir/DependInfo.cmake
new file mode 100644
index 0000000..19fab21
--- /dev/null
+++ b/goo/CMakeFiles/goo.dir/DependInfo.cmake
@@ -0,0 +1,11 @@
+# The set of languages for which implicit dependencies are needed:
+set(CMAKE_DEPENDS_LANGUAGES
+ )
+# The set of files for implicit dependencies of each language:
+
+# 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/goo/CMakeFiles/goo.dir/build.make b/goo/CMakeFiles/goo.dir/build.make
new file mode 100644
index 0000000..9af066d
--- /dev/null
+++ b/goo/CMakeFiles/goo.dir/build.make
@@ -0,0 +1,121 @@
+# 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 goo/CMakeFiles/goo.dir/depend.make
+
+# Include the progress variables for this target.
+include goo/CMakeFiles/goo.dir/progress.make
+
+# Include the compile flags for this target's objects.
+include goo/CMakeFiles/goo.dir/flags.make
+
+# Object files for target goo
+goo_OBJECTS =
+
+# External object files for target goo
+goo_EXTERNAL_OBJECTS = \
+"/home/calvin/src/xpdf-4.04/goo/CMakeFiles/goo_objs.dir/FixedPoint.cc.o" \
+"/home/calvin/src/xpdf-4.04/goo/CMakeFiles/goo_objs.dir/GHash.cc.o" \
+"/home/calvin/src/xpdf-4.04/goo/CMakeFiles/goo_objs.dir/GList.cc.o" \
+"/home/calvin/src/xpdf-4.04/goo/CMakeFiles/goo_objs.dir/GString.cc.o" \
+"/home/calvin/src/xpdf-4.04/goo/CMakeFiles/goo_objs.dir/gfile.cc.o" \
+"/home/calvin/src/xpdf-4.04/goo/CMakeFiles/goo_objs.dir/gmem.cc.o" \
+"/home/calvin/src/xpdf-4.04/goo/CMakeFiles/goo_objs.dir/gmempp.cc.o" \
+"/home/calvin/src/xpdf-4.04/goo/CMakeFiles/goo_objs.dir/parseargs.c.o" \
+"/home/calvin/src/xpdf-4.04/goo/CMakeFiles/goo_objs.dir/Trace.cc.o"
+
+goo/libgoo.a: goo/CMakeFiles/goo_objs.dir/FixedPoint.cc.o
+goo/libgoo.a: goo/CMakeFiles/goo_objs.dir/GHash.cc.o
+goo/libgoo.a: goo/CMakeFiles/goo_objs.dir/GList.cc.o
+goo/libgoo.a: goo/CMakeFiles/goo_objs.dir/GString.cc.o
+goo/libgoo.a: goo/CMakeFiles/goo_objs.dir/gfile.cc.o
+goo/libgoo.a: goo/CMakeFiles/goo_objs.dir/gmem.cc.o
+goo/libgoo.a: goo/CMakeFiles/goo_objs.dir/gmempp.cc.o
+goo/libgoo.a: goo/CMakeFiles/goo_objs.dir/parseargs.c.o
+goo/libgoo.a: goo/CMakeFiles/goo_objs.dir/Trace.cc.o
+goo/libgoo.a: goo/CMakeFiles/goo.dir/build.make
+goo/libgoo.a: goo/CMakeFiles/goo.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_1) "Linking CXX static library libgoo.a"
+ cd /home/calvin/src/xpdf-4.04/goo && $(CMAKE_COMMAND) -P CMakeFiles/goo.dir/cmake_clean_target.cmake
+ cd /home/calvin/src/xpdf-4.04/goo && $(CMAKE_COMMAND) -E cmake_link_script CMakeFiles/goo.dir/link.txt --verbose=$(VERBOSE)
+
+# Rule to build all files generated by this target.
+goo/CMakeFiles/goo.dir/build: goo/libgoo.a
+
+.PHONY : goo/CMakeFiles/goo.dir/build
+
+goo/CMakeFiles/goo.dir/clean:
+ cd /home/calvin/src/xpdf-4.04/goo && $(CMAKE_COMMAND) -P CMakeFiles/goo.dir/cmake_clean.cmake
+.PHONY : goo/CMakeFiles/goo.dir/clean
+
+goo/CMakeFiles/goo.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/goo /home/calvin/src/xpdf-4.04 /home/calvin/src/xpdf-4.04/goo /home/calvin/src/xpdf-4.04/goo/CMakeFiles/goo.dir/DependInfo.cmake --color=$(COLOR)
+.PHONY : goo/CMakeFiles/goo.dir/depend
+
diff --git a/goo/CMakeFiles/goo.dir/cmake_clean.cmake b/goo/CMakeFiles/goo.dir/cmake_clean.cmake
new file mode 100644
index 0000000..9b2dd65
--- /dev/null
+++ b/goo/CMakeFiles/goo.dir/cmake_clean.cmake
@@ -0,0 +1,9 @@
+file(REMOVE_RECURSE
+ "libgoo.a"
+ "libgoo.pdb"
+)
+
+# Per-language clean rules from dependency scanning.
+foreach(lang C CXX)
+ include(CMakeFiles/goo.dir/cmake_clean_${lang}.cmake OPTIONAL)
+endforeach()
diff --git a/goo/CMakeFiles/goo.dir/cmake_clean_target.cmake b/goo/CMakeFiles/goo.dir/cmake_clean_target.cmake
new file mode 100644
index 0000000..539e57d
--- /dev/null
+++ b/goo/CMakeFiles/goo.dir/cmake_clean_target.cmake
@@ -0,0 +1,3 @@
+file(REMOVE_RECURSE
+ "libgoo.a"
+)
diff --git a/goo/CMakeFiles/goo.dir/depend.internal b/goo/CMakeFiles/goo.dir/depend.internal
new file mode 100644
index 0000000..756f521
--- /dev/null
+++ b/goo/CMakeFiles/goo.dir/depend.internal
@@ -0,0 +1,3 @@
+# CMAKE generated file: DO NOT EDIT!
+# Generated by "Unix Makefiles" Generator, CMake Version 3.18
+
diff --git a/goo/CMakeFiles/goo.dir/depend.make b/goo/CMakeFiles/goo.dir/depend.make
new file mode 100644
index 0000000..756f521
--- /dev/null
+++ b/goo/CMakeFiles/goo.dir/depend.make
@@ -0,0 +1,3 @@
+# CMAKE generated file: DO NOT EDIT!
+# Generated by "Unix Makefiles" Generator, CMake Version 3.18
+
diff --git a/goo/CMakeFiles/goo.dir/flags.make b/goo/CMakeFiles/goo.dir/flags.make
new file mode 100644
index 0000000..d049736
--- /dev/null
+++ b/goo/CMakeFiles/goo.dir/flags.make
@@ -0,0 +1,17 @@
+# CMAKE generated file: DO NOT EDIT!
+# Generated by "Unix Makefiles" Generator, CMake Version 3.18
+
+# compile C with /usr/bin/cc
+# compile CXX with /usr/bin/c++
+C_DEFINES =
+
+C_INCLUDES = -I/home/calvin/src/xpdf-4.04
+
+C_FLAGS =
+
+CXX_DEFINES =
+
+CXX_INCLUDES = -I/home/calvin/src/xpdf-4.04
+
+CXX_FLAGS =
+
diff --git a/goo/CMakeFiles/goo.dir/link.txt b/goo/CMakeFiles/goo.dir/link.txt
new file mode 100644
index 0000000..e4ddd3b
--- /dev/null
+++ b/goo/CMakeFiles/goo.dir/link.txt
@@ -0,0 +1,2 @@
+/usr/bin/ar qc libgoo.a CMakeFiles/goo_objs.dir/FixedPoint.cc.o CMakeFiles/goo_objs.dir/GHash.cc.o CMakeFiles/goo_objs.dir/GList.cc.o CMakeFiles/goo_objs.dir/GString.cc.o CMakeFiles/goo_objs.dir/gfile.cc.o CMakeFiles/goo_objs.dir/gmem.cc.o CMakeFiles/goo_objs.dir/gmempp.cc.o CMakeFiles/goo_objs.dir/parseargs.c.o CMakeFiles/goo_objs.dir/Trace.cc.o
+/usr/bin/ranlib libgoo.a
diff --git a/goo/CMakeFiles/goo.dir/progress.make b/goo/CMakeFiles/goo.dir/progress.make
new file mode 100644
index 0000000..225de34
--- /dev/null
+++ b/goo/CMakeFiles/goo.dir/progress.make
@@ -0,0 +1,2 @@
+CMAKE_PROGRESS_1 =
+
diff --git a/goo/CMakeFiles/goo_objs.dir/C.includecache b/goo/CMakeFiles/goo_objs.dir/C.includecache
new file mode 100644
index 0000000..f78a288
--- /dev/null
+++ b/goo/CMakeFiles/goo_objs.dir/C.includecache
@@ -0,0 +1,28 @@
+#IncludeRegexLine: ^[ ]*[#%][ ]*(include|import)[ ]*[<"]([^">]+)([">])
+
+#IncludeRegexScan: ^.*$
+
+#IncludeRegexComplain: ^$
+
+#IncludeRegexTransform:
+
+/home/calvin/src/xpdf-4.04/goo/gtypes.h
+
+/home/calvin/src/xpdf-4.04/goo/parseargs.c
+stdio.h
+-
+stddef.h
+-
+string.h
+-
+stdlib.h
+-
+ctype.h
+-
+parseargs.h
+/home/calvin/src/xpdf-4.04/goo/parseargs.h
+
+/home/calvin/src/xpdf-4.04/goo/parseargs.h
+gtypes.h
+/home/calvin/src/xpdf-4.04/goo/gtypes.h
+
diff --git a/goo/CMakeFiles/goo_objs.dir/CXX.includecache b/goo/CMakeFiles/goo_objs.dir/CXX.includecache
new file mode 100644
index 0000000..5a977ed
--- /dev/null
+++ b/goo/CMakeFiles/goo_objs.dir/CXX.includecache
@@ -0,0 +1,226 @@
+#IncludeRegexLine: ^[ ]*[#%][ ]*(include|import)[ ]*[<"]([^">]+)([">])
+
+#IncludeRegexScan: ^.*$
+
+#IncludeRegexComplain: ^$
+
+#IncludeRegexTransform:
+
+/home/calvin/src/xpdf-4.04/goo/FixedPoint.cc
+aconf.h
+-
+gmempp.h
+/home/calvin/src/xpdf-4.04/goo/gmempp.h
+FixedPoint.h
+/home/calvin/src/xpdf-4.04/goo/FixedPoint.h
+
+/home/calvin/src/xpdf-4.04/goo/FixedPoint.h
+aconf.h
+-
+stdio.h
+-
+stdlib.h
+-
+gtypes.h
+/home/calvin/src/xpdf-4.04/goo/gtypes.h
+
+/home/calvin/src/xpdf-4.04/goo/GHash.cc
+aconf.h
+-
+gmem.h
+/home/calvin/src/xpdf-4.04/goo/gmem.h
+gmempp.h
+/home/calvin/src/xpdf-4.04/goo/gmempp.h
+GString.h
+/home/calvin/src/xpdf-4.04/goo/GString.h
+GHash.h
+/home/calvin/src/xpdf-4.04/goo/GHash.h
+
+/home/calvin/src/xpdf-4.04/goo/GHash.h
+aconf.h
+-
+gtypes.h
+/home/calvin/src/xpdf-4.04/goo/gtypes.h
+
+/home/calvin/src/xpdf-4.04/goo/GList.cc
+aconf.h
+-
+stdlib.h
+-
+string.h
+-
+gmem.h
+/home/calvin/src/xpdf-4.04/goo/gmem.h
+gmempp.h
+/home/calvin/src/xpdf-4.04/goo/gmempp.h
+GList.h
+/home/calvin/src/xpdf-4.04/goo/GList.h
+
+/home/calvin/src/xpdf-4.04/goo/GList.h
+aconf.h
+-
+gtypes.h
+/home/calvin/src/xpdf-4.04/goo/gtypes.h
+
+/home/calvin/src/xpdf-4.04/goo/GString.cc
+aconf.h
+-
+stdlib.h
+-
+stddef.h
+-
+string.h
+-
+ctype.h
+-
+math.h
+-
+limits.h
+-
+gmem.h
+/home/calvin/src/xpdf-4.04/goo/gmem.h
+gmempp.h
+/home/calvin/src/xpdf-4.04/goo/gmempp.h
+GString.h
+/home/calvin/src/xpdf-4.04/goo/GString.h
+
+/home/calvin/src/xpdf-4.04/goo/GString.h
+aconf.h
+-
+limits.h
+-
+stdarg.h
+-
+gtypes.h
+/home/calvin/src/xpdf-4.04/goo/gtypes.h
+
+/home/calvin/src/xpdf-4.04/goo/Trace.cc
+aconf.h
+-
+stdio.h
+-
+stdarg.h
+-
+sys/types.h
+-
+sys/time.h
+-
+unistd.h
+-
+GString.h
+/home/calvin/src/xpdf-4.04/goo/GString.h
+Trace.h
+/home/calvin/src/xpdf-4.04/goo/Trace.h
+
+/home/calvin/src/xpdf-4.04/goo/Trace.h
+aconf.h
+-
+
+/home/calvin/src/xpdf-4.04/goo/gfile.cc
+aconf.h
+-
+windows.h
+-
+time.h
+-
+direct.h
+-
+shobjidl.h
+-
+shlguid.h
+-
+sys/types.h
+-
+sys/stat.h
+-
+fcntl.h
+-
+time.h
+-
+limits.h
+-
+string.h
+-
+pwd.h
+-
+unixlib.h
+-
+gmem.h
+/home/calvin/src/xpdf-4.04/goo/gmem.h
+gmempp.h
+/home/calvin/src/xpdf-4.04/goo/gmempp.h
+GString.h
+/home/calvin/src/xpdf-4.04/goo/GString.h
+gfile.h
+/home/calvin/src/xpdf-4.04/goo/gfile.h
+
+/home/calvin/src/xpdf-4.04/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
+/home/calvin/src/xpdf-4.04/goo/gtypes.h
+
+/home/calvin/src/xpdf-4.04/goo/gmem.cc
+aconf.h
+-
+stdio.h
+-
+stdlib.h
+-
+stddef.h
+-
+stdint.h
+-
+string.h
+-
+limits.h
+-
+windows.h
+-
+gmem.h
+/home/calvin/src/xpdf-4.04/goo/gmem.h
+pthread.h
+-
+
+/home/calvin/src/xpdf-4.04/goo/gmem.h
+stdio.h
+-
+aconf.h
+-
+
+/home/calvin/src/xpdf-4.04/goo/gmempp.cc
+aconf.h
+-
+gmem.h
+/home/calvin/src/xpdf-4.04/goo/gmem.h
+
+/home/calvin/src/xpdf-4.04/goo/gmempp.h
+stdlib.h
+-
+
+/home/calvin/src/xpdf-4.04/goo/gtypes.h
+
+aconf.h
+aconf2.h
+-
+
+aconf2.h
+AvailabilityMacros.h
+-
+
diff --git a/goo/CMakeFiles/goo_objs.dir/DependInfo.cmake b/goo/CMakeFiles/goo_objs.dir/DependInfo.cmake
new file mode 100644
index 0000000..dd5d27c
--- /dev/null
+++ b/goo/CMakeFiles/goo_objs.dir/DependInfo.cmake
@@ -0,0 +1,38 @@
+# The set of languages for which implicit dependencies are needed:
+set(CMAKE_DEPENDS_LANGUAGES
+ "C"
+ "CXX"
+ )
+# The set of files for implicit dependencies of each language:
+set(CMAKE_DEPENDS_CHECK_C
+ "/home/calvin/src/xpdf-4.04/goo/parseargs.c" "/home/calvin/src/xpdf-4.04/goo/CMakeFiles/goo_objs.dir/parseargs.c.o"
+ )
+set(CMAKE_C_COMPILER_ID "GNU")
+
+# The include file search paths:
+set(CMAKE_C_TARGET_INCLUDE_PATH
+ "."
+ )
+set(CMAKE_DEPENDS_CHECK_CXX
+ "/home/calvin/src/xpdf-4.04/goo/FixedPoint.cc" "/home/calvin/src/xpdf-4.04/goo/CMakeFiles/goo_objs.dir/FixedPoint.cc.o"
+ "/home/calvin/src/xpdf-4.04/goo/GHash.cc" "/home/calvin/src/xpdf-4.04/goo/CMakeFiles/goo_objs.dir/GHash.cc.o"
+ "/home/calvin/src/xpdf-4.04/goo/GList.cc" "/home/calvin/src/xpdf-4.04/goo/CMakeFiles/goo_objs.dir/GList.cc.o"
+ "/home/calvin/src/xpdf-4.04/goo/GString.cc" "/home/calvin/src/xpdf-4.04/goo/CMakeFiles/goo_objs.dir/GString.cc.o"
+ "/home/calvin/src/xpdf-4.04/goo/Trace.cc" "/home/calvin/src/xpdf-4.04/goo/CMakeFiles/goo_objs.dir/Trace.cc.o"
+ "/home/calvin/src/xpdf-4.04/goo/gfile.cc" "/home/calvin/src/xpdf-4.04/goo/CMakeFiles/goo_objs.dir/gfile.cc.o"
+ "/home/calvin/src/xpdf-4.04/goo/gmem.cc" "/home/calvin/src/xpdf-4.04/goo/CMakeFiles/goo_objs.dir/gmem.cc.o"
+ "/home/calvin/src/xpdf-4.04/goo/gmempp.cc" "/home/calvin/src/xpdf-4.04/goo/CMakeFiles/goo_objs.dir/gmempp.cc.o"
+ )
+set(CMAKE_CXX_COMPILER_ID "GNU")
+
+# The include file search paths:
+set(CMAKE_CXX_TARGET_INCLUDE_PATH
+ "."
+ )
+
+# 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/goo/CMakeFiles/goo_objs.dir/FixedPoint.cc.o b/goo/CMakeFiles/goo_objs.dir/FixedPoint.cc.o
new file mode 100644
index 0000000..35cc649
--- /dev/null
+++ b/goo/CMakeFiles/goo_objs.dir/FixedPoint.cc.o
Binary files differ
diff --git a/goo/CMakeFiles/goo_objs.dir/GHash.cc.o b/goo/CMakeFiles/goo_objs.dir/GHash.cc.o
new file mode 100644
index 0000000..c187373
--- /dev/null
+++ b/goo/CMakeFiles/goo_objs.dir/GHash.cc.o
Binary files differ
diff --git a/goo/CMakeFiles/goo_objs.dir/GList.cc.o b/goo/CMakeFiles/goo_objs.dir/GList.cc.o
new file mode 100644
index 0000000..22a64f9
--- /dev/null
+++ b/goo/CMakeFiles/goo_objs.dir/GList.cc.o
Binary files differ
diff --git a/goo/CMakeFiles/goo_objs.dir/GString.cc.o b/goo/CMakeFiles/goo_objs.dir/GString.cc.o
new file mode 100644
index 0000000..19329b5
--- /dev/null
+++ b/goo/CMakeFiles/goo_objs.dir/GString.cc.o
Binary files differ
diff --git a/goo/CMakeFiles/goo_objs.dir/Trace.cc.o b/goo/CMakeFiles/goo_objs.dir/Trace.cc.o
new file mode 100644
index 0000000..f43e9c3
--- /dev/null
+++ b/goo/CMakeFiles/goo_objs.dir/Trace.cc.o
Binary files differ
diff --git a/goo/CMakeFiles/goo_objs.dir/build.make b/goo/CMakeFiles/goo_objs.dir/build.make
new file mode 100644
index 0000000..5b104e6
--- /dev/null
+++ b/goo/CMakeFiles/goo_objs.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 goo/CMakeFiles/goo_objs.dir/depend.make
+
+# Include the progress variables for this target.
+include goo/CMakeFiles/goo_objs.dir/progress.make
+
+# Include the compile flags for this target's objects.
+include goo/CMakeFiles/goo_objs.dir/flags.make
+
+goo/CMakeFiles/goo_objs.dir/FixedPoint.cc.o: goo/CMakeFiles/goo_objs.dir/flags.make
+goo/CMakeFiles/goo_objs.dir/FixedPoint.cc.o: goo/FixedPoint.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 goo/CMakeFiles/goo_objs.dir/FixedPoint.cc.o"
+ cd /home/calvin/src/xpdf-4.04/goo && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/goo_objs.dir/FixedPoint.cc.o -c /home/calvin/src/xpdf-4.04/goo/FixedPoint.cc
+
+goo/CMakeFiles/goo_objs.dir/FixedPoint.cc.i: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/goo_objs.dir/FixedPoint.cc.i"
+ cd /home/calvin/src/xpdf-4.04/goo && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/goo/FixedPoint.cc > CMakeFiles/goo_objs.dir/FixedPoint.cc.i
+
+goo/CMakeFiles/goo_objs.dir/FixedPoint.cc.s: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/goo_objs.dir/FixedPoint.cc.s"
+ cd /home/calvin/src/xpdf-4.04/goo && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/goo/FixedPoint.cc -o CMakeFiles/goo_objs.dir/FixedPoint.cc.s
+
+goo/CMakeFiles/goo_objs.dir/GHash.cc.o: goo/CMakeFiles/goo_objs.dir/flags.make
+goo/CMakeFiles/goo_objs.dir/GHash.cc.o: goo/GHash.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 goo/CMakeFiles/goo_objs.dir/GHash.cc.o"
+ cd /home/calvin/src/xpdf-4.04/goo && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/goo_objs.dir/GHash.cc.o -c /home/calvin/src/xpdf-4.04/goo/GHash.cc
+
+goo/CMakeFiles/goo_objs.dir/GHash.cc.i: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/goo_objs.dir/GHash.cc.i"
+ cd /home/calvin/src/xpdf-4.04/goo && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/goo/GHash.cc > CMakeFiles/goo_objs.dir/GHash.cc.i
+
+goo/CMakeFiles/goo_objs.dir/GHash.cc.s: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/goo_objs.dir/GHash.cc.s"
+ cd /home/calvin/src/xpdf-4.04/goo && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/goo/GHash.cc -o CMakeFiles/goo_objs.dir/GHash.cc.s
+
+goo/CMakeFiles/goo_objs.dir/GList.cc.o: goo/CMakeFiles/goo_objs.dir/flags.make
+goo/CMakeFiles/goo_objs.dir/GList.cc.o: goo/GList.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 goo/CMakeFiles/goo_objs.dir/GList.cc.o"
+ cd /home/calvin/src/xpdf-4.04/goo && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/goo_objs.dir/GList.cc.o -c /home/calvin/src/xpdf-4.04/goo/GList.cc
+
+goo/CMakeFiles/goo_objs.dir/GList.cc.i: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/goo_objs.dir/GList.cc.i"
+ cd /home/calvin/src/xpdf-4.04/goo && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/goo/GList.cc > CMakeFiles/goo_objs.dir/GList.cc.i
+
+goo/CMakeFiles/goo_objs.dir/GList.cc.s: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/goo_objs.dir/GList.cc.s"
+ cd /home/calvin/src/xpdf-4.04/goo && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/goo/GList.cc -o CMakeFiles/goo_objs.dir/GList.cc.s
+
+goo/CMakeFiles/goo_objs.dir/GString.cc.o: goo/CMakeFiles/goo_objs.dir/flags.make
+goo/CMakeFiles/goo_objs.dir/GString.cc.o: goo/GString.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 goo/CMakeFiles/goo_objs.dir/GString.cc.o"
+ cd /home/calvin/src/xpdf-4.04/goo && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/goo_objs.dir/GString.cc.o -c /home/calvin/src/xpdf-4.04/goo/GString.cc
+
+goo/CMakeFiles/goo_objs.dir/GString.cc.i: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/goo_objs.dir/GString.cc.i"
+ cd /home/calvin/src/xpdf-4.04/goo && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/goo/GString.cc > CMakeFiles/goo_objs.dir/GString.cc.i
+
+goo/CMakeFiles/goo_objs.dir/GString.cc.s: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/goo_objs.dir/GString.cc.s"
+ cd /home/calvin/src/xpdf-4.04/goo && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/goo/GString.cc -o CMakeFiles/goo_objs.dir/GString.cc.s
+
+goo/CMakeFiles/goo_objs.dir/gfile.cc.o: goo/CMakeFiles/goo_objs.dir/flags.make
+goo/CMakeFiles/goo_objs.dir/gfile.cc.o: goo/gfile.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 goo/CMakeFiles/goo_objs.dir/gfile.cc.o"
+ cd /home/calvin/src/xpdf-4.04/goo && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/goo_objs.dir/gfile.cc.o -c /home/calvin/src/xpdf-4.04/goo/gfile.cc
+
+goo/CMakeFiles/goo_objs.dir/gfile.cc.i: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/goo_objs.dir/gfile.cc.i"
+ cd /home/calvin/src/xpdf-4.04/goo && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/goo/gfile.cc > CMakeFiles/goo_objs.dir/gfile.cc.i
+
+goo/CMakeFiles/goo_objs.dir/gfile.cc.s: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/goo_objs.dir/gfile.cc.s"
+ cd /home/calvin/src/xpdf-4.04/goo && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/goo/gfile.cc -o CMakeFiles/goo_objs.dir/gfile.cc.s
+
+goo/CMakeFiles/goo_objs.dir/gmem.cc.o: goo/CMakeFiles/goo_objs.dir/flags.make
+goo/CMakeFiles/goo_objs.dir/gmem.cc.o: goo/gmem.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 goo/CMakeFiles/goo_objs.dir/gmem.cc.o"
+ cd /home/calvin/src/xpdf-4.04/goo && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/goo_objs.dir/gmem.cc.o -c /home/calvin/src/xpdf-4.04/goo/gmem.cc
+
+goo/CMakeFiles/goo_objs.dir/gmem.cc.i: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/goo_objs.dir/gmem.cc.i"
+ cd /home/calvin/src/xpdf-4.04/goo && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/goo/gmem.cc > CMakeFiles/goo_objs.dir/gmem.cc.i
+
+goo/CMakeFiles/goo_objs.dir/gmem.cc.s: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/goo_objs.dir/gmem.cc.s"
+ cd /home/calvin/src/xpdf-4.04/goo && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/goo/gmem.cc -o CMakeFiles/goo_objs.dir/gmem.cc.s
+
+goo/CMakeFiles/goo_objs.dir/gmempp.cc.o: goo/CMakeFiles/goo_objs.dir/flags.make
+goo/CMakeFiles/goo_objs.dir/gmempp.cc.o: goo/gmempp.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 goo/CMakeFiles/goo_objs.dir/gmempp.cc.o"
+ cd /home/calvin/src/xpdf-4.04/goo && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/goo_objs.dir/gmempp.cc.o -c /home/calvin/src/xpdf-4.04/goo/gmempp.cc
+
+goo/CMakeFiles/goo_objs.dir/gmempp.cc.i: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/goo_objs.dir/gmempp.cc.i"
+ cd /home/calvin/src/xpdf-4.04/goo && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/goo/gmempp.cc > CMakeFiles/goo_objs.dir/gmempp.cc.i
+
+goo/CMakeFiles/goo_objs.dir/gmempp.cc.s: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/goo_objs.dir/gmempp.cc.s"
+ cd /home/calvin/src/xpdf-4.04/goo && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/goo/gmempp.cc -o CMakeFiles/goo_objs.dir/gmempp.cc.s
+
+goo/CMakeFiles/goo_objs.dir/parseargs.c.o: goo/CMakeFiles/goo_objs.dir/flags.make
+goo/CMakeFiles/goo_objs.dir/parseargs.c.o: goo/parseargs.c
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_8) "Building C object goo/CMakeFiles/goo_objs.dir/parseargs.c.o"
+ cd /home/calvin/src/xpdf-4.04/goo && /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -o CMakeFiles/goo_objs.dir/parseargs.c.o -c /home/calvin/src/xpdf-4.04/goo/parseargs.c
+
+goo/CMakeFiles/goo_objs.dir/parseargs.c.i: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing C source to CMakeFiles/goo_objs.dir/parseargs.c.i"
+ cd /home/calvin/src/xpdf-4.04/goo && /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -E /home/calvin/src/xpdf-4.04/goo/parseargs.c > CMakeFiles/goo_objs.dir/parseargs.c.i
+
+goo/CMakeFiles/goo_objs.dir/parseargs.c.s: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling C source to assembly CMakeFiles/goo_objs.dir/parseargs.c.s"
+ cd /home/calvin/src/xpdf-4.04/goo && /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -S /home/calvin/src/xpdf-4.04/goo/parseargs.c -o CMakeFiles/goo_objs.dir/parseargs.c.s
+
+goo/CMakeFiles/goo_objs.dir/Trace.cc.o: goo/CMakeFiles/goo_objs.dir/flags.make
+goo/CMakeFiles/goo_objs.dir/Trace.cc.o: goo/Trace.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 goo/CMakeFiles/goo_objs.dir/Trace.cc.o"
+ cd /home/calvin/src/xpdf-4.04/goo && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/goo_objs.dir/Trace.cc.o -c /home/calvin/src/xpdf-4.04/goo/Trace.cc
+
+goo/CMakeFiles/goo_objs.dir/Trace.cc.i: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/goo_objs.dir/Trace.cc.i"
+ cd /home/calvin/src/xpdf-4.04/goo && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/goo/Trace.cc > CMakeFiles/goo_objs.dir/Trace.cc.i
+
+goo/CMakeFiles/goo_objs.dir/Trace.cc.s: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/goo_objs.dir/Trace.cc.s"
+ cd /home/calvin/src/xpdf-4.04/goo && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/goo/Trace.cc -o CMakeFiles/goo_objs.dir/Trace.cc.s
+
+goo_objs: goo/CMakeFiles/goo_objs.dir/FixedPoint.cc.o
+goo_objs: goo/CMakeFiles/goo_objs.dir/GHash.cc.o
+goo_objs: goo/CMakeFiles/goo_objs.dir/GList.cc.o
+goo_objs: goo/CMakeFiles/goo_objs.dir/GString.cc.o
+goo_objs: goo/CMakeFiles/goo_objs.dir/gfile.cc.o
+goo_objs: goo/CMakeFiles/goo_objs.dir/gmem.cc.o
+goo_objs: goo/CMakeFiles/goo_objs.dir/gmempp.cc.o
+goo_objs: goo/CMakeFiles/goo_objs.dir/parseargs.c.o
+goo_objs: goo/CMakeFiles/goo_objs.dir/Trace.cc.o
+goo_objs: goo/CMakeFiles/goo_objs.dir/build.make
+
+.PHONY : goo_objs
+
+# Rule to build all files generated by this target.
+goo/CMakeFiles/goo_objs.dir/build: goo_objs
+
+.PHONY : goo/CMakeFiles/goo_objs.dir/build
+
+goo/CMakeFiles/goo_objs.dir/clean:
+ cd /home/calvin/src/xpdf-4.04/goo && $(CMAKE_COMMAND) -P CMakeFiles/goo_objs.dir/cmake_clean.cmake
+.PHONY : goo/CMakeFiles/goo_objs.dir/clean
+
+goo/CMakeFiles/goo_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/goo /home/calvin/src/xpdf-4.04 /home/calvin/src/xpdf-4.04/goo /home/calvin/src/xpdf-4.04/goo/CMakeFiles/goo_objs.dir/DependInfo.cmake --color=$(COLOR)
+.PHONY : goo/CMakeFiles/goo_objs.dir/depend
+
diff --git a/goo/CMakeFiles/goo_objs.dir/cmake_clean.cmake b/goo/CMakeFiles/goo_objs.dir/cmake_clean.cmake
new file mode 100644
index 0000000..48b5aea
--- /dev/null
+++ b/goo/CMakeFiles/goo_objs.dir/cmake_clean.cmake
@@ -0,0 +1,16 @@
+file(REMOVE_RECURSE
+ "CMakeFiles/goo_objs.dir/FixedPoint.cc.o"
+ "CMakeFiles/goo_objs.dir/GHash.cc.o"
+ "CMakeFiles/goo_objs.dir/GList.cc.o"
+ "CMakeFiles/goo_objs.dir/GString.cc.o"
+ "CMakeFiles/goo_objs.dir/Trace.cc.o"
+ "CMakeFiles/goo_objs.dir/gfile.cc.o"
+ "CMakeFiles/goo_objs.dir/gmem.cc.o"
+ "CMakeFiles/goo_objs.dir/gmempp.cc.o"
+ "CMakeFiles/goo_objs.dir/parseargs.c.o"
+)
+
+# Per-language clean rules from dependency scanning.
+foreach(lang C CXX)
+ include(CMakeFiles/goo_objs.dir/cmake_clean_${lang}.cmake OPTIONAL)
+endforeach()
diff --git a/goo/CMakeFiles/goo_objs.dir/depend.internal b/goo/CMakeFiles/goo_objs.dir/depend.internal
new file mode 100644
index 0000000..aaa855f
--- /dev/null
+++ b/goo/CMakeFiles/goo_objs.dir/depend.internal
@@ -0,0 +1,65 @@
+# CMAKE generated file: DO NOT EDIT!
+# Generated by "Unix Makefiles" Generator, CMake Version 3.18
+
+goo/CMakeFiles/goo_objs.dir/parseargs.c.o
+ /home/calvin/src/xpdf-4.04/goo/gtypes.h
+ /home/calvin/src/xpdf-4.04/goo/parseargs.c
+ /home/calvin/src/xpdf-4.04/goo/parseargs.h
+goo/CMakeFiles/goo_objs.dir/FixedPoint.cc.o
+ /home/calvin/src/xpdf-4.04/goo/FixedPoint.cc
+ /home/calvin/src/xpdf-4.04/goo/FixedPoint.h
+ /home/calvin/src/xpdf-4.04/goo/gmempp.h
+ /home/calvin/src/xpdf-4.04/goo/gtypes.h
+ aconf.h
+ aconf2.h
+goo/CMakeFiles/goo_objs.dir/GHash.cc.o
+ /home/calvin/src/xpdf-4.04/goo/GHash.cc
+ /home/calvin/src/xpdf-4.04/goo/GHash.h
+ /home/calvin/src/xpdf-4.04/goo/GString.h
+ /home/calvin/src/xpdf-4.04/goo/gmem.h
+ /home/calvin/src/xpdf-4.04/goo/gmempp.h
+ /home/calvin/src/xpdf-4.04/goo/gtypes.h
+ aconf.h
+ aconf2.h
+goo/CMakeFiles/goo_objs.dir/GList.cc.o
+ /home/calvin/src/xpdf-4.04/goo/GList.cc
+ /home/calvin/src/xpdf-4.04/goo/GList.h
+ /home/calvin/src/xpdf-4.04/goo/gmem.h
+ /home/calvin/src/xpdf-4.04/goo/gmempp.h
+ /home/calvin/src/xpdf-4.04/goo/gtypes.h
+ aconf.h
+ aconf2.h
+goo/CMakeFiles/goo_objs.dir/GString.cc.o
+ /home/calvin/src/xpdf-4.04/goo/GString.cc
+ /home/calvin/src/xpdf-4.04/goo/GString.h
+ /home/calvin/src/xpdf-4.04/goo/gmem.h
+ /home/calvin/src/xpdf-4.04/goo/gmempp.h
+ /home/calvin/src/xpdf-4.04/goo/gtypes.h
+ aconf.h
+ aconf2.h
+goo/CMakeFiles/goo_objs.dir/Trace.cc.o
+ /home/calvin/src/xpdf-4.04/goo/GString.h
+ /home/calvin/src/xpdf-4.04/goo/Trace.cc
+ /home/calvin/src/xpdf-4.04/goo/Trace.h
+ /home/calvin/src/xpdf-4.04/goo/gtypes.h
+ aconf.h
+ aconf2.h
+goo/CMakeFiles/goo_objs.dir/gfile.cc.o
+ /home/calvin/src/xpdf-4.04/goo/GString.h
+ /home/calvin/src/xpdf-4.04/goo/gfile.cc
+ /home/calvin/src/xpdf-4.04/goo/gfile.h
+ /home/calvin/src/xpdf-4.04/goo/gmem.h
+ /home/calvin/src/xpdf-4.04/goo/gmempp.h
+ /home/calvin/src/xpdf-4.04/goo/gtypes.h
+ aconf.h
+ aconf2.h
+goo/CMakeFiles/goo_objs.dir/gmem.cc.o
+ /home/calvin/src/xpdf-4.04/goo/gmem.cc
+ /home/calvin/src/xpdf-4.04/goo/gmem.h
+ aconf.h
+ aconf2.h
+goo/CMakeFiles/goo_objs.dir/gmempp.cc.o
+ /home/calvin/src/xpdf-4.04/goo/gmem.h
+ /home/calvin/src/xpdf-4.04/goo/gmempp.cc
+ aconf.h
+ aconf2.h
diff --git a/goo/CMakeFiles/goo_objs.dir/depend.make b/goo/CMakeFiles/goo_objs.dir/depend.make
new file mode 100644
index 0000000..73ddd5e
--- /dev/null
+++ b/goo/CMakeFiles/goo_objs.dir/depend.make
@@ -0,0 +1,65 @@
+# CMAKE generated file: DO NOT EDIT!
+# Generated by "Unix Makefiles" Generator, CMake Version 3.18
+
+goo/CMakeFiles/goo_objs.dir/parseargs.c.o: goo/gtypes.h
+goo/CMakeFiles/goo_objs.dir/parseargs.c.o: goo/parseargs.c
+goo/CMakeFiles/goo_objs.dir/parseargs.c.o: goo/parseargs.h
+
+goo/CMakeFiles/goo_objs.dir/FixedPoint.cc.o: goo/FixedPoint.cc
+goo/CMakeFiles/goo_objs.dir/FixedPoint.cc.o: goo/FixedPoint.h
+goo/CMakeFiles/goo_objs.dir/FixedPoint.cc.o: goo/gmempp.h
+goo/CMakeFiles/goo_objs.dir/FixedPoint.cc.o: goo/gtypes.h
+goo/CMakeFiles/goo_objs.dir/FixedPoint.cc.o: aconf.h
+goo/CMakeFiles/goo_objs.dir/FixedPoint.cc.o: aconf2.h
+
+goo/CMakeFiles/goo_objs.dir/GHash.cc.o: goo/GHash.cc
+goo/CMakeFiles/goo_objs.dir/GHash.cc.o: goo/GHash.h
+goo/CMakeFiles/goo_objs.dir/GHash.cc.o: goo/GString.h
+goo/CMakeFiles/goo_objs.dir/GHash.cc.o: goo/gmem.h
+goo/CMakeFiles/goo_objs.dir/GHash.cc.o: goo/gmempp.h
+goo/CMakeFiles/goo_objs.dir/GHash.cc.o: goo/gtypes.h
+goo/CMakeFiles/goo_objs.dir/GHash.cc.o: aconf.h
+goo/CMakeFiles/goo_objs.dir/GHash.cc.o: aconf2.h
+
+goo/CMakeFiles/goo_objs.dir/GList.cc.o: goo/GList.cc
+goo/CMakeFiles/goo_objs.dir/GList.cc.o: goo/GList.h
+goo/CMakeFiles/goo_objs.dir/GList.cc.o: goo/gmem.h
+goo/CMakeFiles/goo_objs.dir/GList.cc.o: goo/gmempp.h
+goo/CMakeFiles/goo_objs.dir/GList.cc.o: goo/gtypes.h
+goo/CMakeFiles/goo_objs.dir/GList.cc.o: aconf.h
+goo/CMakeFiles/goo_objs.dir/GList.cc.o: aconf2.h
+
+goo/CMakeFiles/goo_objs.dir/GString.cc.o: goo/GString.cc
+goo/CMakeFiles/goo_objs.dir/GString.cc.o: goo/GString.h
+goo/CMakeFiles/goo_objs.dir/GString.cc.o: goo/gmem.h
+goo/CMakeFiles/goo_objs.dir/GString.cc.o: goo/gmempp.h
+goo/CMakeFiles/goo_objs.dir/GString.cc.o: goo/gtypes.h
+goo/CMakeFiles/goo_objs.dir/GString.cc.o: aconf.h
+goo/CMakeFiles/goo_objs.dir/GString.cc.o: aconf2.h
+
+goo/CMakeFiles/goo_objs.dir/Trace.cc.o: goo/GString.h
+goo/CMakeFiles/goo_objs.dir/Trace.cc.o: goo/Trace.cc
+goo/CMakeFiles/goo_objs.dir/Trace.cc.o: goo/Trace.h
+goo/CMakeFiles/goo_objs.dir/Trace.cc.o: goo/gtypes.h
+goo/CMakeFiles/goo_objs.dir/Trace.cc.o: aconf.h
+goo/CMakeFiles/goo_objs.dir/Trace.cc.o: aconf2.h
+
+goo/CMakeFiles/goo_objs.dir/gfile.cc.o: goo/GString.h
+goo/CMakeFiles/goo_objs.dir/gfile.cc.o: goo/gfile.cc
+goo/CMakeFiles/goo_objs.dir/gfile.cc.o: goo/gfile.h
+goo/CMakeFiles/goo_objs.dir/gfile.cc.o: goo/gmem.h
+goo/CMakeFiles/goo_objs.dir/gfile.cc.o: goo/gmempp.h
+goo/CMakeFiles/goo_objs.dir/gfile.cc.o: goo/gtypes.h
+goo/CMakeFiles/goo_objs.dir/gfile.cc.o: aconf.h
+goo/CMakeFiles/goo_objs.dir/gfile.cc.o: aconf2.h
+
+goo/CMakeFiles/goo_objs.dir/gmem.cc.o: goo/gmem.cc
+goo/CMakeFiles/goo_objs.dir/gmem.cc.o: goo/gmem.h
+goo/CMakeFiles/goo_objs.dir/gmem.cc.o: aconf.h
+goo/CMakeFiles/goo_objs.dir/gmem.cc.o: aconf2.h
+
+goo/CMakeFiles/goo_objs.dir/gmempp.cc.o: goo/gmem.h
+goo/CMakeFiles/goo_objs.dir/gmempp.cc.o: goo/gmempp.cc
+goo/CMakeFiles/goo_objs.dir/gmempp.cc.o: aconf.h
+goo/CMakeFiles/goo_objs.dir/gmempp.cc.o: aconf2.h
+
diff --git a/goo/CMakeFiles/goo_objs.dir/flags.make b/goo/CMakeFiles/goo_objs.dir/flags.make
new file mode 100644
index 0000000..333c351
--- /dev/null
+++ b/goo/CMakeFiles/goo_objs.dir/flags.make
@@ -0,0 +1,17 @@
+# CMAKE generated file: DO NOT EDIT!
+# Generated by "Unix Makefiles" Generator, CMake Version 3.18
+
+# compile C with /usr/bin/cc
+# compile CXX with /usr/bin/c++
+C_DEFINES =
+
+C_INCLUDES = -I/home/calvin/src/xpdf-4.04
+
+C_FLAGS = -fPIC
+
+CXX_DEFINES =
+
+CXX_INCLUDES = -I/home/calvin/src/xpdf-4.04
+
+CXX_FLAGS = -fPIC
+
diff --git a/goo/CMakeFiles/goo_objs.dir/gfile.cc.o b/goo/CMakeFiles/goo_objs.dir/gfile.cc.o
new file mode 100644
index 0000000..52c7f2f
--- /dev/null
+++ b/goo/CMakeFiles/goo_objs.dir/gfile.cc.o
Binary files differ
diff --git a/goo/CMakeFiles/goo_objs.dir/gmem.cc.o b/goo/CMakeFiles/goo_objs.dir/gmem.cc.o
new file mode 100644
index 0000000..7cd4f45
--- /dev/null
+++ b/goo/CMakeFiles/goo_objs.dir/gmem.cc.o
Binary files differ
diff --git a/goo/CMakeFiles/goo_objs.dir/gmempp.cc.o b/goo/CMakeFiles/goo_objs.dir/gmempp.cc.o
new file mode 100644
index 0000000..3df2d88
--- /dev/null
+++ b/goo/CMakeFiles/goo_objs.dir/gmempp.cc.o
Binary files differ
diff --git a/goo/CMakeFiles/goo_objs.dir/parseargs.c.o b/goo/CMakeFiles/goo_objs.dir/parseargs.c.o
new file mode 100644
index 0000000..4a12c30
--- /dev/null
+++ b/goo/CMakeFiles/goo_objs.dir/parseargs.c.o
Binary files differ
diff --git a/goo/CMakeFiles/goo_objs.dir/progress.make b/goo/CMakeFiles/goo_objs.dir/progress.make
new file mode 100644
index 0000000..64ccb15
--- /dev/null
+++ b/goo/CMakeFiles/goo_objs.dir/progress.make
@@ -0,0 +1,10 @@
+CMAKE_PROGRESS_1 = 6
+CMAKE_PROGRESS_2 = 7
+CMAKE_PROGRESS_3 = 8
+CMAKE_PROGRESS_4 =
+CMAKE_PROGRESS_5 = 9
+CMAKE_PROGRESS_6 = 10
+CMAKE_PROGRESS_7 = 11
+CMAKE_PROGRESS_8 =
+CMAKE_PROGRESS_9 = 12
+
diff --git a/goo/CMakeFiles/progress.marks b/goo/CMakeFiles/progress.marks
new file mode 100644
index 0000000..7f8f011
--- /dev/null
+++ b/goo/CMakeFiles/progress.marks
@@ -0,0 +1 @@
+7
diff --git a/goo/CMakeLists.txt b/goo/CMakeLists.txt
new file mode 100644
index 0000000..f3f6932
--- /dev/null
+++ b/goo/CMakeLists.txt
@@ -0,0 +1,30 @@
+#========================================================================
+#
+# goo/CMakeLists.txt
+#
+# CMake script for the goo library.
+#
+# Copyright 2015 Glyph & Cog, LLC
+#
+#========================================================================
+
+include_directories("${PROJECT_SOURCE_DIR}")
+include_directories("${PROJECT_BINARY_DIR}")
+
+add_library(goo_objs OBJECT
+ FixedPoint.cc
+ GHash.cc
+ GList.cc
+ GString.cc
+ gfile.cc
+ gmem.cc
+ gmempp.cc
+ parseargs.c
+ Trace.cc
+)
+set_property(TARGET goo_objs
+ PROPERTY POSITION_INDEPENDENT_CODE True)
+
+add_library(goo
+ $<TARGET_OBJECTS:goo_objs>
+)
diff --git a/goo/FixedPoint.cc b/goo/FixedPoint.cc
new file mode 100644
index 0000000..503a06a
--- /dev/null
+++ b/goo/FixedPoint.cc
@@ -0,0 +1,134 @@
+//========================================================================
+//
+// FixedPoint.cc
+//
+// Fixed point type, with C++ operators.
+//
+// Copyright 2004 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <aconf.h>
+
+#if USE_FIXEDPOINT
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include "gmempp.h"
+#include "FixedPoint.h"
+
+#define ln2 ((FixedPoint)0.69314718)
+
+FixedPoint FixedPoint::sqrt(FixedPoint x) {
+ FixedPoint y0, y1, z;
+
+ if (x.val <= 0) {
+ y1.val = 0;
+ } else {
+ y1.val = x.val == 1 ? 2 : x.val >> 1;
+ do {
+ y0.val = y1.val;
+ z = x / y0;
+ y1.val = (y0.val + z.val) >> 1;
+ } while (::abs(y0.val - y1.val) > 1);
+ }
+ return y1;
+}
+
+FixedPoint FixedPoint::pow(FixedPoint x, FixedPoint y) {
+ FixedPoint t, t2, lnx0, lnx, z0, z;
+ int d, n, i;
+
+ if (y.val <= 0) {
+ z.val = 0;
+ } else {
+ // y * ln(x)
+ t = (x - 1) / (x + 1);
+ t2 = t * t;
+ d = 1;
+ lnx = 0;
+ do {
+ lnx0 = lnx;
+ lnx += t / d;
+ t *= t2;
+ d += 2;
+ } while (::abs(lnx.val - lnx0.val) > 2);
+ lnx.val <<= 1;
+ t = y * lnx;
+ // exp(y * ln(x))
+ n = floor(t / ln2);
+ t -= ln2 * n;
+ t2 = t;
+ d = 1;
+ i = 1;
+ z = 1;
+ do {
+ z0 = z;
+ z += t2 / d;
+ t2 *= t;
+ ++i;
+ d *= i;
+ } while (::abs(z.val - z0.val) > 2 && d < (1 << fixptShift));
+ if (n >= 0) {
+ z.val <<= n;
+ } else if (n < 0) {
+ z.val >>= -n;
+ }
+ }
+ return z;
+}
+
+int FixedPoint::mul(int x, int y) {
+ FixPtInt64 z;
+
+ z = ((FixPtInt64)x * y) >> fixptShift;
+ if (z > 0x7fffffffLL) {
+ return 0x7fffffff;
+ } else if (z < -0x80000000LL) {
+ return 0x80000000;
+ } else {
+ return (int)z;
+ }
+}
+
+int FixedPoint::div(int x, int y) {
+ FixPtInt64 z;
+
+ z = ((FixPtInt64)x << fixptShift) / y;
+ if (z > 0x7fffffffLL) {
+ return 0x7fffffff;
+ } else if (z < -0x80000000LL) {
+ return 0x80000000;
+ } else {
+ return (int)z;
+ }
+}
+
+GBool FixedPoint::divCheck(FixedPoint x, FixedPoint y, FixedPoint *result) {
+ FixPtInt64 z;
+
+ z = ((FixPtInt64)x.val << fixptShift) / y.val;
+ if ((z == 0 && x != 0) ||
+ z >= ((FixPtInt64)1 << 31) || z < -((FixPtInt64)1 << 31)) {
+ return gFalse;
+ }
+ result->val = (int)z;
+ return gTrue;
+}
+
+GBool FixedPoint::checkDet(FixedPoint m11, FixedPoint m12,
+ FixedPoint m21, FixedPoint m22,
+ FixedPoint epsilon) {
+ FixPtInt64 det, e;
+
+ det = (FixPtInt64)m11.val * (FixPtInt64)m22.val
+ - (FixPtInt64)m12.val * (FixPtInt64)m21.val;
+ e = (FixPtInt64)epsilon.val << fixptShift;
+ // NB: this comparison has to be >= not > because epsilon can be
+ // truncated to zero as a fixed point value.
+ return det >= e || det <= -e;
+}
+
+#endif // USE_FIXEDPOINT
diff --git a/goo/FixedPoint.h b/goo/FixedPoint.h
new file mode 100644
index 0000000..9f0c324
--- /dev/null
+++ b/goo/FixedPoint.h
@@ -0,0 +1,180 @@
+//========================================================================
+//
+// FixedPoint.h
+//
+// Fixed point type, with C++ operators.
+//
+// Copyright 2004 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef FIXEDPOINT_H
+#define FIXEDPOINT_H
+
+#include <aconf.h>
+
+#if USE_FIXEDPOINT
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "gtypes.h"
+
+#define fixptShift 16
+#define fixptMaskL ((1 << fixptShift) - 1)
+#define fixptMaskH (~fixptMaskL)
+
+typedef long long FixPtInt64;
+
+class FixedPoint {
+public:
+
+ FixedPoint() { val = 0; }
+ FixedPoint(const FixedPoint &x) { val = x.val; }
+ FixedPoint(double x) { val = (int)(x * (1 << fixptShift) + 0.5); }
+ FixedPoint(int x) { val = x << fixptShift; }
+ FixedPoint(Guint x) { val = x << fixptShift; }
+ FixedPoint(long x) { val = (int)x << fixptShift; }
+
+ operator float()
+ { return (float) val * ((float)1 / (float)(1 << fixptShift)); }
+ operator double()
+ { return (double) val * (1.0 / (double)(1 << fixptShift)); }
+ operator int()
+ { return val >> fixptShift; }
+
+ int get16Dot16() { return val; }
+
+ FixedPoint operator =(FixedPoint x) { val = x.val; return *this; }
+
+ bool operator ==(FixedPoint x) const { return val == x.val; }
+ bool operator ==(double x) const { return *this == (FixedPoint)x; }
+ bool operator ==(int x) const { return *this == (FixedPoint)x; }
+ bool operator ==(Guint x) const { return *this == (FixedPoint)x; }
+ bool operator ==(long x) const { return *this == (FixedPoint)x; }
+
+ bool operator !=(FixedPoint x) const { return val != x.val; }
+ bool operator !=(double x) const { return *this != (FixedPoint)x; }
+ bool operator !=(int x) const { return *this != (FixedPoint)x; }
+ bool operator !=(Guint x) const { return *this != (FixedPoint)x; }
+ bool operator !=(long x) const { return *this != (FixedPoint)x; }
+
+ bool operator <(FixedPoint x) const { return val < x.val; }
+ bool operator <(double x) const { return *this < (FixedPoint)x; }
+ bool operator <(int x) const { return *this < (FixedPoint)x; }
+ bool operator <(Guint x) const { return *this < (FixedPoint)x; }
+ bool operator <(long x) const { return *this < (FixedPoint)x; }
+
+ bool operator <=(FixedPoint x) const { return val <= x.val; }
+ bool operator <=(double x) const { return *this <= (FixedPoint)x; }
+ bool operator <=(int x) const { return *this <= (FixedPoint)x; }
+ bool operator <=(Guint x) const { return *this <= (FixedPoint)x; }
+ bool operator <=(long x) const { return *this <= (FixedPoint)x; }
+
+ bool operator >(FixedPoint x) const { return val > x.val; }
+ bool operator >(double x) const { return *this > (FixedPoint)x; }
+ bool operator >(int x) const { return *this > (FixedPoint)x; }
+ bool operator >(Guint x) const { return *this > (FixedPoint)x; }
+ bool operator >(long x) const { return *this > (FixedPoint)x; }
+
+ bool operator >=(FixedPoint x) const { return val >= x.val; }
+ bool operator >=(double x) const { return *this >= (FixedPoint)x; }
+ bool operator >=(int x) const { return *this >= (FixedPoint)x; }
+ bool operator >=(Guint x) const { return *this >= (FixedPoint)x; }
+ bool operator >=(long x) const { return *this >= (FixedPoint)x; }
+
+ FixedPoint operator -() { return make(-val); }
+
+ FixedPoint operator +(FixedPoint x) { return make(val + x.val); }
+ FixedPoint operator +(double x) { return *this + (FixedPoint)x; }
+ FixedPoint operator +(int x) { return *this + (FixedPoint)x; }
+ FixedPoint operator +(Guint x) { return *this + (FixedPoint)x; }
+ FixedPoint operator +(long x) { return *this + (FixedPoint)x; }
+
+ FixedPoint operator +=(FixedPoint x) { val = val + x.val; return *this; }
+ FixedPoint operator +=(double x) { return *this += (FixedPoint)x; }
+ FixedPoint operator +=(int x) { return *this += (FixedPoint)x; }
+ FixedPoint operator +=(Guint x) { return *this += (FixedPoint)x; }
+ FixedPoint operator +=(long x) { return *this += (FixedPoint)x; }
+
+ FixedPoint operator -(FixedPoint x) { return make(val - x.val); }
+ FixedPoint operator -(double x) { return *this - (FixedPoint)x; }
+ FixedPoint operator -(int x) { return *this - (FixedPoint)x; }
+ FixedPoint operator -(Guint x) { return *this - (FixedPoint)x; }
+ FixedPoint operator -(long x) { return *this - (FixedPoint)x; }
+
+ FixedPoint operator -=(FixedPoint x) { val = val - x.val; return *this; }
+ FixedPoint operator -=(double x) { return *this -= (FixedPoint)x; }
+ FixedPoint operator -=(int x) { return *this -= (FixedPoint)x; }
+ FixedPoint operator -=(Guint x) { return *this -= (FixedPoint)x; }
+ FixedPoint operator -=(long x) { return *this -= (FixedPoint)x; }
+
+ FixedPoint operator *(FixedPoint x) { return make(mul(val, x.val)); }
+ FixedPoint operator *(double x) { return *this * (FixedPoint)x; }
+ FixedPoint operator *(int x) { return *this * (FixedPoint)x; }
+ FixedPoint operator *(Guint x) { return *this * (FixedPoint)x; }
+ FixedPoint operator *(long x) { return *this * (FixedPoint)x; }
+
+ FixedPoint operator *=(FixedPoint x) { val = mul(val, x.val); return *this; }
+ FixedPoint operator *=(double x) { return *this *= (FixedPoint)x; }
+ FixedPoint operator *=(int x) { return *this *= (FixedPoint)x; }
+ FixedPoint operator *=(Guint x) { return *this *= (FixedPoint)x; }
+ FixedPoint operator *=(long x) { return *this *= (FixedPoint)x; }
+
+ FixedPoint operator /(FixedPoint x) { return make(div(val, x.val)); }
+ FixedPoint operator /(double x) { return *this / (FixedPoint)x; }
+ FixedPoint operator /(int x) { return *this / (FixedPoint)x; }
+ FixedPoint operator /(Guint x) { return *this / (FixedPoint)x; }
+ FixedPoint operator /(long x) { return *this / (FixedPoint)x; }
+
+ FixedPoint operator /=(FixedPoint x) { val = div(val, x.val); return *this; }
+ FixedPoint operator /=(double x) { return *this /= (FixedPoint)x; }
+ FixedPoint operator /=(int x) { return *this /= (FixedPoint)x; }
+ FixedPoint operator /=(Guint x) { return *this /= (FixedPoint)x; }
+ FixedPoint operator /=(long x) { return *this /= (FixedPoint)x; }
+
+ static FixedPoint abs(FixedPoint x) { return make(::abs(x.val)); }
+
+ static int floor(FixedPoint x) { return x.val >> fixptShift; }
+
+ static int ceil(FixedPoint x)
+ { return (x.val & fixptMaskL) ? ((x.val >> fixptShift) + 1)
+ : (x.val >> fixptShift); }
+
+ static int round(FixedPoint x)
+ { return (x.val + (1 << (fixptShift - 1))) >> fixptShift; }
+
+ // Computes (x+y)/2 avoiding overflow and LSbit accuracy issues.
+ static FixedPoint avg(FixedPoint x, FixedPoint y)
+ { return make((x.val >> 1) + (y.val >> 1) + ((x.val | y.val) & 1)); }
+
+ static FixedPoint sqrt(FixedPoint x);
+
+ static FixedPoint pow(FixedPoint x, FixedPoint y);
+
+ // Compute *result = x/y; return false if there is an underflow or
+ // overflow.
+ static GBool divCheck(FixedPoint x, FixedPoint y, FixedPoint *result);
+
+ // Compute abs(m11*m22 - m12*m21) >= epsilon, handling the case
+ // where the multiplications overflow.
+ static GBool checkDet(FixedPoint m11, FixedPoint m12,
+ FixedPoint m21, FixedPoint m22,
+ FixedPoint epsilon);
+
+private:
+
+ static FixedPoint make(int valA) { FixedPoint x; x.val = valA; return x; }
+
+ static int mul(int x, int y);
+ static int div(int x, int y);
+
+ int val; // fixed point: (n-fixptShift).(fixptShift)
+};
+
+#endif // USE_FIXEDPOINT
+
+#endif
diff --git a/goo/GHash.cc b/goo/GHash.cc
new file mode 100644
index 0000000..e6b3244
--- /dev/null
+++ b/goo/GHash.cc
@@ -0,0 +1,385 @@
+//========================================================================
+//
+// GHash.cc
+//
+// Copyright 2001-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include "gmem.h"
+#include "gmempp.h"
+#include "GString.h"
+#include "GHash.h"
+
+//------------------------------------------------------------------------
+
+struct GHashBucket {
+ GString *key;
+ union {
+ void *p;
+ int i;
+ } val;
+ GHashBucket *next;
+};
+
+struct GHashIter {
+ int h;
+ GHashBucket *p;
+};
+
+//------------------------------------------------------------------------
+
+GHash::GHash(GBool deleteKeysA) {
+ int h;
+
+ deleteKeys = deleteKeysA;
+ size = 7;
+ tab = (GHashBucket **)gmallocn(size, sizeof(GHashBucket *));
+ for (h = 0; h < size; ++h) {
+ tab[h] = NULL;
+ }
+ len = 0;
+}
+
+GHash::~GHash() {
+ GHashBucket *p;
+ int h;
+
+ for (h = 0; h < size; ++h) {
+ while (tab[h]) {
+ p = tab[h];
+ tab[h] = p->next;
+ if (deleteKeys) {
+ delete p->key;
+ }
+ delete p;
+ }
+ }
+ gfree(tab);
+}
+
+void GHash::add(GString *key, void *val) {
+ GHashBucket *p;
+ int h;
+
+ // expand the table if necessary
+ if (len >= size) {
+ expand();
+ }
+
+ // add the new symbol
+ p = new GHashBucket;
+ p->key = key;
+ p->val.p = val;
+ h = hash(key);
+ p->next = tab[h];
+ tab[h] = p;
+ ++len;
+}
+
+void GHash::add(GString *key, int val) {
+ GHashBucket *p;
+ int h;
+
+ // expand the table if necessary
+ if (len >= size) {
+ expand();
+ }
+
+ // add the new symbol
+ p = new GHashBucket;
+ p->key = key;
+ p->val.i = val;
+ h = hash(key);
+ p->next = tab[h];
+ tab[h] = p;
+ ++len;
+}
+
+void GHash::replace(GString *key, void *val) {
+ GHashBucket *p;
+ int h;
+
+ if ((p = find(key, &h))) {
+ p->val.p = val;
+ if (deleteKeys) {
+ delete key;
+ }
+ } else {
+ add(key, val);
+ }
+}
+
+void GHash::replace(GString *key, int val) {
+ GHashBucket *p;
+ int h;
+
+ if ((p = find(key, &h))) {
+ p->val.i = val;
+ if (deleteKeys) {
+ delete key;
+ }
+ } else {
+ add(key, val);
+ }
+}
+
+void *GHash::lookup(GString *key) {
+ GHashBucket *p;
+ int h;
+
+ if (!(p = find(key, &h))) {
+ return NULL;
+ }
+ return p->val.p;
+}
+
+int GHash::lookupInt(GString *key) {
+ GHashBucket *p;
+ int h;
+
+ if (!(p = find(key, &h))) {
+ return 0;
+ }
+ return p->val.i;
+}
+
+void *GHash::lookup(const char *key) {
+ GHashBucket *p;
+ int h;
+
+ if (!(p = find(key, &h))) {
+ return NULL;
+ }
+ return p->val.p;
+}
+
+int GHash::lookupInt(const char *key) {
+ GHashBucket *p;
+ int h;
+
+ if (!(p = find(key, &h))) {
+ return 0;
+ }
+ return p->val.i;
+}
+
+void *GHash::remove(GString *key) {
+ GHashBucket *p;
+ GHashBucket **q;
+ void *val;
+ int h;
+
+ if (!(p = find(key, &h))) {
+ return NULL;
+ }
+ q = &tab[h];
+ while (*q != p) {
+ q = &((*q)->next);
+ }
+ *q = p->next;
+ if (deleteKeys) {
+ delete p->key;
+ }
+ val = p->val.p;
+ delete p;
+ --len;
+ return val;
+}
+
+int GHash::removeInt(GString *key) {
+ GHashBucket *p;
+ GHashBucket **q;
+ int val;
+ int h;
+
+ if (!(p = find(key, &h))) {
+ return 0;
+ }
+ q = &tab[h];
+ while (*q != p) {
+ q = &((*q)->next);
+ }
+ *q = p->next;
+ if (deleteKeys) {
+ delete p->key;
+ }
+ val = p->val.i;
+ delete p;
+ --len;
+ return val;
+}
+
+void *GHash::remove(const char *key) {
+ GHashBucket *p;
+ GHashBucket **q;
+ void *val;
+ int h;
+
+ if (!(p = find(key, &h))) {
+ return NULL;
+ }
+ q = &tab[h];
+ while (*q != p) {
+ q = &((*q)->next);
+ }
+ *q = p->next;
+ if (deleteKeys) {
+ delete p->key;
+ }
+ val = p->val.p;
+ delete p;
+ --len;
+ return val;
+}
+
+int GHash::removeInt(const char *key) {
+ GHashBucket *p;
+ GHashBucket **q;
+ int val;
+ int h;
+
+ if (!(p = find(key, &h))) {
+ return 0;
+ }
+ q = &tab[h];
+ while (*q != p) {
+ q = &((*q)->next);
+ }
+ *q = p->next;
+ if (deleteKeys) {
+ delete p->key;
+ }
+ val = p->val.i;
+ delete p;
+ --len;
+ return val;
+}
+
+void GHash::startIter(GHashIter **iter) {
+ *iter = new GHashIter;
+ (*iter)->h = -1;
+ (*iter)->p = NULL;
+}
+
+GBool GHash::getNext(GHashIter **iter, GString **key, void **val) {
+ if (!*iter) {
+ return gFalse;
+ }
+ if ((*iter)->p) {
+ (*iter)->p = (*iter)->p->next;
+ }
+ while (!(*iter)->p) {
+ if (++(*iter)->h == size) {
+ delete *iter;
+ *iter = NULL;
+ return gFalse;
+ }
+ (*iter)->p = tab[(*iter)->h];
+ }
+ *key = (*iter)->p->key;
+ *val = (*iter)->p->val.p;
+ return gTrue;
+}
+
+GBool GHash::getNext(GHashIter **iter, GString **key, int *val) {
+ if (!*iter) {
+ return gFalse;
+ }
+ if ((*iter)->p) {
+ (*iter)->p = (*iter)->p->next;
+ }
+ while (!(*iter)->p) {
+ if (++(*iter)->h == size) {
+ delete *iter;
+ *iter = NULL;
+ return gFalse;
+ }
+ (*iter)->p = tab[(*iter)->h];
+ }
+ *key = (*iter)->p->key;
+ *val = (*iter)->p->val.i;
+ return gTrue;
+}
+
+void GHash::killIter(GHashIter **iter) {
+ delete *iter;
+ *iter = NULL;
+}
+
+void GHash::expand() {
+ GHashBucket **oldTab;
+ GHashBucket *p;
+ int oldSize, h, i;
+
+ oldSize = size;
+ oldTab = tab;
+ size = 2*size + 1;
+ tab = (GHashBucket **)gmallocn(size, sizeof(GHashBucket *));
+ for (h = 0; h < size; ++h) {
+ tab[h] = NULL;
+ }
+ for (i = 0; i < oldSize; ++i) {
+ while (oldTab[i]) {
+ p = oldTab[i];
+ oldTab[i] = oldTab[i]->next;
+ h = hash(p->key);
+ p->next = tab[h];
+ tab[h] = p;
+ }
+ }
+ gfree(oldTab);
+}
+
+GHashBucket *GHash::find(GString *key, int *h) {
+ GHashBucket *p;
+
+ *h = hash(key);
+ for (p = tab[*h]; p; p = p->next) {
+ if (!p->key->cmp(key)) {
+ return p;
+ }
+ }
+ return NULL;
+}
+
+GHashBucket *GHash::find(const char *key, int *h) {
+ GHashBucket *p;
+
+ *h = hash(key);
+ for (p = tab[*h]; p; p = p->next) {
+ if (!p->key->cmp(key)) {
+ return p;
+ }
+ }
+ return NULL;
+}
+
+int GHash::hash(GString *key) {
+ const char *p;
+ unsigned int h;
+ int i;
+
+ h = 0;
+ for (p = key->getCString(), i = 0; i < key->getLength(); ++p, ++i) {
+ h = 17 * h + (int)(*p & 0xff);
+ }
+ return (int)(h % size);
+}
+
+int GHash::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 % size);
+}
diff --git a/goo/GHash.h b/goo/GHash.h
new file mode 100644
index 0000000..179753a
--- /dev/null
+++ b/goo/GHash.h
@@ -0,0 +1,78 @@
+//========================================================================
+//
+// GHash.h
+//
+// Copyright 2001-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef GHASH_H
+#define GHASH_H
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include "gtypes.h"
+
+class GString;
+struct GHashBucket;
+struct GHashIter;
+
+//------------------------------------------------------------------------
+
+class GHash {
+public:
+
+ GHash(GBool deleteKeysA = gFalse);
+ ~GHash();
+ void add(GString *key, void *val);
+ void add(GString *key, int val);
+ void replace(GString *key, void *val);
+ void replace(GString *key, int val);
+ void *lookup(GString *key);
+ int lookupInt(GString *key);
+ void *lookup(const char *key);
+ int lookupInt(const char *key);
+ void *remove(GString *key);
+ int removeInt(GString *key);
+ void *remove(const char *key);
+ int removeInt(const char *key);
+ int getLength() { return len; }
+ void startIter(GHashIter **iter);
+ GBool getNext(GHashIter **iter, GString **key, void **val);
+ GBool getNext(GHashIter **iter, GString **key, int *val);
+ void killIter(GHashIter **iter);
+
+private:
+
+ void expand();
+ GHashBucket *find(GString *key, int *h);
+ GHashBucket *find(const char *key, int *h);
+ int hash(GString *key);
+ int hash(const char *key);
+
+ GBool deleteKeys; // set if key strings should be deleted
+ int size; // number of buckets
+ int len; // number of entries
+ GHashBucket **tab;
+};
+
+#define deleteGHash(hash, T) \
+ do { \
+ GHash *_hash = (hash); \
+ { \
+ GHashIter *_iter; \
+ GString *_key; \
+ void *_p; \
+ _hash->startIter(&_iter); \
+ while (_hash->getNext(&_iter, &_key, &_p)) { \
+ delete (T*)_p; \
+ } \
+ delete _hash; \
+ } \
+ } while(0)
+
+#endif
diff --git a/goo/GList.cc b/goo/GList.cc
new file mode 100644
index 0000000..c194818
--- /dev/null
+++ b/goo/GList.cc
@@ -0,0 +1,123 @@
+//========================================================================
+//
+// GList.cc
+//
+// Copyright 2001-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include "gmem.h"
+#include "gmempp.h"
+#include "GList.h"
+
+//------------------------------------------------------------------------
+// GList
+//------------------------------------------------------------------------
+
+GList::GList() {
+ size = 8;
+ data = (void **)gmallocn(size, sizeof(void*));
+ length = 0;
+ inc = 0;
+}
+
+GList::GList(int sizeA) {
+ size = sizeA ? sizeA : 8;
+ data = (void **)gmallocn(size, sizeof(void*));
+ length = 0;
+ inc = 0;
+}
+
+GList::~GList() {
+ gfree(data);
+}
+
+GList *GList::copy() {
+ GList *ret;
+
+ ret = new GList(length);
+ ret->length = length;
+ memcpy(ret->data, data, length * sizeof(void *));
+ ret->inc = inc;
+ return ret;
+}
+
+void GList::append(void *p) {
+ if (length >= size) {
+ expand();
+ }
+ data[length++] = p;
+}
+
+void GList::append(GList *list) {
+ int i;
+
+ while (length + list->length > size) {
+ expand();
+ }
+ for (i = 0; i < list->length; ++i) {
+ data[length++] = list->data[i];
+ }
+}
+
+void GList::insert(int i, void *p) {
+ if (length >= size) {
+ expand();
+ }
+ if (i < 0) {
+ i = 0;
+ }
+ if (i < length) {
+ memmove(data+i+1, data+i, (length - i) * sizeof(void *));
+ }
+ data[i] = p;
+ ++length;
+}
+
+void *GList::del(int i) {
+ void *p;
+
+ p = data[i];
+ if (i < length - 1) {
+ memmove(data+i, data+i+1, (length - i - 1) * sizeof(void *));
+ }
+ --length;
+ if (size - length >= ((inc > 0) ? inc : size/2)) {
+ shrink();
+ }
+ return p;
+}
+
+void GList::sort(int (*cmp)(const void *obj1, const void *obj2)) {
+ qsort(data, length, sizeof(void *), cmp);
+}
+
+void GList::reverse() {
+ void *t;
+ int n, i;
+
+ n = length / 2;
+ for (i = 0; i < n; ++i) {
+ t = data[i];
+ data[i] = data[length - 1 - i];
+ data[length - 1 - i] = t;
+ }
+}
+
+void GList::expand() {
+ size += (inc > 0) ? inc : size;
+ data = (void **)greallocn(data, size, sizeof(void*));
+}
+
+void GList::shrink() {
+ size -= (inc > 0) ? inc : size/2;
+ data = (void **)greallocn(data, size, sizeof(void*));
+}
diff --git a/goo/GList.h b/goo/GList.h
new file mode 100644
index 0000000..0050437
--- /dev/null
+++ b/goo/GList.h
@@ -0,0 +1,106 @@
+//========================================================================
+//
+// GList.h
+//
+// Copyright 2001-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef GLIST_H
+#define GLIST_H
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include "gtypes.h"
+
+//------------------------------------------------------------------------
+// GList
+//------------------------------------------------------------------------
+
+class GList {
+public:
+
+ // Create an empty list.
+ GList();
+
+ // Create an empty list with space for <size1> elements.
+ GList(int sizeA);
+
+ // Destructor - does not free pointed-to objects.
+ ~GList();
+
+ //----- general
+
+ // Get the number of elements.
+ int getLength() { return length; }
+
+ // Returns a (shallow) copy of this list.
+ GList *copy();
+
+ //----- ordered list support
+
+ // Return the <i>th element.
+ // Assumes 0 <= i < length.
+ void *get(int i) { return data[i]; }
+
+ // Replace the <i>th element.
+ // Assumes 0 <= i < length.
+ void put(int i, void *p) { data[i] = p; }
+
+ // Append an element to the end of the list.
+ void append(void *p);
+
+ // Append another list to the end of this one.
+ void append(GList *list);
+
+ // Insert an element at index <i>.
+ // Assumes 0 <= i <= length.
+ void insert(int i, void *p);
+
+ // Deletes and returns the element at index <i>.
+ // Assumes 0 <= i < length.
+ void *del(int i);
+
+ // Sort the list accoring to the given comparison function.
+ // NB: this sorts an array of pointers, so the pointer args need to
+ // be double-dereferenced.
+ void sort(int (*cmp)(const void *ptr1, const void *ptr2));
+
+ // Reverse the list.
+ void reverse();
+
+ //----- control
+
+ // Set allocation increment to <inc>. If inc > 0, that many
+ // elements will be allocated every time the list is expanded.
+ // If inc <= 0, the list will be doubled in size.
+ void setAllocIncr(int incA) { inc = incA; }
+
+private:
+
+ void expand();
+ void shrink();
+
+ void **data; // the list elements
+ int size; // size of data array
+ int length; // number of elements on list
+ int inc; // allocation increment
+};
+
+#define deleteGList(list, T) \
+ do { \
+ GList *_list = (list); \
+ { \
+ int _i; \
+ for (_i = 0; _i < _list->getLength(); ++_i) { \
+ delete (T*)_list->get(_i); \
+ } \
+ delete _list; \
+ } \
+ } while (0)
+
+#endif
diff --git a/goo/GMutex.h b/goo/GMutex.h
new file mode 100644
index 0000000..aef4aec
--- /dev/null
+++ b/goo/GMutex.h
@@ -0,0 +1,101 @@
+//========================================================================
+//
+// GMutex.h
+//
+// Portable mutex macros.
+// Portable atomic increment/decrement.
+//
+// Copyright 2002-2014 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef GMUTEX_H
+#define GMUTEX_H
+
+#include <aconf.h>
+#ifdef _WIN32
+# include <windows.h>
+# include <intrin.h>
+#else
+# include <pthread.h>
+#endif
+
+//------------------------------------------------------------------------
+// GMutex
+//------------------------------------------------------------------------
+
+// Usage:
+//
+// GMutex m;
+// gInitMutex(&m);
+// ...
+// gLockMutex(&m);
+// ... critical section ...
+// gUnlockMutex(&m);
+// ...
+// gDestroyMutex(&m);
+
+#ifdef _WIN32
+
+typedef CRITICAL_SECTION GMutex;
+
+#define gInitMutex(m) InitializeCriticalSection(m)
+#define gDestroyMutex(m) DeleteCriticalSection(m)
+#define gLockMutex(m) EnterCriticalSection(m)
+#define gUnlockMutex(m) LeaveCriticalSection(m)
+
+#else // assume pthreads
+
+typedef pthread_mutex_t GMutex;
+
+#define gInitMutex(m) pthread_mutex_init(m, NULL)
+#define gDestroyMutex(m) pthread_mutex_destroy(m)
+#define gLockMutex(m) pthread_mutex_lock(m)
+#define gUnlockMutex(m) pthread_mutex_unlock(m)
+
+#endif
+
+//------------------------------------------------------------------------
+// atomic increment/decrement
+//------------------------------------------------------------------------
+
+// NB: this must be "long" to work on Windows
+typedef long GAtomicCounter;
+
+// Increment *counter by one and return the final value (after the
+// increment).
+static inline GAtomicCounter gAtomicIncrement(GAtomicCounter *counter) {
+ GAtomicCounter newVal;
+
+#if defined(_WIN32)
+ newVal = _InterlockedIncrement(counter);
+#elif defined(__GNUC__) || defined(__xlC__)
+ // __GNUC__ also covers LLVM/clang
+ newVal = __sync_add_and_fetch(counter, 1);
+#elif defined(__SUNPRO_CC)
+ newVal = atomic_inc_ulong_nv((ulong_t *)counter);
+#else
+# error "gAtomicIncrement is not defined for this compiler/platform"
+#endif
+ return newVal;
+}
+
+// Decrement *counter by one and return the final value (after the
+// decrement).
+static inline GAtomicCounter gAtomicDecrement(GAtomicCounter *counter) {
+ GAtomicCounter newVal;
+
+#if defined(_WIN32)
+ newVal = _InterlockedDecrement(counter);
+#elif defined(__GNUC__) || defined(__xlC__)
+ // __GNUC__ also covers LLVM/clang
+ newVal = __sync_sub_and_fetch(counter, 1);
+#elif defined(__SUNPRO_CC)
+ newVal = atomic_dec_ulong_nv((ulong_t *)counter);
+#else
+# error "gAtomicDecrement is not defined for this compiler/platform"
+#endif
+ return newVal;
+}
+
+#endif // GMUTEX_H
diff --git a/goo/GString.cc b/goo/GString.cc
new file mode 100644
index 0000000..54de35b
--- /dev/null
+++ b/goo/GString.cc
@@ -0,0 +1,853 @@
+//========================================================================
+//
+// GString.cc
+//
+// Simple variable-length string type.
+//
+// Copyright 1996-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include <ctype.h>
+#include <math.h>
+#include <limits.h>
+#include "gmem.h"
+#include "gmempp.h"
+#include "GString.h"
+
+//------------------------------------------------------------------------
+
+union GStringFormatArg {
+ int i;
+ Guint ui;
+ long l;
+ Gulong ul;
+#ifdef LLONG_MAX
+ long long ll;
+#endif
+#ifdef ULLONG_MAX
+ unsigned long long ull;
+#endif
+ double f;
+ char c;
+ char *s;
+ GString *gs;
+};
+
+enum GStringFormatType {
+ fmtIntDecimal,
+ fmtIntHex,
+ fmtIntOctal,
+ fmtIntBinary,
+ fmtUIntDecimal,
+ fmtUIntHex,
+ fmtUIntOctal,
+ fmtUIntBinary,
+ fmtLongDecimal,
+ fmtLongHex,
+ fmtLongOctal,
+ fmtLongBinary,
+ fmtULongDecimal,
+ fmtULongHex,
+ fmtULongOctal,
+ fmtULongBinary,
+#ifdef LLONG_MAX
+ fmtLongLongDecimal,
+ fmtLongLongHex,
+ fmtLongLongOctal,
+ fmtLongLongBinary,
+#endif
+#ifdef ULLONG_MAX
+ fmtULongLongDecimal,
+ fmtULongLongHex,
+ fmtULongLongOctal,
+ fmtULongLongBinary,
+#endif
+ fmtDouble,
+ fmtDoubleTrim,
+ fmtChar,
+ fmtString,
+ fmtGString,
+ fmtSpace
+};
+
+static const char *formatStrings[] = {
+ "d", "x", "o", "b", "ud", "ux", "uo", "ub",
+ "ld", "lx", "lo", "lb", "uld", "ulx", "ulo", "ulb",
+#ifdef LLONG_MAX
+ "lld", "llx", "llo", "llb",
+#endif
+#ifdef ULLONG_MAX
+ "ulld", "ullx", "ullo", "ullb",
+#endif
+ "f", "g",
+ "c",
+ "s",
+ "t",
+ "w",
+ NULL
+};
+
+//------------------------------------------------------------------------
+
+static inline int size(int len) {
+ int delta;
+ for (delta = 8; delta < len && delta < 0x100000; delta <<= 1) ;
+ if (len > INT_MAX - delta) {
+ gMemError("Integer overflow in GString::size()");
+ }
+ // this is ((len + 1) + (delta - 1)) & ~(delta - 1)
+ return (len + delta) & ~(delta - 1);
+}
+
+inline void GString::resize(int length1) {
+ char *s1;
+
+ if (length1 < 0) {
+ gMemError("GString::resize() with negative length");
+ }
+ if (!s) {
+ s = new char[size(length1)];
+ } else if (size(length1) != size(length)) {
+ s1 = new char[size(length1)];
+ if (length1 < length) {
+ memcpy(s1, s, length1);
+ s1[length1] = '\0';
+ } else {
+ memcpy(s1, s, length + 1);
+ }
+ delete[] s;
+ s = s1;
+ }
+}
+
+GString::GString() {
+ s = NULL;
+ resize(length = 0);
+ s[0] = '\0';
+}
+
+GString::GString(const char *sA) {
+ int n = (int)strlen(sA);
+
+ s = NULL;
+ resize(length = n);
+ memcpy(s, sA, n + 1);
+}
+
+GString::GString(const char *sA, int lengthA) {
+ s = NULL;
+ resize(length = lengthA);
+ memcpy(s, sA, length * sizeof(char));
+ s[length] = '\0';
+}
+
+GString::GString(GString *str, int idx, int lengthA) {
+ s = NULL;
+ resize(length = lengthA);
+ memcpy(s, str->getCString() + idx, length);
+ s[length] = '\0';
+}
+
+GString::GString(GString *str) {
+ s = NULL;
+ resize(length = str->getLength());
+ memcpy(s, str->getCString(), length + 1);
+}
+
+GString::GString(GString *str1, GString *str2) {
+ int n1 = str1->getLength();
+ int n2 = str2->getLength();
+
+ s = NULL;
+ if (n1 > INT_MAX - n2) {
+ gMemError("Integer overflow in GString::GString()");
+ }
+ resize(length = n1 + n2);
+ memcpy(s, str1->getCString(), n1);
+ memcpy(s + n1, str2->getCString(), n2 + 1);
+}
+
+GString *GString::fromInt(int x) {
+ char buf[24]; // enough space for 64-bit ints plus a little extra
+ const char *p;
+ int len;
+
+ formatInt(x, buf, sizeof(buf), gFalse, 0, 10, &p, &len);
+ return new GString(p, len);
+}
+
+GString *GString::format(const char *fmt, ...) {
+ va_list argList;
+ GString *s;
+
+ s = new GString();
+ va_start(argList, fmt);
+ s->appendfv(fmt, argList);
+ va_end(argList);
+ return s;
+}
+
+GString *GString::formatv(const char *fmt, va_list argList) {
+ GString *s;
+
+ s = new GString();
+ s->appendfv(fmt, argList);
+ return s;
+}
+
+GString::~GString() {
+ delete[] s;
+}
+
+GString *GString::clear() {
+ s[length = 0] = '\0';
+ resize(0);
+ return this;
+}
+
+GString *GString::append(char c) {
+ if (length > INT_MAX - 1) {
+ gMemError("Integer overflow in GString::append()");
+ }
+ resize(length + 1);
+ s[length++] = c;
+ s[length] = '\0';
+ return this;
+}
+
+GString *GString::append(GString *str) {
+ int n = str->getLength();
+
+ if (length > INT_MAX - n) {
+ gMemError("Integer overflow in GString::append()");
+ }
+ resize(length + n);
+ memcpy(s + length, str->getCString(), n + 1);
+ length += n;
+ return this;
+}
+
+GString *GString::append(const char *str) {
+ int n = (int)strlen(str);
+
+ if (length > INT_MAX - n) {
+ gMemError("Integer overflow in GString::append()");
+ }
+ resize(length + n);
+ memcpy(s + length, str, n + 1);
+ length += n;
+ return this;
+}
+
+GString *GString::append(const char *str, int lengthA) {
+ if (lengthA < 0 || length > INT_MAX - lengthA) {
+ gMemError("Integer overflow in GString::append()");
+ }
+ resize(length + lengthA);
+ memcpy(s + length, str, lengthA);
+ length += lengthA;
+ s[length] = '\0';
+ return this;
+}
+
+GString *GString::appendf(const char *fmt, ...) {
+ va_list argList;
+
+ va_start(argList, fmt);
+ appendfv(fmt, argList);
+ va_end(argList);
+ return this;
+}
+
+GString *GString::appendfv(const char *fmt, va_list argList) {
+ GStringFormatArg *args;
+ int argsLen, argsSize;
+ GStringFormatArg arg;
+ int idx, width, prec;
+ GBool reverseAlign, zeroFill;
+ GStringFormatType ft;
+ char buf[65];
+ int len, i;
+ const char *p0, *p1;
+ const char *str;
+
+ argsLen = 0;
+ argsSize = 8;
+ args = (GStringFormatArg *)gmallocn(argsSize, sizeof(GStringFormatArg));
+
+ p0 = fmt;
+ while (*p0) {
+ if (*p0 == '{') {
+ ++p0;
+ if (*p0 == '{') {
+ ++p0;
+ append('{');
+ } else {
+
+ // parse the format string
+ if (!(*p0 >= '0' && *p0 <= '9')) {
+ break;
+ }
+ idx = *p0 - '0';
+ for (++p0; *p0 >= '0' && *p0 <= '9'; ++p0) {
+ idx = 10 * idx + (*p0 - '0');
+ }
+ if (*p0 != ':') {
+ break;
+ }
+ ++p0;
+ if (*p0 == '-') {
+ reverseAlign = gTrue;
+ ++p0;
+ } else {
+ reverseAlign = gFalse;
+ }
+ width = 0;
+ zeroFill = *p0 == '0';
+ for (; *p0 >= '0' && *p0 <= '9'; ++p0) {
+ width = 10 * width + (*p0 - '0');
+ }
+ if (width < 0) {
+ width = 0;
+ }
+ if (*p0 == '.') {
+ ++p0;
+ prec = 0;
+ for (; *p0 >= '0' && *p0 <= '9'; ++p0) {
+ prec = 10 * prec + (*p0 - '0');
+ }
+ } else {
+ prec = 0;
+ }
+ for (ft = (GStringFormatType)0;
+ formatStrings[ft];
+ ft = (GStringFormatType)(ft + 1)) {
+ if (!strncmp(p0, formatStrings[ft], strlen(formatStrings[ft]))) {
+ break;
+ }
+ }
+ if (!formatStrings[ft]) {
+ break;
+ }
+ p0 += strlen(formatStrings[ft]);
+ if (*p0 != '}') {
+ break;
+ }
+ ++p0;
+
+ // fetch the argument
+ if (idx > argsLen) {
+ break;
+ }
+ if (idx == argsLen) {
+ if (argsLen == argsSize) {
+ argsSize *= 2;
+ args = (GStringFormatArg *)greallocn(args, argsSize,
+ sizeof(GStringFormatArg));
+ }
+ switch (ft) {
+ case fmtIntDecimal:
+ case fmtIntHex:
+ case fmtIntOctal:
+ case fmtIntBinary:
+ case fmtSpace:
+ args[argsLen].i = va_arg(argList, int);
+ break;
+ case fmtUIntDecimal:
+ case fmtUIntHex:
+ case fmtUIntOctal:
+ case fmtUIntBinary:
+ args[argsLen].ui = va_arg(argList, Guint);
+ break;
+ case fmtLongDecimal:
+ case fmtLongHex:
+ case fmtLongOctal:
+ case fmtLongBinary:
+ args[argsLen].l = va_arg(argList, long);
+ break;
+ case fmtULongDecimal:
+ case fmtULongHex:
+ case fmtULongOctal:
+ case fmtULongBinary:
+ args[argsLen].ul = va_arg(argList, Gulong);
+ break;
+#ifdef LLONG_MAX
+ case fmtLongLongDecimal:
+ case fmtLongLongHex:
+ case fmtLongLongOctal:
+ case fmtLongLongBinary:
+ args[argsLen].ll = va_arg(argList, long long);
+ break;
+#endif
+#ifdef ULLONG_MAX
+ case fmtULongLongDecimal:
+ case fmtULongLongHex:
+ case fmtULongLongOctal:
+ case fmtULongLongBinary:
+ args[argsLen].ull = va_arg(argList, unsigned long long);
+ break;
+#endif
+ case fmtDouble:
+ case fmtDoubleTrim:
+ args[argsLen].f = va_arg(argList, double);
+ break;
+ case fmtChar:
+ args[argsLen].c = (char)va_arg(argList, int);
+ break;
+ case fmtString:
+ args[argsLen].s = va_arg(argList, char *);
+ break;
+ case fmtGString:
+ args[argsLen].gs = va_arg(argList, GString *);
+ break;
+ }
+ ++argsLen;
+ }
+
+ // format the argument
+ arg = args[idx];
+ switch (ft) {
+ case fmtIntDecimal:
+ formatInt(arg.i, buf, sizeof(buf), zeroFill, width, 10, &str, &len);
+ break;
+ case fmtIntHex:
+ formatInt(arg.i, buf, sizeof(buf), zeroFill, width, 16, &str, &len);
+ break;
+ case fmtIntOctal:
+ formatInt(arg.i, buf, sizeof(buf), zeroFill, width, 8, &str, &len);
+ break;
+ case fmtIntBinary:
+ formatInt(arg.i, buf, sizeof(buf), zeroFill, width, 2, &str, &len);
+ break;
+ case fmtUIntDecimal:
+ formatUInt(arg.ui, buf, sizeof(buf), zeroFill, width, 10,
+ &str, &len);
+ break;
+ case fmtUIntHex:
+ formatUInt(arg.ui, buf, sizeof(buf), zeroFill, width, 16,
+ &str, &len);
+ break;
+ case fmtUIntOctal:
+ formatUInt(arg.ui, buf, sizeof(buf), zeroFill, width, 8, &str, &len);
+ break;
+ case fmtUIntBinary:
+ formatUInt(arg.ui, buf, sizeof(buf), zeroFill, width, 2, &str, &len);
+ break;
+ case fmtLongDecimal:
+ formatInt(arg.l, buf, sizeof(buf), zeroFill, width, 10, &str, &len);
+ break;
+ case fmtLongHex:
+ formatInt(arg.l, buf, sizeof(buf), zeroFill, width, 16, &str, &len);
+ break;
+ case fmtLongOctal:
+ formatInt(arg.l, buf, sizeof(buf), zeroFill, width, 8, &str, &len);
+ break;
+ case fmtLongBinary:
+ formatInt(arg.l, buf, sizeof(buf), zeroFill, width, 2, &str, &len);
+ break;
+ case fmtULongDecimal:
+ formatUInt(arg.ul, buf, sizeof(buf), zeroFill, width, 10,
+ &str, &len);
+ break;
+ case fmtULongHex:
+ formatUInt(arg.ul, buf, sizeof(buf), zeroFill, width, 16,
+ &str, &len);
+ break;
+ case fmtULongOctal:
+ formatUInt(arg.ul, buf, sizeof(buf), zeroFill, width, 8, &str, &len);
+ break;
+ case fmtULongBinary:
+ formatUInt(arg.ul, buf, sizeof(buf), zeroFill, width, 2, &str, &len);
+ break;
+#ifdef LLONG_MAX
+ case fmtLongLongDecimal:
+ formatInt(arg.ll, buf, sizeof(buf), zeroFill, width, 10, &str, &len);
+ break;
+ case fmtLongLongHex:
+ formatInt(arg.ll, buf, sizeof(buf), zeroFill, width, 16, &str, &len);
+ break;
+ case fmtLongLongOctal:
+ formatInt(arg.ll, buf, sizeof(buf), zeroFill, width, 8, &str, &len);
+ break;
+ case fmtLongLongBinary:
+ formatInt(arg.ll, buf, sizeof(buf), zeroFill, width, 2, &str, &len);
+ break;
+#endif
+#ifdef ULLONG_MAX
+ case fmtULongLongDecimal:
+ formatUInt(arg.ull, buf, sizeof(buf), zeroFill, width, 10,
+ &str, &len);
+ break;
+ case fmtULongLongHex:
+ formatUInt(arg.ull, buf, sizeof(buf), zeroFill, width, 16,
+ &str, &len);
+ break;
+ case fmtULongLongOctal:
+ formatUInt(arg.ull, buf, sizeof(buf), zeroFill, width, 8,
+ &str, &len);
+ break;
+ case fmtULongLongBinary:
+ formatUInt(arg.ull, buf, sizeof(buf), zeroFill, width, 2,
+ &str, &len);
+ break;
+#endif
+ case fmtDouble:
+ formatDouble(arg.f, buf, sizeof(buf), prec, gFalse, &str, &len);
+ break;
+ case fmtDoubleTrim:
+ formatDouble(arg.f, buf, sizeof(buf), prec, gTrue, &str, &len);
+ break;
+ case fmtChar:
+ buf[0] = arg.c;
+ str = buf;
+ len = 1;
+ reverseAlign = !reverseAlign;
+ break;
+ case fmtString:
+ if (arg.s) {
+ str = arg.s;
+ len = (int)strlen(str);
+ } else {
+ str = "(null)";
+ len = 6;
+ }
+ reverseAlign = !reverseAlign;
+ break;
+ case fmtGString:
+ if (arg.gs) {
+ str = arg.gs->getCString();
+ len = arg.gs->getLength();
+ } else {
+ str = "(null)";
+ len = 6;
+ }
+ reverseAlign = !reverseAlign;
+ break;
+ case fmtSpace:
+ str = buf;
+ len = 0;
+ width = arg.i;
+ break;
+ }
+
+ // append the formatted arg, handling width and alignment
+ if (!reverseAlign && len < width) {
+ for (i = len; i < width; ++i) {
+ append(' ');
+ }
+ }
+ append(str, len);
+ if (reverseAlign && len < width) {
+ for (i = len; i < width; ++i) {
+ append(' ');
+ }
+ }
+ }
+
+ } else if (*p0 == '}') {
+ ++p0;
+ if (*p0 == '}') {
+ ++p0;
+ }
+ append('}');
+
+ } else {
+ for (p1 = p0 + 1; *p1 && *p1 != '{' && *p1 != '}'; ++p1) ;
+ append(p0, (int)(p1 - p0));
+ p0 = p1;
+ }
+ }
+
+ gfree(args);
+ return this;
+}
+
+#ifdef LLONG_MAX
+void GString::formatInt(long long x, char *buf, int bufSize,
+ GBool zeroFill, int width, int base,
+ const char **p, int *len) {
+#else
+void GString::formatInt(long x, char *buf, int bufSize,
+ GBool zeroFill, int width, int base,
+ const char **p, int *len) {
+#endif
+ static char vals[17] = "0123456789abcdef";
+ GBool neg;
+ int start, i, j;
+
+ i = bufSize;
+ if ((neg = x < 0)) {
+ x = -x;
+ }
+ start = neg ? 1 : 0;
+ if (x == 0) {
+ buf[--i] = '0';
+ } else {
+ while (i > start && x) {
+ buf[--i] = vals[x % base];
+ x /= base;
+ }
+ }
+ if (zeroFill) {
+ for (j = bufSize - i; i > start && j < width - start; ++j) {
+ buf[--i] = '0';
+ }
+ }
+ if (neg) {
+ buf[--i] = '-';
+ }
+ *p = buf + i;
+ *len = bufSize - i;
+}
+
+#ifdef ULLONG_MAX
+void GString::formatUInt(unsigned long long x, char *buf, int bufSize,
+ GBool zeroFill, int width, int base,
+ const char **p, int *len) {
+#else
+void GString::formatUInt(Gulong x, char *buf, int bufSize,
+ GBool zeroFill, int width, int base,
+ const char **p, int *len) {
+#endif
+ static char vals[17] = "0123456789abcdef";
+ int i, j;
+
+ i = bufSize;
+ if (x == 0) {
+ buf[--i] = '0';
+ } else {
+ while (i > 0 && x) {
+ buf[--i] = vals[x % base];
+ x /= base;
+ }
+ }
+ if (zeroFill) {
+ for (j = bufSize - i; i > 0 && j < width; ++j) {
+ buf[--i] = '0';
+ }
+ }
+ *p = buf + i;
+ *len = bufSize - i;
+}
+
+void GString::formatDouble(double x, char *buf, int bufSize, int prec,
+ GBool trim, const char **p, int *len) {
+ GBool neg, started;
+ double x2;
+ int d, i, j;
+
+ if ((neg = x < 0)) {
+ x = -x;
+ }
+ x = floor(x * pow(10.0, prec) + 0.5);
+ i = bufSize;
+ started = !trim;
+ for (j = 0; j < prec && i > 1; ++j) {
+ x2 = floor(0.1 * (x + 0.5));
+ d = (int)floor(x - 10 * x2 + 0.5);
+ if (started || d != 0) {
+ buf[--i] = (char)('0' + d);
+ started = gTrue;
+ }
+ x = x2;
+ }
+ if (i > 1 && started) {
+ buf[--i] = '.';
+ }
+ if (i > 1) {
+ do {
+ x2 = floor(0.1 * (x + 0.5));
+ d = (int)floor(x - 10 * x2 + 0.5);
+ buf[--i] = (char)('0' + d);
+ x = x2;
+ } while (i > 1 && x);
+ }
+ if (neg) {
+ buf[--i] = '-';
+ }
+ *p = buf + i;
+ *len = bufSize - i;
+}
+
+GString *GString::insert(int i, char c) {
+ int j;
+
+ if (length > INT_MAX - 1) {
+ gMemError("Integer overflow in GString::insert()");
+ }
+ resize(length + 1);
+ for (j = length + 1; j > i; --j)
+ s[j] = s[j-1];
+ s[i] = c;
+ ++length;
+ return this;
+}
+
+GString *GString::insert(int i, GString *str) {
+ int n = str->getLength();
+ int j;
+
+ if (length > INT_MAX - n) {
+ gMemError("Integer overflow in GString::insert()");
+ }
+ resize(length + n);
+ for (j = length; j >= i; --j)
+ s[j+n] = s[j];
+ memcpy(s+i, str->getCString(), n);
+ length += n;
+ return this;
+}
+
+GString *GString::insert(int i, const char *str) {
+ int n = (int)strlen(str);
+ int j;
+
+ if (length > INT_MAX - n) {
+ gMemError("Integer overflow in GString::insert()");
+ }
+ resize(length + n);
+ for (j = length; j >= i; --j)
+ s[j+n] = s[j];
+ memcpy(s+i, str, n);
+ length += n;
+ return this;
+}
+
+GString *GString::insert(int i, const char *str, int lengthA) {
+ int j;
+
+ if (lengthA < 0 || length > INT_MAX - lengthA) {
+ gMemError("Integer overflow in GString::insert()");
+ }
+ resize(length + lengthA);
+ for (j = length; j >= i; --j)
+ s[j+lengthA] = s[j];
+ memcpy(s+i, str, lengthA);
+ length += lengthA;
+ return this;
+}
+
+GString *GString::del(int i, int n) {
+ int j;
+
+ if (i >= 0 && n > 0 && i <= INT_MAX - n) {
+ if (i + n > length) {
+ n = length - i;
+ }
+ for (j = i; j <= length - n; ++j) {
+ s[j] = s[j + n];
+ }
+ resize(length -= n);
+ }
+ return this;
+}
+
+GString *GString::upperCase() {
+ int i;
+
+ for (i = 0; i < length; ++i) {
+ if (islower(s[i] & 0xff)) {
+ s[i] = (char)toupper(s[i] & 0xff);
+ }
+ }
+ return this;
+}
+
+GString *GString::lowerCase() {
+ int i;
+
+ for (i = 0; i < length; ++i) {
+ if (isupper(s[i] & 0xff)) {
+ s[i] = (char)tolower(s[i] & 0xff);
+ }
+ }
+ return this;
+}
+
+int GString::cmp(GString *str) {
+ int n1, n2, i, x;
+ char *p1, *p2;
+
+ n1 = length;
+ n2 = str->length;
+ for (i = 0, p1 = s, p2 = str->s; i < n1 && i < n2; ++i, ++p1, ++p2) {
+ x = (*p1 & 0xff) - (*p2 & 0xff);
+ if (x != 0) {
+ return x;
+ }
+ }
+ return n1 - n2;
+}
+
+int GString::cmpN(GString *str, int n) {
+ int n1, n2, i, x;
+ char *p1, *p2;
+
+ n1 = length;
+ n2 = str->length;
+ for (i = 0, p1 = s, p2 = str->s;
+ i < n1 && i < n2 && i < n;
+ ++i, ++p1, ++p2) {
+ x = (*p1 & 0xff) - (*p2 & 0xff);
+ if (x != 0) {
+ return x;
+ }
+ }
+ if (i == n) {
+ return 0;
+ }
+ return n1 - n2;
+}
+
+int GString::cmp(const char *sA) {
+ int n1, i, x;
+ const char *p1, *p2;
+
+ n1 = length;
+ for (i = 0, p1 = s, p2 = sA; i < n1 && *p2; ++i, ++p1, ++p2) {
+ x = (*p1 & 0xff) - (*p2 & 0xff);
+ if (x != 0) {
+ return x;
+ }
+ }
+ if (i < n1) {
+ return 1;
+ }
+ if (*p2) {
+ return -1;
+ }
+ return 0;
+}
+
+int GString::cmpN(const char *sA, int n) {
+ int n1, i, x;
+ const char *p1, *p2;
+
+ n1 = length;
+ for (i = 0, p1 = s, p2 = sA; i < n1 && *p2 && i < n; ++i, ++p1, ++p2) {
+ x = (*p1 & 0xff) - (*p2 & 0xff);
+ if (x != 0) {
+ return x;
+ }
+ }
+ if (i == n) {
+ return 0;
+ }
+ if (i < n1) {
+ return 1;
+ }
+ if (*p2) {
+ return -1;
+ }
+ return 0;
+}
diff --git a/goo/GString.h b/goo/GString.h
new file mode 100644
index 0000000..6b342f8
--- /dev/null
+++ b/goo/GString.h
@@ -0,0 +1,151 @@
+//========================================================================
+//
+// GString.h
+//
+// Simple variable-length string type.
+//
+// Copyright 1996-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef GSTRING_H
+#define GSTRING_H
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include <limits.h> // for LLONG_MAX and ULLONG_MAX
+#include <stdarg.h>
+#include "gtypes.h"
+
+class GString {
+public:
+
+ // Create an empty string.
+ GString();
+
+ // Create a string from a C string.
+ GString(const char *sA);
+
+ // Create a string from <lengthA> chars at <sA>. This string
+ // can contain null characters.
+ GString(const char *sA, int lengthA);
+
+ // Create a string from <lengthA> chars at <idx> in <str>.
+ GString(GString *str, int idx, int lengthA);
+
+ // Copy a string.
+ GString(GString *str);
+ GString *copy() { return new GString(this); }
+
+ // Concatenate two strings.
+ GString(GString *str1, GString *str2);
+
+ // Convert an integer to a string.
+ static GString *fromInt(int x);
+
+ // Create a formatted string. Similar to printf, but without the
+ // string overflow issues. Formatting elements consist of:
+ // {<arg>:[<width>][.<precision>]<type>}
+ // where:
+ // - <arg> is the argument number (arg 0 is the first argument
+ // following the format string) -- NB: args must be first used in
+ // order; they can be reused in any order
+ // - <width> is the field width -- negative to reverse the alignment;
+ // starting with a leading zero to zero-fill (for integers)
+ // - <precision> is the number of digits to the right of the decimal
+ // point (for floating point numbers)
+ // - <type> is one of:
+ // d, x, o, b -- int in decimal, hex, octal, binary
+ // ud, ux, uo, ub -- unsigned int
+ // ld, lx, lo, lb, uld, ulx, ulo, ulb -- long, unsigned long
+ // lld, llx, llo, llb, ulld, ullx, ullo, ullb
+ // -- long long, unsigned long long
+ // f, g -- double
+ // c -- char
+ // s -- string (char *)
+ // t -- GString *
+ // w -- blank space; arg determines width
+ // To get literal curly braces, use {{ or }}.
+ static GString *format(const char *fmt, ...);
+ static GString *formatv(const char *fmt, va_list argList);
+
+ // Destructor.
+ ~GString();
+
+ // Get length.
+ int getLength() { return length; }
+
+ // Get C string.
+ char *getCString() { return s; }
+
+ // Get <i>th character.
+ char getChar(int i) { return s[i]; }
+
+ // Change <i>th character.
+ void setChar(int i, char c) { s[i] = c; }
+
+ // Clear string to zero length.
+ GString *clear();
+
+ // Append a character or string.
+ GString *append(char c);
+ GString *append(GString *str);
+ GString *append(const char *str);
+ GString *append(const char *str, int lengthA);
+
+ // Append a formatted string.
+ GString *appendf(const char *fmt, ...);
+ GString *appendfv(const char *fmt, va_list argList);
+
+ // Insert a character or string.
+ GString *insert(int i, char c);
+ GString *insert(int i, GString *str);
+ GString *insert(int i, const char *str);
+ GString *insert(int i, const char *str, int lengthA);
+
+ // Delete a character or range of characters.
+ GString *del(int i, int n = 1);
+
+ // Convert string to all-upper/all-lower case.
+ GString *upperCase();
+ GString *lowerCase();
+
+ // Compare two strings: -1:< 0:= +1:>
+ int cmp(GString *str);
+ int cmpN(GString *str, int n);
+ int cmp(const char *sA);
+ int cmpN(const char *sA, int n);
+
+private:
+
+ int length;
+ char *s;
+
+ void resize(int length1);
+#ifdef LLONG_MAX
+ static void formatInt(long long x, char *buf, int bufSize,
+ GBool zeroFill, int width, int base,
+ const char **p, int *len);
+#else
+ static void formatInt(long x, char *buf, int bufSize,
+ GBool zeroFill, int width, int base,
+ const char **p, int *len);
+#endif
+#ifdef ULLONG_MAX
+ static void formatUInt(unsigned long long x, char *buf, int bufSize,
+ GBool zeroFill, int width, int base,
+ const char **p, int *len);
+#else
+ static void formatUInt(Gulong x, char *buf, int bufSize,
+ GBool zeroFill, int width, int base,
+ const char **p, int *len);
+#endif
+ static void formatDouble(double x, char *buf, int bufSize, int prec,
+ GBool trim, const char **p, int *len);
+};
+
+#endif
diff --git a/goo/Makefile b/goo/Makefile
new file mode 100644
index 0000000..5904ab2
--- /dev/null
+++ b/goo/Makefile
@@ -0,0 +1,505 @@
+# 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 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 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 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/goo//CMakeFiles/progress.marks
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 goo/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 goo/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 goo/preinstall
+.PHONY : preinstall
+
+# Prepare targets for installation.
+preinstall/fast:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 goo/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.
+goo/CMakeFiles/goo.dir/rule:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 goo/CMakeFiles/goo.dir/rule
+.PHONY : goo/CMakeFiles/goo.dir/rule
+
+# Convenience name for target.
+goo: goo/CMakeFiles/goo.dir/rule
+
+.PHONY : goo
+
+# fast build rule for target.
+goo/fast:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f goo/CMakeFiles/goo.dir/build.make goo/CMakeFiles/goo.dir/build
+.PHONY : goo/fast
+
+# Convenience name for target.
+goo/CMakeFiles/goo_objs.dir/rule:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 goo/CMakeFiles/goo_objs.dir/rule
+.PHONY : goo/CMakeFiles/goo_objs.dir/rule
+
+# Convenience name for target.
+goo_objs: goo/CMakeFiles/goo_objs.dir/rule
+
+.PHONY : goo_objs
+
+# fast build rule for target.
+goo_objs/fast:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f goo/CMakeFiles/goo_objs.dir/build.make goo/CMakeFiles/goo_objs.dir/build
+.PHONY : goo_objs/fast
+
+FixedPoint.o: FixedPoint.cc.o
+
+.PHONY : FixedPoint.o
+
+# target to build an object file
+FixedPoint.cc.o:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f goo/CMakeFiles/goo_objs.dir/build.make goo/CMakeFiles/goo_objs.dir/FixedPoint.cc.o
+.PHONY : FixedPoint.cc.o
+
+FixedPoint.i: FixedPoint.cc.i
+
+.PHONY : FixedPoint.i
+
+# target to preprocess a source file
+FixedPoint.cc.i:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f goo/CMakeFiles/goo_objs.dir/build.make goo/CMakeFiles/goo_objs.dir/FixedPoint.cc.i
+.PHONY : FixedPoint.cc.i
+
+FixedPoint.s: FixedPoint.cc.s
+
+.PHONY : FixedPoint.s
+
+# target to generate assembly for a file
+FixedPoint.cc.s:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f goo/CMakeFiles/goo_objs.dir/build.make goo/CMakeFiles/goo_objs.dir/FixedPoint.cc.s
+.PHONY : FixedPoint.cc.s
+
+GHash.o: GHash.cc.o
+
+.PHONY : GHash.o
+
+# target to build an object file
+GHash.cc.o:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f goo/CMakeFiles/goo_objs.dir/build.make goo/CMakeFiles/goo_objs.dir/GHash.cc.o
+.PHONY : GHash.cc.o
+
+GHash.i: GHash.cc.i
+
+.PHONY : GHash.i
+
+# target to preprocess a source file
+GHash.cc.i:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f goo/CMakeFiles/goo_objs.dir/build.make goo/CMakeFiles/goo_objs.dir/GHash.cc.i
+.PHONY : GHash.cc.i
+
+GHash.s: GHash.cc.s
+
+.PHONY : GHash.s
+
+# target to generate assembly for a file
+GHash.cc.s:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f goo/CMakeFiles/goo_objs.dir/build.make goo/CMakeFiles/goo_objs.dir/GHash.cc.s
+.PHONY : GHash.cc.s
+
+GList.o: GList.cc.o
+
+.PHONY : GList.o
+
+# target to build an object file
+GList.cc.o:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f goo/CMakeFiles/goo_objs.dir/build.make goo/CMakeFiles/goo_objs.dir/GList.cc.o
+.PHONY : GList.cc.o
+
+GList.i: GList.cc.i
+
+.PHONY : GList.i
+
+# target to preprocess a source file
+GList.cc.i:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f goo/CMakeFiles/goo_objs.dir/build.make goo/CMakeFiles/goo_objs.dir/GList.cc.i
+.PHONY : GList.cc.i
+
+GList.s: GList.cc.s
+
+.PHONY : GList.s
+
+# target to generate assembly for a file
+GList.cc.s:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f goo/CMakeFiles/goo_objs.dir/build.make goo/CMakeFiles/goo_objs.dir/GList.cc.s
+.PHONY : GList.cc.s
+
+GString.o: GString.cc.o
+
+.PHONY : GString.o
+
+# target to build an object file
+GString.cc.o:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f goo/CMakeFiles/goo_objs.dir/build.make goo/CMakeFiles/goo_objs.dir/GString.cc.o
+.PHONY : GString.cc.o
+
+GString.i: GString.cc.i
+
+.PHONY : GString.i
+
+# target to preprocess a source file
+GString.cc.i:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f goo/CMakeFiles/goo_objs.dir/build.make goo/CMakeFiles/goo_objs.dir/GString.cc.i
+.PHONY : GString.cc.i
+
+GString.s: GString.cc.s
+
+.PHONY : GString.s
+
+# target to generate assembly for a file
+GString.cc.s:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f goo/CMakeFiles/goo_objs.dir/build.make goo/CMakeFiles/goo_objs.dir/GString.cc.s
+.PHONY : GString.cc.s
+
+Trace.o: Trace.cc.o
+
+.PHONY : Trace.o
+
+# target to build an object file
+Trace.cc.o:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f goo/CMakeFiles/goo_objs.dir/build.make goo/CMakeFiles/goo_objs.dir/Trace.cc.o
+.PHONY : Trace.cc.o
+
+Trace.i: Trace.cc.i
+
+.PHONY : Trace.i
+
+# target to preprocess a source file
+Trace.cc.i:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f goo/CMakeFiles/goo_objs.dir/build.make goo/CMakeFiles/goo_objs.dir/Trace.cc.i
+.PHONY : Trace.cc.i
+
+Trace.s: Trace.cc.s
+
+.PHONY : Trace.s
+
+# target to generate assembly for a file
+Trace.cc.s:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f goo/CMakeFiles/goo_objs.dir/build.make goo/CMakeFiles/goo_objs.dir/Trace.cc.s
+.PHONY : Trace.cc.s
+
+gfile.o: gfile.cc.o
+
+.PHONY : gfile.o
+
+# target to build an object file
+gfile.cc.o:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f goo/CMakeFiles/goo_objs.dir/build.make goo/CMakeFiles/goo_objs.dir/gfile.cc.o
+.PHONY : gfile.cc.o
+
+gfile.i: gfile.cc.i
+
+.PHONY : gfile.i
+
+# target to preprocess a source file
+gfile.cc.i:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f goo/CMakeFiles/goo_objs.dir/build.make goo/CMakeFiles/goo_objs.dir/gfile.cc.i
+.PHONY : gfile.cc.i
+
+gfile.s: gfile.cc.s
+
+.PHONY : gfile.s
+
+# target to generate assembly for a file
+gfile.cc.s:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f goo/CMakeFiles/goo_objs.dir/build.make goo/CMakeFiles/goo_objs.dir/gfile.cc.s
+.PHONY : gfile.cc.s
+
+gmem.o: gmem.cc.o
+
+.PHONY : gmem.o
+
+# target to build an object file
+gmem.cc.o:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f goo/CMakeFiles/goo_objs.dir/build.make goo/CMakeFiles/goo_objs.dir/gmem.cc.o
+.PHONY : gmem.cc.o
+
+gmem.i: gmem.cc.i
+
+.PHONY : gmem.i
+
+# target to preprocess a source file
+gmem.cc.i:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f goo/CMakeFiles/goo_objs.dir/build.make goo/CMakeFiles/goo_objs.dir/gmem.cc.i
+.PHONY : gmem.cc.i
+
+gmem.s: gmem.cc.s
+
+.PHONY : gmem.s
+
+# target to generate assembly for a file
+gmem.cc.s:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f goo/CMakeFiles/goo_objs.dir/build.make goo/CMakeFiles/goo_objs.dir/gmem.cc.s
+.PHONY : gmem.cc.s
+
+gmempp.o: gmempp.cc.o
+
+.PHONY : gmempp.o
+
+# target to build an object file
+gmempp.cc.o:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f goo/CMakeFiles/goo_objs.dir/build.make goo/CMakeFiles/goo_objs.dir/gmempp.cc.o
+.PHONY : gmempp.cc.o
+
+gmempp.i: gmempp.cc.i
+
+.PHONY : gmempp.i
+
+# target to preprocess a source file
+gmempp.cc.i:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f goo/CMakeFiles/goo_objs.dir/build.make goo/CMakeFiles/goo_objs.dir/gmempp.cc.i
+.PHONY : gmempp.cc.i
+
+gmempp.s: gmempp.cc.s
+
+.PHONY : gmempp.s
+
+# target to generate assembly for a file
+gmempp.cc.s:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f goo/CMakeFiles/goo_objs.dir/build.make goo/CMakeFiles/goo_objs.dir/gmempp.cc.s
+.PHONY : gmempp.cc.s
+
+parseargs.o: parseargs.c.o
+
+.PHONY : parseargs.o
+
+# target to build an object file
+parseargs.c.o:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f goo/CMakeFiles/goo_objs.dir/build.make goo/CMakeFiles/goo_objs.dir/parseargs.c.o
+.PHONY : parseargs.c.o
+
+parseargs.i: parseargs.c.i
+
+.PHONY : parseargs.i
+
+# target to preprocess a source file
+parseargs.c.i:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f goo/CMakeFiles/goo_objs.dir/build.make goo/CMakeFiles/goo_objs.dir/parseargs.c.i
+.PHONY : parseargs.c.i
+
+parseargs.s: parseargs.c.s
+
+.PHONY : parseargs.s
+
+# target to generate assembly for a file
+parseargs.c.s:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f goo/CMakeFiles/goo_objs.dir/build.make goo/CMakeFiles/goo_objs.dir/parseargs.c.s
+.PHONY : parseargs.c.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 "... goo"
+ @echo "... goo_objs"
+ @echo "... FixedPoint.o"
+ @echo "... FixedPoint.i"
+ @echo "... FixedPoint.s"
+ @echo "... GHash.o"
+ @echo "... GHash.i"
+ @echo "... GHash.s"
+ @echo "... GList.o"
+ @echo "... GList.i"
+ @echo "... GList.s"
+ @echo "... GString.o"
+ @echo "... GString.i"
+ @echo "... GString.s"
+ @echo "... Trace.o"
+ @echo "... Trace.i"
+ @echo "... Trace.s"
+ @echo "... gfile.o"
+ @echo "... gfile.i"
+ @echo "... gfile.s"
+ @echo "... gmem.o"
+ @echo "... gmem.i"
+ @echo "... gmem.s"
+ @echo "... gmempp.o"
+ @echo "... gmempp.i"
+ @echo "... gmempp.s"
+ @echo "... parseargs.o"
+ @echo "... parseargs.i"
+ @echo "... parseargs.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/goo/Trace.cc b/goo/Trace.cc
new file mode 100644
index 0000000..4b730e5
--- /dev/null
+++ b/goo/Trace.cc
@@ -0,0 +1,114 @@
+//========================================================================
+//
+// Trace.cc
+//
+// Nested tracing.
+//
+// Copyright 2020 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <aconf.h>
+
+#if ENABLE_TRACING
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include "GString.h"
+#include "Trace.h"
+
+// NB: This module is NOT thread-safe.
+
+static bool traceInitialized = false;
+static FILE *traceOut = NULL;
+
+static void traceInit() {
+ if (traceInitialized) {
+ return;
+ }
+ //~ this could read an env var to set up an output file
+ GString *fileName = GString::format("/tmp/trace.{0:d}", (int)getpid());
+ traceOut = fopen(fileName->getCString(), "w");
+ delete fileName;
+ traceInitialized = true;
+}
+
+static void traceHeader(char flag, void *handle) {
+ timeval tv;
+ gettimeofday(&tv, NULL);
+ if (handle) {
+ fprintf(traceOut, "%c %ld %06ld %p ", flag, tv.tv_sec, tv.tv_usec, handle);
+ } else {
+ fprintf(traceOut, "%c %ld %06ld 0x0 ", flag, tv.tv_sec, tv.tv_usec);
+ }
+}
+
+void traceBegin(void *nestHandle, const char *fmt, ...) {
+ traceInit();
+ if (!traceOut) {
+ return;
+ }
+ traceHeader('B', nestHandle);
+ va_list args;
+ va_start(args, fmt);
+ vfprintf(traceOut, fmt, args);
+ va_end(args);
+ fprintf(traceOut, "\n");
+}
+
+void traceEnd(void *nestHandle, const char *fmt, ...) {
+ traceInit();
+ if (!traceOut) {
+ return;
+ }
+ traceHeader('E', nestHandle);
+ va_list args;
+ va_start(args, fmt);
+ vfprintf(traceOut, fmt, args);
+ va_end(args);
+ fprintf(traceOut, "\n");
+}
+
+void traceAlloc(void *resourceHandle, const char *fmt, ...) {
+ traceInit();
+ if (!traceOut) {
+ return;
+ }
+ traceHeader('A', resourceHandle);
+ va_list args;
+ va_start(args, fmt);
+ vfprintf(traceOut, fmt, args);
+ va_end(args);
+ fprintf(traceOut, "\n");
+}
+
+void traceFree(void *resourceHandle, const char *fmt, ...) {
+ traceInit();
+ if (!traceOut) {
+ return;
+ }
+ traceHeader('F', resourceHandle);
+ va_list args;
+ va_start(args, fmt);
+ vfprintf(traceOut, fmt, args);
+ va_end(args);
+ fprintf(traceOut, "\n");
+}
+
+void traceMessage(const char *fmt, ...) {
+ traceInit();
+ if (!traceOut) {
+ return;
+ }
+ traceHeader('M', NULL);
+ va_list args;
+ va_start(args, fmt);
+ vfprintf(traceOut, fmt, args);
+ va_end(args);
+ fprintf(traceOut, "\n");
+}
+
+#endif // ENABLE_TRACING
diff --git a/goo/Trace.h b/goo/Trace.h
new file mode 100644
index 0000000..9f53ac5
--- /dev/null
+++ b/goo/Trace.h
@@ -0,0 +1,43 @@
+//========================================================================
+//
+// Trace.h
+//
+// Nested tracing.
+//
+// Copyright 2020 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef TRACING_H
+#define TRACING_H
+
+#include <aconf.h>
+
+#if ENABLE_TRACING
+
+// Enter a nesting level.
+extern void traceBegin(void *nestHandle, const char *fmt, ...);
+
+// Exit a nesting level.
+extern void traceEnd(void *nestHandle, const char *fmt, ...);
+
+// Mark a resource as allocated.
+extern void traceAlloc(void *resourceHandle, const char *fmt, ...);
+
+// Mark a resource as freed.
+extern void traceFree(void *resourceHandle, const char *fmt, ...);
+
+// Misc message.
+extern void traceMessage(const char *fmt, ...);
+
+#else // ENABLE_TRACING
+
+static inline void traceBegin(void *nestHandle, const char *fmt, ...) {}
+static inline void traceEnd(void *nestHandle, const char *fmt, ...) {}
+static inline void traceAlloc(void *resourceHandle, const char *fmt, ...) {}
+static inline void traceFree(void *nestHandle, const char *fmt, ...) {}
+static inline void traceMessage(const char *fmt, ...) {}
+
+#endif // ENABLE_TRACING
+
+#endif // TRACING_H
diff --git a/goo/cmake_install.cmake b/goo/cmake_install.cmake
new file mode 100644
index 0000000..d9838e2
--- /dev/null
+++ b/goo/cmake_install.cmake
@@ -0,0 +1,44 @@
+# Install script for directory: /home/calvin/src/xpdf-4.04/goo
+
+# 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()
+
diff --git a/goo/gfile.cc b/goo/gfile.cc
new file mode 100644
index 0000000..9ec8bae
--- /dev/null
+++ b/goo/gfile.cc
@@ -0,0 +1,779 @@
+//========================================================================
+//
+// gfile.cc
+//
+// Miscellaneous file and directory name manipulation.
+//
+// Copyright 1996-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <aconf.h>
+
+#ifdef _WIN32
+# undef WIN32_LEAN_AND_MEAN
+# include <windows.h>
+# include <time.h>
+# include <direct.h>
+# include <shobjidl.h>
+# include <shlguid.h>
+#else
+# if !defined(ACORN)
+# include <sys/types.h>
+# include <sys/stat.h>
+# include <fcntl.h>
+# endif
+# include <time.h>
+# include <limits.h>
+# include <string.h>
+# if !defined(VMS) && !defined(ACORN)
+# include <pwd.h>
+# endif
+# if defined(VMS) && (__DECCXX_VER < 50200000)
+# include <unixlib.h>
+# endif
+#endif // _WIN32
+#include "gmem.h"
+#include "gmempp.h"
+#include "GString.h"
+#include "gfile.h"
+
+// Some systems don't define this, so just make it something reasonably
+// large.
+#ifndef PATH_MAX
+#define PATH_MAX 1024
+#endif
+
+//------------------------------------------------------------------------
+
+GString *getHomeDir() {
+#ifdef VMS
+ //---------- VMS ----------
+ return new GString("SYS$LOGIN:");
+
+#elif defined(_WIN32)
+ //---------- Win32 ----------
+ char *s;
+ GString *ret;
+
+ if ((s = getenv("USERPROFILE")))
+ ret = new GString(s);
+ else
+ ret = new GString(".");
+ return ret;
+
+#elif defined(__EMX__)
+ //---------- OS/2+EMX ----------
+ char *s;
+ GString *ret;
+
+ if ((s = getenv("HOME")))
+ ret = new GString(s);
+ else
+ ret = new GString(".");
+ return ret;
+
+#elif defined(ACORN)
+ //---------- RISCOS ----------
+ return new GString("@");
+
+#else
+ //---------- Unix ----------
+ char *s;
+ struct passwd *pw;
+ GString *ret;
+
+ if ((s = getenv("HOME"))) {
+ ret = new GString(s);
+ } else {
+ if ((s = getenv("USER")))
+ pw = getpwnam(s);
+ else
+ pw = getpwuid(getuid());
+ if (pw)
+ ret = new GString(pw->pw_dir);
+ else
+ ret = new GString(".");
+ }
+ return ret;
+#endif
+}
+
+GString *getCurrentDir() {
+ char buf[PATH_MAX+1];
+
+#if defined(__EMX__)
+ if (_getcwd2(buf, sizeof(buf)))
+#elif defined(_WIN32)
+ if (GetCurrentDirectoryA(sizeof(buf), buf))
+#elif defined(ACORN)
+ if (strcpy(buf, "@"))
+#else
+ if (getcwd(buf, sizeof(buf)))
+#endif
+ return new GString(buf);
+ return new GString();
+}
+
+GString *appendToPath(GString *path, const char *fileName) {
+#if defined(VMS)
+ //---------- VMS ----------
+ //~ this should handle everything necessary for file
+ //~ requesters, but it's certainly not complete
+ char *p0, *p1, *p2;
+ char *q1;
+
+ p0 = path->getCString();
+ p1 = p0 + path->getLength() - 1;
+ if (!strcmp(fileName, "-")) {
+ if (*p1 == ']') {
+ for (p2 = p1; p2 > p0 && *p2 != '.' && *p2 != '['; --p2) ;
+ if (*p2 == '[')
+ ++p2;
+ path->del(p2 - p0, p1 - p2);
+ } else if (*p1 == ':') {
+ path->append("[-]");
+ } else {
+ path->clear();
+ path->append("[-]");
+ }
+ } else if ((q1 = strrchr(fileName, '.')) && !strncmp(q1, ".DIR;", 5)) {
+ if (*p1 == ']') {
+ path->insert(p1 - p0, '.');
+ path->insert(p1 - p0 + 1, fileName, q1 - fileName);
+ } else if (*p1 == ':') {
+ path->append('[');
+ path->append(']');
+ path->append(fileName, q1 - fileName);
+ } else {
+ path->clear();
+ path->append(fileName, q1 - fileName);
+ }
+ } else {
+ if (*p1 != ']' && *p1 != ':')
+ path->clear();
+ path->append(fileName);
+ }
+ return path;
+
+#elif defined(_WIN32)
+ //---------- Win32 ----------
+ GString *tmp;
+ char buf[256];
+ char *fp;
+
+ tmp = new GString(path);
+ tmp->append('/');
+ tmp->append(fileName);
+ GetFullPathNameA(tmp->getCString(), sizeof(buf), buf, &fp);
+ delete tmp;
+ path->clear();
+ path->append(buf);
+ return path;
+
+#elif defined(ACORN)
+ //---------- RISCOS ----------
+ char *p;
+ int i;
+
+ path->append(".");
+ i = path->getLength();
+ path->append(fileName);
+ for (p = path->getCString() + i; *p; ++p) {
+ if (*p == '/') {
+ *p = '.';
+ } else if (*p == '.') {
+ *p = '/';
+ }
+ }
+ return path;
+
+#elif defined(__EMX__)
+ //---------- OS/2+EMX ----------
+ int i;
+
+ // appending "." does nothing
+ if (!strcmp(fileName, "."))
+ return path;
+
+ // appending ".." goes up one directory
+ if (!strcmp(fileName, "..")) {
+ for (i = path->getLength() - 2; i >= 0; --i) {
+ if (path->getChar(i) == '/' || path->getChar(i) == '\\' ||
+ path->getChar(i) == ':')
+ break;
+ }
+ if (i <= 0) {
+ if (path->getChar(0) == '/' || path->getChar(0) == '\\') {
+ path->del(1, path->getLength() - 1);
+ } else if (path->getLength() >= 2 && path->getChar(1) == ':') {
+ path->del(2, path->getLength() - 2);
+ } else {
+ path->clear();
+ path->append("..");
+ }
+ } else {
+ if (path->getChar(i-1) == ':')
+ ++i;
+ path->del(i, path->getLength() - i);
+ }
+ return path;
+ }
+
+ // otherwise, append "/" and new path component
+ if (path->getLength() > 0 &&
+ path->getChar(path->getLength() - 1) != '/' &&
+ path->getChar(path->getLength() - 1) != '\\')
+ path->append('/');
+ path->append(fileName);
+ return path;
+
+#else
+ //---------- Unix ----------
+ int i;
+
+ // appending "." does nothing
+ if (!strcmp(fileName, "."))
+ return path;
+
+ // appending ".." goes up one directory
+ if (!strcmp(fileName, "..")) {
+ for (i = path->getLength() - 2; i >= 0; --i) {
+ if (path->getChar(i) == '/')
+ break;
+ }
+ if (i <= 0) {
+ if (path->getChar(0) == '/') {
+ path->del(1, path->getLength() - 1);
+ } else {
+ path->clear();
+ path->append("..");
+ }
+ } else {
+ path->del(i, path->getLength() - i);
+ }
+ return path;
+ }
+
+ // otherwise, append "/" and new path component
+ if (path->getLength() > 0 &&
+ path->getChar(path->getLength() - 1) != '/')
+ path->append('/');
+ path->append(fileName);
+ return path;
+#endif
+}
+
+GString *grabPath(char *fileName) {
+#ifdef VMS
+ //---------- VMS ----------
+ char *p;
+
+ if ((p = strrchr(fileName, ']')))
+ return new GString(fileName, p + 1 - fileName);
+ if ((p = strrchr(fileName, ':')))
+ return new GString(fileName, p + 1 - fileName);
+ return new GString();
+
+#elif defined(__EMX__) || defined(_WIN32)
+ //---------- OS/2+EMX and Win32 ----------
+ char *p;
+
+ if ((p = strrchr(fileName, '/')))
+ return new GString(fileName, (int)(p - fileName));
+ if ((p = strrchr(fileName, '\\')))
+ return new GString(fileName, (int)(p - fileName));
+ if ((p = strrchr(fileName, ':')))
+ return new GString(fileName, (int)(p + 1 - fileName));
+ return new GString();
+
+#elif defined(ACORN)
+ //---------- RISCOS ----------
+ char *p;
+
+ if ((p = strrchr(fileName, '.')))
+ return new GString(fileName, p - fileName);
+ return new GString();
+
+#else
+ //---------- Unix ----------
+ char *p;
+
+ if ((p = strrchr(fileName, '/')))
+ return new GString(fileName, (int)(p - fileName));
+ return new GString();
+#endif
+}
+
+GBool isAbsolutePath(char *path) {
+#ifdef VMS
+ //---------- VMS ----------
+ return strchr(path, ':') ||
+ (path[0] == '[' && path[1] != '.' && path[1] != '-');
+
+#elif defined(__EMX__) || defined(_WIN32)
+ //---------- OS/2+EMX and Win32 ----------
+ return path[0] == '/' || path[0] == '\\' || path[1] == ':';
+
+#elif defined(ACORN)
+ //---------- RISCOS ----------
+ return path[0] == '$';
+
+#else
+ //---------- Unix ----------
+ return path[0] == '/';
+#endif
+}
+
+GString *makePathAbsolute(GString *path) {
+#ifdef VMS
+ //---------- VMS ----------
+ char buf[PATH_MAX+1];
+
+ if (!isAbsolutePath(path->getCString())) {
+ if (getcwd(buf, sizeof(buf))) {
+ path->insert(0, buf);
+ }
+ }
+ return path;
+
+#elif defined(_WIN32)
+ //---------- Win32 ----------
+ char buf[MAX_PATH];
+ char *fp;
+
+ buf[0] = '\0';
+ if (!GetFullPathNameA(path->getCString(), MAX_PATH, buf, &fp)) {
+ path->clear();
+ return path;
+ }
+ path->clear();
+ path->append(buf);
+ return path;
+
+#elif defined(ACORN)
+ //---------- RISCOS ----------
+ path->insert(0, '@');
+ return path;
+
+#else
+ //---------- Unix and OS/2+EMX ----------
+ struct passwd *pw;
+ char buf[PATH_MAX+1];
+ GString *s;
+ char *p1, *p2;
+ int n;
+
+ if (path->getChar(0) == '~') {
+ if (path->getChar(1) == '/' ||
+#ifdef __EMX__
+ path->getChar(1) == '\\' ||
+#endif
+ path->getLength() == 1) {
+ path->del(0, 1);
+ s = getHomeDir();
+ path->insert(0, s);
+ delete s;
+ } else {
+ p1 = path->getCString() + 1;
+#ifdef __EMX__
+ for (p2 = p1; *p2 && *p2 != '/' && *p2 != '\\'; ++p2) ;
+#else
+ for (p2 = p1; *p2 && *p2 != '/'; ++p2) ;
+#endif
+ if ((n = (int)(p2 - p1)) > PATH_MAX)
+ n = PATH_MAX;
+ strncpy(buf, p1, n);
+ buf[n] = '\0';
+ if ((pw = getpwnam(buf))) {
+ path->del(0, (int)(p2 - p1 + 1));
+ path->insert(0, pw->pw_dir);
+ }
+ }
+ } else if (!isAbsolutePath(path->getCString())) {
+ if (getcwd(buf, sizeof(buf))) {
+#ifndef __EMX__
+ path->insert(0, '/');
+#endif
+ path->insert(0, buf);
+ }
+ }
+ return path;
+#endif
+}
+
+GBool pathIsFile(const char *path) {
+#ifdef _WIN32
+ wchar_t wPath[winMaxLongPath + 1];
+ fileNameToUCS2(path, wPath, winMaxLongPath + 1);
+ DWORD attr = GetFileAttributesW(wPath);
+ return attr != INVALID_FILE_ATTRIBUTES &&
+ !(attr & (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_DEVICE));
+#else
+ struct stat statBuf;
+ return stat(path, &statBuf) == 0 && S_ISREG(statBuf.st_mode);
+#endif
+}
+
+time_t getModTime(char *fileName) {
+#ifdef _WIN32
+ //~ should implement this, but it's (currently) only used in xpdf
+ return 0;
+#else
+ struct stat statBuf;
+
+ if (stat(fileName, &statBuf)) {
+ return 0;
+ }
+ return statBuf.st_mtime;
+#endif
+}
+
+GBool openTempFile(GString **name, FILE **f,
+ const char *mode, const char *ext) {
+#if defined(_WIN32)
+ //---------- Win32 ----------
+ char tempPath[MAX_PATH + 1];
+ GString *s, *s2;
+ FILE *f2;
+ DWORD n;
+ int t, i;
+
+ // this has the standard race condition problem, but I haven't found
+ // a better way to generate temp file names with extensions on
+ // Windows
+ n = GetTempPathA(sizeof(tempPath), tempPath);
+ if (n > 0 && n <= sizeof(tempPath)) {
+ s = new GString(tempPath);
+ if (tempPath[n-1] != '\\') {
+ s->append('\\');
+ }
+ } else {
+ s = new GString(".\\");
+ }
+ s->appendf("xpdf_{0:d}_{1:d}_",
+ (int)GetCurrentProcessId(), (int)GetCurrentThreadId());
+ t = (int)time(NULL);
+ for (i = 0; i < 1000; ++i) {
+ s2 = GString::format("{0:t}{1:d}", s, t + i);
+ if (ext) {
+ s2->append(ext);
+ }
+ if (!(f2 = fopen(s2->getCString(), "r"))) {
+ if (!(f2 = fopen(s2->getCString(), mode))) {
+ delete s2;
+ delete s;
+ return gFalse;
+ }
+ *name = s2;
+ *f = f2;
+ delete s;
+ return gTrue;
+ }
+ fclose(f2);
+ delete s2;
+ }
+ delete s;
+ return gFalse;
+#elif defined(VMS) || defined(__EMX__) || defined(ACORN)
+ //---------- non-Unix ----------
+ char *s;
+
+ // There is a security hole here: an attacker can create a symlink
+ // with this file name after the tmpnam call and before the fopen
+ // call. I will happily accept fixes to this function for non-Unix
+ // OSs.
+ if (!(s = tmpnam(NULL))) {
+ return gFalse;
+ }
+ *name = new GString(s);
+ if (ext) {
+ (*name)->append(ext);
+ }
+ if (!(*f = fopen((*name)->getCString(), mode))) {
+ delete (*name);
+ *name = NULL;
+ return gFalse;
+ }
+ return gTrue;
+#else
+ //---------- Unix ----------
+ char *s;
+ int fd;
+
+ if (ext) {
+#if HAVE_MKSTEMPS
+ if ((s = getenv("TMPDIR"))) {
+ *name = new GString(s);
+ } else {
+ *name = new GString("/tmp");
+ }
+ (*name)->append("/XXXXXX")->append(ext);
+ fd = mkstemps((*name)->getCString(), (int)strlen(ext));
+#else
+ if (!(s = tmpnam(NULL))) {
+ return gFalse;
+ }
+ *name = new GString(s);
+ (*name)->append(ext);
+ fd = open((*name)->getCString(), O_WRONLY | O_CREAT | O_EXCL, 0600);
+#endif
+ } else {
+#if HAVE_MKSTEMP
+ if ((s = getenv("TMPDIR"))) {
+ *name = new GString(s);
+ } else {
+ *name = new GString("/tmp");
+ }
+ (*name)->append("/XXXXXX");
+ fd = mkstemp((*name)->getCString());
+#else // HAVE_MKSTEMP
+ if (!(s = tmpnam(NULL))) {
+ return gFalse;
+ }
+ *name = new GString(s);
+ fd = open((*name)->getCString(), O_WRONLY | O_CREAT | O_EXCL, 0600);
+#endif // HAVE_MKSTEMP
+ }
+ if (fd < 0 || !(*f = fdopen(fd, mode))) {
+ delete *name;
+ *name = NULL;
+ return gFalse;
+ }
+ return gTrue;
+#endif
+}
+
+GBool createDir(char *path, int mode) {
+#ifdef _WIN32
+ return !_mkdir(path);
+#else
+ return !mkdir(path, mode);
+#endif
+}
+
+GBool executeCommand(char *cmd) {
+#ifdef VMS
+ return system(cmd) ? gTrue : gFalse;
+#else
+ return system(cmd) ? gFalse : gTrue;
+#endif
+}
+
+#ifdef _WIN32
+GString *fileNameToUTF8(char *path) {
+ GString *s;
+ char *p;
+
+ s = new GString();
+ for (p = path; *p; ++p) {
+ if (*p & 0x80) {
+ s->append((char)(0xc0 | ((*p >> 6) & 0x03)));
+ s->append((char)(0x80 | (*p & 0x3f)));
+ } else {
+ s->append(*p);
+ }
+ }
+ return s;
+}
+
+GString *fileNameToUTF8(wchar_t *path) {
+ GString *s;
+ wchar_t *p;
+
+ s = new GString();
+ for (p = path; *p; ++p) {
+ if (*p < 0x80) {
+ s->append((char)*p);
+ } else if (*p < 0x800) {
+ s->append((char)(0xc0 | ((*p >> 6) & 0x1f)));
+ s->append((char)(0x80 | (*p & 0x3f)));
+ } else {
+ s->append((char)(0xe0 | ((*p >> 12) & 0x0f)));
+ s->append((char)(0x80 | ((*p >> 6) & 0x3f)));
+ s->append((char)(0x80 | (*p & 0x3f)));
+ }
+ }
+ return s;
+}
+
+wchar_t *fileNameToUCS2(const char *path, wchar_t *out, size_t outSize) {
+ const char *p;
+ size_t i;
+
+ for (p = path, i = 0; *p && i < outSize - 1; ++i) {
+ if ((p[0] & 0xe0) == 0xc0 &&
+ p[1] && (p[1] & 0xc0) == 0x80) {
+ out[i] = (wchar_t)(((p[0] & 0x1f) << 6) |
+ (p[1] & 0x3f));
+ p += 2;
+ } else if ((p[0] & 0xf0) == 0xe0 &&
+ (p[1] & 0xc0) == 0x80 &&
+ (p[2] & 0xc0) == 0x80) {
+ out[i] = (wchar_t)(((p[0] & 0x0f) << 12) |
+ ((p[1] & 0x3f) << 6) |
+ (p[2] & 0x3f));
+ p += 3;
+ } else {
+ out[i] = (wchar_t)(p[0] & 0xff);
+ p += 1;
+ }
+ }
+ out[i] = (wchar_t)0;
+ return out;
+}
+#endif
+
+FILE *openFile(const char *path, const char *mode) {
+#if defined(_WIN32)
+ wchar_t wPath[winMaxLongPath + 1];
+ wchar_t wMode[8];
+ int i;
+
+ fileNameToUCS2(path, wPath, winMaxLongPath + 1);
+ for (i = 0; mode[i] && i < sizeof(wMode)/sizeof(wchar_t) - 1; ++i) {
+ wMode[i] = (wchar_t)(mode[i] & 0xff);
+ }
+ wMode[i] = (wchar_t)0;
+ readWindowsShortcut(wPath, winMaxLongPath + 1);
+ return _wfopen(wPath, wMode);
+#elif defined(VMS)
+ return fopen(path, mode, "ctx=stm");
+#else
+ return fopen(path, mode);
+#endif
+}
+
+#ifdef _WIN32
+void readWindowsShortcut(wchar_t *wPath, size_t wPathSize) {
+ size_t n = wcslen(wPath);
+ if (n < 4 || wcscmp(wPath + n - 4, L".lnk")) {
+ return;
+ }
+ IShellLinkW *shellLink;
+ HRESULT hres;
+ hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
+ IID_IShellLinkW, (LPVOID *)&shellLink);
+ bool needCoUninit = false;
+ if (hres == CO_E_NOTINITIALIZED) {
+ CoInitialize(NULL);
+ needCoUninit = true;
+ hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
+ IID_IShellLinkW, (LPVOID *)&shellLink);
+ }
+ if (FAILED(hres)) {
+ return;
+ }
+ IPersistFile *persistFile;
+ hres = shellLink->QueryInterface(IID_IPersistFile, (LPVOID *)&persistFile);
+ if (FAILED(hres)) {
+ return;
+ }
+ hres = persistFile->Load(wPath, STGM_READ);
+ if (FAILED(hres)) {
+ fprintf(stderr, "IPersistFile.Load failed: 0x%08x\n", hres);
+ exit(1);
+ }
+ wchar_t target[winMaxLongPath + 1];
+ hres = shellLink->GetPath(target, winMaxLongPath + 1, NULL, 0);
+ if (FAILED(hres)) {
+ return;
+ }
+ shellLink->Release();
+ if (needCoUninit) {
+ CoUninitialize();
+ }
+ if (wcslen(target) > wPathSize - 1) {
+ return;
+ }
+ wcscpy(wPath, target);
+}
+#endif
+
+int makeDir(const char *path, int mode) {
+#ifdef _WIN32
+ wchar_t wPath[winMaxLongPath + 1];
+ return _wmkdir(fileNameToUCS2(path, wPath, winMaxLongPath + 1));
+#else
+ return mkdir(path, (mode_t)mode);
+#endif
+}
+
+char *getLine(char *buf, int size, FILE *f) {
+ int c, i;
+
+ i = 0;
+ while (i < size - 1) {
+ if ((c = fgetc(f)) == EOF) {
+ break;
+ }
+ buf[i++] = (char)c;
+ if (c == '\x0a') {
+ break;
+ }
+ if (c == '\x0d') {
+ c = fgetc(f);
+ if (c == '\x0a' && i < size - 1) {
+ buf[i++] = (char)c;
+ } else if (c != EOF) {
+ ungetc(c, f);
+ }
+ break;
+ }
+ }
+ buf[i] = '\0';
+ if (i == 0) {
+ return NULL;
+ }
+ return buf;
+}
+
+int gfseek(FILE *f, GFileOffset offset, int whence) {
+#if HAVE_FSEEKO
+ return fseeko(f, offset, whence);
+#elif HAVE_FSEEK64
+ return fseek64(f, offset, whence);
+#elif HAVE_FSEEKI64
+ return _fseeki64(f, offset, whence);
+#else
+ return fseek(f, offset, whence);
+#endif
+}
+
+GFileOffset gftell(FILE *f) {
+#if HAVE_FSEEKO
+ return ftello(f);
+#elif HAVE_FSEEK64
+ return ftell64(f);
+#elif HAVE_FSEEKI64
+ return _ftelli64(f);
+#else
+ return ftell(f);
+#endif
+}
+
+void fixCommandLine(int *argc, char **argv[]) {
+#ifdef _WIN32
+ int argcw;
+ wchar_t **argvw;
+ GString *arg;
+ int i;
+
+ argvw = CommandLineToArgvW(GetCommandLineW(), &argcw);
+ if (!argvw || argcw < 0) {
+ return;
+ }
+
+ *argc = argcw;
+
+ *argv = (char **)gmallocn(argcw + 1, sizeof(char *));
+ for (i = 0; i < argcw; ++i) {
+ arg = fileNameToUTF8(argvw[i]);
+ (*argv)[i] = copyString(arg->getCString());
+ delete arg;
+ }
+ (*argv)[argcw] = NULL;
+
+ LocalFree(argvw);
+#endif
+}
diff --git a/goo/gfile.h b/goo/gfile.h
new file mode 100644
index 0000000..202e6ee
--- /dev/null
+++ b/goo/gfile.h
@@ -0,0 +1,144 @@
+//========================================================================
+//
+// gfile.h
+//
+// Miscellaneous file and directory name manipulation.
+//
+// Copyright 1996-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef GFILE_H
+#define GFILE_H
+
+#include <aconf.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#if defined(_WIN32)
+# include <sys/stat.h>
+# ifdef FPTEX
+# include <win32lib.h>
+# else
+# include <windows.h>
+# endif
+#elif defined(ACORN)
+#elif defined(ANDROID)
+#else
+# include <unistd.h>
+# include <sys/types.h>
+#endif
+#include "gtypes.h"
+
+// Windows 10 supports long paths - with a registry setting, and only
+// with Unicode (...W) functions.
+#ifdef _WIN32
+# define winMaxLongPath 32767
+#endif
+
+class GString;
+
+//------------------------------------------------------------------------
+
+// Get home directory path.
+extern GString *getHomeDir();
+
+// Get current directory.
+extern GString *getCurrentDir();
+
+// Append a file name to a path string. <path> may be an empty
+// string, denoting the current directory). Returns <path>.
+extern GString *appendToPath(GString *path, const char *fileName);
+
+// Grab the path from the front of the file name. If there is no
+// directory component in <fileName>, returns an empty string.
+extern GString *grabPath(char *fileName);
+
+// Is this an absolute path or file name?
+extern GBool isAbsolutePath(char *path);
+
+// Make this path absolute by prepending current directory (if path is
+// relative) or prepending user's directory (if path starts with '~').
+extern GString *makePathAbsolute(GString *path);
+
+// Returns true if [path] exists and is a regular file.
+extern GBool pathIsFile(const char *path);
+
+// Get the modification time for <fileName>. Returns 0 if there is an
+// error.
+extern time_t getModTime(char *fileName);
+
+// Create a temporary file and open it for writing. If <ext> is not
+// NULL, it will be used as the file name extension. Returns both the
+// name and the file pointer. For security reasons, all writing
+// should be done to the returned file pointer; the file may be
+// reopened later for reading, but not for writing. The <mode> string
+// should be "w" or "wb". Returns true on success.
+extern GBool openTempFile(GString **name, FILE **f,
+ const char *mode, const char *ext);
+
+// Create a directory. Returns true on success.
+extern GBool createDir(char *path, int mode);
+
+// Execute <command>. Returns true on success.
+extern GBool executeCommand(char *cmd);
+
+#ifdef _WIN32
+// Convert a file name from Latin-1 to UTF-8.
+extern GString *fileNameToUTF8(char *path);
+
+// Convert a file name from UCS-2 to UTF-8.
+extern GString *fileNameToUTF8(wchar_t *path);
+
+// Convert a file name from UTF-8 to UCS-2. [out] has space for
+// [outSize] wchar_t elements (including the trailing zero). Returns
+// [out].
+extern wchar_t *fileNameToUCS2(const char *path, wchar_t *out, size_t outSize);
+#endif
+
+// Open a file. On Windows, this converts the path from UTF-8 to
+// UCS-2 and calls _wfopen(). On other OSes, this simply calls fopen().
+extern FILE *openFile(const char *path, const char *mode);
+
+#ifdef _WIN32
+// If [wPath] is a Windows shortcut (.lnk file), read the target path
+// and store it back into [wPath].
+extern void readWindowsShortcut(wchar_t *wPath, size_t wPathSize);
+#endif
+
+// Create a directory. On Windows, this converts the path from UTF-8
+// to UCS-2 and calls _wmkdir(), ignoring the mode argument. On other
+// OSes, this simply calls mkdir().
+extern int makeDir(const char *path, int mode);
+
+// Just like fgets, but handles Unix, Mac, and/or DOS end-of-line
+// conventions.
+extern char *getLine(char *buf, int size, FILE *f);
+
+// Type used by gfseek/gftell for file offsets. This will be 64 bits
+// on systems that support it.
+#if HAVE_FSEEKO
+typedef off_t GFileOffset;
+#define GFILEOFFSET_MAX 0x7fffffffffffffffLL
+#elif HAVE_FSEEK64
+typedef long long GFileOffset;
+#define GFILEOFFSET_MAX 0x7fffffffffffffffLL
+#elif HAVE_FSEEKI64
+typedef __int64 GFileOffset;
+#define GFILEOFFSET_MAX 0x7fffffffffffffffLL
+#else
+typedef long GFileOffset;
+#define GFILEOFFSET_MAX LONG_MAX
+#endif
+
+// Like fseek, but uses a 64-bit file offset if available.
+extern int gfseek(FILE *f, GFileOffset offset, int whence);
+
+// Like ftell, but returns a 64-bit file offset if available.
+extern GFileOffset gftell(FILE *f);
+
+// On Windows, this gets the Unicode command line and converts it to
+// UTF-8. On other systems, this is a nop.
+extern void fixCommandLine(int *argc, char **argv[]);
+
+#endif
diff --git a/goo/gmem.cc b/goo/gmem.cc
new file mode 100644
index 0000000..7291f20
--- /dev/null
+++ b/goo/gmem.cc
@@ -0,0 +1,396 @@
+/*
+ * gmem.c
+ *
+ * Memory routines with out-of-memory checking.
+ *
+ * Copyright 1996-2003 Glyph & Cog, LLC
+ */
+
+#include <aconf.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+// older compilers won't define SIZE_MAX in stdint.h without this
+#ifndef __STDC_LIMIT_MACROS
+# define __STDC_LIMIT_MACROS 1
+#endif
+#include <stdint.h>
+#include <string.h>
+#include <limits.h>
+#if MULTITHREADED && defined(_WIN32)
+# include <windows.h>
+#endif
+#include "gmem.h"
+
+#ifdef DEBUG_MEM
+
+typedef struct _GMemHdr {
+ unsigned int magic;
+ int index;
+ size_t size;
+ struct _GMemHdr *next, *prev;
+} GMemHdr;
+
+#define gMemHdrSize ((sizeof(GMemHdr) + 7) & ~7)
+#define gMemTrlSize (sizeof(long))
+
+#define gMemMagic 0xabcd9999
+
+#if ULONG_MAX > 0xffffffffL
+#define gMemDeadVal 0xdeadbeefdeadbeefUL
+#else
+#define gMemDeadVal 0xdeadbeefUL
+#endif
+
+/* round data size so trailer will be aligned */
+#define gMemDataSize(size) \
+ (int)(((((size) + gMemTrlSize - 1) / gMemTrlSize) * gMemTrlSize))
+
+#define gMemDataSize64(size) \
+ (size_t)(((((size) + gMemTrlSize - 1) / gMemTrlSize) * gMemTrlSize))
+
+static GMemHdr *gMemHead = NULL;
+static GMemHdr *gMemTail = NULL;
+
+static int gMemIndex = 0;
+static int gMemAlloc = 0;
+static size_t gMemInUse = 0;
+static size_t gMaxMemInUse = 0;
+
+#if MULTITHREADED
+# ifdef _WIN32
+ static CRITICAL_SECTION gMemMutex;
+ static INIT_ONCE gMemMutexInitStruct = INIT_ONCE_STATIC_INIT;
+ static BOOL CALLBACK gMemMutexInitFunc(PINIT_ONCE initOnce, PVOID param,
+ PVOID *context) {
+ InitializeCriticalSection(&gMemMutex);
+ return TRUE;
+ }
+# define gMemInitMutex InitOnceExecuteOnce(&gMemMutexInitStruct, \
+ &gMemMutexInitFunc, NULL, NULL)
+# define gMemLock EnterCriticalSection(&gMemMutex);
+# define gMemUnlock LeaveCriticalSection(&gMemMutex);
+# else
+# include <pthread.h>
+ static pthread_mutex_t gMemMutex = PTHREAD_MUTEX_INITIALIZER;
+# define gMemInitMutex
+# define gMemLock pthread_mutex_lock(&gMemMutex)
+# define gMemUnlock pthread_mutex_unlock(&gMemMutex)
+# endif
+#else
+# define gMemInitMutex
+# define gMemLock
+# define gMemUnlock
+#endif
+
+#endif /* DEBUG_MEM */
+
+#ifdef DEBUG_MEM
+void *gmalloc(int size, int ignore) GMEM_EXCEP {
+ int size1;
+ char *mem;
+ GMemHdr *hdr;
+ void *data;
+ unsigned long *trl, *p;
+
+ gMemInitMutex;
+ if (size < 0) {
+ gMemError("Invalid memory allocation size");
+ }
+ if (size == 0) {
+ return NULL;
+ }
+ size1 = gMemDataSize(size);
+ if (!(mem = (char *)malloc(size1 + gMemHdrSize + gMemTrlSize))) {
+ gMemError("Out of memory");
+ }
+ hdr = (GMemHdr *)mem;
+ data = (void *)(mem + gMemHdrSize);
+ trl = (unsigned long *)(mem + gMemHdrSize + size1);
+ hdr->magic = gMemMagic;
+ hdr->size = size;
+ gMemLock;
+ if (ignore) {
+ hdr->index = -1;
+ } else {
+ hdr->index = gMemIndex++;
+ }
+ if (gMemTail) {
+ gMemTail->next = hdr;
+ hdr->prev = gMemTail;
+ gMemTail = hdr;
+ } else {
+ hdr->prev = NULL;
+ gMemHead = gMemTail = hdr;
+ }
+ hdr->next = NULL;
+ ++gMemAlloc;
+ gMemInUse += size;
+ if (gMemInUse > gMaxMemInUse) {
+ gMaxMemInUse = gMemInUse;
+ }
+ gMemUnlock;
+ for (p = (unsigned long *)data; p <= trl; ++p) {
+ *p = gMemDeadVal;
+ }
+ return data;
+}
+#else
+void *gmalloc(int size) GMEM_EXCEP {
+ void *p;
+
+ if (size < 0) {
+ gMemError("Invalid memory allocation size");
+ }
+ if (size == 0) {
+ return NULL;
+ }
+ if (!(p = malloc(size))) {
+ gMemError("Out of memory");
+ }
+ return p;
+}
+#endif
+
+void *grealloc(void *p, int size) GMEM_EXCEP {
+#ifdef DEBUG_MEM
+ GMemHdr *hdr;
+ void *q;
+ int oldSize;
+
+ if (size < 0) {
+ gMemError("Invalid memory allocation size");
+ }
+ if (size == 0) {
+ if (p) {
+ gfree(p);
+ }
+ return NULL;
+ }
+ if (p) {
+ hdr = (GMemHdr *)((char *)p - gMemHdrSize);
+ oldSize = (int)hdr->size;
+ q = gmalloc(size);
+ memcpy(q, p, size < oldSize ? size : oldSize);
+ gfree(p);
+ } else {
+ q = gmalloc(size);
+ }
+ return q;
+#else
+ void *q;
+
+ if (size < 0) {
+ gMemError("Invalid memory allocation size");
+ }
+ if (size == 0) {
+ if (p) {
+ free(p);
+ }
+ return NULL;
+ }
+ if (p) {
+ q = realloc(p, size);
+ } else {
+ q = malloc(size);
+ }
+ if (!q) {
+ gMemError("Out of memory");
+ }
+ return q;
+#endif
+}
+
+void *gmallocn(int nObjs, int objSize) GMEM_EXCEP {
+ int n;
+
+ if (nObjs == 0) {
+ return NULL;
+ }
+ n = nObjs * objSize;
+ if (objSize <= 0 || nObjs < 0 || nObjs >= INT_MAX / objSize) {
+ gMemError("Bogus memory allocation size");
+ }
+ return gmalloc(n);
+}
+
+#ifdef DEBUG_MEM
+void *gmalloc64(size_t size, int ignore) GMEM_EXCEP {
+ size_t size1;
+ char *mem;
+ GMemHdr *hdr;
+ void *data;
+ unsigned long *trl, *p;
+
+ gMemInitMutex;
+ if (size == 0) {
+ return NULL;
+ }
+ size1 = gMemDataSize64(size);
+ if (!(mem = (char *)malloc(size1 + gMemHdrSize + gMemTrlSize))) {
+ gMemError("Out of memory");
+ }
+ hdr = (GMemHdr *)mem;
+ data = (void *)(mem + gMemHdrSize);
+ trl = (unsigned long *)(mem + gMemHdrSize + size1);
+ hdr->magic = gMemMagic;
+ hdr->size = size;
+ gMemLock;
+ if (ignore) {
+ hdr->index = -1;
+ } else {
+ hdr->index = gMemIndex++;
+ }
+ if (gMemTail) {
+ gMemTail->next = hdr;
+ hdr->prev = gMemTail;
+ gMemTail = hdr;
+ } else {
+ hdr->prev = NULL;
+ gMemHead = gMemTail = hdr;
+ }
+ hdr->next = NULL;
+ ++gMemAlloc;
+ gMemInUse += size;
+ if (gMemInUse > gMaxMemInUse) {
+ gMaxMemInUse = gMemInUse;
+ }
+ gMemUnlock;
+ for (p = (unsigned long *)data; p <= trl; ++p) {
+ *p = gMemDeadVal;
+ }
+ return data;
+}
+#else
+void *gmalloc64(size_t size) GMEM_EXCEP {
+ void *p;
+
+ if (size == 0) {
+ return NULL;
+ }
+ if (!(p = malloc(size))) {
+ gMemError("Out of memory");
+ }
+ return p;
+}
+#endif
+
+void *gmallocn64(int nObjs, size_t objSize) GMEM_EXCEP {
+ size_t n;
+
+ if (nObjs == 0) {
+ return NULL;
+ }
+ n = nObjs * objSize;
+ if (nObjs < 0 || (size_t)nObjs >= SIZE_MAX / objSize) {
+ gMemError("Bogus memory allocation size");
+ }
+ return gmalloc64(n);
+}
+
+void *greallocn(void *p, int nObjs, int objSize) GMEM_EXCEP {
+ int n;
+
+ if (nObjs == 0) {
+ if (p) {
+ gfree(p);
+ }
+ return NULL;
+ }
+ n = nObjs * objSize;
+ if (objSize <= 0 || nObjs < 0 || nObjs >= INT_MAX / objSize) {
+ gMemError("Bogus memory allocation size");
+ }
+ return grealloc(p, n);
+}
+
+void gfree(void *p) {
+#ifdef DEBUG_MEM
+ size_t size;
+ GMemHdr *hdr;
+ unsigned long *trl, *clr;
+
+ if (p) {
+ hdr = (GMemHdr *)((char *)p - gMemHdrSize);
+ gMemLock;
+ if (hdr->magic == gMemMagic &&
+ ((hdr->prev == NULL) == (hdr == gMemHead)) &&
+ ((hdr->next == NULL) == (hdr == gMemTail))) {
+ if (hdr->prev) {
+ hdr->prev->next = hdr->next;
+ } else {
+ gMemHead = hdr->next;
+ }
+ if (hdr->next) {
+ hdr->next->prev = hdr->prev;
+ } else {
+ gMemTail = hdr->prev;
+ }
+ --gMemAlloc;
+ gMemInUse -= hdr->size;
+ gMemUnlock;
+ size = gMemDataSize64(hdr->size);
+ trl = (unsigned long *)((char *)hdr + gMemHdrSize + size);
+ if (*trl != gMemDeadVal) {
+ fprintf(stderr, "Overwrite past end of block %d at address %p\n",
+ hdr->index, p);
+ }
+ for (clr = (unsigned long *)hdr; clr <= trl; ++clr) {
+ *clr = gMemDeadVal;
+ }
+ free(hdr);
+ } else {
+ gMemUnlock;
+ fprintf(stderr, "Attempted to free bad address %p\n", p);
+ }
+ }
+#else
+ if (p) {
+ free(p);
+ }
+#endif
+}
+
+void gMemError(const char *msg) GMEM_EXCEP {
+#if USE_EXCEPTIONS
+ throw GMemException();
+#else
+ fprintf(stderr, "%s\n", msg);
+ exit(1);
+#endif
+}
+
+#ifdef DEBUG_MEM
+void gMemReport(FILE *f) {
+ GMemHdr *p;
+ int left;
+
+ fprintf(f, "%d memory allocations in all\n", gMemIndex);
+ fprintf(f, "maximum memory in use: %zd bytes\n", gMaxMemInUse);
+ left = 0;
+ if (gMemAlloc > 0) {
+ for (p = gMemHead; p; p = p->next) {
+ if (p->index >= 0) {
+ if (!left) {
+ fprintf(f, "%d memory blocks left allocated:\n", gMemAlloc);
+ fprintf(f, " index size\n");
+ fprintf(f, "-------- --------\n");
+ left = 1;
+ }
+ fprintf(f, "%8d %8zd\n", p->index, p->size);
+ }
+ }
+ }
+ if (!left) {
+ fprintf(f, "No memory blocks left allocated\n");
+ }
+}
+#endif
+
+char *copyString(const char *s) {
+ char *s1;
+
+ s1 = (char *)gmalloc((int)strlen(s) + 1);
+ strcpy(s1, s);
+ return s1;
+}
diff --git a/goo/gmem.h b/goo/gmem.h
new file mode 100644
index 0000000..f131c17
--- /dev/null
+++ b/goo/gmem.h
@@ -0,0 +1,95 @@
+/*
+ * gmem.h
+ *
+ * Memory routines with out-of-memory checking.
+ *
+ * Copyright 1996-2003 Glyph & Cog, LLC
+ */
+
+#ifndef GMEM_H
+#define GMEM_H
+
+#include <stdio.h>
+#include <aconf.h>
+
+#if USE_EXCEPTIONS
+
+class GMemException {
+public:
+ GMemException() {}
+ ~GMemException() {}
+};
+
+// This used to be:
+// #define GMEM_EXCEP throw(GMemException)
+// but the throw decl was never really very useful, and is deprecated
+// as of C++11 and illegal as of C++17.
+#define GMEM_EXCEP
+
+#else // USE_EXCEPTIONS
+
+#define GMEM_EXCEP
+
+#endif // USE_EXCEPTIONS
+
+/*
+ * Same as malloc, but prints error message and exits if malloc()
+ * returns NULL.
+ */
+#ifdef DEBUG_MEM
+extern void *gmalloc(int size, int ignore = 0) GMEM_EXCEP;
+#else
+extern void *gmalloc(int size) GMEM_EXCEP;
+#endif
+
+/*
+ * Same as realloc, but prints error message and exits if realloc()
+ * returns NULL. If <p> is NULL, calls malloc instead of realloc().
+ */
+extern void *grealloc(void *p, int size) GMEM_EXCEP;
+
+/*
+ * These are similar to gmalloc and grealloc, but take an object count
+ * and size. The result is similar to allocating nObjs * objSize
+ * bytes, but there is an additional error check that the total size
+ * doesn't overflow an int.
+ */
+extern void *gmallocn(int nObjs, int objSize) GMEM_EXCEP;
+extern void *greallocn(void *p, int nObjs, int objSize) GMEM_EXCEP;
+
+/*
+ * Same as gmalloc and gmallocn, but allow a 64-bit size on 64-bit
+ * systems.
+ */
+#ifdef DEBUG_MEM
+extern void *gmalloc64(size_t size, int ignore = 0) GMEM_EXCEP;
+#else
+extern void *gmalloc64(size_t size) GMEM_EXCEP;
+#endif
+extern void *gmallocn64(int nObjs, size_t objSize) GMEM_EXCEP;
+
+/*
+ * Same as free, but checks for and ignores NULL pointers.
+ */
+extern void gfree(void *p);
+
+/*
+ * Report a memory error.
+ */
+extern void gMemError(const char *msg) GMEM_EXCEP;
+
+#ifdef DEBUG_MEM
+/*
+ * Report on unfreed memory.
+ */
+extern void gMemReport(FILE *f);
+#else
+#define gMemReport(f)
+#endif
+
+/*
+ * Allocate memory and copy a string into it.
+ */
+extern char *copyString(const char *s);
+
+#endif
diff --git a/goo/gmempp.cc b/goo/gmempp.cc
new file mode 100644
index 0000000..fe5790b
--- /dev/null
+++ b/goo/gmempp.cc
@@ -0,0 +1,51 @@
+//========================================================================
+//
+// gmempp.cc
+//
+// Use gmalloc/gfree for C++ new/delete operators.
+//
+// Copyright 1996-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <aconf.h>
+#include "gmem.h"
+// NB: do not include gmempp.h here.
+
+#ifdef DEBUG_MEM
+
+void *operator new(size_t size) {
+ return gmalloc((int)size, 1);
+}
+
+void *operator new(size_t size, int dummy) {
+ return gmalloc((int)size, 0);
+}
+
+void *operator new[](size_t size) {
+ return gmalloc((int)size, 1);
+}
+
+void *operator new[](size_t size, int dummy) {
+ return gmalloc((int)size, 0);
+}
+
+void operator delete(void *p) {
+ gfree(p);
+}
+
+// This is only called if a constructor throws an exception.
+void operator delete(void *p, int dummy) {
+ gfree(p);
+}
+
+void operator delete[](void *p) {
+ gfree(p);
+}
+
+// This is only called if a constructor throws an exception.
+void operator delete[](void *p, int dummy) {
+ gfree(p);
+}
+
+#endif
diff --git a/goo/gmempp.h b/goo/gmempp.h
new file mode 100644
index 0000000..27f7fe7
--- /dev/null
+++ b/goo/gmempp.h
@@ -0,0 +1,48 @@
+//========================================================================
+//
+// gmempp.h
+//
+// Redefine the new and delete operators to call the debugging malloc.
+//
+// This is a hack: some libraries (Qt) allocate global objects and
+// never free them, so this file #define's new to have an argument, so
+// that we can differentiate our new calls from external library new
+// calls. Calls from external libraries will not be counted when
+// un-freed memory is listed. There's no guarantee that this will
+// work in all cases: if some external library also defines a new
+// operator that takes the same extra argument, things will break
+// horribly.
+//
+// This entire .h file is wrapped in '#ifdef DEBUG_MEM'. I.e., if you
+// don't define DEBUG_MEM, this hack goes away and can't cause any
+// problems. Do not define DEBUG_MEM in production code.
+//
+// To use this .h file, it must be #included *after* all system
+// includes. Calls to new in any modules that do not include this .h
+// file will not be counted as un-freed memory.
+//
+//========================================================================
+
+#ifndef GMEMPP_H
+#define GMEMPP_H
+
+#ifdef DEBUG_MEM
+
+#include <stdlib.h>
+
+extern void *operator new(size_t size, int dummy);
+extern void *operator new[](size_t size, int dummy);
+
+// These have to be defined (and declared) to avoid a compiler warning
+// with Visual Studio.
+extern void operator delete(void *p, int dummy);
+extern void operator delete[](void *p, int dummy);
+
+// This transforms 'new Foo(...)' into 'new (1) Foo(...)', which
+// forces a call to the operator new variant with the 'int dummy' arg.
+#define debug_new new (1)
+#define new debug_new
+
+#endif // DEBUG_MEM
+
+#endif // GMEMPP_H
diff --git a/goo/gtypes.h b/goo/gtypes.h
new file mode 100644
index 0000000..9f64f57
--- /dev/null
+++ b/goo/gtypes.h
@@ -0,0 +1,29 @@
+/*
+ * gtypes.h
+ *
+ * Some useful simple types.
+ *
+ * Copyright 1996-2003 Glyph & Cog, LLC
+ */
+
+#ifndef GTYPES_H
+#define GTYPES_H
+
+/*
+ * These have stupid names to avoid conflicts with some (but not all)
+ * C++ compilers which define them.
+ */
+typedef int GBool;
+#define gTrue 1
+#define gFalse 0
+
+/*
+ * These have stupid names to avoid conflicts with <sys/types.h>,
+ * which on various systems defines some random subset of these.
+ */
+typedef unsigned char Guchar;
+typedef unsigned short Gushort;
+typedef unsigned int Guint;
+typedef unsigned long Gulong;
+
+#endif
diff --git a/goo/libgoo.a b/goo/libgoo.a
new file mode 100644
index 0000000..9af04b8
--- /dev/null
+++ b/goo/libgoo.a
Binary files differ
diff --git a/goo/parseargs.c b/goo/parseargs.c
new file mode 100644
index 0000000..2f5844f
--- /dev/null
+++ b/goo/parseargs.c
@@ -0,0 +1,195 @@
+/*
+ * parseargs.h
+ *
+ * Command line argument parser.
+ *
+ * Copyright 1996-2003 Glyph & Cog, LLC
+ */
+
+#include <stdio.h>
+#include <stddef.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include "parseargs.h"
+
+static ArgDesc *findArg(ArgDesc *args, char *arg);
+static GBool grabArg(ArgDesc *arg, int i, int *argc, char *argv[]);
+
+GBool parseArgs(ArgDesc *args, int *argc, char *argv[]) {
+ ArgDesc *arg;
+ int i, j;
+ GBool ok;
+
+ ok = gTrue;
+ i = 1;
+ while (i < *argc) {
+ if (!strcmp(argv[i], "--")) {
+ --*argc;
+ for (j = i; j < *argc; ++j) {
+ argv[j] = argv[j+1];
+ }
+ break;
+ } else if ((arg = findArg(args, argv[i]))) {
+ if (!grabArg(arg, i, argc, argv)) {
+ ok = gFalse;
+ }
+ } else if (argv[i][0] == '-') {
+ ok = gFalse;
+ break;
+ } else {
+ break;
+ }
+ }
+ return ok;
+}
+
+void printUsage(const char *program, const char *otherArgs, ArgDesc *args) {
+ ArgDesc *arg;
+ char *typ;
+ int w, w1;
+
+ w = 0;
+ for (arg = args; arg->arg; ++arg) {
+ if ((w1 = (int)strlen(arg->arg)) > w)
+ w = w1;
+ }
+
+ fprintf(stderr, "Usage: %s [options]", program);
+ if (otherArgs)
+ fprintf(stderr, " %s", otherArgs);
+ fprintf(stderr, "\n");
+
+ for (arg = args; arg->arg; ++arg) {
+ fprintf(stderr, " %s", arg->arg);
+ w1 = 9 + w - (int)strlen(arg->arg);
+ switch (arg->kind) {
+ case argInt:
+ case argIntDummy:
+ typ = " <int>";
+ break;
+ case argFP:
+ case argFPDummy:
+ typ = " <number>";
+ break;
+ case argString:
+ case argStringDummy:
+ typ = " <string>";
+ break;
+ case argFlag:
+ case argFlagDummy:
+ default:
+ typ = "";
+ break;
+ }
+ fprintf(stderr, "%-*s", w1, typ);
+ if (arg->usage)
+ fprintf(stderr, ": %s", arg->usage);
+ fprintf(stderr, "\n");
+ }
+}
+
+static ArgDesc *findArg(ArgDesc *args, char *arg) {
+ ArgDesc *p;
+
+ for (p = args; p->arg; ++p) {
+ if (p->kind < argFlagDummy && !strcmp(p->arg, arg))
+ return p;
+ }
+ return NULL;
+}
+
+static GBool grabArg(ArgDesc *arg, int i, int *argc, char *argv[]) {
+ int n;
+ int j;
+ GBool ok;
+
+ ok = gTrue;
+ n = 0;
+ switch (arg->kind) {
+ case argFlag:
+ *(GBool *)arg->val = gTrue;
+ n = 1;
+ break;
+ case argInt:
+ if (i + 1 < *argc && isInt(argv[i+1])) {
+ *(int *)arg->val = atoi(argv[i+1]);
+ n = 2;
+ } else {
+ ok = gFalse;
+ n = 1;
+ }
+ break;
+ case argFP:
+ if (i + 1 < *argc && isFP(argv[i+1])) {
+ *(double *)arg->val = atof(argv[i+1]);
+ n = 2;
+ } else {
+ ok = gFalse;
+ n = 1;
+ }
+ break;
+ case argString:
+ if (i + 1 < *argc) {
+ strncpy((char *)arg->val, argv[i+1], arg->size - 1);
+ ((char *)arg->val)[arg->size - 1] = '\0';
+ n = 2;
+ } else {
+ ok = gFalse;
+ n = 1;
+ }
+ break;
+ default:
+ fprintf(stderr, "Internal error in arg table\n");
+ n = 1;
+ break;
+ }
+ if (n > 0) {
+ *argc -= n;
+ for (j = i; j < *argc; ++j)
+ argv[j] = argv[j+n];
+ }
+ return ok;
+}
+
+GBool isInt(char *s) {
+ if (*s == '-' || *s == '+')
+ ++s;
+ while (isdigit(*s & 0xff))
+ ++s;
+ if (*s)
+ return gFalse;
+ return gTrue;
+}
+
+GBool isFP(char *s) {
+ int n;
+
+ if (*s == '-' || *s == '+')
+ ++s;
+ n = 0;
+ while (isdigit(*s & 0xff)) {
+ ++s;
+ ++n;
+ }
+ if (*s == '.')
+ ++s;
+ while (isdigit(*s & 0xff)) {
+ ++s;
+ ++n;
+ }
+ if (n > 0 && (*s == 'e' || *s == 'E')) {
+ ++s;
+ if (*s == '-' || *s == '+')
+ ++s;
+ n = 0;
+ if (!isdigit(*s & 0xff))
+ return gFalse;
+ do {
+ ++s;
+ } while (isdigit(*s & 0xff));
+ }
+ if (*s)
+ return gFalse;
+ return gTrue;
+}
diff --git a/goo/parseargs.h b/goo/parseargs.h
new file mode 100644
index 0000000..b4daa3f
--- /dev/null
+++ b/goo/parseargs.h
@@ -0,0 +1,72 @@
+/*
+ * parseargs.h
+ *
+ * Command line argument parser.
+ *
+ * Copyright 1996-2003 Glyph & Cog, LLC
+ */
+
+#ifndef PARSEARGS_H
+#define PARSEARGS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "gtypes.h"
+
+/*
+ * Argument kinds.
+ */
+typedef enum {
+ argFlag, /* flag (present / not-present) */
+ /* [val: GBool *] */
+ argInt, /* integer arg */
+ /* [val: int *] */
+ argFP, /* floating point arg */
+ /* [val: double *] */
+ argString, /* string arg */
+ /* [val: char *] */
+ /* dummy entries -- these show up in the usage listing only; */
+ /* useful for X args, for example */
+ argFlagDummy,
+ argIntDummy,
+ argFPDummy,
+ argStringDummy
+} ArgKind;
+
+/*
+ * Argument descriptor.
+ */
+typedef struct {
+ const char *arg; /* the command line switch */
+ ArgKind kind; /* kind of arg */
+ void *val; /* place to store value */
+ int size; /* for argString: size of string */
+ const char *usage; /* usage string */
+} ArgDesc;
+
+/*
+ * Parse command line. Removes all args which are found in the arg
+ * descriptor list <args>. Stops parsing if "--" is found (and removes
+ * it). Returns gFalse if there was an error.
+ */
+extern GBool parseArgs(ArgDesc *args, int *argc, char *argv[]);
+
+/*
+ * Print usage message, based on arg descriptor list.
+ */
+extern void printUsage(const char *program, const char *otherArgs,
+ ArgDesc *args);
+
+/*
+ * Check if a string is a valid integer or floating point number.
+ */
+extern GBool isInt(char *s);
+extern GBool isFP(char *s);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/splash/CMakeFiles/CMakeDirectoryInformation.cmake b/splash/CMakeFiles/CMakeDirectoryInformation.cmake
new file mode 100644
index 0000000..aef4d6c
--- /dev/null
+++ b/splash/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/splash/CMakeFiles/progress.marks b/splash/CMakeFiles/progress.marks
new file mode 100644
index 0000000..48082f7
--- /dev/null
+++ b/splash/CMakeFiles/progress.marks
@@ -0,0 +1 @@
+12
diff --git a/splash/CMakeFiles/splash.dir/DependInfo.cmake b/splash/CMakeFiles/splash.dir/DependInfo.cmake
new file mode 100644
index 0000000..19fab21
--- /dev/null
+++ b/splash/CMakeFiles/splash.dir/DependInfo.cmake
@@ -0,0 +1,11 @@
+# The set of languages for which implicit dependencies are needed:
+set(CMAKE_DEPENDS_LANGUAGES
+ )
+# The set of files for implicit dependencies of each language:
+
+# 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/splash/CMakeFiles/splash.dir/build.make b/splash/CMakeFiles/splash.dir/build.make
new file mode 100644
index 0000000..3d6695a
--- /dev/null
+++ b/splash/CMakeFiles/splash.dir/build.make
@@ -0,0 +1,135 @@
+# 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 splash/CMakeFiles/splash.dir/depend.make
+
+# Include the progress variables for this target.
+include splash/CMakeFiles/splash.dir/progress.make
+
+# Include the compile flags for this target's objects.
+include splash/CMakeFiles/splash.dir/flags.make
+
+# Object files for target splash
+splash_OBJECTS =
+
+# External object files for target splash
+splash_EXTERNAL_OBJECTS = \
+"/home/calvin/src/xpdf-4.04/splash/CMakeFiles/splash_objs.dir/Splash.cc.o" \
+"/home/calvin/src/xpdf-4.04/splash/CMakeFiles/splash_objs.dir/SplashBitmap.cc.o" \
+"/home/calvin/src/xpdf-4.04/splash/CMakeFiles/splash_objs.dir/SplashClip.cc.o" \
+"/home/calvin/src/xpdf-4.04/splash/CMakeFiles/splash_objs.dir/SplashFTFont.cc.o" \
+"/home/calvin/src/xpdf-4.04/splash/CMakeFiles/splash_objs.dir/SplashFTFontEngine.cc.o" \
+"/home/calvin/src/xpdf-4.04/splash/CMakeFiles/splash_objs.dir/SplashFTFontFile.cc.o" \
+"/home/calvin/src/xpdf-4.04/splash/CMakeFiles/splash_objs.dir/SplashFont.cc.o" \
+"/home/calvin/src/xpdf-4.04/splash/CMakeFiles/splash_objs.dir/SplashFontEngine.cc.o" \
+"/home/calvin/src/xpdf-4.04/splash/CMakeFiles/splash_objs.dir/SplashFontFile.cc.o" \
+"/home/calvin/src/xpdf-4.04/splash/CMakeFiles/splash_objs.dir/SplashFontFileID.cc.o" \
+"/home/calvin/src/xpdf-4.04/splash/CMakeFiles/splash_objs.dir/SplashPath.cc.o" \
+"/home/calvin/src/xpdf-4.04/splash/CMakeFiles/splash_objs.dir/SplashPattern.cc.o" \
+"/home/calvin/src/xpdf-4.04/splash/CMakeFiles/splash_objs.dir/SplashScreen.cc.o" \
+"/home/calvin/src/xpdf-4.04/splash/CMakeFiles/splash_objs.dir/SplashState.cc.o" \
+"/home/calvin/src/xpdf-4.04/splash/CMakeFiles/splash_objs.dir/SplashXPath.cc.o" \
+"/home/calvin/src/xpdf-4.04/splash/CMakeFiles/splash_objs.dir/SplashXPathScanner.cc.o"
+
+splash/libsplash.a: splash/CMakeFiles/splash_objs.dir/Splash.cc.o
+splash/libsplash.a: splash/CMakeFiles/splash_objs.dir/SplashBitmap.cc.o
+splash/libsplash.a: splash/CMakeFiles/splash_objs.dir/SplashClip.cc.o
+splash/libsplash.a: splash/CMakeFiles/splash_objs.dir/SplashFTFont.cc.o
+splash/libsplash.a: splash/CMakeFiles/splash_objs.dir/SplashFTFontEngine.cc.o
+splash/libsplash.a: splash/CMakeFiles/splash_objs.dir/SplashFTFontFile.cc.o
+splash/libsplash.a: splash/CMakeFiles/splash_objs.dir/SplashFont.cc.o
+splash/libsplash.a: splash/CMakeFiles/splash_objs.dir/SplashFontEngine.cc.o
+splash/libsplash.a: splash/CMakeFiles/splash_objs.dir/SplashFontFile.cc.o
+splash/libsplash.a: splash/CMakeFiles/splash_objs.dir/SplashFontFileID.cc.o
+splash/libsplash.a: splash/CMakeFiles/splash_objs.dir/SplashPath.cc.o
+splash/libsplash.a: splash/CMakeFiles/splash_objs.dir/SplashPattern.cc.o
+splash/libsplash.a: splash/CMakeFiles/splash_objs.dir/SplashScreen.cc.o
+splash/libsplash.a: splash/CMakeFiles/splash_objs.dir/SplashState.cc.o
+splash/libsplash.a: splash/CMakeFiles/splash_objs.dir/SplashXPath.cc.o
+splash/libsplash.a: splash/CMakeFiles/splash_objs.dir/SplashXPathScanner.cc.o
+splash/libsplash.a: splash/CMakeFiles/splash.dir/build.make
+splash/libsplash.a: splash/CMakeFiles/splash.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_1) "Linking CXX static library libsplash.a"
+ cd /home/calvin/src/xpdf-4.04/splash && $(CMAKE_COMMAND) -P CMakeFiles/splash.dir/cmake_clean_target.cmake
+ cd /home/calvin/src/xpdf-4.04/splash && $(CMAKE_COMMAND) -E cmake_link_script CMakeFiles/splash.dir/link.txt --verbose=$(VERBOSE)
+
+# Rule to build all files generated by this target.
+splash/CMakeFiles/splash.dir/build: splash/libsplash.a
+
+.PHONY : splash/CMakeFiles/splash.dir/build
+
+splash/CMakeFiles/splash.dir/clean:
+ cd /home/calvin/src/xpdf-4.04/splash && $(CMAKE_COMMAND) -P CMakeFiles/splash.dir/cmake_clean.cmake
+.PHONY : splash/CMakeFiles/splash.dir/clean
+
+splash/CMakeFiles/splash.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/splash /home/calvin/src/xpdf-4.04 /home/calvin/src/xpdf-4.04/splash /home/calvin/src/xpdf-4.04/splash/CMakeFiles/splash.dir/DependInfo.cmake --color=$(COLOR)
+.PHONY : splash/CMakeFiles/splash.dir/depend
+
diff --git a/splash/CMakeFiles/splash.dir/cmake_clean.cmake b/splash/CMakeFiles/splash.dir/cmake_clean.cmake
new file mode 100644
index 0000000..905e817
--- /dev/null
+++ b/splash/CMakeFiles/splash.dir/cmake_clean.cmake
@@ -0,0 +1,9 @@
+file(REMOVE_RECURSE
+ "libsplash.a"
+ "libsplash.pdb"
+)
+
+# Per-language clean rules from dependency scanning.
+foreach(lang CXX)
+ include(CMakeFiles/splash.dir/cmake_clean_${lang}.cmake OPTIONAL)
+endforeach()
diff --git a/splash/CMakeFiles/splash.dir/cmake_clean_target.cmake b/splash/CMakeFiles/splash.dir/cmake_clean_target.cmake
new file mode 100644
index 0000000..4294aad
--- /dev/null
+++ b/splash/CMakeFiles/splash.dir/cmake_clean_target.cmake
@@ -0,0 +1,3 @@
+file(REMOVE_RECURSE
+ "libsplash.a"
+)
diff --git a/splash/CMakeFiles/splash.dir/depend.internal b/splash/CMakeFiles/splash.dir/depend.internal
new file mode 100644
index 0000000..756f521
--- /dev/null
+++ b/splash/CMakeFiles/splash.dir/depend.internal
@@ -0,0 +1,3 @@
+# CMAKE generated file: DO NOT EDIT!
+# Generated by "Unix Makefiles" Generator, CMake Version 3.18
+
diff --git a/splash/CMakeFiles/splash.dir/depend.make b/splash/CMakeFiles/splash.dir/depend.make
new file mode 100644
index 0000000..756f521
--- /dev/null
+++ b/splash/CMakeFiles/splash.dir/depend.make
@@ -0,0 +1,3 @@
+# CMAKE generated file: DO NOT EDIT!
+# Generated by "Unix Makefiles" Generator, CMake Version 3.18
+
diff --git a/splash/CMakeFiles/splash.dir/flags.make b/splash/CMakeFiles/splash.dir/flags.make
new file mode 100644
index 0000000..ae623ab
--- /dev/null
+++ b/splash/CMakeFiles/splash.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/usr/include/freetype2
+
+CXX_FLAGS =
+
diff --git a/splash/CMakeFiles/splash.dir/link.txt b/splash/CMakeFiles/splash.dir/link.txt
new file mode 100644
index 0000000..1c08a0a
--- /dev/null
+++ b/splash/CMakeFiles/splash.dir/link.txt
@@ -0,0 +1,2 @@
+/usr/bin/ar qc libsplash.a CMakeFiles/splash_objs.dir/Splash.cc.o CMakeFiles/splash_objs.dir/SplashBitmap.cc.o CMakeFiles/splash_objs.dir/SplashClip.cc.o CMakeFiles/splash_objs.dir/SplashFTFont.cc.o CMakeFiles/splash_objs.dir/SplashFTFontEngine.cc.o CMakeFiles/splash_objs.dir/SplashFTFontFile.cc.o CMakeFiles/splash_objs.dir/SplashFont.cc.o CMakeFiles/splash_objs.dir/SplashFontEngine.cc.o CMakeFiles/splash_objs.dir/SplashFontFile.cc.o CMakeFiles/splash_objs.dir/SplashFontFileID.cc.o CMakeFiles/splash_objs.dir/SplashPath.cc.o CMakeFiles/splash_objs.dir/SplashPattern.cc.o CMakeFiles/splash_objs.dir/SplashScreen.cc.o CMakeFiles/splash_objs.dir/SplashState.cc.o CMakeFiles/splash_objs.dir/SplashXPath.cc.o CMakeFiles/splash_objs.dir/SplashXPathScanner.cc.o
+/usr/bin/ranlib libsplash.a
diff --git a/splash/CMakeFiles/splash.dir/progress.make b/splash/CMakeFiles/splash.dir/progress.make
new file mode 100644
index 0000000..225de34
--- /dev/null
+++ b/splash/CMakeFiles/splash.dir/progress.make
@@ -0,0 +1,2 @@
+CMAKE_PROGRESS_1 =
+
diff --git a/splash/CMakeFiles/splash_objs.dir/CXX.includecache b/splash/CMakeFiles/splash_objs.dir/CXX.includecache
new file mode 100644
index 0000000..408e937
--- /dev/null
+++ b/splash/CMakeFiles/splash_objs.dir/CXX.includecache
@@ -0,0 +1,596 @@
+#IncludeRegexLine: ^[ ]*[#%][ ]*(include|import)[ ]*[<"]([^">]+)([">])
+
+#IncludeRegexScan: ^.*$
+
+#IncludeRegexComplain: ^$
+
+#IncludeRegexTransform:
+
+/home/calvin/src/xpdf-4.04/splash/Splash.cc
+aconf.h
+-
+stdlib.h
+-
+string.h
+-
+limits.h
+-
+math.h
+-
+gmem.h
+/home/calvin/src/xpdf-4.04/splash/gmem.h
+gmempp.h
+/home/calvin/src/xpdf-4.04/splash/gmempp.h
+GString.h
+/home/calvin/src/xpdf-4.04/splash/GString.h
+SplashErrorCodes.h
+/home/calvin/src/xpdf-4.04/splash/SplashErrorCodes.h
+SplashMath.h
+/home/calvin/src/xpdf-4.04/splash/SplashMath.h
+SplashBitmap.h
+/home/calvin/src/xpdf-4.04/splash/SplashBitmap.h
+SplashState.h
+/home/calvin/src/xpdf-4.04/splash/SplashState.h
+SplashPath.h
+/home/calvin/src/xpdf-4.04/splash/SplashPath.h
+SplashXPath.h
+/home/calvin/src/xpdf-4.04/splash/SplashXPath.h
+SplashXPathScanner.h
+/home/calvin/src/xpdf-4.04/splash/SplashXPathScanner.h
+SplashPattern.h
+/home/calvin/src/xpdf-4.04/splash/SplashPattern.h
+SplashScreen.h
+/home/calvin/src/xpdf-4.04/splash/SplashScreen.h
+SplashFont.h
+/home/calvin/src/xpdf-4.04/splash/SplashFont.h
+SplashGlyphBitmap.h
+/home/calvin/src/xpdf-4.04/splash/SplashGlyphBitmap.h
+Splash.h
+/home/calvin/src/xpdf-4.04/splash/Splash.h
+
+/home/calvin/src/xpdf-4.04/splash/Splash.h
+aconf.h
+-
+SplashTypes.h
+/home/calvin/src/xpdf-4.04/splash/SplashTypes.h
+SplashClip.h
+/home/calvin/src/xpdf-4.04/splash/SplashClip.h
+
+/home/calvin/src/xpdf-4.04/splash/SplashBitmap.cc
+aconf.h
+-
+stdio.h
+-
+limits.h
+-
+gmem.h
+/home/calvin/src/xpdf-4.04/splash/gmem.h
+gmempp.h
+/home/calvin/src/xpdf-4.04/splash/gmempp.h
+gfile.h
+/home/calvin/src/xpdf-4.04/splash/gfile.h
+Trace.h
+/home/calvin/src/xpdf-4.04/splash/Trace.h
+SplashErrorCodes.h
+/home/calvin/src/xpdf-4.04/splash/SplashErrorCodes.h
+SplashBitmap.h
+/home/calvin/src/xpdf-4.04/splash/SplashBitmap.h
+
+/home/calvin/src/xpdf-4.04/splash/SplashBitmap.h
+aconf.h
+-
+stdio.h
+-
+limits.h
+-
+stdint.h
+-
+SplashTypes.h
+/home/calvin/src/xpdf-4.04/splash/SplashTypes.h
+
+/home/calvin/src/xpdf-4.04/splash/SplashClip.cc
+aconf.h
+-
+stdlib.h
+-
+string.h
+-
+gmem.h
+/home/calvin/src/xpdf-4.04/splash/gmem.h
+gmempp.h
+/home/calvin/src/xpdf-4.04/splash/gmempp.h
+SplashErrorCodes.h
+/home/calvin/src/xpdf-4.04/splash/SplashErrorCodes.h
+SplashPath.h
+/home/calvin/src/xpdf-4.04/splash/SplashPath.h
+SplashXPath.h
+/home/calvin/src/xpdf-4.04/splash/SplashXPath.h
+SplashXPathScanner.h
+/home/calvin/src/xpdf-4.04/splash/SplashXPathScanner.h
+SplashClip.h
+/home/calvin/src/xpdf-4.04/splash/SplashClip.h
+
+/home/calvin/src/xpdf-4.04/splash/SplashClip.h
+aconf.h
+-
+SplashTypes.h
+/home/calvin/src/xpdf-4.04/splash/SplashTypes.h
+SplashMath.h
+/home/calvin/src/xpdf-4.04/splash/SplashMath.h
+
+/home/calvin/src/xpdf-4.04/splash/SplashErrorCodes.h
+aconf.h
+-
+
+/home/calvin/src/xpdf-4.04/splash/SplashFTFont.cc
+aconf.h
+-
+ft2build.h
+-
+gmem.h
+/home/calvin/src/xpdf-4.04/splash/gmem.h
+gmempp.h
+/home/calvin/src/xpdf-4.04/splash/gmempp.h
+SplashMath.h
+/home/calvin/src/xpdf-4.04/splash/SplashMath.h
+SplashGlyphBitmap.h
+/home/calvin/src/xpdf-4.04/splash/SplashGlyphBitmap.h
+SplashPath.h
+/home/calvin/src/xpdf-4.04/splash/SplashPath.h
+SplashFontEngine.h
+/home/calvin/src/xpdf-4.04/splash/SplashFontEngine.h
+SplashFTFontEngine.h
+/home/calvin/src/xpdf-4.04/splash/SplashFTFontEngine.h
+SplashFTFontFile.h
+/home/calvin/src/xpdf-4.04/splash/SplashFTFontFile.h
+SplashFTFont.h
+/home/calvin/src/xpdf-4.04/splash/SplashFTFont.h
+
+/home/calvin/src/xpdf-4.04/splash/SplashFTFont.h
+aconf.h
+-
+ft2build.h
+-
+SplashFont.h
+/home/calvin/src/xpdf-4.04/splash/SplashFont.h
+
+/home/calvin/src/xpdf-4.04/splash/SplashFTFontEngine.cc
+aconf.h
+-
+stdio.h
+-
+unistd.h
+-
+gmem.h
+/home/calvin/src/xpdf-4.04/splash/gmem.h
+gmempp.h
+/home/calvin/src/xpdf-4.04/splash/gmempp.h
+GString.h
+/home/calvin/src/xpdf-4.04/splash/GString.h
+gfile.h
+/home/calvin/src/xpdf-4.04/splash/gfile.h
+FoFiTrueType.h
+/home/calvin/src/xpdf-4.04/splash/FoFiTrueType.h
+FoFiType1C.h
+/home/calvin/src/xpdf-4.04/splash/FoFiType1C.h
+SplashFTFontFile.h
+/home/calvin/src/xpdf-4.04/splash/SplashFTFontFile.h
+SplashFTFontEngine.h
+/home/calvin/src/xpdf-4.04/splash/SplashFTFontEngine.h
+
+/home/calvin/src/xpdf-4.04/splash/SplashFTFontEngine.h
+aconf.h
+-
+ft2build.h
+-
+gtypes.h
+/home/calvin/src/xpdf-4.04/splash/gtypes.h
+
+/home/calvin/src/xpdf-4.04/splash/SplashFTFontFile.cc
+aconf.h
+-
+gmem.h
+/home/calvin/src/xpdf-4.04/splash/gmem.h
+gmempp.h
+/home/calvin/src/xpdf-4.04/splash/gmempp.h
+GString.h
+/home/calvin/src/xpdf-4.04/splash/GString.h
+SplashFTFontEngine.h
+/home/calvin/src/xpdf-4.04/splash/SplashFTFontEngine.h
+SplashFTFont.h
+/home/calvin/src/xpdf-4.04/splash/SplashFTFont.h
+SplashFTFontFile.h
+/home/calvin/src/xpdf-4.04/splash/SplashFTFontFile.h
+
+/home/calvin/src/xpdf-4.04/splash/SplashFTFontFile.h
+aconf.h
+-
+ft2build.h
+-
+SplashFontFile.h
+/home/calvin/src/xpdf-4.04/splash/SplashFontFile.h
+
+/home/calvin/src/xpdf-4.04/splash/SplashFont.cc
+aconf.h
+-
+string.h
+-
+gmem.h
+/home/calvin/src/xpdf-4.04/splash/gmem.h
+gmempp.h
+/home/calvin/src/xpdf-4.04/splash/gmempp.h
+SplashMath.h
+/home/calvin/src/xpdf-4.04/splash/SplashMath.h
+SplashGlyphBitmap.h
+/home/calvin/src/xpdf-4.04/splash/SplashGlyphBitmap.h
+SplashFontFile.h
+/home/calvin/src/xpdf-4.04/splash/SplashFontFile.h
+SplashFont.h
+/home/calvin/src/xpdf-4.04/splash/SplashFont.h
+
+/home/calvin/src/xpdf-4.04/splash/SplashFont.h
+aconf.h
+-
+gtypes.h
+/home/calvin/src/xpdf-4.04/splash/gtypes.h
+SplashTypes.h
+/home/calvin/src/xpdf-4.04/splash/SplashTypes.h
+SplashMath.h
+/home/calvin/src/xpdf-4.04/splash/SplashMath.h
+
+/home/calvin/src/xpdf-4.04/splash/SplashFontEngine.cc
+aconf.h
+-
+stdlib.h
+-
+stdio.h
+-
+unistd.h
+-
+gmem.h
+/home/calvin/src/xpdf-4.04/splash/gmem.h
+gmempp.h
+/home/calvin/src/xpdf-4.04/splash/gmempp.h
+GString.h
+/home/calvin/src/xpdf-4.04/splash/GString.h
+GList.h
+/home/calvin/src/xpdf-4.04/splash/GList.h
+SplashMath.h
+/home/calvin/src/xpdf-4.04/splash/SplashMath.h
+SplashFTFontEngine.h
+/home/calvin/src/xpdf-4.04/splash/SplashFTFontEngine.h
+SplashFontFile.h
+/home/calvin/src/xpdf-4.04/splash/SplashFontFile.h
+SplashFontFileID.h
+/home/calvin/src/xpdf-4.04/splash/SplashFontFileID.h
+SplashFont.h
+/home/calvin/src/xpdf-4.04/splash/SplashFont.h
+SplashFontEngine.h
+/home/calvin/src/xpdf-4.04/splash/SplashFontEngine.h
+
+/home/calvin/src/xpdf-4.04/splash/SplashFontEngine.h
+aconf.h
+-
+gtypes.h
+/home/calvin/src/xpdf-4.04/splash/gtypes.h
+
+/home/calvin/src/xpdf-4.04/splash/SplashFontFile.cc
+aconf.h
+-
+stdio.h
+-
+unistd.h
+-
+gmempp.h
+/home/calvin/src/xpdf-4.04/splash/gmempp.h
+GString.h
+/home/calvin/src/xpdf-4.04/splash/GString.h
+SplashFontFile.h
+/home/calvin/src/xpdf-4.04/splash/SplashFontFile.h
+SplashFontFileID.h
+/home/calvin/src/xpdf-4.04/splash/SplashFontFileID.h
+
+/home/calvin/src/xpdf-4.04/splash/SplashFontFile.h
+aconf.h
+-
+gtypes.h
+/home/calvin/src/xpdf-4.04/splash/gtypes.h
+SplashTypes.h
+/home/calvin/src/xpdf-4.04/splash/SplashTypes.h
+GMutex.h
+/home/calvin/src/xpdf-4.04/splash/GMutex.h
+
+/home/calvin/src/xpdf-4.04/splash/SplashFontFileID.cc
+aconf.h
+-
+gmempp.h
+/home/calvin/src/xpdf-4.04/splash/gmempp.h
+SplashFontFileID.h
+/home/calvin/src/xpdf-4.04/splash/SplashFontFileID.h
+
+/home/calvin/src/xpdf-4.04/splash/SplashFontFileID.h
+aconf.h
+-
+gtypes.h
+/home/calvin/src/xpdf-4.04/splash/gtypes.h
+
+/home/calvin/src/xpdf-4.04/splash/SplashGlyphBitmap.h
+aconf.h
+-
+gtypes.h
+/home/calvin/src/xpdf-4.04/splash/gtypes.h
+
+/home/calvin/src/xpdf-4.04/splash/SplashMath.h
+aconf.h
+-
+FixedPoint.h
+/home/calvin/src/xpdf-4.04/splash/FixedPoint.h
+math.h
+-
+emmintrin.h
+-
+SplashTypes.h
+/home/calvin/src/xpdf-4.04/splash/SplashTypes.h
+
+/home/calvin/src/xpdf-4.04/splash/SplashPath.cc
+aconf.h
+-
+string.h
+-
+gmem.h
+/home/calvin/src/xpdf-4.04/splash/gmem.h
+gmempp.h
+/home/calvin/src/xpdf-4.04/splash/gmempp.h
+SplashErrorCodes.h
+/home/calvin/src/xpdf-4.04/splash/SplashErrorCodes.h
+SplashPath.h
+/home/calvin/src/xpdf-4.04/splash/SplashPath.h
+
+/home/calvin/src/xpdf-4.04/splash/SplashPath.h
+aconf.h
+-
+SplashTypes.h
+/home/calvin/src/xpdf-4.04/splash/SplashTypes.h
+
+/home/calvin/src/xpdf-4.04/splash/SplashPattern.cc
+aconf.h
+-
+gmempp.h
+/home/calvin/src/xpdf-4.04/splash/gmempp.h
+SplashMath.h
+/home/calvin/src/xpdf-4.04/splash/SplashMath.h
+SplashScreen.h
+/home/calvin/src/xpdf-4.04/splash/SplashScreen.h
+SplashPattern.h
+/home/calvin/src/xpdf-4.04/splash/SplashPattern.h
+
+/home/calvin/src/xpdf-4.04/splash/SplashPattern.h
+aconf.h
+-
+SplashTypes.h
+/home/calvin/src/xpdf-4.04/splash/SplashTypes.h
+
+/home/calvin/src/xpdf-4.04/splash/SplashScreen.cc
+aconf.h
+-
+stdlib.h
+-
+string.h
+-
+algorithm
+-
+gmem.h
+/home/calvin/src/xpdf-4.04/splash/gmem.h
+gmempp.h
+/home/calvin/src/xpdf-4.04/splash/gmempp.h
+SplashMath.h
+/home/calvin/src/xpdf-4.04/splash/SplashMath.h
+SplashScreen.h
+/home/calvin/src/xpdf-4.04/splash/SplashScreen.h
+
+/home/calvin/src/xpdf-4.04/splash/SplashScreen.h
+aconf.h
+-
+SplashTypes.h
+/home/calvin/src/xpdf-4.04/splash/SplashTypes.h
+
+/home/calvin/src/xpdf-4.04/splash/SplashState.cc
+aconf.h
+-
+string.h
+-
+gmem.h
+/home/calvin/src/xpdf-4.04/splash/gmem.h
+gmempp.h
+/home/calvin/src/xpdf-4.04/splash/gmempp.h
+SplashPattern.h
+/home/calvin/src/xpdf-4.04/splash/SplashPattern.h
+SplashScreen.h
+/home/calvin/src/xpdf-4.04/splash/SplashScreen.h
+SplashClip.h
+/home/calvin/src/xpdf-4.04/splash/SplashClip.h
+SplashBitmap.h
+/home/calvin/src/xpdf-4.04/splash/SplashBitmap.h
+SplashState.h
+/home/calvin/src/xpdf-4.04/splash/SplashState.h
+
+/home/calvin/src/xpdf-4.04/splash/SplashState.h
+aconf.h
+-
+SplashTypes.h
+/home/calvin/src/xpdf-4.04/splash/SplashTypes.h
+
+/home/calvin/src/xpdf-4.04/splash/SplashTypes.h
+aconf.h
+-
+gtypes.h
+/home/calvin/src/xpdf-4.04/splash/gtypes.h
+FixedPoint.h
+/home/calvin/src/xpdf-4.04/splash/FixedPoint.h
+
+/home/calvin/src/xpdf-4.04/splash/SplashXPath.cc
+aconf.h
+-
+stdlib.h
+-
+string.h
+-
+algorithm
+-
+gmem.h
+/home/calvin/src/xpdf-4.04/splash/gmem.h
+gmempp.h
+/home/calvin/src/xpdf-4.04/splash/gmempp.h
+SplashMath.h
+/home/calvin/src/xpdf-4.04/splash/SplashMath.h
+SplashPath.h
+/home/calvin/src/xpdf-4.04/splash/SplashPath.h
+SplashXPath.h
+/home/calvin/src/xpdf-4.04/splash/SplashXPath.h
+
+/home/calvin/src/xpdf-4.04/splash/SplashXPath.h
+aconf.h
+-
+SplashTypes.h
+/home/calvin/src/xpdf-4.04/splash/SplashTypes.h
+
+/home/calvin/src/xpdf-4.04/splash/SplashXPathScanner.cc
+aconf.h
+-
+stdlib.h
+-
+string.h
+-
+algorithm
+-
+gmem.h
+/home/calvin/src/xpdf-4.04/splash/gmem.h
+gmempp.h
+/home/calvin/src/xpdf-4.04/splash/gmempp.h
+GList.h
+/home/calvin/src/xpdf-4.04/splash/GList.h
+SplashMath.h
+/home/calvin/src/xpdf-4.04/splash/SplashMath.h
+SplashXPath.h
+/home/calvin/src/xpdf-4.04/splash/SplashXPath.h
+SplashXPathScanner.h
+/home/calvin/src/xpdf-4.04/splash/SplashXPathScanner.h
+
+/home/calvin/src/xpdf-4.04/splash/SplashXPathScanner.h
+aconf.h
+-
+SplashTypes.h
+/home/calvin/src/xpdf-4.04/splash/SplashTypes.h
+SplashXPath.h
+/home/calvin/src/xpdf-4.04/splash/SplashXPath.h
+
+/usr/include/freetype2/freetype/config/ftheader.h
+
+/usr/include/freetype2/ft2build.h
+freetype/config/ftheader.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/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
+
diff --git a/splash/CMakeFiles/splash_objs.dir/DependInfo.cmake b/splash/CMakeFiles/splash_objs.dir/DependInfo.cmake
new file mode 100644
index 0000000..66c827f
--- /dev/null
+++ b/splash/CMakeFiles/splash_objs.dir/DependInfo.cmake
@@ -0,0 +1,39 @@
+# 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/splash/Splash.cc" "/home/calvin/src/xpdf-4.04/splash/CMakeFiles/splash_objs.dir/Splash.cc.o"
+ "/home/calvin/src/xpdf-4.04/splash/SplashBitmap.cc" "/home/calvin/src/xpdf-4.04/splash/CMakeFiles/splash_objs.dir/SplashBitmap.cc.o"
+ "/home/calvin/src/xpdf-4.04/splash/SplashClip.cc" "/home/calvin/src/xpdf-4.04/splash/CMakeFiles/splash_objs.dir/SplashClip.cc.o"
+ "/home/calvin/src/xpdf-4.04/splash/SplashFTFont.cc" "/home/calvin/src/xpdf-4.04/splash/CMakeFiles/splash_objs.dir/SplashFTFont.cc.o"
+ "/home/calvin/src/xpdf-4.04/splash/SplashFTFontEngine.cc" "/home/calvin/src/xpdf-4.04/splash/CMakeFiles/splash_objs.dir/SplashFTFontEngine.cc.o"
+ "/home/calvin/src/xpdf-4.04/splash/SplashFTFontFile.cc" "/home/calvin/src/xpdf-4.04/splash/CMakeFiles/splash_objs.dir/SplashFTFontFile.cc.o"
+ "/home/calvin/src/xpdf-4.04/splash/SplashFont.cc" "/home/calvin/src/xpdf-4.04/splash/CMakeFiles/splash_objs.dir/SplashFont.cc.o"
+ "/home/calvin/src/xpdf-4.04/splash/SplashFontEngine.cc" "/home/calvin/src/xpdf-4.04/splash/CMakeFiles/splash_objs.dir/SplashFontEngine.cc.o"
+ "/home/calvin/src/xpdf-4.04/splash/SplashFontFile.cc" "/home/calvin/src/xpdf-4.04/splash/CMakeFiles/splash_objs.dir/SplashFontFile.cc.o"
+ "/home/calvin/src/xpdf-4.04/splash/SplashFontFileID.cc" "/home/calvin/src/xpdf-4.04/splash/CMakeFiles/splash_objs.dir/SplashFontFileID.cc.o"
+ "/home/calvin/src/xpdf-4.04/splash/SplashPath.cc" "/home/calvin/src/xpdf-4.04/splash/CMakeFiles/splash_objs.dir/SplashPath.cc.o"
+ "/home/calvin/src/xpdf-4.04/splash/SplashPattern.cc" "/home/calvin/src/xpdf-4.04/splash/CMakeFiles/splash_objs.dir/SplashPattern.cc.o"
+ "/home/calvin/src/xpdf-4.04/splash/SplashScreen.cc" "/home/calvin/src/xpdf-4.04/splash/CMakeFiles/splash_objs.dir/SplashScreen.cc.o"
+ "/home/calvin/src/xpdf-4.04/splash/SplashState.cc" "/home/calvin/src/xpdf-4.04/splash/CMakeFiles/splash_objs.dir/SplashState.cc.o"
+ "/home/calvin/src/xpdf-4.04/splash/SplashXPath.cc" "/home/calvin/src/xpdf-4.04/splash/CMakeFiles/splash_objs.dir/SplashXPath.cc.o"
+ "/home/calvin/src/xpdf-4.04/splash/SplashXPathScanner.cc" "/home/calvin/src/xpdf-4.04/splash/CMakeFiles/splash_objs.dir/SplashXPathScanner.cc.o"
+ )
+set(CMAKE_CXX_COMPILER_ID "GNU")
+
+# The include file search paths:
+set(CMAKE_CXX_TARGET_INCLUDE_PATH
+ "."
+ "goo"
+ "fofi"
+ "/usr/include/freetype2"
+ )
+
+# 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/splash/CMakeFiles/splash_objs.dir/Splash.cc.o b/splash/CMakeFiles/splash_objs.dir/Splash.cc.o
new file mode 100644
index 0000000..cdaae0f
--- /dev/null
+++ b/splash/CMakeFiles/splash_objs.dir/Splash.cc.o
Binary files differ
diff --git a/splash/CMakeFiles/splash_objs.dir/SplashBitmap.cc.o b/splash/CMakeFiles/splash_objs.dir/SplashBitmap.cc.o
new file mode 100644
index 0000000..a90c30a
--- /dev/null
+++ b/splash/CMakeFiles/splash_objs.dir/SplashBitmap.cc.o
Binary files differ
diff --git a/splash/CMakeFiles/splash_objs.dir/SplashClip.cc.o b/splash/CMakeFiles/splash_objs.dir/SplashClip.cc.o
new file mode 100644
index 0000000..9475a08
--- /dev/null
+++ b/splash/CMakeFiles/splash_objs.dir/SplashClip.cc.o
Binary files differ
diff --git a/splash/CMakeFiles/splash_objs.dir/SplashFTFont.cc.o b/splash/CMakeFiles/splash_objs.dir/SplashFTFont.cc.o
new file mode 100644
index 0000000..140121f
--- /dev/null
+++ b/splash/CMakeFiles/splash_objs.dir/SplashFTFont.cc.o
Binary files differ
diff --git a/splash/CMakeFiles/splash_objs.dir/SplashFTFontEngine.cc.o b/splash/CMakeFiles/splash_objs.dir/SplashFTFontEngine.cc.o
new file mode 100644
index 0000000..8680956
--- /dev/null
+++ b/splash/CMakeFiles/splash_objs.dir/SplashFTFontEngine.cc.o
Binary files differ
diff --git a/splash/CMakeFiles/splash_objs.dir/SplashFTFontFile.cc.o b/splash/CMakeFiles/splash_objs.dir/SplashFTFontFile.cc.o
new file mode 100644
index 0000000..d5eb5bf
--- /dev/null
+++ b/splash/CMakeFiles/splash_objs.dir/SplashFTFontFile.cc.o
Binary files differ
diff --git a/splash/CMakeFiles/splash_objs.dir/SplashFont.cc.o b/splash/CMakeFiles/splash_objs.dir/SplashFont.cc.o
new file mode 100644
index 0000000..d83e7e5
--- /dev/null
+++ b/splash/CMakeFiles/splash_objs.dir/SplashFont.cc.o
Binary files differ
diff --git a/splash/CMakeFiles/splash_objs.dir/SplashFontEngine.cc.o b/splash/CMakeFiles/splash_objs.dir/SplashFontEngine.cc.o
new file mode 100644
index 0000000..c5ea42d
--- /dev/null
+++ b/splash/CMakeFiles/splash_objs.dir/SplashFontEngine.cc.o
Binary files differ
diff --git a/splash/CMakeFiles/splash_objs.dir/SplashFontFile.cc.o b/splash/CMakeFiles/splash_objs.dir/SplashFontFile.cc.o
new file mode 100644
index 0000000..73ca08f
--- /dev/null
+++ b/splash/CMakeFiles/splash_objs.dir/SplashFontFile.cc.o
Binary files differ
diff --git a/splash/CMakeFiles/splash_objs.dir/SplashFontFileID.cc.o b/splash/CMakeFiles/splash_objs.dir/SplashFontFileID.cc.o
new file mode 100644
index 0000000..de10eb8
--- /dev/null
+++ b/splash/CMakeFiles/splash_objs.dir/SplashFontFileID.cc.o
Binary files differ
diff --git a/splash/CMakeFiles/splash_objs.dir/SplashPath.cc.o b/splash/CMakeFiles/splash_objs.dir/SplashPath.cc.o
new file mode 100644
index 0000000..296a5e6
--- /dev/null
+++ b/splash/CMakeFiles/splash_objs.dir/SplashPath.cc.o
Binary files differ
diff --git a/splash/CMakeFiles/splash_objs.dir/SplashPattern.cc.o b/splash/CMakeFiles/splash_objs.dir/SplashPattern.cc.o
new file mode 100644
index 0000000..fd9038c
--- /dev/null
+++ b/splash/CMakeFiles/splash_objs.dir/SplashPattern.cc.o
Binary files differ
diff --git a/splash/CMakeFiles/splash_objs.dir/SplashScreen.cc.o b/splash/CMakeFiles/splash_objs.dir/SplashScreen.cc.o
new file mode 100644
index 0000000..808a540
--- /dev/null
+++ b/splash/CMakeFiles/splash_objs.dir/SplashScreen.cc.o
Binary files differ
diff --git a/splash/CMakeFiles/splash_objs.dir/SplashState.cc.o b/splash/CMakeFiles/splash_objs.dir/SplashState.cc.o
new file mode 100644
index 0000000..5693eee
--- /dev/null
+++ b/splash/CMakeFiles/splash_objs.dir/SplashState.cc.o
Binary files differ
diff --git a/splash/CMakeFiles/splash_objs.dir/SplashXPath.cc.o b/splash/CMakeFiles/splash_objs.dir/SplashXPath.cc.o
new file mode 100644
index 0000000..61c8bdd
--- /dev/null
+++ b/splash/CMakeFiles/splash_objs.dir/SplashXPath.cc.o
Binary files differ
diff --git a/splash/CMakeFiles/splash_objs.dir/SplashXPathScanner.cc.o b/splash/CMakeFiles/splash_objs.dir/SplashXPathScanner.cc.o
new file mode 100644
index 0000000..5f90f60
--- /dev/null
+++ b/splash/CMakeFiles/splash_objs.dir/SplashXPathScanner.cc.o
Binary files differ
diff --git a/splash/CMakeFiles/splash_objs.dir/build.make b/splash/CMakeFiles/splash_objs.dir/build.make
new file mode 100644
index 0000000..ab89f9f
--- /dev/null
+++ b/splash/CMakeFiles/splash_objs.dir/build.make
@@ -0,0 +1,319 @@
+# 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 splash/CMakeFiles/splash_objs.dir/depend.make
+
+# Include the progress variables for this target.
+include splash/CMakeFiles/splash_objs.dir/progress.make
+
+# Include the compile flags for this target's objects.
+include splash/CMakeFiles/splash_objs.dir/flags.make
+
+splash/CMakeFiles/splash_objs.dir/Splash.cc.o: splash/CMakeFiles/splash_objs.dir/flags.make
+splash/CMakeFiles/splash_objs.dir/Splash.cc.o: splash/Splash.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 splash/CMakeFiles/splash_objs.dir/Splash.cc.o"
+ cd /home/calvin/src/xpdf-4.04/splash && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/splash_objs.dir/Splash.cc.o -c /home/calvin/src/xpdf-4.04/splash/Splash.cc
+
+splash/CMakeFiles/splash_objs.dir/Splash.cc.i: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/splash_objs.dir/Splash.cc.i"
+ cd /home/calvin/src/xpdf-4.04/splash && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/splash/Splash.cc > CMakeFiles/splash_objs.dir/Splash.cc.i
+
+splash/CMakeFiles/splash_objs.dir/Splash.cc.s: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/splash_objs.dir/Splash.cc.s"
+ cd /home/calvin/src/xpdf-4.04/splash && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/splash/Splash.cc -o CMakeFiles/splash_objs.dir/Splash.cc.s
+
+splash/CMakeFiles/splash_objs.dir/SplashBitmap.cc.o: splash/CMakeFiles/splash_objs.dir/flags.make
+splash/CMakeFiles/splash_objs.dir/SplashBitmap.cc.o: splash/SplashBitmap.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 splash/CMakeFiles/splash_objs.dir/SplashBitmap.cc.o"
+ cd /home/calvin/src/xpdf-4.04/splash && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/splash_objs.dir/SplashBitmap.cc.o -c /home/calvin/src/xpdf-4.04/splash/SplashBitmap.cc
+
+splash/CMakeFiles/splash_objs.dir/SplashBitmap.cc.i: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/splash_objs.dir/SplashBitmap.cc.i"
+ cd /home/calvin/src/xpdf-4.04/splash && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/splash/SplashBitmap.cc > CMakeFiles/splash_objs.dir/SplashBitmap.cc.i
+
+splash/CMakeFiles/splash_objs.dir/SplashBitmap.cc.s: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/splash_objs.dir/SplashBitmap.cc.s"
+ cd /home/calvin/src/xpdf-4.04/splash && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/splash/SplashBitmap.cc -o CMakeFiles/splash_objs.dir/SplashBitmap.cc.s
+
+splash/CMakeFiles/splash_objs.dir/SplashClip.cc.o: splash/CMakeFiles/splash_objs.dir/flags.make
+splash/CMakeFiles/splash_objs.dir/SplashClip.cc.o: splash/SplashClip.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 splash/CMakeFiles/splash_objs.dir/SplashClip.cc.o"
+ cd /home/calvin/src/xpdf-4.04/splash && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/splash_objs.dir/SplashClip.cc.o -c /home/calvin/src/xpdf-4.04/splash/SplashClip.cc
+
+splash/CMakeFiles/splash_objs.dir/SplashClip.cc.i: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/splash_objs.dir/SplashClip.cc.i"
+ cd /home/calvin/src/xpdf-4.04/splash && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/splash/SplashClip.cc > CMakeFiles/splash_objs.dir/SplashClip.cc.i
+
+splash/CMakeFiles/splash_objs.dir/SplashClip.cc.s: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/splash_objs.dir/SplashClip.cc.s"
+ cd /home/calvin/src/xpdf-4.04/splash && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/splash/SplashClip.cc -o CMakeFiles/splash_objs.dir/SplashClip.cc.s
+
+splash/CMakeFiles/splash_objs.dir/SplashFTFont.cc.o: splash/CMakeFiles/splash_objs.dir/flags.make
+splash/CMakeFiles/splash_objs.dir/SplashFTFont.cc.o: splash/SplashFTFont.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 splash/CMakeFiles/splash_objs.dir/SplashFTFont.cc.o"
+ cd /home/calvin/src/xpdf-4.04/splash && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/splash_objs.dir/SplashFTFont.cc.o -c /home/calvin/src/xpdf-4.04/splash/SplashFTFont.cc
+
+splash/CMakeFiles/splash_objs.dir/SplashFTFont.cc.i: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/splash_objs.dir/SplashFTFont.cc.i"
+ cd /home/calvin/src/xpdf-4.04/splash && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/splash/SplashFTFont.cc > CMakeFiles/splash_objs.dir/SplashFTFont.cc.i
+
+splash/CMakeFiles/splash_objs.dir/SplashFTFont.cc.s: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/splash_objs.dir/SplashFTFont.cc.s"
+ cd /home/calvin/src/xpdf-4.04/splash && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/splash/SplashFTFont.cc -o CMakeFiles/splash_objs.dir/SplashFTFont.cc.s
+
+splash/CMakeFiles/splash_objs.dir/SplashFTFontEngine.cc.o: splash/CMakeFiles/splash_objs.dir/flags.make
+splash/CMakeFiles/splash_objs.dir/SplashFTFontEngine.cc.o: splash/SplashFTFontEngine.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 splash/CMakeFiles/splash_objs.dir/SplashFTFontEngine.cc.o"
+ cd /home/calvin/src/xpdf-4.04/splash && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/splash_objs.dir/SplashFTFontEngine.cc.o -c /home/calvin/src/xpdf-4.04/splash/SplashFTFontEngine.cc
+
+splash/CMakeFiles/splash_objs.dir/SplashFTFontEngine.cc.i: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/splash_objs.dir/SplashFTFontEngine.cc.i"
+ cd /home/calvin/src/xpdf-4.04/splash && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/splash/SplashFTFontEngine.cc > CMakeFiles/splash_objs.dir/SplashFTFontEngine.cc.i
+
+splash/CMakeFiles/splash_objs.dir/SplashFTFontEngine.cc.s: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/splash_objs.dir/SplashFTFontEngine.cc.s"
+ cd /home/calvin/src/xpdf-4.04/splash && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/splash/SplashFTFontEngine.cc -o CMakeFiles/splash_objs.dir/SplashFTFontEngine.cc.s
+
+splash/CMakeFiles/splash_objs.dir/SplashFTFontFile.cc.o: splash/CMakeFiles/splash_objs.dir/flags.make
+splash/CMakeFiles/splash_objs.dir/SplashFTFontFile.cc.o: splash/SplashFTFontFile.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 splash/CMakeFiles/splash_objs.dir/SplashFTFontFile.cc.o"
+ cd /home/calvin/src/xpdf-4.04/splash && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/splash_objs.dir/SplashFTFontFile.cc.o -c /home/calvin/src/xpdf-4.04/splash/SplashFTFontFile.cc
+
+splash/CMakeFiles/splash_objs.dir/SplashFTFontFile.cc.i: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/splash_objs.dir/SplashFTFontFile.cc.i"
+ cd /home/calvin/src/xpdf-4.04/splash && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/splash/SplashFTFontFile.cc > CMakeFiles/splash_objs.dir/SplashFTFontFile.cc.i
+
+splash/CMakeFiles/splash_objs.dir/SplashFTFontFile.cc.s: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/splash_objs.dir/SplashFTFontFile.cc.s"
+ cd /home/calvin/src/xpdf-4.04/splash && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/splash/SplashFTFontFile.cc -o CMakeFiles/splash_objs.dir/SplashFTFontFile.cc.s
+
+splash/CMakeFiles/splash_objs.dir/SplashFont.cc.o: splash/CMakeFiles/splash_objs.dir/flags.make
+splash/CMakeFiles/splash_objs.dir/SplashFont.cc.o: splash/SplashFont.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 splash/CMakeFiles/splash_objs.dir/SplashFont.cc.o"
+ cd /home/calvin/src/xpdf-4.04/splash && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/splash_objs.dir/SplashFont.cc.o -c /home/calvin/src/xpdf-4.04/splash/SplashFont.cc
+
+splash/CMakeFiles/splash_objs.dir/SplashFont.cc.i: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/splash_objs.dir/SplashFont.cc.i"
+ cd /home/calvin/src/xpdf-4.04/splash && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/splash/SplashFont.cc > CMakeFiles/splash_objs.dir/SplashFont.cc.i
+
+splash/CMakeFiles/splash_objs.dir/SplashFont.cc.s: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/splash_objs.dir/SplashFont.cc.s"
+ cd /home/calvin/src/xpdf-4.04/splash && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/splash/SplashFont.cc -o CMakeFiles/splash_objs.dir/SplashFont.cc.s
+
+splash/CMakeFiles/splash_objs.dir/SplashFontEngine.cc.o: splash/CMakeFiles/splash_objs.dir/flags.make
+splash/CMakeFiles/splash_objs.dir/SplashFontEngine.cc.o: splash/SplashFontEngine.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 splash/CMakeFiles/splash_objs.dir/SplashFontEngine.cc.o"
+ cd /home/calvin/src/xpdf-4.04/splash && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/splash_objs.dir/SplashFontEngine.cc.o -c /home/calvin/src/xpdf-4.04/splash/SplashFontEngine.cc
+
+splash/CMakeFiles/splash_objs.dir/SplashFontEngine.cc.i: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/splash_objs.dir/SplashFontEngine.cc.i"
+ cd /home/calvin/src/xpdf-4.04/splash && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/splash/SplashFontEngine.cc > CMakeFiles/splash_objs.dir/SplashFontEngine.cc.i
+
+splash/CMakeFiles/splash_objs.dir/SplashFontEngine.cc.s: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/splash_objs.dir/SplashFontEngine.cc.s"
+ cd /home/calvin/src/xpdf-4.04/splash && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/splash/SplashFontEngine.cc -o CMakeFiles/splash_objs.dir/SplashFontEngine.cc.s
+
+splash/CMakeFiles/splash_objs.dir/SplashFontFile.cc.o: splash/CMakeFiles/splash_objs.dir/flags.make
+splash/CMakeFiles/splash_objs.dir/SplashFontFile.cc.o: splash/SplashFontFile.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 splash/CMakeFiles/splash_objs.dir/SplashFontFile.cc.o"
+ cd /home/calvin/src/xpdf-4.04/splash && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/splash_objs.dir/SplashFontFile.cc.o -c /home/calvin/src/xpdf-4.04/splash/SplashFontFile.cc
+
+splash/CMakeFiles/splash_objs.dir/SplashFontFile.cc.i: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/splash_objs.dir/SplashFontFile.cc.i"
+ cd /home/calvin/src/xpdf-4.04/splash && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/splash/SplashFontFile.cc > CMakeFiles/splash_objs.dir/SplashFontFile.cc.i
+
+splash/CMakeFiles/splash_objs.dir/SplashFontFile.cc.s: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/splash_objs.dir/SplashFontFile.cc.s"
+ cd /home/calvin/src/xpdf-4.04/splash && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/splash/SplashFontFile.cc -o CMakeFiles/splash_objs.dir/SplashFontFile.cc.s
+
+splash/CMakeFiles/splash_objs.dir/SplashFontFileID.cc.o: splash/CMakeFiles/splash_objs.dir/flags.make
+splash/CMakeFiles/splash_objs.dir/SplashFontFileID.cc.o: splash/SplashFontFileID.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 splash/CMakeFiles/splash_objs.dir/SplashFontFileID.cc.o"
+ cd /home/calvin/src/xpdf-4.04/splash && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/splash_objs.dir/SplashFontFileID.cc.o -c /home/calvin/src/xpdf-4.04/splash/SplashFontFileID.cc
+
+splash/CMakeFiles/splash_objs.dir/SplashFontFileID.cc.i: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/splash_objs.dir/SplashFontFileID.cc.i"
+ cd /home/calvin/src/xpdf-4.04/splash && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/splash/SplashFontFileID.cc > CMakeFiles/splash_objs.dir/SplashFontFileID.cc.i
+
+splash/CMakeFiles/splash_objs.dir/SplashFontFileID.cc.s: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/splash_objs.dir/SplashFontFileID.cc.s"
+ cd /home/calvin/src/xpdf-4.04/splash && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/splash/SplashFontFileID.cc -o CMakeFiles/splash_objs.dir/SplashFontFileID.cc.s
+
+splash/CMakeFiles/splash_objs.dir/SplashPath.cc.o: splash/CMakeFiles/splash_objs.dir/flags.make
+splash/CMakeFiles/splash_objs.dir/SplashPath.cc.o: splash/SplashPath.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 splash/CMakeFiles/splash_objs.dir/SplashPath.cc.o"
+ cd /home/calvin/src/xpdf-4.04/splash && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/splash_objs.dir/SplashPath.cc.o -c /home/calvin/src/xpdf-4.04/splash/SplashPath.cc
+
+splash/CMakeFiles/splash_objs.dir/SplashPath.cc.i: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/splash_objs.dir/SplashPath.cc.i"
+ cd /home/calvin/src/xpdf-4.04/splash && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/splash/SplashPath.cc > CMakeFiles/splash_objs.dir/SplashPath.cc.i
+
+splash/CMakeFiles/splash_objs.dir/SplashPath.cc.s: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/splash_objs.dir/SplashPath.cc.s"
+ cd /home/calvin/src/xpdf-4.04/splash && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/splash/SplashPath.cc -o CMakeFiles/splash_objs.dir/SplashPath.cc.s
+
+splash/CMakeFiles/splash_objs.dir/SplashPattern.cc.o: splash/CMakeFiles/splash_objs.dir/flags.make
+splash/CMakeFiles/splash_objs.dir/SplashPattern.cc.o: splash/SplashPattern.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 splash/CMakeFiles/splash_objs.dir/SplashPattern.cc.o"
+ cd /home/calvin/src/xpdf-4.04/splash && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/splash_objs.dir/SplashPattern.cc.o -c /home/calvin/src/xpdf-4.04/splash/SplashPattern.cc
+
+splash/CMakeFiles/splash_objs.dir/SplashPattern.cc.i: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/splash_objs.dir/SplashPattern.cc.i"
+ cd /home/calvin/src/xpdf-4.04/splash && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/splash/SplashPattern.cc > CMakeFiles/splash_objs.dir/SplashPattern.cc.i
+
+splash/CMakeFiles/splash_objs.dir/SplashPattern.cc.s: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/splash_objs.dir/SplashPattern.cc.s"
+ cd /home/calvin/src/xpdf-4.04/splash && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/splash/SplashPattern.cc -o CMakeFiles/splash_objs.dir/SplashPattern.cc.s
+
+splash/CMakeFiles/splash_objs.dir/SplashScreen.cc.o: splash/CMakeFiles/splash_objs.dir/flags.make
+splash/CMakeFiles/splash_objs.dir/SplashScreen.cc.o: splash/SplashScreen.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 splash/CMakeFiles/splash_objs.dir/SplashScreen.cc.o"
+ cd /home/calvin/src/xpdf-4.04/splash && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/splash_objs.dir/SplashScreen.cc.o -c /home/calvin/src/xpdf-4.04/splash/SplashScreen.cc
+
+splash/CMakeFiles/splash_objs.dir/SplashScreen.cc.i: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/splash_objs.dir/SplashScreen.cc.i"
+ cd /home/calvin/src/xpdf-4.04/splash && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/splash/SplashScreen.cc > CMakeFiles/splash_objs.dir/SplashScreen.cc.i
+
+splash/CMakeFiles/splash_objs.dir/SplashScreen.cc.s: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/splash_objs.dir/SplashScreen.cc.s"
+ cd /home/calvin/src/xpdf-4.04/splash && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/splash/SplashScreen.cc -o CMakeFiles/splash_objs.dir/SplashScreen.cc.s
+
+splash/CMakeFiles/splash_objs.dir/SplashState.cc.o: splash/CMakeFiles/splash_objs.dir/flags.make
+splash/CMakeFiles/splash_objs.dir/SplashState.cc.o: splash/SplashState.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 splash/CMakeFiles/splash_objs.dir/SplashState.cc.o"
+ cd /home/calvin/src/xpdf-4.04/splash && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/splash_objs.dir/SplashState.cc.o -c /home/calvin/src/xpdf-4.04/splash/SplashState.cc
+
+splash/CMakeFiles/splash_objs.dir/SplashState.cc.i: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/splash_objs.dir/SplashState.cc.i"
+ cd /home/calvin/src/xpdf-4.04/splash && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/splash/SplashState.cc > CMakeFiles/splash_objs.dir/SplashState.cc.i
+
+splash/CMakeFiles/splash_objs.dir/SplashState.cc.s: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/splash_objs.dir/SplashState.cc.s"
+ cd /home/calvin/src/xpdf-4.04/splash && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/splash/SplashState.cc -o CMakeFiles/splash_objs.dir/SplashState.cc.s
+
+splash/CMakeFiles/splash_objs.dir/SplashXPath.cc.o: splash/CMakeFiles/splash_objs.dir/flags.make
+splash/CMakeFiles/splash_objs.dir/SplashXPath.cc.o: splash/SplashXPath.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 splash/CMakeFiles/splash_objs.dir/SplashXPath.cc.o"
+ cd /home/calvin/src/xpdf-4.04/splash && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/splash_objs.dir/SplashXPath.cc.o -c /home/calvin/src/xpdf-4.04/splash/SplashXPath.cc
+
+splash/CMakeFiles/splash_objs.dir/SplashXPath.cc.i: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/splash_objs.dir/SplashXPath.cc.i"
+ cd /home/calvin/src/xpdf-4.04/splash && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/splash/SplashXPath.cc > CMakeFiles/splash_objs.dir/SplashXPath.cc.i
+
+splash/CMakeFiles/splash_objs.dir/SplashXPath.cc.s: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/splash_objs.dir/SplashXPath.cc.s"
+ cd /home/calvin/src/xpdf-4.04/splash && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/splash/SplashXPath.cc -o CMakeFiles/splash_objs.dir/SplashXPath.cc.s
+
+splash/CMakeFiles/splash_objs.dir/SplashXPathScanner.cc.o: splash/CMakeFiles/splash_objs.dir/flags.make
+splash/CMakeFiles/splash_objs.dir/SplashXPathScanner.cc.o: splash/SplashXPathScanner.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 splash/CMakeFiles/splash_objs.dir/SplashXPathScanner.cc.o"
+ cd /home/calvin/src/xpdf-4.04/splash && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/splash_objs.dir/SplashXPathScanner.cc.o -c /home/calvin/src/xpdf-4.04/splash/SplashXPathScanner.cc
+
+splash/CMakeFiles/splash_objs.dir/SplashXPathScanner.cc.i: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/splash_objs.dir/SplashXPathScanner.cc.i"
+ cd /home/calvin/src/xpdf-4.04/splash && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/splash/SplashXPathScanner.cc > CMakeFiles/splash_objs.dir/SplashXPathScanner.cc.i
+
+splash/CMakeFiles/splash_objs.dir/SplashXPathScanner.cc.s: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/splash_objs.dir/SplashXPathScanner.cc.s"
+ cd /home/calvin/src/xpdf-4.04/splash && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/splash/SplashXPathScanner.cc -o CMakeFiles/splash_objs.dir/SplashXPathScanner.cc.s
+
+splash_objs: splash/CMakeFiles/splash_objs.dir/Splash.cc.o
+splash_objs: splash/CMakeFiles/splash_objs.dir/SplashBitmap.cc.o
+splash_objs: splash/CMakeFiles/splash_objs.dir/SplashClip.cc.o
+splash_objs: splash/CMakeFiles/splash_objs.dir/SplashFTFont.cc.o
+splash_objs: splash/CMakeFiles/splash_objs.dir/SplashFTFontEngine.cc.o
+splash_objs: splash/CMakeFiles/splash_objs.dir/SplashFTFontFile.cc.o
+splash_objs: splash/CMakeFiles/splash_objs.dir/SplashFont.cc.o
+splash_objs: splash/CMakeFiles/splash_objs.dir/SplashFontEngine.cc.o
+splash_objs: splash/CMakeFiles/splash_objs.dir/SplashFontFile.cc.o
+splash_objs: splash/CMakeFiles/splash_objs.dir/SplashFontFileID.cc.o
+splash_objs: splash/CMakeFiles/splash_objs.dir/SplashPath.cc.o
+splash_objs: splash/CMakeFiles/splash_objs.dir/SplashPattern.cc.o
+splash_objs: splash/CMakeFiles/splash_objs.dir/SplashScreen.cc.o
+splash_objs: splash/CMakeFiles/splash_objs.dir/SplashState.cc.o
+splash_objs: splash/CMakeFiles/splash_objs.dir/SplashXPath.cc.o
+splash_objs: splash/CMakeFiles/splash_objs.dir/SplashXPathScanner.cc.o
+splash_objs: splash/CMakeFiles/splash_objs.dir/build.make
+
+.PHONY : splash_objs
+
+# Rule to build all files generated by this target.
+splash/CMakeFiles/splash_objs.dir/build: splash_objs
+
+.PHONY : splash/CMakeFiles/splash_objs.dir/build
+
+splash/CMakeFiles/splash_objs.dir/clean:
+ cd /home/calvin/src/xpdf-4.04/splash && $(CMAKE_COMMAND) -P CMakeFiles/splash_objs.dir/cmake_clean.cmake
+.PHONY : splash/CMakeFiles/splash_objs.dir/clean
+
+splash/CMakeFiles/splash_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/splash /home/calvin/src/xpdf-4.04 /home/calvin/src/xpdf-4.04/splash /home/calvin/src/xpdf-4.04/splash/CMakeFiles/splash_objs.dir/DependInfo.cmake --color=$(COLOR)
+.PHONY : splash/CMakeFiles/splash_objs.dir/depend
+
diff --git a/splash/CMakeFiles/splash_objs.dir/cmake_clean.cmake b/splash/CMakeFiles/splash_objs.dir/cmake_clean.cmake
new file mode 100644
index 0000000..4ddf7b4
--- /dev/null
+++ b/splash/CMakeFiles/splash_objs.dir/cmake_clean.cmake
@@ -0,0 +1,23 @@
+file(REMOVE_RECURSE
+ "CMakeFiles/splash_objs.dir/Splash.cc.o"
+ "CMakeFiles/splash_objs.dir/SplashBitmap.cc.o"
+ "CMakeFiles/splash_objs.dir/SplashClip.cc.o"
+ "CMakeFiles/splash_objs.dir/SplashFTFont.cc.o"
+ "CMakeFiles/splash_objs.dir/SplashFTFontEngine.cc.o"
+ "CMakeFiles/splash_objs.dir/SplashFTFontFile.cc.o"
+ "CMakeFiles/splash_objs.dir/SplashFont.cc.o"
+ "CMakeFiles/splash_objs.dir/SplashFontEngine.cc.o"
+ "CMakeFiles/splash_objs.dir/SplashFontFile.cc.o"
+ "CMakeFiles/splash_objs.dir/SplashFontFileID.cc.o"
+ "CMakeFiles/splash_objs.dir/SplashPath.cc.o"
+ "CMakeFiles/splash_objs.dir/SplashPattern.cc.o"
+ "CMakeFiles/splash_objs.dir/SplashScreen.cc.o"
+ "CMakeFiles/splash_objs.dir/SplashState.cc.o"
+ "CMakeFiles/splash_objs.dir/SplashXPath.cc.o"
+ "CMakeFiles/splash_objs.dir/SplashXPathScanner.cc.o"
+)
+
+# Per-language clean rules from dependency scanning.
+foreach(lang CXX)
+ include(CMakeFiles/splash_objs.dir/cmake_clean_${lang}.cmake OPTIONAL)
+endforeach()
diff --git a/splash/CMakeFiles/splash_objs.dir/depend.internal b/splash/CMakeFiles/splash_objs.dir/depend.internal
new file mode 100644
index 0000000..c3ffc51
--- /dev/null
+++ b/splash/CMakeFiles/splash_objs.dir/depend.internal
@@ -0,0 +1,240 @@
+# CMAKE generated file: DO NOT EDIT!
+# Generated by "Unix Makefiles" Generator, CMake Version 3.18
+
+splash/CMakeFiles/splash_objs.dir/Splash.cc.o
+ /home/calvin/src/xpdf-4.04/splash/Splash.cc
+ /home/calvin/src/xpdf-4.04/splash/Splash.h
+ /home/calvin/src/xpdf-4.04/splash/SplashBitmap.h
+ /home/calvin/src/xpdf-4.04/splash/SplashClip.h
+ /home/calvin/src/xpdf-4.04/splash/SplashErrorCodes.h
+ /home/calvin/src/xpdf-4.04/splash/SplashFont.h
+ /home/calvin/src/xpdf-4.04/splash/SplashGlyphBitmap.h
+ /home/calvin/src/xpdf-4.04/splash/SplashMath.h
+ /home/calvin/src/xpdf-4.04/splash/SplashPath.h
+ /home/calvin/src/xpdf-4.04/splash/SplashPattern.h
+ /home/calvin/src/xpdf-4.04/splash/SplashScreen.h
+ /home/calvin/src/xpdf-4.04/splash/SplashState.h
+ /home/calvin/src/xpdf-4.04/splash/SplashTypes.h
+ /home/calvin/src/xpdf-4.04/splash/SplashXPath.h
+ /home/calvin/src/xpdf-4.04/splash/SplashXPathScanner.h
+ aconf.h
+ aconf2.h
+ goo/FixedPoint.h
+ goo/GString.h
+ goo/gmem.h
+ goo/gmempp.h
+ goo/gtypes.h
+splash/CMakeFiles/splash_objs.dir/SplashBitmap.cc.o
+ /home/calvin/src/xpdf-4.04/splash/SplashBitmap.cc
+ /home/calvin/src/xpdf-4.04/splash/SplashBitmap.h
+ /home/calvin/src/xpdf-4.04/splash/SplashErrorCodes.h
+ /home/calvin/src/xpdf-4.04/splash/SplashTypes.h
+ aconf.h
+ aconf2.h
+ goo/FixedPoint.h
+ goo/Trace.h
+ goo/gfile.h
+ goo/gmem.h
+ goo/gmempp.h
+ goo/gtypes.h
+splash/CMakeFiles/splash_objs.dir/SplashClip.cc.o
+ /home/calvin/src/xpdf-4.04/splash/SplashClip.cc
+ /home/calvin/src/xpdf-4.04/splash/SplashClip.h
+ /home/calvin/src/xpdf-4.04/splash/SplashErrorCodes.h
+ /home/calvin/src/xpdf-4.04/splash/SplashMath.h
+ /home/calvin/src/xpdf-4.04/splash/SplashPath.h
+ /home/calvin/src/xpdf-4.04/splash/SplashTypes.h
+ /home/calvin/src/xpdf-4.04/splash/SplashXPath.h
+ /home/calvin/src/xpdf-4.04/splash/SplashXPathScanner.h
+ aconf.h
+ aconf2.h
+ goo/FixedPoint.h
+ goo/gmem.h
+ goo/gmempp.h
+ goo/gtypes.h
+splash/CMakeFiles/splash_objs.dir/SplashFTFont.cc.o
+ /home/calvin/src/xpdf-4.04/splash/SplashFTFont.cc
+ /home/calvin/src/xpdf-4.04/splash/SplashFTFont.h
+ /home/calvin/src/xpdf-4.04/splash/SplashFTFontEngine.h
+ /home/calvin/src/xpdf-4.04/splash/SplashFTFontFile.h
+ /home/calvin/src/xpdf-4.04/splash/SplashFont.h
+ /home/calvin/src/xpdf-4.04/splash/SplashFontEngine.h
+ /home/calvin/src/xpdf-4.04/splash/SplashFontFile.h
+ /home/calvin/src/xpdf-4.04/splash/SplashGlyphBitmap.h
+ /home/calvin/src/xpdf-4.04/splash/SplashMath.h
+ /home/calvin/src/xpdf-4.04/splash/SplashPath.h
+ /home/calvin/src/xpdf-4.04/splash/SplashTypes.h
+ /usr/include/freetype2/freetype/config/ftheader.h
+ /usr/include/freetype2/ft2build.h
+ aconf.h
+ aconf2.h
+ goo/FixedPoint.h
+ goo/GMutex.h
+ goo/gmem.h
+ goo/gmempp.h
+ goo/gtypes.h
+splash/CMakeFiles/splash_objs.dir/SplashFTFontEngine.cc.o
+ /home/calvin/src/xpdf-4.04/splash/SplashFTFontEngine.cc
+ /home/calvin/src/xpdf-4.04/splash/SplashFTFontEngine.h
+ /home/calvin/src/xpdf-4.04/splash/SplashFTFontFile.h
+ /home/calvin/src/xpdf-4.04/splash/SplashFontFile.h
+ /home/calvin/src/xpdf-4.04/splash/SplashTypes.h
+ /usr/include/freetype2/freetype/config/ftheader.h
+ /usr/include/freetype2/ft2build.h
+ aconf.h
+ aconf2.h
+ fofi/FoFiBase.h
+ fofi/FoFiTrueType.h
+ fofi/FoFiType1C.h
+ goo/FixedPoint.h
+ goo/GMutex.h
+ goo/GString.h
+ goo/gfile.h
+ goo/gmem.h
+ goo/gmempp.h
+ goo/gtypes.h
+splash/CMakeFiles/splash_objs.dir/SplashFTFontFile.cc.o
+ /home/calvin/src/xpdf-4.04/splash/SplashFTFont.h
+ /home/calvin/src/xpdf-4.04/splash/SplashFTFontEngine.h
+ /home/calvin/src/xpdf-4.04/splash/SplashFTFontFile.cc
+ /home/calvin/src/xpdf-4.04/splash/SplashFTFontFile.h
+ /home/calvin/src/xpdf-4.04/splash/SplashFont.h
+ /home/calvin/src/xpdf-4.04/splash/SplashFontFile.h
+ /home/calvin/src/xpdf-4.04/splash/SplashMath.h
+ /home/calvin/src/xpdf-4.04/splash/SplashTypes.h
+ /usr/include/freetype2/freetype/config/ftheader.h
+ /usr/include/freetype2/ft2build.h
+ aconf.h
+ aconf2.h
+ goo/FixedPoint.h
+ goo/GMutex.h
+ goo/GString.h
+ goo/gmem.h
+ goo/gmempp.h
+ goo/gtypes.h
+splash/CMakeFiles/splash_objs.dir/SplashFont.cc.o
+ /home/calvin/src/xpdf-4.04/splash/SplashFont.cc
+ /home/calvin/src/xpdf-4.04/splash/SplashFont.h
+ /home/calvin/src/xpdf-4.04/splash/SplashFontFile.h
+ /home/calvin/src/xpdf-4.04/splash/SplashGlyphBitmap.h
+ /home/calvin/src/xpdf-4.04/splash/SplashMath.h
+ /home/calvin/src/xpdf-4.04/splash/SplashTypes.h
+ aconf.h
+ aconf2.h
+ goo/FixedPoint.h
+ goo/GMutex.h
+ goo/gmem.h
+ goo/gmempp.h
+ goo/gtypes.h
+splash/CMakeFiles/splash_objs.dir/SplashFontEngine.cc.o
+ /home/calvin/src/xpdf-4.04/splash/SplashFTFontEngine.h
+ /home/calvin/src/xpdf-4.04/splash/SplashFont.h
+ /home/calvin/src/xpdf-4.04/splash/SplashFontEngine.cc
+ /home/calvin/src/xpdf-4.04/splash/SplashFontEngine.h
+ /home/calvin/src/xpdf-4.04/splash/SplashFontFile.h
+ /home/calvin/src/xpdf-4.04/splash/SplashFontFileID.h
+ /home/calvin/src/xpdf-4.04/splash/SplashMath.h
+ /home/calvin/src/xpdf-4.04/splash/SplashTypes.h
+ /usr/include/freetype2/freetype/config/ftheader.h
+ /usr/include/freetype2/ft2build.h
+ aconf.h
+ aconf2.h
+ goo/FixedPoint.h
+ goo/GList.h
+ goo/GMutex.h
+ goo/GString.h
+ goo/gmem.h
+ goo/gmempp.h
+ goo/gtypes.h
+splash/CMakeFiles/splash_objs.dir/SplashFontFile.cc.o
+ /home/calvin/src/xpdf-4.04/splash/SplashFontFile.cc
+ /home/calvin/src/xpdf-4.04/splash/SplashFontFile.h
+ /home/calvin/src/xpdf-4.04/splash/SplashFontFileID.h
+ /home/calvin/src/xpdf-4.04/splash/SplashTypes.h
+ aconf.h
+ aconf2.h
+ goo/FixedPoint.h
+ goo/GMutex.h
+ goo/GString.h
+ goo/gmempp.h
+ goo/gtypes.h
+splash/CMakeFiles/splash_objs.dir/SplashFontFileID.cc.o
+ /home/calvin/src/xpdf-4.04/splash/SplashFontFileID.cc
+ /home/calvin/src/xpdf-4.04/splash/SplashFontFileID.h
+ aconf.h
+ aconf2.h
+ goo/gmempp.h
+ goo/gtypes.h
+splash/CMakeFiles/splash_objs.dir/SplashPath.cc.o
+ /home/calvin/src/xpdf-4.04/splash/SplashErrorCodes.h
+ /home/calvin/src/xpdf-4.04/splash/SplashPath.cc
+ /home/calvin/src/xpdf-4.04/splash/SplashPath.h
+ /home/calvin/src/xpdf-4.04/splash/SplashTypes.h
+ aconf.h
+ aconf2.h
+ goo/FixedPoint.h
+ goo/gmem.h
+ goo/gmempp.h
+ goo/gtypes.h
+splash/CMakeFiles/splash_objs.dir/SplashPattern.cc.o
+ /home/calvin/src/xpdf-4.04/splash/SplashMath.h
+ /home/calvin/src/xpdf-4.04/splash/SplashPattern.cc
+ /home/calvin/src/xpdf-4.04/splash/SplashPattern.h
+ /home/calvin/src/xpdf-4.04/splash/SplashScreen.h
+ /home/calvin/src/xpdf-4.04/splash/SplashTypes.h
+ aconf.h
+ aconf2.h
+ goo/FixedPoint.h
+ goo/gmempp.h
+ goo/gtypes.h
+splash/CMakeFiles/splash_objs.dir/SplashScreen.cc.o
+ /home/calvin/src/xpdf-4.04/splash/SplashMath.h
+ /home/calvin/src/xpdf-4.04/splash/SplashScreen.cc
+ /home/calvin/src/xpdf-4.04/splash/SplashScreen.h
+ /home/calvin/src/xpdf-4.04/splash/SplashTypes.h
+ aconf.h
+ aconf2.h
+ goo/FixedPoint.h
+ goo/gmem.h
+ goo/gmempp.h
+ goo/gtypes.h
+splash/CMakeFiles/splash_objs.dir/SplashState.cc.o
+ /home/calvin/src/xpdf-4.04/splash/SplashBitmap.h
+ /home/calvin/src/xpdf-4.04/splash/SplashClip.h
+ /home/calvin/src/xpdf-4.04/splash/SplashMath.h
+ /home/calvin/src/xpdf-4.04/splash/SplashPattern.h
+ /home/calvin/src/xpdf-4.04/splash/SplashScreen.h
+ /home/calvin/src/xpdf-4.04/splash/SplashState.cc
+ /home/calvin/src/xpdf-4.04/splash/SplashState.h
+ /home/calvin/src/xpdf-4.04/splash/SplashTypes.h
+ aconf.h
+ aconf2.h
+ goo/FixedPoint.h
+ goo/gmem.h
+ goo/gmempp.h
+ goo/gtypes.h
+splash/CMakeFiles/splash_objs.dir/SplashXPath.cc.o
+ /home/calvin/src/xpdf-4.04/splash/SplashMath.h
+ /home/calvin/src/xpdf-4.04/splash/SplashPath.h
+ /home/calvin/src/xpdf-4.04/splash/SplashTypes.h
+ /home/calvin/src/xpdf-4.04/splash/SplashXPath.cc
+ /home/calvin/src/xpdf-4.04/splash/SplashXPath.h
+ aconf.h
+ aconf2.h
+ goo/FixedPoint.h
+ goo/gmem.h
+ goo/gmempp.h
+ goo/gtypes.h
+splash/CMakeFiles/splash_objs.dir/SplashXPathScanner.cc.o
+ /home/calvin/src/xpdf-4.04/splash/SplashMath.h
+ /home/calvin/src/xpdf-4.04/splash/SplashTypes.h
+ /home/calvin/src/xpdf-4.04/splash/SplashXPath.h
+ /home/calvin/src/xpdf-4.04/splash/SplashXPathScanner.cc
+ /home/calvin/src/xpdf-4.04/splash/SplashXPathScanner.h
+ aconf.h
+ aconf2.h
+ goo/FixedPoint.h
+ goo/GList.h
+ goo/gmem.h
+ goo/gmempp.h
+ goo/gtypes.h
diff --git a/splash/CMakeFiles/splash_objs.dir/depend.make b/splash/CMakeFiles/splash_objs.dir/depend.make
new file mode 100644
index 0000000..a0f85ab
--- /dev/null
+++ b/splash/CMakeFiles/splash_objs.dir/depend.make
@@ -0,0 +1,240 @@
+# CMAKE generated file: DO NOT EDIT!
+# Generated by "Unix Makefiles" Generator, CMake Version 3.18
+
+splash/CMakeFiles/splash_objs.dir/Splash.cc.o: splash/Splash.cc
+splash/CMakeFiles/splash_objs.dir/Splash.cc.o: splash/Splash.h
+splash/CMakeFiles/splash_objs.dir/Splash.cc.o: splash/SplashBitmap.h
+splash/CMakeFiles/splash_objs.dir/Splash.cc.o: splash/SplashClip.h
+splash/CMakeFiles/splash_objs.dir/Splash.cc.o: splash/SplashErrorCodes.h
+splash/CMakeFiles/splash_objs.dir/Splash.cc.o: splash/SplashFont.h
+splash/CMakeFiles/splash_objs.dir/Splash.cc.o: splash/SplashGlyphBitmap.h
+splash/CMakeFiles/splash_objs.dir/Splash.cc.o: splash/SplashMath.h
+splash/CMakeFiles/splash_objs.dir/Splash.cc.o: splash/SplashPath.h
+splash/CMakeFiles/splash_objs.dir/Splash.cc.o: splash/SplashPattern.h
+splash/CMakeFiles/splash_objs.dir/Splash.cc.o: splash/SplashScreen.h
+splash/CMakeFiles/splash_objs.dir/Splash.cc.o: splash/SplashState.h
+splash/CMakeFiles/splash_objs.dir/Splash.cc.o: splash/SplashTypes.h
+splash/CMakeFiles/splash_objs.dir/Splash.cc.o: splash/SplashXPath.h
+splash/CMakeFiles/splash_objs.dir/Splash.cc.o: splash/SplashXPathScanner.h
+splash/CMakeFiles/splash_objs.dir/Splash.cc.o: aconf.h
+splash/CMakeFiles/splash_objs.dir/Splash.cc.o: aconf2.h
+splash/CMakeFiles/splash_objs.dir/Splash.cc.o: goo/FixedPoint.h
+splash/CMakeFiles/splash_objs.dir/Splash.cc.o: goo/GString.h
+splash/CMakeFiles/splash_objs.dir/Splash.cc.o: goo/gmem.h
+splash/CMakeFiles/splash_objs.dir/Splash.cc.o: goo/gmempp.h
+splash/CMakeFiles/splash_objs.dir/Splash.cc.o: goo/gtypes.h
+
+splash/CMakeFiles/splash_objs.dir/SplashBitmap.cc.o: splash/SplashBitmap.cc
+splash/CMakeFiles/splash_objs.dir/SplashBitmap.cc.o: splash/SplashBitmap.h
+splash/CMakeFiles/splash_objs.dir/SplashBitmap.cc.o: splash/SplashErrorCodes.h
+splash/CMakeFiles/splash_objs.dir/SplashBitmap.cc.o: splash/SplashTypes.h
+splash/CMakeFiles/splash_objs.dir/SplashBitmap.cc.o: aconf.h
+splash/CMakeFiles/splash_objs.dir/SplashBitmap.cc.o: aconf2.h
+splash/CMakeFiles/splash_objs.dir/SplashBitmap.cc.o: goo/FixedPoint.h
+splash/CMakeFiles/splash_objs.dir/SplashBitmap.cc.o: goo/Trace.h
+splash/CMakeFiles/splash_objs.dir/SplashBitmap.cc.o: goo/gfile.h
+splash/CMakeFiles/splash_objs.dir/SplashBitmap.cc.o: goo/gmem.h
+splash/CMakeFiles/splash_objs.dir/SplashBitmap.cc.o: goo/gmempp.h
+splash/CMakeFiles/splash_objs.dir/SplashBitmap.cc.o: goo/gtypes.h
+
+splash/CMakeFiles/splash_objs.dir/SplashClip.cc.o: splash/SplashClip.cc
+splash/CMakeFiles/splash_objs.dir/SplashClip.cc.o: splash/SplashClip.h
+splash/CMakeFiles/splash_objs.dir/SplashClip.cc.o: splash/SplashErrorCodes.h
+splash/CMakeFiles/splash_objs.dir/SplashClip.cc.o: splash/SplashMath.h
+splash/CMakeFiles/splash_objs.dir/SplashClip.cc.o: splash/SplashPath.h
+splash/CMakeFiles/splash_objs.dir/SplashClip.cc.o: splash/SplashTypes.h
+splash/CMakeFiles/splash_objs.dir/SplashClip.cc.o: splash/SplashXPath.h
+splash/CMakeFiles/splash_objs.dir/SplashClip.cc.o: splash/SplashXPathScanner.h
+splash/CMakeFiles/splash_objs.dir/SplashClip.cc.o: aconf.h
+splash/CMakeFiles/splash_objs.dir/SplashClip.cc.o: aconf2.h
+splash/CMakeFiles/splash_objs.dir/SplashClip.cc.o: goo/FixedPoint.h
+splash/CMakeFiles/splash_objs.dir/SplashClip.cc.o: goo/gmem.h
+splash/CMakeFiles/splash_objs.dir/SplashClip.cc.o: goo/gmempp.h
+splash/CMakeFiles/splash_objs.dir/SplashClip.cc.o: goo/gtypes.h
+
+splash/CMakeFiles/splash_objs.dir/SplashFTFont.cc.o: splash/SplashFTFont.cc
+splash/CMakeFiles/splash_objs.dir/SplashFTFont.cc.o: splash/SplashFTFont.h
+splash/CMakeFiles/splash_objs.dir/SplashFTFont.cc.o: splash/SplashFTFontEngine.h
+splash/CMakeFiles/splash_objs.dir/SplashFTFont.cc.o: splash/SplashFTFontFile.h
+splash/CMakeFiles/splash_objs.dir/SplashFTFont.cc.o: splash/SplashFont.h
+splash/CMakeFiles/splash_objs.dir/SplashFTFont.cc.o: splash/SplashFontEngine.h
+splash/CMakeFiles/splash_objs.dir/SplashFTFont.cc.o: splash/SplashFontFile.h
+splash/CMakeFiles/splash_objs.dir/SplashFTFont.cc.o: splash/SplashGlyphBitmap.h
+splash/CMakeFiles/splash_objs.dir/SplashFTFont.cc.o: splash/SplashMath.h
+splash/CMakeFiles/splash_objs.dir/SplashFTFont.cc.o: splash/SplashPath.h
+splash/CMakeFiles/splash_objs.dir/SplashFTFont.cc.o: splash/SplashTypes.h
+splash/CMakeFiles/splash_objs.dir/SplashFTFont.cc.o: /usr/include/freetype2/freetype/config/ftheader.h
+splash/CMakeFiles/splash_objs.dir/SplashFTFont.cc.o: /usr/include/freetype2/ft2build.h
+splash/CMakeFiles/splash_objs.dir/SplashFTFont.cc.o: aconf.h
+splash/CMakeFiles/splash_objs.dir/SplashFTFont.cc.o: aconf2.h
+splash/CMakeFiles/splash_objs.dir/SplashFTFont.cc.o: goo/FixedPoint.h
+splash/CMakeFiles/splash_objs.dir/SplashFTFont.cc.o: goo/GMutex.h
+splash/CMakeFiles/splash_objs.dir/SplashFTFont.cc.o: goo/gmem.h
+splash/CMakeFiles/splash_objs.dir/SplashFTFont.cc.o: goo/gmempp.h
+splash/CMakeFiles/splash_objs.dir/SplashFTFont.cc.o: goo/gtypes.h
+
+splash/CMakeFiles/splash_objs.dir/SplashFTFontEngine.cc.o: splash/SplashFTFontEngine.cc
+splash/CMakeFiles/splash_objs.dir/SplashFTFontEngine.cc.o: splash/SplashFTFontEngine.h
+splash/CMakeFiles/splash_objs.dir/SplashFTFontEngine.cc.o: splash/SplashFTFontFile.h
+splash/CMakeFiles/splash_objs.dir/SplashFTFontEngine.cc.o: splash/SplashFontFile.h
+splash/CMakeFiles/splash_objs.dir/SplashFTFontEngine.cc.o: splash/SplashTypes.h
+splash/CMakeFiles/splash_objs.dir/SplashFTFontEngine.cc.o: /usr/include/freetype2/freetype/config/ftheader.h
+splash/CMakeFiles/splash_objs.dir/SplashFTFontEngine.cc.o: /usr/include/freetype2/ft2build.h
+splash/CMakeFiles/splash_objs.dir/SplashFTFontEngine.cc.o: aconf.h
+splash/CMakeFiles/splash_objs.dir/SplashFTFontEngine.cc.o: aconf2.h
+splash/CMakeFiles/splash_objs.dir/SplashFTFontEngine.cc.o: fofi/FoFiBase.h
+splash/CMakeFiles/splash_objs.dir/SplashFTFontEngine.cc.o: fofi/FoFiTrueType.h
+splash/CMakeFiles/splash_objs.dir/SplashFTFontEngine.cc.o: fofi/FoFiType1C.h
+splash/CMakeFiles/splash_objs.dir/SplashFTFontEngine.cc.o: goo/FixedPoint.h
+splash/CMakeFiles/splash_objs.dir/SplashFTFontEngine.cc.o: goo/GMutex.h
+splash/CMakeFiles/splash_objs.dir/SplashFTFontEngine.cc.o: goo/GString.h
+splash/CMakeFiles/splash_objs.dir/SplashFTFontEngine.cc.o: goo/gfile.h
+splash/CMakeFiles/splash_objs.dir/SplashFTFontEngine.cc.o: goo/gmem.h
+splash/CMakeFiles/splash_objs.dir/SplashFTFontEngine.cc.o: goo/gmempp.h
+splash/CMakeFiles/splash_objs.dir/SplashFTFontEngine.cc.o: goo/gtypes.h
+
+splash/CMakeFiles/splash_objs.dir/SplashFTFontFile.cc.o: splash/SplashFTFont.h
+splash/CMakeFiles/splash_objs.dir/SplashFTFontFile.cc.o: splash/SplashFTFontEngine.h
+splash/CMakeFiles/splash_objs.dir/SplashFTFontFile.cc.o: splash/SplashFTFontFile.cc
+splash/CMakeFiles/splash_objs.dir/SplashFTFontFile.cc.o: splash/SplashFTFontFile.h
+splash/CMakeFiles/splash_objs.dir/SplashFTFontFile.cc.o: splash/SplashFont.h
+splash/CMakeFiles/splash_objs.dir/SplashFTFontFile.cc.o: splash/SplashFontFile.h
+splash/CMakeFiles/splash_objs.dir/SplashFTFontFile.cc.o: splash/SplashMath.h
+splash/CMakeFiles/splash_objs.dir/SplashFTFontFile.cc.o: splash/SplashTypes.h
+splash/CMakeFiles/splash_objs.dir/SplashFTFontFile.cc.o: /usr/include/freetype2/freetype/config/ftheader.h
+splash/CMakeFiles/splash_objs.dir/SplashFTFontFile.cc.o: /usr/include/freetype2/ft2build.h
+splash/CMakeFiles/splash_objs.dir/SplashFTFontFile.cc.o: aconf.h
+splash/CMakeFiles/splash_objs.dir/SplashFTFontFile.cc.o: aconf2.h
+splash/CMakeFiles/splash_objs.dir/SplashFTFontFile.cc.o: goo/FixedPoint.h
+splash/CMakeFiles/splash_objs.dir/SplashFTFontFile.cc.o: goo/GMutex.h
+splash/CMakeFiles/splash_objs.dir/SplashFTFontFile.cc.o: goo/GString.h
+splash/CMakeFiles/splash_objs.dir/SplashFTFontFile.cc.o: goo/gmem.h
+splash/CMakeFiles/splash_objs.dir/SplashFTFontFile.cc.o: goo/gmempp.h
+splash/CMakeFiles/splash_objs.dir/SplashFTFontFile.cc.o: goo/gtypes.h
+
+splash/CMakeFiles/splash_objs.dir/SplashFont.cc.o: splash/SplashFont.cc
+splash/CMakeFiles/splash_objs.dir/SplashFont.cc.o: splash/SplashFont.h
+splash/CMakeFiles/splash_objs.dir/SplashFont.cc.o: splash/SplashFontFile.h
+splash/CMakeFiles/splash_objs.dir/SplashFont.cc.o: splash/SplashGlyphBitmap.h
+splash/CMakeFiles/splash_objs.dir/SplashFont.cc.o: splash/SplashMath.h
+splash/CMakeFiles/splash_objs.dir/SplashFont.cc.o: splash/SplashTypes.h
+splash/CMakeFiles/splash_objs.dir/SplashFont.cc.o: aconf.h
+splash/CMakeFiles/splash_objs.dir/SplashFont.cc.o: aconf2.h
+splash/CMakeFiles/splash_objs.dir/SplashFont.cc.o: goo/FixedPoint.h
+splash/CMakeFiles/splash_objs.dir/SplashFont.cc.o: goo/GMutex.h
+splash/CMakeFiles/splash_objs.dir/SplashFont.cc.o: goo/gmem.h
+splash/CMakeFiles/splash_objs.dir/SplashFont.cc.o: goo/gmempp.h
+splash/CMakeFiles/splash_objs.dir/SplashFont.cc.o: goo/gtypes.h
+
+splash/CMakeFiles/splash_objs.dir/SplashFontEngine.cc.o: splash/SplashFTFontEngine.h
+splash/CMakeFiles/splash_objs.dir/SplashFontEngine.cc.o: splash/SplashFont.h
+splash/CMakeFiles/splash_objs.dir/SplashFontEngine.cc.o: splash/SplashFontEngine.cc
+splash/CMakeFiles/splash_objs.dir/SplashFontEngine.cc.o: splash/SplashFontEngine.h
+splash/CMakeFiles/splash_objs.dir/SplashFontEngine.cc.o: splash/SplashFontFile.h
+splash/CMakeFiles/splash_objs.dir/SplashFontEngine.cc.o: splash/SplashFontFileID.h
+splash/CMakeFiles/splash_objs.dir/SplashFontEngine.cc.o: splash/SplashMath.h
+splash/CMakeFiles/splash_objs.dir/SplashFontEngine.cc.o: splash/SplashTypes.h
+splash/CMakeFiles/splash_objs.dir/SplashFontEngine.cc.o: /usr/include/freetype2/freetype/config/ftheader.h
+splash/CMakeFiles/splash_objs.dir/SplashFontEngine.cc.o: /usr/include/freetype2/ft2build.h
+splash/CMakeFiles/splash_objs.dir/SplashFontEngine.cc.o: aconf.h
+splash/CMakeFiles/splash_objs.dir/SplashFontEngine.cc.o: aconf2.h
+splash/CMakeFiles/splash_objs.dir/SplashFontEngine.cc.o: goo/FixedPoint.h
+splash/CMakeFiles/splash_objs.dir/SplashFontEngine.cc.o: goo/GList.h
+splash/CMakeFiles/splash_objs.dir/SplashFontEngine.cc.o: goo/GMutex.h
+splash/CMakeFiles/splash_objs.dir/SplashFontEngine.cc.o: goo/GString.h
+splash/CMakeFiles/splash_objs.dir/SplashFontEngine.cc.o: goo/gmem.h
+splash/CMakeFiles/splash_objs.dir/SplashFontEngine.cc.o: goo/gmempp.h
+splash/CMakeFiles/splash_objs.dir/SplashFontEngine.cc.o: goo/gtypes.h
+
+splash/CMakeFiles/splash_objs.dir/SplashFontFile.cc.o: splash/SplashFontFile.cc
+splash/CMakeFiles/splash_objs.dir/SplashFontFile.cc.o: splash/SplashFontFile.h
+splash/CMakeFiles/splash_objs.dir/SplashFontFile.cc.o: splash/SplashFontFileID.h
+splash/CMakeFiles/splash_objs.dir/SplashFontFile.cc.o: splash/SplashTypes.h
+splash/CMakeFiles/splash_objs.dir/SplashFontFile.cc.o: aconf.h
+splash/CMakeFiles/splash_objs.dir/SplashFontFile.cc.o: aconf2.h
+splash/CMakeFiles/splash_objs.dir/SplashFontFile.cc.o: goo/FixedPoint.h
+splash/CMakeFiles/splash_objs.dir/SplashFontFile.cc.o: goo/GMutex.h
+splash/CMakeFiles/splash_objs.dir/SplashFontFile.cc.o: goo/GString.h
+splash/CMakeFiles/splash_objs.dir/SplashFontFile.cc.o: goo/gmempp.h
+splash/CMakeFiles/splash_objs.dir/SplashFontFile.cc.o: goo/gtypes.h
+
+splash/CMakeFiles/splash_objs.dir/SplashFontFileID.cc.o: splash/SplashFontFileID.cc
+splash/CMakeFiles/splash_objs.dir/SplashFontFileID.cc.o: splash/SplashFontFileID.h
+splash/CMakeFiles/splash_objs.dir/SplashFontFileID.cc.o: aconf.h
+splash/CMakeFiles/splash_objs.dir/SplashFontFileID.cc.o: aconf2.h
+splash/CMakeFiles/splash_objs.dir/SplashFontFileID.cc.o: goo/gmempp.h
+splash/CMakeFiles/splash_objs.dir/SplashFontFileID.cc.o: goo/gtypes.h
+
+splash/CMakeFiles/splash_objs.dir/SplashPath.cc.o: splash/SplashErrorCodes.h
+splash/CMakeFiles/splash_objs.dir/SplashPath.cc.o: splash/SplashPath.cc
+splash/CMakeFiles/splash_objs.dir/SplashPath.cc.o: splash/SplashPath.h
+splash/CMakeFiles/splash_objs.dir/SplashPath.cc.o: splash/SplashTypes.h
+splash/CMakeFiles/splash_objs.dir/SplashPath.cc.o: aconf.h
+splash/CMakeFiles/splash_objs.dir/SplashPath.cc.o: aconf2.h
+splash/CMakeFiles/splash_objs.dir/SplashPath.cc.o: goo/FixedPoint.h
+splash/CMakeFiles/splash_objs.dir/SplashPath.cc.o: goo/gmem.h
+splash/CMakeFiles/splash_objs.dir/SplashPath.cc.o: goo/gmempp.h
+splash/CMakeFiles/splash_objs.dir/SplashPath.cc.o: goo/gtypes.h
+
+splash/CMakeFiles/splash_objs.dir/SplashPattern.cc.o: splash/SplashMath.h
+splash/CMakeFiles/splash_objs.dir/SplashPattern.cc.o: splash/SplashPattern.cc
+splash/CMakeFiles/splash_objs.dir/SplashPattern.cc.o: splash/SplashPattern.h
+splash/CMakeFiles/splash_objs.dir/SplashPattern.cc.o: splash/SplashScreen.h
+splash/CMakeFiles/splash_objs.dir/SplashPattern.cc.o: splash/SplashTypes.h
+splash/CMakeFiles/splash_objs.dir/SplashPattern.cc.o: aconf.h
+splash/CMakeFiles/splash_objs.dir/SplashPattern.cc.o: aconf2.h
+splash/CMakeFiles/splash_objs.dir/SplashPattern.cc.o: goo/FixedPoint.h
+splash/CMakeFiles/splash_objs.dir/SplashPattern.cc.o: goo/gmempp.h
+splash/CMakeFiles/splash_objs.dir/SplashPattern.cc.o: goo/gtypes.h
+
+splash/CMakeFiles/splash_objs.dir/SplashScreen.cc.o: splash/SplashMath.h
+splash/CMakeFiles/splash_objs.dir/SplashScreen.cc.o: splash/SplashScreen.cc
+splash/CMakeFiles/splash_objs.dir/SplashScreen.cc.o: splash/SplashScreen.h
+splash/CMakeFiles/splash_objs.dir/SplashScreen.cc.o: splash/SplashTypes.h
+splash/CMakeFiles/splash_objs.dir/SplashScreen.cc.o: aconf.h
+splash/CMakeFiles/splash_objs.dir/SplashScreen.cc.o: aconf2.h
+splash/CMakeFiles/splash_objs.dir/SplashScreen.cc.o: goo/FixedPoint.h
+splash/CMakeFiles/splash_objs.dir/SplashScreen.cc.o: goo/gmem.h
+splash/CMakeFiles/splash_objs.dir/SplashScreen.cc.o: goo/gmempp.h
+splash/CMakeFiles/splash_objs.dir/SplashScreen.cc.o: goo/gtypes.h
+
+splash/CMakeFiles/splash_objs.dir/SplashState.cc.o: splash/SplashBitmap.h
+splash/CMakeFiles/splash_objs.dir/SplashState.cc.o: splash/SplashClip.h
+splash/CMakeFiles/splash_objs.dir/SplashState.cc.o: splash/SplashMath.h
+splash/CMakeFiles/splash_objs.dir/SplashState.cc.o: splash/SplashPattern.h
+splash/CMakeFiles/splash_objs.dir/SplashState.cc.o: splash/SplashScreen.h
+splash/CMakeFiles/splash_objs.dir/SplashState.cc.o: splash/SplashState.cc
+splash/CMakeFiles/splash_objs.dir/SplashState.cc.o: splash/SplashState.h
+splash/CMakeFiles/splash_objs.dir/SplashState.cc.o: splash/SplashTypes.h
+splash/CMakeFiles/splash_objs.dir/SplashState.cc.o: aconf.h
+splash/CMakeFiles/splash_objs.dir/SplashState.cc.o: aconf2.h
+splash/CMakeFiles/splash_objs.dir/SplashState.cc.o: goo/FixedPoint.h
+splash/CMakeFiles/splash_objs.dir/SplashState.cc.o: goo/gmem.h
+splash/CMakeFiles/splash_objs.dir/SplashState.cc.o: goo/gmempp.h
+splash/CMakeFiles/splash_objs.dir/SplashState.cc.o: goo/gtypes.h
+
+splash/CMakeFiles/splash_objs.dir/SplashXPath.cc.o: splash/SplashMath.h
+splash/CMakeFiles/splash_objs.dir/SplashXPath.cc.o: splash/SplashPath.h
+splash/CMakeFiles/splash_objs.dir/SplashXPath.cc.o: splash/SplashTypes.h
+splash/CMakeFiles/splash_objs.dir/SplashXPath.cc.o: splash/SplashXPath.cc
+splash/CMakeFiles/splash_objs.dir/SplashXPath.cc.o: splash/SplashXPath.h
+splash/CMakeFiles/splash_objs.dir/SplashXPath.cc.o: aconf.h
+splash/CMakeFiles/splash_objs.dir/SplashXPath.cc.o: aconf2.h
+splash/CMakeFiles/splash_objs.dir/SplashXPath.cc.o: goo/FixedPoint.h
+splash/CMakeFiles/splash_objs.dir/SplashXPath.cc.o: goo/gmem.h
+splash/CMakeFiles/splash_objs.dir/SplashXPath.cc.o: goo/gmempp.h
+splash/CMakeFiles/splash_objs.dir/SplashXPath.cc.o: goo/gtypes.h
+
+splash/CMakeFiles/splash_objs.dir/SplashXPathScanner.cc.o: splash/SplashMath.h
+splash/CMakeFiles/splash_objs.dir/SplashXPathScanner.cc.o: splash/SplashTypes.h
+splash/CMakeFiles/splash_objs.dir/SplashXPathScanner.cc.o: splash/SplashXPath.h
+splash/CMakeFiles/splash_objs.dir/SplashXPathScanner.cc.o: splash/SplashXPathScanner.cc
+splash/CMakeFiles/splash_objs.dir/SplashXPathScanner.cc.o: splash/SplashXPathScanner.h
+splash/CMakeFiles/splash_objs.dir/SplashXPathScanner.cc.o: aconf.h
+splash/CMakeFiles/splash_objs.dir/SplashXPathScanner.cc.o: aconf2.h
+splash/CMakeFiles/splash_objs.dir/SplashXPathScanner.cc.o: goo/FixedPoint.h
+splash/CMakeFiles/splash_objs.dir/SplashXPathScanner.cc.o: goo/GList.h
+splash/CMakeFiles/splash_objs.dir/SplashXPathScanner.cc.o: goo/gmem.h
+splash/CMakeFiles/splash_objs.dir/SplashXPathScanner.cc.o: goo/gmempp.h
+splash/CMakeFiles/splash_objs.dir/SplashXPathScanner.cc.o: goo/gtypes.h
+
diff --git a/splash/CMakeFiles/splash_objs.dir/flags.make b/splash/CMakeFiles/splash_objs.dir/flags.make
new file mode 100644
index 0000000..2adb3c6
--- /dev/null
+++ b/splash/CMakeFiles/splash_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/usr/include/freetype2
+
+CXX_FLAGS = -fPIC
+
diff --git a/splash/CMakeFiles/splash_objs.dir/progress.make b/splash/CMakeFiles/splash_objs.dir/progress.make
new file mode 100644
index 0000000..3fb0f77
--- /dev/null
+++ b/splash/CMakeFiles/splash_objs.dir/progress.make
@@ -0,0 +1,17 @@
+CMAKE_PROGRESS_1 = 38
+CMAKE_PROGRESS_2 = 39
+CMAKE_PROGRESS_3 = 40
+CMAKE_PROGRESS_4 =
+CMAKE_PROGRESS_5 = 41
+CMAKE_PROGRESS_6 = 42
+CMAKE_PROGRESS_7 =
+CMAKE_PROGRESS_8 = 43
+CMAKE_PROGRESS_9 = 44
+CMAKE_PROGRESS_10 = 45
+CMAKE_PROGRESS_11 =
+CMAKE_PROGRESS_12 = 46
+CMAKE_PROGRESS_13 = 47
+CMAKE_PROGRESS_14 = 48
+CMAKE_PROGRESS_15 =
+CMAKE_PROGRESS_16 = 49
+
diff --git a/splash/CMakeLists.txt b/splash/CMakeLists.txt
new file mode 100644
index 0000000..4ac14ed
--- /dev/null
+++ b/splash/CMakeLists.txt
@@ -0,0 +1,49 @@
+#========================================================================
+#
+# splash/CMakeLists.txt
+#
+# CMake script for the splash library.
+#
+# Copyright 2015 Glyph & Cog, LLC
+#
+#========================================================================
+
+if (HAVE_SPLASH)
+ include_directories("${PROJECT_SOURCE_DIR}")
+ include_directories("${PROJECT_BINARY_DIR}")
+ include_directories("${PROJECT_SOURCE_DIR}/goo")
+ include_directories("${PROJECT_SOURCE_DIR}/fofi")
+ include_directories("${FREETYPE_INCLUDE_DIRS}")
+
+ if (HAVE_DTYPE4_H)
+ include_directories("${DTYPE_INCLUDE_DIR}")
+ set(DTYPE_SRCS
+ SplashDT4Font.cc SplashDT4FontEngine.cc SplashDT4FontFile.cc)
+ endif ()
+
+ add_library(splash_objs OBJECT
+ Splash.cc
+ SplashBitmap.cc
+ SplashClip.cc
+ SplashFTFont.cc
+ SplashFTFontEngine.cc
+ SplashFTFontFile.cc
+ SplashFont.cc
+ SplashFontEngine.cc
+ SplashFontFile.cc
+ SplashFontFileID.cc
+ SplashPath.cc
+ SplashPattern.cc
+ SplashScreen.cc
+ SplashState.cc
+ SplashXPath.cc
+ SplashXPathScanner.cc
+ ${DTYPE_SRCS}
+ )
+ set_property(TARGET splash_objs
+ PROPERTY POSITION_INDEPENDENT_CODE True)
+
+ add_library(splash
+ $<TARGET_OBJECTS:splash_objs>
+ )
+endif ()
diff --git a/splash/Makefile b/splash/Makefile
new file mode 100644
index 0000000..cf5a512
--- /dev/null
+++ b/splash/Makefile
@@ -0,0 +1,715 @@
+# 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 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 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 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/splash//CMakeFiles/progress.marks
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 splash/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 splash/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 splash/preinstall
+.PHONY : preinstall
+
+# Prepare targets for installation.
+preinstall/fast:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 splash/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.
+splash/CMakeFiles/splash.dir/rule:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 splash/CMakeFiles/splash.dir/rule
+.PHONY : splash/CMakeFiles/splash.dir/rule
+
+# Convenience name for target.
+splash: splash/CMakeFiles/splash.dir/rule
+
+.PHONY : splash
+
+# fast build rule for target.
+splash/fast:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f splash/CMakeFiles/splash.dir/build.make splash/CMakeFiles/splash.dir/build
+.PHONY : splash/fast
+
+# Convenience name for target.
+splash/CMakeFiles/splash_objs.dir/rule:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 splash/CMakeFiles/splash_objs.dir/rule
+.PHONY : splash/CMakeFiles/splash_objs.dir/rule
+
+# Convenience name for target.
+splash_objs: splash/CMakeFiles/splash_objs.dir/rule
+
+.PHONY : splash_objs
+
+# fast build rule for target.
+splash_objs/fast:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f splash/CMakeFiles/splash_objs.dir/build.make splash/CMakeFiles/splash_objs.dir/build
+.PHONY : splash_objs/fast
+
+Splash.o: Splash.cc.o
+
+.PHONY : Splash.o
+
+# target to build an object file
+Splash.cc.o:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f splash/CMakeFiles/splash_objs.dir/build.make splash/CMakeFiles/splash_objs.dir/Splash.cc.o
+.PHONY : Splash.cc.o
+
+Splash.i: Splash.cc.i
+
+.PHONY : Splash.i
+
+# target to preprocess a source file
+Splash.cc.i:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f splash/CMakeFiles/splash_objs.dir/build.make splash/CMakeFiles/splash_objs.dir/Splash.cc.i
+.PHONY : Splash.cc.i
+
+Splash.s: Splash.cc.s
+
+.PHONY : Splash.s
+
+# target to generate assembly for a file
+Splash.cc.s:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f splash/CMakeFiles/splash_objs.dir/build.make splash/CMakeFiles/splash_objs.dir/Splash.cc.s
+.PHONY : Splash.cc.s
+
+SplashBitmap.o: SplashBitmap.cc.o
+
+.PHONY : SplashBitmap.o
+
+# target to build an object file
+SplashBitmap.cc.o:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f splash/CMakeFiles/splash_objs.dir/build.make splash/CMakeFiles/splash_objs.dir/SplashBitmap.cc.o
+.PHONY : SplashBitmap.cc.o
+
+SplashBitmap.i: SplashBitmap.cc.i
+
+.PHONY : SplashBitmap.i
+
+# target to preprocess a source file
+SplashBitmap.cc.i:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f splash/CMakeFiles/splash_objs.dir/build.make splash/CMakeFiles/splash_objs.dir/SplashBitmap.cc.i
+.PHONY : SplashBitmap.cc.i
+
+SplashBitmap.s: SplashBitmap.cc.s
+
+.PHONY : SplashBitmap.s
+
+# target to generate assembly for a file
+SplashBitmap.cc.s:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f splash/CMakeFiles/splash_objs.dir/build.make splash/CMakeFiles/splash_objs.dir/SplashBitmap.cc.s
+.PHONY : SplashBitmap.cc.s
+
+SplashClip.o: SplashClip.cc.o
+
+.PHONY : SplashClip.o
+
+# target to build an object file
+SplashClip.cc.o:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f splash/CMakeFiles/splash_objs.dir/build.make splash/CMakeFiles/splash_objs.dir/SplashClip.cc.o
+.PHONY : SplashClip.cc.o
+
+SplashClip.i: SplashClip.cc.i
+
+.PHONY : SplashClip.i
+
+# target to preprocess a source file
+SplashClip.cc.i:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f splash/CMakeFiles/splash_objs.dir/build.make splash/CMakeFiles/splash_objs.dir/SplashClip.cc.i
+.PHONY : SplashClip.cc.i
+
+SplashClip.s: SplashClip.cc.s
+
+.PHONY : SplashClip.s
+
+# target to generate assembly for a file
+SplashClip.cc.s:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f splash/CMakeFiles/splash_objs.dir/build.make splash/CMakeFiles/splash_objs.dir/SplashClip.cc.s
+.PHONY : SplashClip.cc.s
+
+SplashFTFont.o: SplashFTFont.cc.o
+
+.PHONY : SplashFTFont.o
+
+# target to build an object file
+SplashFTFont.cc.o:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f splash/CMakeFiles/splash_objs.dir/build.make splash/CMakeFiles/splash_objs.dir/SplashFTFont.cc.o
+.PHONY : SplashFTFont.cc.o
+
+SplashFTFont.i: SplashFTFont.cc.i
+
+.PHONY : SplashFTFont.i
+
+# target to preprocess a source file
+SplashFTFont.cc.i:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f splash/CMakeFiles/splash_objs.dir/build.make splash/CMakeFiles/splash_objs.dir/SplashFTFont.cc.i
+.PHONY : SplashFTFont.cc.i
+
+SplashFTFont.s: SplashFTFont.cc.s
+
+.PHONY : SplashFTFont.s
+
+# target to generate assembly for a file
+SplashFTFont.cc.s:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f splash/CMakeFiles/splash_objs.dir/build.make splash/CMakeFiles/splash_objs.dir/SplashFTFont.cc.s
+.PHONY : SplashFTFont.cc.s
+
+SplashFTFontEngine.o: SplashFTFontEngine.cc.o
+
+.PHONY : SplashFTFontEngine.o
+
+# target to build an object file
+SplashFTFontEngine.cc.o:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f splash/CMakeFiles/splash_objs.dir/build.make splash/CMakeFiles/splash_objs.dir/SplashFTFontEngine.cc.o
+.PHONY : SplashFTFontEngine.cc.o
+
+SplashFTFontEngine.i: SplashFTFontEngine.cc.i
+
+.PHONY : SplashFTFontEngine.i
+
+# target to preprocess a source file
+SplashFTFontEngine.cc.i:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f splash/CMakeFiles/splash_objs.dir/build.make splash/CMakeFiles/splash_objs.dir/SplashFTFontEngine.cc.i
+.PHONY : SplashFTFontEngine.cc.i
+
+SplashFTFontEngine.s: SplashFTFontEngine.cc.s
+
+.PHONY : SplashFTFontEngine.s
+
+# target to generate assembly for a file
+SplashFTFontEngine.cc.s:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f splash/CMakeFiles/splash_objs.dir/build.make splash/CMakeFiles/splash_objs.dir/SplashFTFontEngine.cc.s
+.PHONY : SplashFTFontEngine.cc.s
+
+SplashFTFontFile.o: SplashFTFontFile.cc.o
+
+.PHONY : SplashFTFontFile.o
+
+# target to build an object file
+SplashFTFontFile.cc.o:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f splash/CMakeFiles/splash_objs.dir/build.make splash/CMakeFiles/splash_objs.dir/SplashFTFontFile.cc.o
+.PHONY : SplashFTFontFile.cc.o
+
+SplashFTFontFile.i: SplashFTFontFile.cc.i
+
+.PHONY : SplashFTFontFile.i
+
+# target to preprocess a source file
+SplashFTFontFile.cc.i:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f splash/CMakeFiles/splash_objs.dir/build.make splash/CMakeFiles/splash_objs.dir/SplashFTFontFile.cc.i
+.PHONY : SplashFTFontFile.cc.i
+
+SplashFTFontFile.s: SplashFTFontFile.cc.s
+
+.PHONY : SplashFTFontFile.s
+
+# target to generate assembly for a file
+SplashFTFontFile.cc.s:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f splash/CMakeFiles/splash_objs.dir/build.make splash/CMakeFiles/splash_objs.dir/SplashFTFontFile.cc.s
+.PHONY : SplashFTFontFile.cc.s
+
+SplashFont.o: SplashFont.cc.o
+
+.PHONY : SplashFont.o
+
+# target to build an object file
+SplashFont.cc.o:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f splash/CMakeFiles/splash_objs.dir/build.make splash/CMakeFiles/splash_objs.dir/SplashFont.cc.o
+.PHONY : SplashFont.cc.o
+
+SplashFont.i: SplashFont.cc.i
+
+.PHONY : SplashFont.i
+
+# target to preprocess a source file
+SplashFont.cc.i:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f splash/CMakeFiles/splash_objs.dir/build.make splash/CMakeFiles/splash_objs.dir/SplashFont.cc.i
+.PHONY : SplashFont.cc.i
+
+SplashFont.s: SplashFont.cc.s
+
+.PHONY : SplashFont.s
+
+# target to generate assembly for a file
+SplashFont.cc.s:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f splash/CMakeFiles/splash_objs.dir/build.make splash/CMakeFiles/splash_objs.dir/SplashFont.cc.s
+.PHONY : SplashFont.cc.s
+
+SplashFontEngine.o: SplashFontEngine.cc.o
+
+.PHONY : SplashFontEngine.o
+
+# target to build an object file
+SplashFontEngine.cc.o:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f splash/CMakeFiles/splash_objs.dir/build.make splash/CMakeFiles/splash_objs.dir/SplashFontEngine.cc.o
+.PHONY : SplashFontEngine.cc.o
+
+SplashFontEngine.i: SplashFontEngine.cc.i
+
+.PHONY : SplashFontEngine.i
+
+# target to preprocess a source file
+SplashFontEngine.cc.i:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f splash/CMakeFiles/splash_objs.dir/build.make splash/CMakeFiles/splash_objs.dir/SplashFontEngine.cc.i
+.PHONY : SplashFontEngine.cc.i
+
+SplashFontEngine.s: SplashFontEngine.cc.s
+
+.PHONY : SplashFontEngine.s
+
+# target to generate assembly for a file
+SplashFontEngine.cc.s:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f splash/CMakeFiles/splash_objs.dir/build.make splash/CMakeFiles/splash_objs.dir/SplashFontEngine.cc.s
+.PHONY : SplashFontEngine.cc.s
+
+SplashFontFile.o: SplashFontFile.cc.o
+
+.PHONY : SplashFontFile.o
+
+# target to build an object file
+SplashFontFile.cc.o:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f splash/CMakeFiles/splash_objs.dir/build.make splash/CMakeFiles/splash_objs.dir/SplashFontFile.cc.o
+.PHONY : SplashFontFile.cc.o
+
+SplashFontFile.i: SplashFontFile.cc.i
+
+.PHONY : SplashFontFile.i
+
+# target to preprocess a source file
+SplashFontFile.cc.i:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f splash/CMakeFiles/splash_objs.dir/build.make splash/CMakeFiles/splash_objs.dir/SplashFontFile.cc.i
+.PHONY : SplashFontFile.cc.i
+
+SplashFontFile.s: SplashFontFile.cc.s
+
+.PHONY : SplashFontFile.s
+
+# target to generate assembly for a file
+SplashFontFile.cc.s:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f splash/CMakeFiles/splash_objs.dir/build.make splash/CMakeFiles/splash_objs.dir/SplashFontFile.cc.s
+.PHONY : SplashFontFile.cc.s
+
+SplashFontFileID.o: SplashFontFileID.cc.o
+
+.PHONY : SplashFontFileID.o
+
+# target to build an object file
+SplashFontFileID.cc.o:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f splash/CMakeFiles/splash_objs.dir/build.make splash/CMakeFiles/splash_objs.dir/SplashFontFileID.cc.o
+.PHONY : SplashFontFileID.cc.o
+
+SplashFontFileID.i: SplashFontFileID.cc.i
+
+.PHONY : SplashFontFileID.i
+
+# target to preprocess a source file
+SplashFontFileID.cc.i:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f splash/CMakeFiles/splash_objs.dir/build.make splash/CMakeFiles/splash_objs.dir/SplashFontFileID.cc.i
+.PHONY : SplashFontFileID.cc.i
+
+SplashFontFileID.s: SplashFontFileID.cc.s
+
+.PHONY : SplashFontFileID.s
+
+# target to generate assembly for a file
+SplashFontFileID.cc.s:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f splash/CMakeFiles/splash_objs.dir/build.make splash/CMakeFiles/splash_objs.dir/SplashFontFileID.cc.s
+.PHONY : SplashFontFileID.cc.s
+
+SplashPath.o: SplashPath.cc.o
+
+.PHONY : SplashPath.o
+
+# target to build an object file
+SplashPath.cc.o:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f splash/CMakeFiles/splash_objs.dir/build.make splash/CMakeFiles/splash_objs.dir/SplashPath.cc.o
+.PHONY : SplashPath.cc.o
+
+SplashPath.i: SplashPath.cc.i
+
+.PHONY : SplashPath.i
+
+# target to preprocess a source file
+SplashPath.cc.i:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f splash/CMakeFiles/splash_objs.dir/build.make splash/CMakeFiles/splash_objs.dir/SplashPath.cc.i
+.PHONY : SplashPath.cc.i
+
+SplashPath.s: SplashPath.cc.s
+
+.PHONY : SplashPath.s
+
+# target to generate assembly for a file
+SplashPath.cc.s:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f splash/CMakeFiles/splash_objs.dir/build.make splash/CMakeFiles/splash_objs.dir/SplashPath.cc.s
+.PHONY : SplashPath.cc.s
+
+SplashPattern.o: SplashPattern.cc.o
+
+.PHONY : SplashPattern.o
+
+# target to build an object file
+SplashPattern.cc.o:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f splash/CMakeFiles/splash_objs.dir/build.make splash/CMakeFiles/splash_objs.dir/SplashPattern.cc.o
+.PHONY : SplashPattern.cc.o
+
+SplashPattern.i: SplashPattern.cc.i
+
+.PHONY : SplashPattern.i
+
+# target to preprocess a source file
+SplashPattern.cc.i:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f splash/CMakeFiles/splash_objs.dir/build.make splash/CMakeFiles/splash_objs.dir/SplashPattern.cc.i
+.PHONY : SplashPattern.cc.i
+
+SplashPattern.s: SplashPattern.cc.s
+
+.PHONY : SplashPattern.s
+
+# target to generate assembly for a file
+SplashPattern.cc.s:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f splash/CMakeFiles/splash_objs.dir/build.make splash/CMakeFiles/splash_objs.dir/SplashPattern.cc.s
+.PHONY : SplashPattern.cc.s
+
+SplashScreen.o: SplashScreen.cc.o
+
+.PHONY : SplashScreen.o
+
+# target to build an object file
+SplashScreen.cc.o:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f splash/CMakeFiles/splash_objs.dir/build.make splash/CMakeFiles/splash_objs.dir/SplashScreen.cc.o
+.PHONY : SplashScreen.cc.o
+
+SplashScreen.i: SplashScreen.cc.i
+
+.PHONY : SplashScreen.i
+
+# target to preprocess a source file
+SplashScreen.cc.i:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f splash/CMakeFiles/splash_objs.dir/build.make splash/CMakeFiles/splash_objs.dir/SplashScreen.cc.i
+.PHONY : SplashScreen.cc.i
+
+SplashScreen.s: SplashScreen.cc.s
+
+.PHONY : SplashScreen.s
+
+# target to generate assembly for a file
+SplashScreen.cc.s:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f splash/CMakeFiles/splash_objs.dir/build.make splash/CMakeFiles/splash_objs.dir/SplashScreen.cc.s
+.PHONY : SplashScreen.cc.s
+
+SplashState.o: SplashState.cc.o
+
+.PHONY : SplashState.o
+
+# target to build an object file
+SplashState.cc.o:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f splash/CMakeFiles/splash_objs.dir/build.make splash/CMakeFiles/splash_objs.dir/SplashState.cc.o
+.PHONY : SplashState.cc.o
+
+SplashState.i: SplashState.cc.i
+
+.PHONY : SplashState.i
+
+# target to preprocess a source file
+SplashState.cc.i:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f splash/CMakeFiles/splash_objs.dir/build.make splash/CMakeFiles/splash_objs.dir/SplashState.cc.i
+.PHONY : SplashState.cc.i
+
+SplashState.s: SplashState.cc.s
+
+.PHONY : SplashState.s
+
+# target to generate assembly for a file
+SplashState.cc.s:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f splash/CMakeFiles/splash_objs.dir/build.make splash/CMakeFiles/splash_objs.dir/SplashState.cc.s
+.PHONY : SplashState.cc.s
+
+SplashXPath.o: SplashXPath.cc.o
+
+.PHONY : SplashXPath.o
+
+# target to build an object file
+SplashXPath.cc.o:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f splash/CMakeFiles/splash_objs.dir/build.make splash/CMakeFiles/splash_objs.dir/SplashXPath.cc.o
+.PHONY : SplashXPath.cc.o
+
+SplashXPath.i: SplashXPath.cc.i
+
+.PHONY : SplashXPath.i
+
+# target to preprocess a source file
+SplashXPath.cc.i:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f splash/CMakeFiles/splash_objs.dir/build.make splash/CMakeFiles/splash_objs.dir/SplashXPath.cc.i
+.PHONY : SplashXPath.cc.i
+
+SplashXPath.s: SplashXPath.cc.s
+
+.PHONY : SplashXPath.s
+
+# target to generate assembly for a file
+SplashXPath.cc.s:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f splash/CMakeFiles/splash_objs.dir/build.make splash/CMakeFiles/splash_objs.dir/SplashXPath.cc.s
+.PHONY : SplashXPath.cc.s
+
+SplashXPathScanner.o: SplashXPathScanner.cc.o
+
+.PHONY : SplashXPathScanner.o
+
+# target to build an object file
+SplashXPathScanner.cc.o:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f splash/CMakeFiles/splash_objs.dir/build.make splash/CMakeFiles/splash_objs.dir/SplashXPathScanner.cc.o
+.PHONY : SplashXPathScanner.cc.o
+
+SplashXPathScanner.i: SplashXPathScanner.cc.i
+
+.PHONY : SplashXPathScanner.i
+
+# target to preprocess a source file
+SplashXPathScanner.cc.i:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f splash/CMakeFiles/splash_objs.dir/build.make splash/CMakeFiles/splash_objs.dir/SplashXPathScanner.cc.i
+.PHONY : SplashXPathScanner.cc.i
+
+SplashXPathScanner.s: SplashXPathScanner.cc.s
+
+.PHONY : SplashXPathScanner.s
+
+# target to generate assembly for a file
+SplashXPathScanner.cc.s:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f splash/CMakeFiles/splash_objs.dir/build.make splash/CMakeFiles/splash_objs.dir/SplashXPathScanner.cc.s
+.PHONY : SplashXPathScanner.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 "... splash"
+ @echo "... splash_objs"
+ @echo "... Splash.o"
+ @echo "... Splash.i"
+ @echo "... Splash.s"
+ @echo "... SplashBitmap.o"
+ @echo "... SplashBitmap.i"
+ @echo "... SplashBitmap.s"
+ @echo "... SplashClip.o"
+ @echo "... SplashClip.i"
+ @echo "... SplashClip.s"
+ @echo "... SplashFTFont.o"
+ @echo "... SplashFTFont.i"
+ @echo "... SplashFTFont.s"
+ @echo "... SplashFTFontEngine.o"
+ @echo "... SplashFTFontEngine.i"
+ @echo "... SplashFTFontEngine.s"
+ @echo "... SplashFTFontFile.o"
+ @echo "... SplashFTFontFile.i"
+ @echo "... SplashFTFontFile.s"
+ @echo "... SplashFont.o"
+ @echo "... SplashFont.i"
+ @echo "... SplashFont.s"
+ @echo "... SplashFontEngine.o"
+ @echo "... SplashFontEngine.i"
+ @echo "... SplashFontEngine.s"
+ @echo "... SplashFontFile.o"
+ @echo "... SplashFontFile.i"
+ @echo "... SplashFontFile.s"
+ @echo "... SplashFontFileID.o"
+ @echo "... SplashFontFileID.i"
+ @echo "... SplashFontFileID.s"
+ @echo "... SplashPath.o"
+ @echo "... SplashPath.i"
+ @echo "... SplashPath.s"
+ @echo "... SplashPattern.o"
+ @echo "... SplashPattern.i"
+ @echo "... SplashPattern.s"
+ @echo "... SplashScreen.o"
+ @echo "... SplashScreen.i"
+ @echo "... SplashScreen.s"
+ @echo "... SplashState.o"
+ @echo "... SplashState.i"
+ @echo "... SplashState.s"
+ @echo "... SplashXPath.o"
+ @echo "... SplashXPath.i"
+ @echo "... SplashXPath.s"
+ @echo "... SplashXPathScanner.o"
+ @echo "... SplashXPathScanner.i"
+ @echo "... SplashXPathScanner.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/splash/Splash.cc b/splash/Splash.cc
new file mode 100644
index 0000000..4afe21b
--- /dev/null
+++ b/splash/Splash.cc
@@ -0,0 +1,8521 @@
+//========================================================================
+//
+// Splash.cc
+//
+// Copyright 2003-2020 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <math.h>
+#include "gmem.h"
+#include "gmempp.h"
+#include "GString.h"
+#include "SplashErrorCodes.h"
+#include "SplashMath.h"
+#include "SplashBitmap.h"
+#include "SplashState.h"
+#include "SplashPath.h"
+#include "SplashXPath.h"
+#include "SplashXPathScanner.h"
+#include "SplashPattern.h"
+#include "SplashScreen.h"
+#include "SplashFont.h"
+#include "SplashGlyphBitmap.h"
+#include "Splash.h"
+
+// the MSVC math.h doesn't define this
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
+//------------------------------------------------------------------------
+
+// distance of Bezier control point from center for circle approximation
+// = (4 * (sqrt(2) - 1) / 3) * r
+#define bezierCircle ((SplashCoord)0.55228475)
+#define bezierCircle2 ((SplashCoord)(0.5 * 0.55228475))
+
+// 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;
+}
+
+// Used by drawImage and fillImageMask to divide the target
+// quadrilateral into sections.
+struct ImageSection {
+ int y0, y1; // actual y range
+ int ia0, ia1; // vertex indices for edge A
+ int ib0, ib1; // vertex indices for edge B
+ SplashCoord xa0, ya0, xa1, ya1; // edge A
+ SplashCoord dxdya; // slope of edge A
+ SplashCoord xb0, yb0, xb1, yb1; // edge B
+ SplashCoord dxdyb; // slope of edge B
+};
+
+//------------------------------------------------------------------------
+// SplashPipe
+//------------------------------------------------------------------------
+
+#define splashPipeMaxStages 9
+
+struct SplashPipe {
+ // source pattern
+ SplashPattern *pattern;
+
+ // source alpha and color
+ Guchar aInput;
+ SplashColor cSrcVal;
+
+ // source overprint mask
+ //~ this is a kludge - this pointer should be passed as an arg to the
+ //~ pipeRun function, but that would require passing in a lot of
+ //~ null pointers, since it's rarely used
+ Guint *srcOverprintMaskPtr;
+
+ // special cases and result color
+ GBool noTransparency;
+ GBool shapeOnly;
+ SplashPipeResultColorCtrl resultColorCtrl;
+
+ // non-isolated group correction
+ // (this is only used when Splash::composite() is called to composite
+ // a non-isolated group onto the backdrop)
+ GBool nonIsolatedGroup;
+
+ // the "run" function
+ void (Splash::*run)(SplashPipe *pipe, int x0, int x1, int y,
+ Guchar *shapePtr, SplashColorPtr cSrcPtr);
+};
+
+SplashPipeResultColorCtrl Splash::pipeResultColorNoAlphaBlend[] = {
+ splashPipeResultColorNoAlphaBlendMono,
+ splashPipeResultColorNoAlphaBlendMono,
+ splashPipeResultColorNoAlphaBlendRGB,
+ splashPipeResultColorNoAlphaBlendRGB
+#if SPLASH_CMYK
+ ,
+ splashPipeResultColorNoAlphaBlendCMYK
+#endif
+};
+
+SplashPipeResultColorCtrl Splash::pipeResultColorAlphaNoBlend[] = {
+ splashPipeResultColorAlphaNoBlendMono,
+ splashPipeResultColorAlphaNoBlendMono,
+ splashPipeResultColorAlphaNoBlendRGB,
+ splashPipeResultColorAlphaNoBlendRGB
+#if SPLASH_CMYK
+ ,
+ splashPipeResultColorAlphaNoBlendCMYK
+#endif
+};
+
+SplashPipeResultColorCtrl Splash::pipeResultColorAlphaBlend[] = {
+ splashPipeResultColorAlphaBlendMono,
+ splashPipeResultColorAlphaBlendMono,
+ splashPipeResultColorAlphaBlendRGB,
+ splashPipeResultColorAlphaBlendRGB
+#if SPLASH_CMYK
+ ,
+ splashPipeResultColorAlphaBlendCMYK
+#endif
+};
+
+//------------------------------------------------------------------------
+// modified region
+//------------------------------------------------------------------------
+
+void Splash::clearModRegion() {
+ modXMin = bitmap->width;
+ modYMin = bitmap->height;
+ modXMax = -1;
+ modYMax = -1;
+}
+
+inline void Splash::updateModX(int x) {
+ if (x < modXMin) {
+ modXMin = x;
+ }
+ if (x > modXMax) {
+ modXMax = x;
+ }
+}
+
+inline void Splash::updateModY(int y) {
+ if (y < modYMin) {
+ modYMin = y;
+ }
+ if (y > modYMax) {
+ modYMax = y;
+ }
+}
+
+//------------------------------------------------------------------------
+// pipeline
+//------------------------------------------------------------------------
+
+inline void Splash::pipeInit(SplashPipe *pipe, SplashPattern *pattern,
+ Guchar aInput, GBool usesShape,
+ GBool nonIsolatedGroup, GBool usesSrcOverprint) {
+ SplashColorMode mode;
+
+ mode = bitmap->mode;
+
+ pipe->pattern = NULL;
+
+ // source color
+ if (pattern && pattern->isStatic()) {
+ pattern->getColor(0, 0, pipe->cSrcVal);
+ pipe->pattern = NULL;
+ } else {
+ pipe->pattern = pattern;
+ }
+
+ // source alpha
+ pipe->aInput = aInput;
+
+ // source overprint mask
+ pipe->srcOverprintMaskPtr = NULL;
+
+ // special cases
+ pipe->noTransparency = aInput == 255 &&
+ !state->softMask &&
+ !usesShape &&
+ !state->inNonIsolatedGroup &&
+ !state->inKnockoutGroup &&
+ !nonIsolatedGroup &&
+ state->overprintMask == 0xffffffff;
+ pipe->shapeOnly = aInput == 255 &&
+ !state->softMask &&
+ usesShape &&
+ !state->inNonIsolatedGroup &&
+ !state->inKnockoutGroup &&
+ !nonIsolatedGroup &&
+ state->overprintMask == 0xffffffff;
+
+ // result color
+ if (pipe->noTransparency) {
+ // the !state->blendFunc case is handled separately in pipeRun
+ pipe->resultColorCtrl = pipeResultColorNoAlphaBlend[mode];
+ } else if (!state->blendFunc) {
+ pipe->resultColorCtrl = pipeResultColorAlphaNoBlend[mode];
+ } else {
+ pipe->resultColorCtrl = pipeResultColorAlphaBlend[mode];
+ }
+
+ // non-isolated group correction
+ pipe->nonIsolatedGroup = nonIsolatedGroup;
+
+ // select the 'run' function
+ pipe->run = &Splash::pipeRun;
+ if (overprintMaskBitmap || usesSrcOverprint) {
+ // use Splash::pipeRun
+ } else if (!pipe->pattern && pipe->noTransparency && !state->blendFunc) {
+ if (mode == splashModeMono1 && !bitmap->alpha) {
+ pipe->run = &Splash::pipeRunSimpleMono1;
+ } else if (mode == splashModeMono8 && bitmap->alpha) {
+ pipe->run = &Splash::pipeRunSimpleMono8;
+ } else if (mode == splashModeRGB8 && bitmap->alpha) {
+ pipe->run = &Splash::pipeRunSimpleRGB8;
+ } else if (mode == splashModeBGR8 && bitmap->alpha) {
+ pipe->run = &Splash::pipeRunSimpleBGR8;
+#if SPLASH_CMYK
+ } else if (mode == splashModeCMYK8 && bitmap->alpha) {
+ pipe->run = &Splash::pipeRunSimpleCMYK8;
+#endif
+ }
+ } else if (!pipe->pattern && pipe->shapeOnly && !state->blendFunc) {
+ if (mode == splashModeMono1 && !bitmap->alpha) {
+ pipe->run = &Splash::pipeRunShapeMono1;
+ } else if (mode == splashModeMono8 && bitmap->alpha) {
+ pipe->run = &Splash::pipeRunShapeMono8;
+ } else if (mode == splashModeRGB8 && bitmap->alpha) {
+ pipe->run = &Splash::pipeRunShapeRGB8;
+ } else if (mode == splashModeBGR8 && bitmap->alpha) {
+ pipe->run = &Splash::pipeRunShapeBGR8;
+#if SPLASH_CMYK
+ } else if (mode == splashModeCMYK8 && bitmap->alpha) {
+ pipe->run = &Splash::pipeRunShapeCMYK8;
+#endif
+ } else if (mode == splashModeMono8 && !bitmap->alpha) {
+ // this is used when drawing soft-masked images
+ pipe->run = &Splash::pipeRunShapeNoAlphaMono8;
+ }
+ } else if (!pipe->pattern && !pipe->noTransparency && !state->softMask &&
+ usesShape &&
+ !(state->inNonIsolatedGroup && groupBackBitmap->alpha) &&
+ !state->inKnockoutGroup &&
+ !state->blendFunc && !pipe->nonIsolatedGroup) {
+ if (mode == splashModeMono1 && !bitmap->alpha) {
+ pipe->run = &Splash::pipeRunAAMono1;
+ } else if (mode == splashModeMono8 && bitmap->alpha) {
+ pipe->run = &Splash::pipeRunAAMono8;
+ } else if (mode == splashModeRGB8 && bitmap->alpha) {
+ pipe->run = &Splash::pipeRunAARGB8;
+ } else if (mode == splashModeBGR8 && bitmap->alpha) {
+ pipe->run = &Splash::pipeRunAABGR8;
+#if SPLASH_CMYK
+ } else if (mode == splashModeCMYK8 && bitmap->alpha) {
+ pipe->run = &Splash::pipeRunAACMYK8;
+#endif
+ }
+ } else if (!pipe->pattern &&
+ aInput == 255 &&
+ state->softMask &&
+ usesShape &&
+ !state->inNonIsolatedGroup &&
+ !state->inKnockoutGroup &&
+ !nonIsolatedGroup &&
+ state->overprintMask == 0xffffffff &&
+ !state->blendFunc) {
+ if (mode == splashModeMono8 && bitmap->alpha) {
+ pipe->run = &Splash::pipeRunSoftMaskMono8;
+ } else if (mode == splashModeRGB8 && bitmap->alpha) {
+ pipe->run = &Splash::pipeRunSoftMaskRGB8;
+ } else if (mode == splashModeBGR8 && bitmap->alpha) {
+ pipe->run = &Splash::pipeRunSoftMaskBGR8;
+#if SPLASH_CMYK
+ } else if (mode == splashModeCMYK8 && bitmap->alpha) {
+ pipe->run = &Splash::pipeRunSoftMaskCMYK8;
+#endif
+ }
+ } else if (!pipe->pattern && !pipe->noTransparency && !state->softMask &&
+ usesShape &&
+ state->inNonIsolatedGroup && groupBackBitmap->alpha &&
+ !state->inKnockoutGroup &&
+ !state->blendFunc && !pipe->nonIsolatedGroup) {
+ if (mode == splashModeMono8 && bitmap->alpha) {
+ pipe->run = &Splash::pipeRunNonIsoMono8;
+ } else if (mode == splashModeRGB8 && bitmap->alpha) {
+ pipe->run = &Splash::pipeRunNonIsoRGB8;
+ } else if (mode == splashModeBGR8 && bitmap->alpha) {
+ pipe->run = &Splash::pipeRunNonIsoBGR8;
+#if SPLASH_CMYK
+ } else if (mode == splashModeCMYK8 && bitmap->alpha) {
+ pipe->run = &Splash::pipeRunNonIsoCMYK8;
+#endif
+ }
+ }
+}
+
+// general case
+void Splash::pipeRun(SplashPipe *pipe, int x0, int x1, int y,
+ Guchar *shapePtr, SplashColorPtr cSrcPtr) {
+ Guchar *shapePtr2;
+ Guchar shape, aSrc, aDest, alphaI, alphaIm1, alpha0, aResult;
+ SplashColor cSrc, cDest, cBlend;
+ Guchar shapeVal, cResult0, cResult1, cResult2, cResult3;
+ int cSrcStride, shapeStride, x, lastX, t;
+ SplashColorPtr destColorPtr;
+ Guchar destColorMask;
+ Guchar *destAlphaPtr;
+ SplashColorPtr color0Ptr;
+ Guchar color0Mask;
+ Guchar *alpha0Ptr;
+ SplashColorPtr softMaskPtr;
+ Guint overprintMask;
+ Guint *overprintMaskPtr;
+#if SPLASH_CMYK
+ Guchar aPrev;
+ SplashColor cSrc2, cDest2;
+#endif
+
+ if (cSrcPtr && !pipe->pattern) {
+ cSrcStride = bitmapComps;
+ } else {
+ cSrcPtr = pipe->cSrcVal;
+ cSrcStride = 0;
+ }
+
+ if (shapePtr) {
+ shapePtr2 = shapePtr;
+ shapeStride = 1;
+ for (; x0 <= x1; ++x0) {
+ if (*shapePtr2) {
+ break;
+ }
+ cSrcPtr += cSrcStride;
+ ++shapePtr2;
+ if (pipe->srcOverprintMaskPtr) {
+ ++pipe->srcOverprintMaskPtr;
+ }
+ }
+ } else {
+ shapeVal = 0xff;
+ shapePtr2 = &shapeVal;
+ shapeStride = 0;
+ }
+ if (x0 > x1) {
+ return;
+ }
+ updateModX(x0);
+ updateModY(y);
+ lastX = x0;
+
+ useDestRow(y);
+
+ if (bitmap->mode == splashModeMono1) {
+ destColorPtr = &bitmap->data[y * bitmap->rowSize + (x0 >> 3)];
+ destColorMask = (Guchar)(0x80 >> (x0 & 7));
+ } else {
+ destColorPtr = &bitmap->data[y * bitmap->rowSize + x0 * bitmapComps];
+ destColorMask = 0; // make gcc happy
+ }
+ if (bitmap->alpha) {
+ destAlphaPtr = &bitmap->alpha[y * bitmap->alphaRowSize + x0];
+ } else {
+ destAlphaPtr = NULL;
+ }
+ if (state->softMask) {
+ softMaskPtr = &state->softMask->data[y * state->softMask->rowSize + x0];
+ } else {
+ softMaskPtr = NULL;
+ }
+ if (state->inKnockoutGroup) {
+ if (bitmap->mode == splashModeMono1) {
+ color0Ptr =
+ &groupBackBitmap->data[(groupBackY + y) * groupBackBitmap->rowSize +
+ ((groupBackX + x0) >> 3)];
+ color0Mask = (Guchar)(0x80 >> ((groupBackX + x0) & 7));
+ } else {
+ color0Ptr =
+ &groupBackBitmap->data[(groupBackY + y) * groupBackBitmap->rowSize +
+ (groupBackX + x0) * bitmapComps];
+ color0Mask = 0; // make gcc happy
+ }
+ } else {
+ color0Ptr = NULL;
+ color0Mask = 0; // make gcc happy
+ }
+ if (state->inNonIsolatedGroup && groupBackBitmap->alpha) {
+ alpha0Ptr =
+ &groupBackBitmap->alpha[(groupBackY + y)
+ * groupBackBitmap->alphaRowSize +
+ (groupBackX + x0)];
+ } else {
+ alpha0Ptr = NULL;
+ }
+ if (overprintMaskBitmap) {
+ overprintMaskPtr = overprintMaskBitmap + y * bitmap->width + x0;
+ } else {
+ overprintMaskPtr = NULL;
+ }
+
+ for (x = x0; x <= x1; ++x) {
+
+ //----- shape
+
+ shape = *shapePtr2;
+ if (!shape) {
+ if (bitmap->mode == splashModeMono1) {
+ destColorPtr += destColorMask & 1;
+ destColorMask = (Guchar)((destColorMask << 7) | (destColorMask >> 1));
+ } else {
+ destColorPtr += bitmapComps;
+ }
+ if (destAlphaPtr) {
+ ++destAlphaPtr;
+ }
+ if (softMaskPtr) {
+ ++softMaskPtr;
+ }
+ if (color0Ptr) {
+ if (bitmap->mode == splashModeMono1) {
+ color0Ptr += color0Mask & 1;
+ color0Mask = (Guchar)((color0Mask << 7) | (color0Mask >> 1));
+ } else {
+ color0Ptr += bitmapComps;
+ }
+ }
+ if (alpha0Ptr) {
+ ++alpha0Ptr;
+ }
+ cSrcPtr += cSrcStride;
+ shapePtr2 += shapeStride;
+ if (pipe->srcOverprintMaskPtr) {
+ ++pipe->srcOverprintMaskPtr;
+ }
+ if (overprintMaskPtr) {
+ ++overprintMaskPtr;
+ }
+ continue;
+ }
+ lastX = x;
+
+ //----- source color
+
+ // static pattern: handled in pipeInit
+ // fixed color: handled in pipeInit
+
+ // dynamic pattern
+ if (pipe->pattern) {
+ pipe->pattern->getColor(x, y, pipe->cSrcVal);
+ }
+
+ cResult0 = cResult1 = cResult2 = cResult3 = 0; // make gcc happy
+
+ if (pipe->noTransparency && !state->blendFunc) {
+
+ //----- handle overprint
+
+ if (overprintMaskPtr) {
+ *overprintMaskPtr++ = 0xffffffff;
+ }
+
+ //----- result color
+
+ switch (bitmap->mode) {
+ case splashModeMono1:
+ case splashModeMono8:
+ cResult0 = state->grayTransfer[cSrcPtr[0]];
+ break;
+ case splashModeRGB8:
+ case splashModeBGR8:
+ cResult0 = state->rgbTransferR[cSrcPtr[0]];
+ cResult1 = state->rgbTransferG[cSrcPtr[1]];
+ cResult2 = state->rgbTransferB[cSrcPtr[2]];
+ break;
+#if SPLASH_CMYK
+ case splashModeCMYK8:
+ cResult0 = state->cmykTransferC[cSrcPtr[0]];
+ cResult1 = state->cmykTransferM[cSrcPtr[1]];
+ cResult2 = state->cmykTransferY[cSrcPtr[2]];
+ cResult3 = state->cmykTransferK[cSrcPtr[3]];
+ break;
+#endif
+ }
+ aResult = 255;
+
+ } else { // if (noTransparency && !blendFunc)
+
+ //----- read destination pixel
+ // (or backdrop color, for knockout groups)
+
+ if (color0Ptr) {
+
+ switch (bitmap->mode) {
+ case splashModeMono1:
+ cDest[0] = (*color0Ptr & color0Mask) ? 0xff : 0x00;
+ color0Ptr += color0Mask & 1;
+ color0Mask = (Guchar)((color0Mask << 7) | (color0Mask >> 1));
+ break;
+ case splashModeMono8:
+ cDest[0] = *color0Ptr++;
+ break;
+ case splashModeRGB8:
+ cDest[0] = color0Ptr[0];
+ cDest[1] = color0Ptr[1];
+ cDest[2] = color0Ptr[2];
+ color0Ptr += 3;
+ break;
+ case splashModeBGR8:
+ cDest[2] = color0Ptr[0];
+ cDest[1] = color0Ptr[1];
+ cDest[0] = color0Ptr[2];
+ color0Ptr += 3;
+ break;
+#if SPLASH_CMYK
+ case splashModeCMYK8:
+ cDest[0] = color0Ptr[0];
+ cDest[1] = color0Ptr[1];
+ cDest[2] = color0Ptr[2];
+ cDest[3] = color0Ptr[3];
+ color0Ptr += 4;
+ break;
+#endif
+ }
+
+ } else {
+
+ switch (bitmap->mode) {
+ case splashModeMono1:
+ cDest[0] = (*destColorPtr & destColorMask) ? 0xff : 0x00;
+ break;
+ case splashModeMono8:
+ cDest[0] = *destColorPtr;
+ break;
+ case splashModeRGB8:
+ cDest[0] = destColorPtr[0];
+ cDest[1] = destColorPtr[1];
+ cDest[2] = destColorPtr[2];
+ break;
+ case splashModeBGR8:
+ cDest[0] = destColorPtr[2];
+ cDest[1] = destColorPtr[1];
+ cDest[2] = destColorPtr[0];
+ break;
+#if SPLASH_CMYK
+ case splashModeCMYK8:
+ cDest[0] = destColorPtr[0];
+ cDest[1] = destColorPtr[1];
+ cDest[2] = destColorPtr[2];
+ cDest[3] = destColorPtr[3];
+ break;
+#endif
+ }
+
+ }
+
+ if (destAlphaPtr) {
+ aDest = *destAlphaPtr;
+ } else {
+ aDest = 0xff;
+ }
+
+ //----- read source color; handle overprint
+
+ if (pipe->srcOverprintMaskPtr) {
+ overprintMask = *pipe->srcOverprintMaskPtr++;
+ } else {
+ overprintMask = state->overprintMask;
+ }
+ if (overprintMaskPtr) {
+ *overprintMaskPtr++ |= overprintMask;
+ }
+
+ switch (bitmap->mode) {
+ case splashModeMono1:
+ case splashModeMono8:
+ cSrc[0] = state->grayTransfer[cSrcPtr[0]];
+ break;
+ case splashModeRGB8:
+ case splashModeBGR8:
+ cSrc[0] = state->rgbTransferR[cSrcPtr[0]];
+ cSrc[1] = state->rgbTransferG[cSrcPtr[1]];
+ cSrc[2] = state->rgbTransferB[cSrcPtr[2]];
+ break;
+#if SPLASH_CMYK
+ case splashModeCMYK8:
+ if (alpha0Ptr) { // non-isolated group
+ if (color0Ptr) { // non-isolated, knockout group
+ aPrev = *alpha0Ptr;
+ } else { // non-isolated, non-knockout group
+ aPrev = (Guchar)(*alpha0Ptr + aDest - div255(*alpha0Ptr * aDest));
+ }
+ } else { // isolated group
+ if (color0Ptr) { // isolated, knockout group
+ aPrev = 0;
+ } else { // isolated, non-knockout group
+ aPrev = aDest;
+ }
+ }
+ if (overprintMask & 0x01) {
+ cSrc[0] = state->cmykTransferC[cSrcPtr[0]];
+ } else {
+ cSrc[0] = div255(aPrev * cDest[0]);
+ }
+ if (overprintMask & 0x02) {
+ cSrc[1] = state->cmykTransferM[cSrcPtr[1]];
+ } else {
+ cSrc[1] = div255(aPrev * cDest[1]);
+ }
+ if (overprintMask & 0x04) {
+ cSrc[2] = state->cmykTransferY[cSrcPtr[2]];
+ } else {
+ cSrc[2] = div255(aPrev * cDest[2]);
+ }
+ if (overprintMask & 0x08) {
+ cSrc[3] = state->cmykTransferK[cSrcPtr[3]];
+ } else {
+ cSrc[3] = div255(aPrev * cDest[3]);
+ }
+ break;
+#endif
+ }
+
+ //----- source alpha
+
+ if (softMaskPtr) {
+ if (shapePtr) {
+ aSrc = div255(div255(pipe->aInput * *softMaskPtr++) * shape);
+ } else {
+ aSrc = div255(pipe->aInput * *softMaskPtr++);
+ }
+ } else if (shapePtr) {
+ aSrc = div255(pipe->aInput * shape);
+ } else {
+ aSrc = pipe->aInput;
+ }
+
+ //----- non-isolated group correction
+
+ if (pipe->nonIsolatedGroup) {
+ // This path is only used when Splash::composite() is called to
+ // composite a non-isolated group onto the backdrop. In this
+ // case, shape is the source (group) alpha.
+ //
+ // In a nested non-isolated group, i.e., if the destination is
+ // also a non-isolated group (state->inNonIsolatedGroup), we
+ // need to compute the corrected alpha, because the
+ // destination is is storing group alpha (same computation as
+ // blitCorrectedAlpha).
+ if (alpha0Ptr) {
+ t = *alpha0Ptr;
+ t = (Guchar)(aDest + t - div255(aDest * t));
+ } else {
+ t = aDest;
+ }
+ t = (t * 255) / shape - t;
+ switch (bitmap->mode) {
+#if SPLASH_CMYK
+ case splashModeCMYK8:
+ cSrc[3] = clip255(cSrc[3] + ((cSrc[3] - cDest[3]) * t) / 255);
+#endif
+ case splashModeRGB8:
+ case splashModeBGR8:
+ cSrc[2] = clip255(cSrc[2] + ((cSrc[2] - cDest[2]) * t) / 255);
+ cSrc[1] = clip255(cSrc[1] + ((cSrc[1] - cDest[1]) * t) / 255);
+ case splashModeMono1:
+ case splashModeMono8:
+ cSrc[0] = clip255(cSrc[0] + ((cSrc[0] - cDest[0]) * t) / 255);
+ break;
+ }
+ }
+
+ //----- blend function
+
+ if (state->blendFunc) {
+#if SPLASH_CMYK
+ if (bitmap->mode == splashModeCMYK8) {
+ // convert colors to additive
+ cSrc2[0] = (Guchar)(0xff - cSrc[0]);
+ cSrc2[1] = (Guchar)(0xff - cSrc[1]);
+ cSrc2[2] = (Guchar)(0xff - cSrc[2]);
+ cSrc2[3] = (Guchar)(0xff - cSrc[3]);
+ cDest2[0] = (Guchar)(0xff - cDest[0]);
+ cDest2[1] = (Guchar)(0xff - cDest[1]);
+ cDest2[2] = (Guchar)(0xff - cDest[2]);
+ cDest2[3] = (Guchar)(0xff - cDest[3]);
+ (*state->blendFunc)(cSrc2, cDest2, cBlend, bitmap->mode);
+ // convert result back to subtractive
+ cBlend[0] = (Guchar)(0xff - cBlend[0]);
+ cBlend[1] = (Guchar)(0xff - cBlend[1]);
+ cBlend[2] = (Guchar)(0xff - cBlend[2]);
+ cBlend[3] = (Guchar)(0xff - cBlend[3]);
+ } else
+#endif
+ (*state->blendFunc)(cSrc, cDest, cBlend, bitmap->mode);
+ }
+
+ //----- result alpha and non-isolated group element correction
+
+ // alphaI = alpha_i
+ // alphaIm1 = alpha_(i-1)
+
+ if (pipe->noTransparency) {
+ alphaI = alphaIm1 = aResult = 255;
+ } else if (alpha0Ptr) {
+ if (color0Ptr) {
+ // non-isolated, knockout
+ aResult = aSrc;
+ alpha0 = *alpha0Ptr++;
+ alphaI = (Guchar)(aSrc + alpha0 - div255(aSrc * alpha0));
+ alphaIm1 = alpha0;
+ } else {
+ // non-isolated, non-knockout
+ aResult = (Guchar)(aSrc + aDest - div255(aSrc * aDest));
+ alpha0 = *alpha0Ptr++;
+ alphaI = (Guchar)(aResult + alpha0 - div255(aResult * alpha0));
+ alphaIm1 = (Guchar)(alpha0 + aDest - div255(alpha0 * aDest));
+ }
+ } else {
+ if (color0Ptr) {
+ // isolated, knockout
+ aResult = aSrc;
+ alphaI = aSrc;
+ alphaIm1 = 0;
+ } else {
+ // isolated, non-knockout
+ aResult = (Guchar)(aSrc + aDest - div255(aSrc * aDest));
+ alphaI = aResult;
+ alphaIm1 = aDest;
+ }
+ }
+
+ //----- result color
+
+ switch (pipe->resultColorCtrl) {
+
+ case splashPipeResultColorNoAlphaBlendMono:
+ cResult0 = div255((255 - aDest) * cSrc[0] + aDest * cBlend[0]);
+ break;
+ case splashPipeResultColorNoAlphaBlendRGB:
+ cResult0 = div255((255 - aDest) * cSrc[0] + aDest * cBlend[0]);
+ cResult1 = div255((255 - aDest) * cSrc[1] + aDest * cBlend[1]);
+ cResult2 = div255((255 - aDest) * cSrc[2] + aDest * cBlend[2]);
+ break;
+#if SPLASH_CMYK
+ case splashPipeResultColorNoAlphaBlendCMYK:
+ cResult0 = div255((255 - aDest) * cSrc[0] + aDest * cBlend[0]);
+ cResult1 = div255((255 - aDest) * cSrc[1] + aDest * cBlend[1]);
+ cResult2 = div255((255 - aDest) * cSrc[2] + aDest * cBlend[2]);
+ cResult3 = div255((255 - aDest) * cSrc[3] + aDest * cBlend[3]);
+ break;
+#endif
+
+ case splashPipeResultColorAlphaNoBlendMono:
+ if (alphaI == 0) {
+ cResult0 = 0;
+ } else {
+ cResult0 = (Guchar)(((alphaI - aSrc) * cDest[0] + aSrc * cSrc[0])
+ / alphaI);
+ }
+ break;
+ case splashPipeResultColorAlphaNoBlendRGB:
+ if (alphaI == 0) {
+ cResult0 = 0;
+ cResult1 = 0;
+ cResult2 = 0;
+ } else {
+ cResult0 = (Guchar)(((alphaI - aSrc) * cDest[0] + aSrc * cSrc[0])
+ / alphaI);
+ cResult1 = (Guchar)(((alphaI - aSrc) * cDest[1] + aSrc * cSrc[1])
+ / alphaI);
+ cResult2 = (Guchar)(((alphaI - aSrc) * cDest[2] + aSrc * cSrc[2])
+ / alphaI);
+ }
+ break;
+#if SPLASH_CMYK
+ case splashPipeResultColorAlphaNoBlendCMYK:
+ if (alphaI == 0) {
+ cResult0 = 0;
+ cResult1 = 0;
+ cResult2 = 0;
+ cResult3 = 0;
+ } else {
+ cResult0 = (Guchar)(((alphaI - aSrc) * cDest[0] + aSrc * cSrc[0])
+ / alphaI);
+ cResult1 = (Guchar)(((alphaI - aSrc) * cDest[1] + aSrc * cSrc[1])
+ / alphaI);
+ cResult2 = (Guchar)(((alphaI - aSrc) * cDest[2] + aSrc * cSrc[2])
+ / alphaI);
+ cResult3 = (Guchar)(((alphaI - aSrc) * cDest[3] + aSrc * cSrc[3])
+ / alphaI);
+ }
+ break;
+#endif
+
+ case splashPipeResultColorAlphaBlendMono:
+ if (alphaI == 0) {
+ cResult0 = 0;
+ } else {
+ cResult0 = (Guchar)(((alphaI - aSrc) * cDest[0] +
+ aSrc * ((255 - alphaIm1) * cSrc[0] +
+ alphaIm1 * cBlend[0]) / 255)
+ / alphaI);
+ }
+ break;
+ case splashPipeResultColorAlphaBlendRGB:
+ if (alphaI == 0) {
+ cResult0 = 0;
+ cResult1 = 0;
+ cResult2 = 0;
+ } else {
+ cResult0 = (Guchar)(((alphaI - aSrc) * cDest[0] +
+ aSrc * ((255 - alphaIm1) * cSrc[0] +
+ alphaIm1 * cBlend[0]) / 255)
+ / alphaI);
+ cResult1 = (Guchar)(((alphaI - aSrc) * cDest[1] +
+ aSrc * ((255 - alphaIm1) * cSrc[1] +
+ alphaIm1 * cBlend[1]) / 255)
+ / alphaI);
+ cResult2 = (Guchar)(((alphaI - aSrc) * cDest[2] +
+ aSrc * ((255 - alphaIm1) * cSrc[2] +
+ alphaIm1 * cBlend[2]) / 255)
+ / alphaI);
+ }
+ break;
+#if SPLASH_CMYK
+ case splashPipeResultColorAlphaBlendCMYK:
+ if (alphaI == 0) {
+ cResult0 = 0;
+ cResult1 = 0;
+ cResult2 = 0;
+ cResult3 = 0;
+ } else {
+ cResult0 = (Guchar)(((alphaI - aSrc) * cDest[0] +
+ aSrc * ((255 - alphaIm1) * cSrc[0] +
+ alphaIm1 * cBlend[0]) / 255)
+ / alphaI);
+ cResult1 = (Guchar)(((alphaI - aSrc) * cDest[1] +
+ aSrc * ((255 - alphaIm1) * cSrc[1] +
+ alphaIm1 * cBlend[1]) / 255)
+ / alphaI);
+ cResult2 = (Guchar)(((alphaI - aSrc) * cDest[2] +
+ aSrc * ((255 - alphaIm1) * cSrc[2] +
+ alphaIm1 * cBlend[2]) / 255)
+ / alphaI);
+ cResult3 = (Guchar)(((alphaI - aSrc) * cDest[3] +
+ aSrc * ((255 - alphaIm1) * cSrc[3] +
+ alphaIm1 * cBlend[3]) / 255)
+ / alphaI);
+ }
+ break;
+#endif
+ }
+
+ } // if (noTransparency && !blendFunc)
+
+ //----- write destination pixel
+
+ switch (bitmap->mode) {
+ case splashModeMono1:
+ if (state->screen->test(x, y, cResult0)) {
+ *destColorPtr |= destColorMask;
+ } else {
+ *destColorPtr &= (Guchar)~destColorMask;
+ }
+ destColorPtr += destColorMask & 1;
+ destColorMask = (Guchar)((destColorMask << 7) | (destColorMask >> 1));
+ break;
+ case splashModeMono8:
+ *destColorPtr++ = cResult0;
+ break;
+ case splashModeRGB8:
+ destColorPtr[0] = cResult0;
+ destColorPtr[1] = cResult1;
+ destColorPtr[2] = cResult2;
+ destColorPtr += 3;
+ break;
+ case splashModeBGR8:
+ destColorPtr[0] = cResult2;
+ destColorPtr[1] = cResult1;
+ destColorPtr[2] = cResult0;
+ destColorPtr += 3;
+ break;
+#if SPLASH_CMYK
+ case splashModeCMYK8:
+ destColorPtr[0] = cResult0;
+ destColorPtr[1] = cResult1;
+ destColorPtr[2] = cResult2;
+ destColorPtr[3] = cResult3;
+ destColorPtr += 4;
+ break;
+#endif
+ }
+ if (destAlphaPtr) {
+ *destAlphaPtr++ = aResult;
+ }
+
+ cSrcPtr += cSrcStride;
+ shapePtr2 += shapeStride;
+ } // for (x ...)
+
+ updateModX(lastX);
+}
+
+// special case:
+// !pipe->pattern && pipe->noTransparency && !state->blendFunc &&
+// bitmap->mode == splashModeMono1 && !bitmap->alpha) {
+void Splash::pipeRunSimpleMono1(SplashPipe *pipe, int x0, int x1, int y,
+ Guchar *shapePtr, SplashColorPtr cSrcPtr) {
+ Guchar cResult0;
+ SplashColorPtr destColorPtr;
+ Guchar destColorMask;
+ SplashScreenCursor screenCursor;
+ int cSrcStride, x;
+
+ if (cSrcPtr) {
+ cSrcStride = 1;
+ } else {
+ cSrcPtr = pipe->cSrcVal;
+ cSrcStride = 0;
+ }
+ if (x0 > x1) {
+ return;
+ }
+ updateModX(x0);
+ updateModX(x1);
+ updateModY(y);
+
+ useDestRow(y);
+
+ destColorPtr = &bitmap->data[y * bitmap->rowSize + (x0 >> 3)];
+ destColorMask = (Guchar)(0x80 >> (x0 & 7));
+
+ screenCursor = state->screen->getTestCursor(y);
+
+ for (x = x0; x <= x1; ++x) {
+
+ //----- write destination pixel
+ cResult0 = state->grayTransfer[cSrcPtr[0]];
+ if (state->screen->testWithCursor(screenCursor, x, cResult0)) {
+ *destColorPtr |= destColorMask;
+ } else {
+ *destColorPtr &= (Guchar)~destColorMask;
+ }
+ destColorPtr += destColorMask & 1;
+ destColorMask = (Guchar)((destColorMask << 7) | (destColorMask >> 1));
+
+ cSrcPtr += cSrcStride;
+ }
+}
+
+// special case:
+// !pipe->pattern && pipe->noTransparency && !state->blendFunc &&
+// bitmap->mode == splashModeMono8 && bitmap->alpha) {
+void Splash::pipeRunSimpleMono8(SplashPipe *pipe, int x0, int x1, int y,
+ Guchar *shapePtr, SplashColorPtr cSrcPtr) {
+ SplashColorPtr destColorPtr;
+ Guchar *destAlphaPtr;
+ int cSrcStride, x;
+
+ if (cSrcPtr) {
+ cSrcStride = 1;
+ } else {
+ cSrcPtr = pipe->cSrcVal;
+ cSrcStride = 0;
+ }
+ if (x0 > x1) {
+ return;
+ }
+ updateModX(x0);
+ updateModX(x1);
+ updateModY(y);
+
+ useDestRow(y);
+
+ destColorPtr = &bitmap->data[y * bitmap->rowSize + x0];
+ destAlphaPtr = &bitmap->alpha[y * bitmap->alphaRowSize + x0];
+
+ for (x = x0; x <= x1; ++x) {
+
+ //----- write destination pixel
+ *destColorPtr++ = state->grayTransfer[cSrcPtr[0]];
+ *destAlphaPtr++ = 255;
+
+ cSrcPtr += cSrcStride;
+ }
+}
+
+// special case:
+// !pipe->pattern && pipe->noTransparency && !state->blendFunc &&
+// bitmap->mode == splashModeRGB8 && bitmap->alpha) {
+void Splash::pipeRunSimpleRGB8(SplashPipe *pipe, int x0, int x1, int y,
+ Guchar *shapePtr, SplashColorPtr cSrcPtr) {
+ SplashColorPtr destColorPtr;
+ Guchar *destAlphaPtr;
+ int cSrcStride, x;
+
+ if (cSrcPtr) {
+ cSrcStride = 3;
+ } else {
+ cSrcPtr = pipe->cSrcVal;
+ cSrcStride = 0;
+ }
+ if (x0 > x1) {
+ return;
+ }
+ updateModX(x0);
+ updateModX(x1);
+ updateModY(y);
+
+ useDestRow(y);
+
+ destColorPtr = &bitmap->data[y * bitmap->rowSize + 3 * x0];
+ destAlphaPtr = &bitmap->alpha[y * bitmap->alphaRowSize + x0];
+
+ for (x = x0; x <= x1; ++x) {
+
+ //----- write destination pixel
+ destColorPtr[0] = state->rgbTransferR[cSrcPtr[0]];
+ destColorPtr[1] = state->rgbTransferG[cSrcPtr[1]];
+ destColorPtr[2] = state->rgbTransferB[cSrcPtr[2]];
+ destColorPtr += 3;
+ *destAlphaPtr++ = 255;
+
+ cSrcPtr += cSrcStride;
+ }
+}
+
+// special case:
+// !pipe->pattern && pipe->noTransparency && !state->blendFunc &&
+// bitmap->mode == splashModeBGR8 && bitmap->alpha) {
+void Splash::pipeRunSimpleBGR8(SplashPipe *pipe, int x0, int x1, int y,
+ Guchar *shapePtr, SplashColorPtr cSrcPtr) {
+ SplashColorPtr destColorPtr;
+ Guchar *destAlphaPtr;
+ int cSrcStride, x;
+
+ if (cSrcPtr) {
+ cSrcStride = 3;
+ } else {
+ cSrcPtr = pipe->cSrcVal;
+ cSrcStride = 0;
+ }
+ if (x0 > x1) {
+ return;
+ }
+ updateModX(x0);
+ updateModX(x1);
+ updateModY(y);
+
+ useDestRow(y);
+
+ destColorPtr = &bitmap->data[y * bitmap->rowSize + 3 * x0];
+ destAlphaPtr = &bitmap->alpha[y * bitmap->alphaRowSize + x0];
+
+ for (x = x0; x <= x1; ++x) {
+
+ //----- write destination pixel
+ destColorPtr[0] = state->rgbTransferB[cSrcPtr[2]];
+ destColorPtr[1] = state->rgbTransferG[cSrcPtr[1]];
+ destColorPtr[2] = state->rgbTransferR[cSrcPtr[0]];
+ destColorPtr += 3;
+ *destAlphaPtr++ = 255;
+
+ cSrcPtr += cSrcStride;
+ }
+}
+
+#if SPLASH_CMYK
+// special case:
+// !pipe->pattern && pipe->noTransparency && !state->blendFunc &&
+// bitmap->mode == splashModeCMYK8 && bitmap->alpha) {
+void Splash::pipeRunSimpleCMYK8(SplashPipe *pipe, int x0, int x1, int y,
+ Guchar *shapePtr, SplashColorPtr cSrcPtr) {
+ SplashColorPtr destColorPtr;
+ Guchar *destAlphaPtr;
+ int cSrcStride, x;
+
+ if (cSrcPtr) {
+ cSrcStride = 4;
+ } else {
+ cSrcPtr = pipe->cSrcVal;
+ cSrcStride = 0;
+ }
+ if (x0 > x1) {
+ return;
+ }
+ updateModX(x0);
+ updateModX(x1);
+ updateModY(y);
+
+ useDestRow(y);
+
+ destColorPtr = &bitmap->data[y * bitmap->rowSize + 4 * x0];
+ destAlphaPtr = &bitmap->alpha[y * bitmap->alphaRowSize + x0];
+
+ for (x = x0; x <= x1; ++x) {
+
+ //----- write destination pixel
+ destColorPtr[0] = state->cmykTransferC[cSrcPtr[0]];
+ destColorPtr[1] = state->cmykTransferM[cSrcPtr[1]];
+ destColorPtr[2] = state->cmykTransferY[cSrcPtr[2]];
+ destColorPtr[3] = state->cmykTransferK[cSrcPtr[3]];
+ destColorPtr += 4;
+ *destAlphaPtr++ = 255;
+
+ cSrcPtr += cSrcStride;
+ }
+}
+#endif
+
+
+// special case:
+// !pipe->pattern && pipe->shapeOnly && !state->blendFunc &&
+// bitmap->mode == splashModeMono1 && !bitmap->alpha
+void Splash::pipeRunShapeMono1(SplashPipe *pipe, int x0, int x1, int y,
+ Guchar *shapePtr, SplashColorPtr cSrcPtr) {
+ Guchar shape, aSrc, cSrc0, cDest0, cResult0;
+ SplashColorPtr destColorPtr;
+ Guchar destColorMask;
+ SplashScreenCursor screenCursor;
+ int cSrcStride, x, lastX;
+
+ if (cSrcPtr) {
+ cSrcStride = 1;
+ } else {
+ cSrcPtr = pipe->cSrcVal;
+ cSrcStride = 0;
+ }
+ for (; x0 <= x1; ++x0) {
+ if (*shapePtr) {
+ break;
+ }
+ cSrcPtr += cSrcStride;
+ ++shapePtr;
+ }
+ if (x0 > x1) {
+ return;
+ }
+ updateModX(x0);
+ updateModY(y);
+ lastX = x0;
+
+ useDestRow(y);
+
+ destColorPtr = &bitmap->data[y * bitmap->rowSize + (x0 >> 3)];
+ destColorMask = (Guchar)(0x80 >> (x0 & 7));
+
+ screenCursor = state->screen->getTestCursor(y);
+
+ for (x = x0; x <= x1; ++x) {
+
+ //----- shape
+ shape = *shapePtr;
+ if (!shape) {
+ destColorPtr += destColorMask & 1;
+ destColorMask = (Guchar)((destColorMask << 7) | (destColorMask >> 1));
+ cSrcPtr += cSrcStride;
+ ++shapePtr;
+ continue;
+ }
+ lastX = x;
+
+ //----- source color
+ cSrc0 = state->grayTransfer[cSrcPtr[0]];
+
+ //----- source alpha
+ aSrc = shape;
+
+ //----- special case for aSrc = 255
+ if (aSrc == 255) {
+ cResult0 = cSrc0;
+ } else {
+
+ //----- read destination pixel
+ cDest0 = (*destColorPtr & destColorMask) ? 0xff : 0x00;
+
+ //----- result color
+ // note: aDest = alphaI = aResult = 0xff
+ cResult0 = (Guchar)div255((0xff - aSrc) * cDest0 + aSrc * cSrc0);
+ }
+
+ //----- write destination pixel
+ if (state->screen->testWithCursor(screenCursor, x, cResult0)) {
+ *destColorPtr |= destColorMask;
+ } else {
+ *destColorPtr &= (Guchar)~destColorMask;
+ }
+ destColorPtr += destColorMask & 1;
+ destColorMask = (Guchar)((destColorMask << 7) | (destColorMask >> 1));
+
+ cSrcPtr += cSrcStride;
+ ++shapePtr;
+ }
+
+ updateModX(lastX);
+}
+
+// special case:
+// !pipe->pattern && pipe->shapeOnly && !state->blendFunc &&
+// bitmap->mode == splashModeMono8 && bitmap->alpha
+void Splash::pipeRunShapeMono8(SplashPipe *pipe, int x0, int x1, int y,
+ Guchar *shapePtr, SplashColorPtr cSrcPtr) {
+ Guchar shape, aSrc, aDest, alphaI, aResult, cSrc0, cDest0, cResult0;
+ SplashColorPtr destColorPtr;
+ Guchar *destAlphaPtr;
+ int cSrcStride, x, lastX;
+
+ if (cSrcPtr) {
+ cSrcStride = 1;
+ } else {
+ cSrcPtr = pipe->cSrcVal;
+ cSrcStride = 0;
+ }
+ for (; x0 <= x1; ++x0) {
+ if (*shapePtr) {
+ break;
+ }
+ cSrcPtr += cSrcStride;
+ ++shapePtr;
+ }
+ if (x0 > x1) {
+ return;
+ }
+ updateModX(x0);
+ updateModY(y);
+ lastX = x0;
+
+ useDestRow(y);
+
+ destColorPtr = &bitmap->data[y * bitmap->rowSize + x0];
+ destAlphaPtr = &bitmap->alpha[y * bitmap->alphaRowSize + x0];
+
+ for (x = x0; x <= x1; ++x) {
+
+ //----- shape
+ shape = *shapePtr;
+ if (!shape) {
+ ++destColorPtr;
+ ++destAlphaPtr;
+ cSrcPtr += cSrcStride;
+ ++shapePtr;
+ continue;
+ }
+ lastX = x;
+
+ //----- source color
+ cSrc0 = state->grayTransfer[cSrcPtr[0]];
+
+ //----- source alpha
+ aSrc = shape;
+
+ //----- special case for aSrc = 255
+ if (aSrc == 255) {
+ aResult = 255;
+ cResult0 = cSrc0;
+ } else {
+
+ //----- read destination alpha
+ aDest = *destAlphaPtr;
+
+ //----- special case for aDest = 0
+ if (aDest == 0) {
+ aResult = aSrc;
+ cResult0 = cSrc0;
+ } else {
+
+ //----- read destination pixel
+ cDest0 = *destColorPtr;
+
+ //----- result alpha and non-isolated group element correction
+ aResult = (Guchar)(aSrc + aDest - div255(aSrc * aDest));
+ alphaI = aResult;
+
+ //----- result color
+ cResult0 = (Guchar)(((alphaI - aSrc) * cDest0 + aSrc * cSrc0) / alphaI);
+ }
+ }
+
+ //----- write destination pixel
+ *destColorPtr++ = cResult0;
+ *destAlphaPtr++ = aResult;
+
+ cSrcPtr += cSrcStride;
+ ++shapePtr;
+ }
+
+ updateModX(lastX);
+}
+
+// special case:
+// !pipe->pattern && pipe->shapeOnly && !state->blendFunc &&
+// bitmap->mode == splashModeRGB8 && bitmap->alpha
+void Splash::pipeRunShapeRGB8(SplashPipe *pipe, int x0, int x1, int y,
+ Guchar *shapePtr, SplashColorPtr cSrcPtr) {
+ Guchar shape, aSrc, aDest, alphaI, aResult;
+ Guchar cSrc0, cSrc1, cSrc2;
+ Guchar cDest0, cDest1, cDest2;
+ Guchar cResult0, cResult1, cResult2;
+ SplashColorPtr destColorPtr;
+ Guchar *destAlphaPtr;
+ int cSrcStride, x, lastX;
+
+ if (cSrcPtr) {
+ cSrcStride = 3;
+ } else {
+ cSrcPtr = pipe->cSrcVal;
+ cSrcStride = 0;
+ }
+ for (; x0 <= x1; ++x0) {
+ if (*shapePtr) {
+ break;
+ }
+ cSrcPtr += cSrcStride;
+ ++shapePtr;
+ }
+ if (x0 > x1) {
+ return;
+ }
+ updateModX(x0);
+ updateModY(y);
+ lastX = x0;
+
+ useDestRow(y);
+
+ destColorPtr = &bitmap->data[y * bitmap->rowSize + 3 * x0];
+ destAlphaPtr = &bitmap->alpha[y * bitmap->alphaRowSize + x0];
+
+ for (x = x0; x <= x1; ++x) {
+
+ //----- shape
+ shape = *shapePtr;
+ if (!shape) {
+ destColorPtr += 3;
+ ++destAlphaPtr;
+ cSrcPtr += cSrcStride;
+ ++shapePtr;
+ continue;
+ }
+ lastX = x;
+
+ //----- source color
+ cSrc0 = state->rgbTransferR[cSrcPtr[0]];
+ cSrc1 = state->rgbTransferG[cSrcPtr[1]];
+ cSrc2 = state->rgbTransferB[cSrcPtr[2]];
+
+ //----- source alpha
+ aSrc = shape;
+
+ //----- special case for aSrc = 255
+ if (aSrc == 255) {
+ aResult = 255;
+ cResult0 = cSrc0;
+ cResult1 = cSrc1;
+ cResult2 = cSrc2;
+ } else {
+
+ //----- read destination alpha
+ aDest = *destAlphaPtr;
+
+ //----- special case for aDest = 0
+ if (aDest == 0) {
+ aResult = aSrc;
+ cResult0 = cSrc0;
+ cResult1 = cSrc1;
+ cResult2 = cSrc2;
+ } else {
+
+ //----- read destination pixel
+ cDest0 = destColorPtr[0];
+ cDest1 = destColorPtr[1];
+ cDest2 = destColorPtr[2];
+
+ //----- result alpha and non-isolated group element correction
+ aResult = (Guchar)(aSrc + aDest - div255(aSrc * aDest));
+ alphaI = aResult;
+
+ //----- result color
+ cResult0 = (Guchar)(((alphaI - aSrc) * cDest0 + aSrc * cSrc0) / alphaI);
+ cResult1 = (Guchar)(((alphaI - aSrc) * cDest1 + aSrc * cSrc1) / alphaI);
+ cResult2 = (Guchar)(((alphaI - aSrc) * cDest2 + aSrc * cSrc2) / alphaI);
+ }
+ }
+
+ //----- write destination pixel
+ destColorPtr[0] = cResult0;
+ destColorPtr[1] = cResult1;
+ destColorPtr[2] = cResult2;
+ destColorPtr += 3;
+ *destAlphaPtr++ = aResult;
+
+ cSrcPtr += cSrcStride;
+ ++shapePtr;
+ }
+
+ updateModX(lastX);
+}
+
+// special case:
+// !pipe->pattern && pipe->shapeOnly && !state->blendFunc &&
+// bitmap->mode == splashModeBGR8 && bitmap->alpha
+void Splash::pipeRunShapeBGR8(SplashPipe *pipe, int x0, int x1, int y,
+ Guchar *shapePtr, SplashColorPtr cSrcPtr) {
+ Guchar shape, aSrc, aDest, alphaI, aResult;
+ Guchar cSrc0, cSrc1, cSrc2;
+ Guchar cDest0, cDest1, cDest2;
+ Guchar cResult0, cResult1, cResult2;
+ SplashColorPtr destColorPtr;
+ Guchar *destAlphaPtr;
+ int cSrcStride, x, lastX;
+
+ if (cSrcPtr) {
+ cSrcStride = 3;
+ } else {
+ cSrcPtr = pipe->cSrcVal;
+ cSrcStride = 0;
+ }
+ for (; x0 <= x1; ++x0) {
+ if (*shapePtr) {
+ break;
+ }
+ cSrcPtr += cSrcStride;
+ ++shapePtr;
+ }
+ if (x0 > x1) {
+ return;
+ }
+ updateModX(x0);
+ updateModY(y);
+ lastX = x0;
+
+ useDestRow(y);
+
+ destColorPtr = &bitmap->data[y * bitmap->rowSize + 3 * x0];
+ destAlphaPtr = &bitmap->alpha[y * bitmap->alphaRowSize + x0];
+
+ for (x = x0; x <= x1; ++x) {
+
+ //----- shape
+ shape = *shapePtr;
+ if (!shape) {
+ destColorPtr += 3;
+ ++destAlphaPtr;
+ cSrcPtr += cSrcStride;
+ ++shapePtr;
+ continue;
+ }
+ lastX = x;
+
+ //----- source color
+ cSrc0 = state->rgbTransferR[cSrcPtr[0]];
+ cSrc1 = state->rgbTransferG[cSrcPtr[1]];
+ cSrc2 = state->rgbTransferB[cSrcPtr[2]];
+
+ //----- source alpha
+ aSrc = shape;
+
+ //----- special case for aSrc = 255
+ if (aSrc == 255) {
+ aResult = 255;
+ cResult0 = cSrc0;
+ cResult1 = cSrc1;
+ cResult2 = cSrc2;
+ } else {
+
+ //----- read destination alpha
+ aDest = *destAlphaPtr;
+
+ //----- special case for aDest = 0
+ if (aDest == 0) {
+ aResult = aSrc;
+ cResult0 = cSrc0;
+ cResult1 = cSrc1;
+ cResult2 = cSrc2;
+ } else {
+
+ //----- read destination pixel
+ cDest0 = destColorPtr[2];
+ cDest1 = destColorPtr[1];
+ cDest2 = destColorPtr[0];
+
+ //----- result alpha and non-isolated group element correction
+ aResult = (Guchar)(aSrc + aDest - div255(aSrc * aDest));
+ alphaI = aResult;
+
+ //----- result color
+ cResult0 = (Guchar)(((alphaI - aSrc) * cDest0 + aSrc * cSrc0) / alphaI);
+ cResult1 = (Guchar)(((alphaI - aSrc) * cDest1 + aSrc * cSrc1) / alphaI);
+ cResult2 = (Guchar)(((alphaI - aSrc) * cDest2 + aSrc * cSrc2) / alphaI);
+ }
+ }
+
+ //----- write destination pixel
+ destColorPtr[0] = cResult2;
+ destColorPtr[1] = cResult1;
+ destColorPtr[2] = cResult0;
+ destColorPtr += 3;
+ *destAlphaPtr++ = aResult;
+
+ cSrcPtr += cSrcStride;
+ ++shapePtr;
+ }
+
+ updateModX(lastX);
+}
+
+#if SPLASH_CMYK
+// special case:
+// !pipe->pattern && pipe->shapeOnly && !state->blendFunc &&
+// bitmap->mode == splashModeCMYK8 && bitmap->alpha
+void Splash::pipeRunShapeCMYK8(SplashPipe *pipe, int x0, int x1, int y,
+ Guchar *shapePtr, SplashColorPtr cSrcPtr) {
+ Guchar shape, aSrc, aDest, alphaI, aResult;
+ Guchar cSrc0, cSrc1, cSrc2, cSrc3;
+ Guchar cDest0, cDest1, cDest2, cDest3;
+ Guchar cResult0, cResult1, cResult2, cResult3;
+ SplashColorPtr destColorPtr;
+ Guchar *destAlphaPtr;
+ int cSrcStride, x, lastX;
+
+ if (cSrcPtr) {
+ cSrcStride = 4;
+ } else {
+ cSrcPtr = pipe->cSrcVal;
+ cSrcStride = 0;
+ }
+ for (; x0 <= x1; ++x0) {
+ if (*shapePtr) {
+ break;
+ }
+ cSrcPtr += cSrcStride;
+ ++shapePtr;
+ }
+ if (x0 > x1) {
+ return;
+ }
+ updateModX(x0);
+ updateModY(y);
+ lastX = x0;
+
+ useDestRow(y);
+
+ destColorPtr = &bitmap->data[y * bitmap->rowSize + 4 * x0];
+ destAlphaPtr = &bitmap->alpha[y * bitmap->alphaRowSize + x0];
+
+ for (x = x0; x <= x1; ++x) {
+
+ //----- shape
+ shape = *shapePtr;
+ if (!shape) {
+ destColorPtr += 4;
+ ++destAlphaPtr;
+ cSrcPtr += cSrcStride;
+ ++shapePtr;
+ continue;
+ }
+ lastX = x;
+
+ //----- read destination pixel
+ cDest0 = destColorPtr[0];
+ cDest1 = destColorPtr[1];
+ cDest2 = destColorPtr[2];
+ cDest3 = destColorPtr[3];
+ aDest = *destAlphaPtr;
+
+ //----- overprint
+ cSrc0 = state->cmykTransferC[cSrcPtr[0]];
+ cSrc1 = state->cmykTransferM[cSrcPtr[1]];
+ cSrc2 = state->cmykTransferY[cSrcPtr[2]];
+ cSrc3 = state->cmykTransferK[cSrcPtr[3]];
+
+ //----- source alpha
+ aSrc = shape;
+
+ //----- special case for aSrc = 255
+ if (aSrc == 255) {
+ aResult = 255;
+ cResult0 = cSrc0;
+ cResult1 = cSrc1;
+ cResult2 = cSrc2;
+ cResult3 = cSrc3;
+ } else {
+
+ //----- special case for aDest = 0
+ if (aDest == 0) {
+ aResult = aSrc;
+ cResult0 = cSrc0;
+ cResult1 = cSrc1;
+ cResult2 = cSrc2;
+ cResult3 = cSrc3;
+ } else {
+
+ //----- result alpha and non-isolated group element correction
+ aResult = (Guchar)(aSrc + aDest - div255(aSrc * aDest));
+ alphaI = aResult;
+
+ //----- result color
+ cResult0 = (Guchar)(((alphaI - aSrc) * cDest0 + aSrc * cSrc0) / alphaI);
+ cResult1 = (Guchar)(((alphaI - aSrc) * cDest1 + aSrc * cSrc1) / alphaI);
+ cResult2 = (Guchar)(((alphaI - aSrc) * cDest2 + aSrc * cSrc2) / alphaI);
+ cResult3 = (Guchar)(((alphaI - aSrc) * cDest3 + aSrc * cSrc3) / alphaI);
+ }
+ }
+
+ //----- write destination pixel
+ destColorPtr[0] = cResult0;
+ destColorPtr[1] = cResult1;
+ destColorPtr[2] = cResult2;
+ destColorPtr[3] = cResult3;
+ destColorPtr += 4;
+ *destAlphaPtr++ = aResult;
+
+ cSrcPtr += cSrcStride;
+ ++shapePtr;
+ }
+
+ updateModX(lastX);
+}
+#endif
+
+
+// special case:
+// !pipe->pattern && pipe->shapeOnly && !state->blendFunc &&
+// bitmap->mode == splashModeMono8 && !bitmap->alpha
+void Splash::pipeRunShapeNoAlphaMono8(SplashPipe *pipe, int x0, int x1, int y,
+ Guchar *shapePtr,
+ SplashColorPtr cSrcPtr) {
+ Guchar shape, aSrc, cSrc0, cDest0, cResult0;
+ SplashColorPtr destColorPtr;
+ int cSrcStride, x, lastX;
+
+ if (cSrcPtr) {
+ cSrcStride = 1;
+ } else {
+ cSrcPtr = pipe->cSrcVal;
+ cSrcStride = 0;
+ }
+ for (; x0 <= x1; ++x0) {
+ if (*shapePtr) {
+ break;
+ }
+ cSrcPtr += cSrcStride;
+ ++shapePtr;
+ }
+ if (x0 > x1) {
+ return;
+ }
+ updateModX(x0);
+ updateModY(y);
+ lastX = x0;
+
+ useDestRow(y);
+
+ destColorPtr = &bitmap->data[y * bitmap->rowSize + x0];
+
+ for (x = x0; x <= x1; ++x) {
+
+ //----- shape
+ shape = *shapePtr;
+ if (!shape) {
+ ++destColorPtr;
+ cSrcPtr += cSrcStride;
+ ++shapePtr;
+ continue;
+ }
+ lastX = x;
+
+ //----- source color
+ cSrc0 = state->grayTransfer[cSrcPtr[0]];
+
+ //----- source alpha
+ aSrc = shape;
+
+ //----- special case for aSrc = 255
+ if (aSrc == 255) {
+ cResult0 = cSrc0;
+ } else {
+
+ //----- read destination pixel
+ cDest0 = *destColorPtr;
+
+ //----- result color
+ cResult0 = div255((255 - aSrc) * cDest0 + aSrc * cSrc0);
+ }
+
+ //----- write destination pixel
+ *destColorPtr++ = cResult0;
+
+ cSrcPtr += cSrcStride;
+ ++shapePtr;
+ }
+
+ updateModX(lastX);
+}
+
+// special case:
+// !pipe->pattern && !pipe->noTransparency && !state->softMask &&
+// pipe->usesShape && !pipe->alpha0Ptr && !state->blendFunc &&
+// !pipe->nonIsolatedGroup &&
+// bitmap->mode == splashModeMono1 && !bitmap->alpha
+void Splash::pipeRunAAMono1(SplashPipe *pipe, int x0, int x1, int y,
+ Guchar *shapePtr, SplashColorPtr cSrcPtr) {
+ Guchar shape, aSrc, cSrc0, cDest0, cResult0;
+ SplashColorPtr destColorPtr;
+ Guchar destColorMask;
+ SplashScreenCursor screenCursor;
+ int cSrcStride, x, lastX;
+
+ if (cSrcPtr) {
+ cSrcStride = 1;
+ } else {
+ cSrcPtr = pipe->cSrcVal;
+ cSrcStride = 0;
+ }
+ for (; x0 <= x1; ++x0) {
+ if (*shapePtr) {
+ break;
+ }
+ cSrcPtr += cSrcStride;
+ ++shapePtr;
+ }
+ if (x0 > x1) {
+ return;
+ }
+ updateModX(x0);
+ updateModY(y);
+ lastX = x0;
+
+ useDestRow(y);
+
+ destColorPtr = &bitmap->data[y * bitmap->rowSize + (x0 >> 3)];
+ destColorMask = (Guchar)(0x80 >> (x0 & 7));
+
+ screenCursor = state->screen->getTestCursor(y);
+
+ for (x = x0; x <= x1; ++x) {
+
+ //----- shape
+ shape = *shapePtr;
+ if (!shape) {
+ destColorPtr += destColorMask & 1;
+ destColorMask = (Guchar)((destColorMask << 7) | (destColorMask >> 1));
+ cSrcPtr += cSrcStride;
+ ++shapePtr;
+ continue;
+ }
+ lastX = x;
+
+ //----- read destination pixel
+ cDest0 = (*destColorPtr & destColorMask) ? 0xff : 0x00;
+
+ //----- source color
+ cSrc0 = state->grayTransfer[cSrcPtr[0]];
+
+ //----- source alpha
+ aSrc = div255(pipe->aInput * shape);
+
+ //----- result color
+ // note: aDest = alphaI = aResult = 0xff
+ cResult0 = (Guchar)div255((0xff - aSrc) * cDest0 + aSrc * cSrc0);
+
+ //----- write destination pixel
+ if (state->screen->testWithCursor(screenCursor, x, cResult0)) {
+ *destColorPtr |= destColorMask;
+ } else {
+ *destColorPtr &= (Guchar)~destColorMask;
+ }
+ destColorPtr += destColorMask & 1;
+ destColorMask = (Guchar)((destColorMask << 7) | (destColorMask >> 1));
+
+ cSrcPtr += cSrcStride;
+ ++shapePtr;
+ }
+
+ updateModX(lastX);
+}
+
+// special case:
+// !pipe->pattern && !pipe->noTransparency && !state->softMask &&
+// pipe->usesShape && !pipe->alpha0Ptr && !state->blendFunc &&
+// !pipe->nonIsolatedGroup &&
+// bitmap->mode == splashModeMono8 && bitmap->alpha
+void Splash::pipeRunAAMono8(SplashPipe *pipe, int x0, int x1, int y,
+ Guchar *shapePtr, SplashColorPtr cSrcPtr) {
+ Guchar shape, aSrc, aDest, alphaI, aResult, cSrc0, cDest0, cResult0;
+ SplashColorPtr destColorPtr;
+ Guchar *destAlphaPtr;
+ int cSrcStride, x, lastX;
+
+ if (cSrcPtr) {
+ cSrcStride = 1;
+ } else {
+ cSrcPtr = pipe->cSrcVal;
+ cSrcStride = 0;
+ }
+ for (; x0 <= x1; ++x0) {
+ if (*shapePtr) {
+ break;
+ }
+ cSrcPtr += cSrcStride;
+ ++shapePtr;
+ }
+ if (x0 > x1) {
+ return;
+ }
+ updateModX(x0);
+ updateModY(y);
+ lastX = x0;
+
+ useDestRow(y);
+
+ destColorPtr = &bitmap->data[y * bitmap->rowSize + x0];
+ destAlphaPtr = &bitmap->alpha[y * bitmap->alphaRowSize + x0];
+
+ for (x = x0; x <= x1; ++x) {
+
+ //----- shape
+ shape = *shapePtr;
+ if (!shape) {
+ ++destColorPtr;
+ ++destAlphaPtr;
+ cSrcPtr += cSrcStride;
+ ++shapePtr;
+ continue;
+ }
+ lastX = x;
+
+ //----- read destination pixel
+ cDest0 = *destColorPtr;
+ aDest = *destAlphaPtr;
+
+ //----- source color
+ cSrc0 = state->grayTransfer[cSrcPtr[0]];
+
+ //----- source alpha
+ aSrc = div255(pipe->aInput * shape);
+
+ //----- result alpha and non-isolated group element correction
+ aResult = (Guchar)(aSrc + aDest - div255(aSrc * aDest));
+ alphaI = aResult;
+
+ //----- result color
+ if (alphaI == 0) {
+ cResult0 = 0;
+ } else {
+ cResult0 = (Guchar)(((alphaI - aSrc) * cDest0 + aSrc * cSrc0) / alphaI);
+ }
+
+ //----- write destination pixel
+ *destColorPtr++ = cResult0;
+ *destAlphaPtr++ = aResult;
+
+ cSrcPtr += cSrcStride;
+ ++shapePtr;
+ }
+
+ updateModX(lastX);
+}
+
+// special case:
+// !pipe->pattern && !pipe->noTransparency && !state->softMask &&
+// pipe->usesShape && !pipe->alpha0Ptr && !state->blendFunc &&
+// !pipe->nonIsolatedGroup &&
+// bitmap->mode == splashModeRGB8 && bitmap->alpha
+void Splash::pipeRunAARGB8(SplashPipe *pipe, int x0, int x1, int y,
+ Guchar *shapePtr, SplashColorPtr cSrcPtr) {
+ Guchar shape, aSrc, aDest, alphaI, aResult;
+ Guchar cSrc0, cSrc1, cSrc2;
+ Guchar cDest0, cDest1, cDest2;
+ Guchar cResult0, cResult1, cResult2;
+ SplashColorPtr destColorPtr;
+ Guchar *destAlphaPtr;
+ int cSrcStride, x, lastX;
+
+ if (cSrcPtr) {
+ cSrcStride = 3;
+ } else {
+ cSrcPtr = pipe->cSrcVal;
+ cSrcStride = 0;
+ }
+ for (; x0 <= x1; ++x0) {
+ if (*shapePtr) {
+ break;
+ }
+ cSrcPtr += cSrcStride;
+ ++shapePtr;
+ }
+ if (x0 > x1) {
+ return;
+ }
+ updateModX(x0);
+ updateModY(y);
+ lastX = x0;
+
+ useDestRow(y);
+
+ destColorPtr = &bitmap->data[y * bitmap->rowSize + 3 * x0];
+ destAlphaPtr = &bitmap->alpha[y * bitmap->alphaRowSize + x0];
+
+ for (x = x0; x <= x1; ++x) {
+
+ //----- shape
+ shape = *shapePtr;
+ if (!shape) {
+ destColorPtr += 3;
+ ++destAlphaPtr;
+ cSrcPtr += cSrcStride;
+ ++shapePtr;
+ continue;
+ }
+ lastX = x;
+
+ //----- read destination pixel
+ cDest0 = destColorPtr[0];
+ cDest1 = destColorPtr[1];
+ cDest2 = destColorPtr[2];
+ aDest = *destAlphaPtr;
+
+ //----- source color
+ cSrc0 = state->rgbTransferR[cSrcPtr[0]];
+ cSrc1 = state->rgbTransferG[cSrcPtr[1]];
+ cSrc2 = state->rgbTransferB[cSrcPtr[2]];
+
+ //----- source alpha
+ aSrc = div255(pipe->aInput * shape);
+
+ //----- result alpha and non-isolated group element correction
+ aResult = (Guchar)(aSrc + aDest - div255(aSrc * aDest));
+ alphaI = aResult;
+
+ //----- result color
+ if (alphaI == 0) {
+ cResult0 = 0;
+ cResult1 = 0;
+ cResult2 = 0;
+ } else {
+ cResult0 = (Guchar)(((alphaI - aSrc) * cDest0 + aSrc * cSrc0) / alphaI);
+ cResult1 = (Guchar)(((alphaI - aSrc) * cDest1 + aSrc * cSrc1) / alphaI);
+ cResult2 = (Guchar)(((alphaI - aSrc) * cDest2 + aSrc * cSrc2) / alphaI);
+ }
+
+ //----- write destination pixel
+ destColorPtr[0] = cResult0;
+ destColorPtr[1] = cResult1;
+ destColorPtr[2] = cResult2;
+ destColorPtr += 3;
+ *destAlphaPtr++ = aResult;
+
+ cSrcPtr += cSrcStride;
+ ++shapePtr;
+ }
+
+ updateModX(lastX);
+}
+
+// special case:
+// !pipe->pattern && !pipe->noTransparency && !state->softMask &&
+// pipe->usesShape && !pipe->alpha0Ptr && !state->blendFunc &&
+// !pipe->nonIsolatedGroup &&
+// bitmap->mode == splashModeBGR8 && bitmap->alpha
+void Splash::pipeRunAABGR8(SplashPipe *pipe, int x0, int x1, int y,
+ Guchar *shapePtr, SplashColorPtr cSrcPtr) {
+ Guchar shape, aSrc, aDest, alphaI, aResult;
+ Guchar cSrc0, cSrc1, cSrc2;
+ Guchar cDest0, cDest1, cDest2;
+ Guchar cResult0, cResult1, cResult2;
+ SplashColorPtr destColorPtr;
+ Guchar *destAlphaPtr;
+ int cSrcStride, x, lastX;
+
+ if (cSrcPtr) {
+ cSrcStride = 3;
+ } else {
+ cSrcPtr = pipe->cSrcVal;
+ cSrcStride = 0;
+ }
+ for (; x0 <= x1; ++x0) {
+ if (*shapePtr) {
+ break;
+ }
+ cSrcPtr += cSrcStride;
+ ++shapePtr;
+ }
+ if (x0 > x1) {
+ return;
+ }
+ updateModX(x0);
+ updateModY(y);
+ lastX = x0;
+
+ useDestRow(y);
+
+ destColorPtr = &bitmap->data[y * bitmap->rowSize + 3 * x0];
+ destAlphaPtr = &bitmap->alpha[y * bitmap->alphaRowSize + x0];
+
+ for (x = x0; x <= x1; ++x) {
+
+ //----- shape
+ shape = *shapePtr;
+ if (!shape) {
+ destColorPtr += 3;
+ ++destAlphaPtr;
+ cSrcPtr += cSrcStride;
+ ++shapePtr;
+ continue;
+ }
+ lastX = x;
+
+ //----- read destination pixel
+ cDest0 = destColorPtr[2];
+ cDest1 = destColorPtr[1];
+ cDest2 = destColorPtr[0];
+ aDest = *destAlphaPtr;
+
+ //----- source color
+ cSrc0 = state->rgbTransferR[cSrcPtr[0]];
+ cSrc1 = state->rgbTransferG[cSrcPtr[1]];
+ cSrc2 = state->rgbTransferB[cSrcPtr[2]];
+
+ //----- source alpha
+ aSrc = div255(pipe->aInput * shape);
+
+ //----- result alpha and non-isolated group element correction
+ aResult = (Guchar)(aSrc + aDest - div255(aSrc * aDest));
+ alphaI = aResult;
+
+ //----- result color
+ if (alphaI == 0) {
+ cResult0 = 0;
+ cResult1 = 0;
+ cResult2 = 0;
+ } else {
+ cResult0 = (Guchar)(((alphaI - aSrc) * cDest0 + aSrc * cSrc0) / alphaI);
+ cResult1 = (Guchar)(((alphaI - aSrc) * cDest1 + aSrc * cSrc1) / alphaI);
+ cResult2 = (Guchar)(((alphaI - aSrc) * cDest2 + aSrc * cSrc2) / alphaI);
+ }
+
+ //----- write destination pixel
+ destColorPtr[0] = cResult2;
+ destColorPtr[1] = cResult1;
+ destColorPtr[2] = cResult0;
+ destColorPtr += 3;
+ *destAlphaPtr++ = aResult;
+
+ cSrcPtr += cSrcStride;
+ ++shapePtr;
+ }
+
+ updateModX(lastX);
+}
+
+#if SPLASH_CMYK
+// special case:
+// !pipe->pattern && !pipe->noTransparency && !state->softMask &&
+// pipe->usesShape && !pipe->alpha0Ptr && !state->blendFunc &&
+// !pipe->nonIsolatedGroup &&
+// bitmap->mode == splashModeCMYK8 && bitmap->alpha
+void Splash::pipeRunAACMYK8(SplashPipe *pipe, int x0, int x1, int y,
+ Guchar *shapePtr, SplashColorPtr cSrcPtr) {
+ Guchar shape, aSrc, aDest, alphaI, aResult;
+ Guchar cSrc0, cSrc1, cSrc2, cSrc3;
+ Guchar cDest0, cDest1, cDest2, cDest3;
+ Guchar cResult0, cResult1, cResult2, cResult3;
+ SplashColorPtr destColorPtr;
+ Guchar *destAlphaPtr;
+ int cSrcStride, x, lastX;
+
+ if (cSrcPtr) {
+ cSrcStride = 4;
+ } else {
+ cSrcPtr = pipe->cSrcVal;
+ cSrcStride = 0;
+ }
+ for (; x0 <= x1; ++x0) {
+ if (*shapePtr) {
+ break;
+ }
+ cSrcPtr += cSrcStride;
+ ++shapePtr;
+ }
+ if (x0 > x1) {
+ return;
+ }
+ updateModX(x0);
+ updateModY(y);
+ lastX = x0;
+
+ useDestRow(y);
+
+ destColorPtr = &bitmap->data[y * bitmap->rowSize + 4 * x0];
+ destAlphaPtr = &bitmap->alpha[y * bitmap->alphaRowSize + x0];
+
+ for (x = x0; x <= x1; ++x) {
+
+ //----- shape
+ shape = *shapePtr;
+ if (!shape) {
+ destColorPtr += 4;
+ ++destAlphaPtr;
+ cSrcPtr += cSrcStride;
+ ++shapePtr;
+ continue;
+ }
+ lastX = x;
+
+ //----- read destination pixel
+ cDest0 = destColorPtr[0];
+ cDest1 = destColorPtr[1];
+ cDest2 = destColorPtr[2];
+ cDest3 = destColorPtr[3];
+ aDest = *destAlphaPtr;
+
+ //----- overprint
+ if (state->overprintMask & 1) {
+ cSrc0 = state->cmykTransferC[cSrcPtr[0]];
+ } else {
+ cSrc0 = div255(aDest * cDest0);
+ }
+ if (state->overprintMask & 2) {
+ cSrc1 = state->cmykTransferM[cSrcPtr[1]];
+ } else {
+ cSrc1 = div255(aDest * cDest1);
+ }
+ if (state->overprintMask & 4) {
+ cSrc2 = state->cmykTransferY[cSrcPtr[2]];
+ } else {
+ cSrc2 = div255(aDest * cDest2);
+ }
+ if (state->overprintMask & 8) {
+ cSrc3 = state->cmykTransferK[cSrcPtr[3]];
+ } else {
+ cSrc3 = div255(aDest * cDest3);
+ }
+
+ //----- source alpha
+ aSrc = div255(pipe->aInput * shape);
+
+ //----- result alpha and non-isolated group element correction
+ aResult = (Guchar)(aSrc + aDest - div255(aSrc * aDest));
+ alphaI = aResult;
+
+ //----- result color
+ if (alphaI == 0) {
+ cResult0 = 0;
+ cResult1 = 0;
+ cResult2 = 0;
+ cResult3 = 0;
+ } else {
+ cResult0 = (Guchar)(((alphaI - aSrc) * cDest0 + aSrc * cSrc0) / alphaI);
+ cResult1 = (Guchar)(((alphaI - aSrc) * cDest1 + aSrc * cSrc1) / alphaI);
+ cResult2 = (Guchar)(((alphaI - aSrc) * cDest2 + aSrc * cSrc2) / alphaI);
+ cResult3 = (Guchar)(((alphaI - aSrc) * cDest3 + aSrc * cSrc3) / alphaI);
+ }
+
+ //----- write destination pixel
+ destColorPtr[0] = cResult0;
+ destColorPtr[1] = cResult1;
+ destColorPtr[2] = cResult2;
+ destColorPtr[3] = cResult3;
+ destColorPtr += 4;
+ *destAlphaPtr++ = aResult;
+
+ cSrcPtr += cSrcStride;
+ ++shapePtr;
+ }
+
+ updateModX(lastX);
+}
+#endif
+
+
+// special case:
+// !pipe->pattern && aInput == 255 && state->softMask && usesShape &&
+// !state->inNonIsolatedGroup && !state->inKnockoutGroup &&
+// !nonIsolatedGroup && state->overprintMask == 0xffffffff &&
+// !state->blendFunc &&
+// bitmap->mode == splashModeMono8 && bitmap->alpha
+void Splash::pipeRunSoftMaskMono8(SplashPipe *pipe, int x0, int x1, int y,
+ Guchar *shapePtr, SplashColorPtr cSrcPtr) {
+ Guchar shape, aSrc, aDest, alphaI, aResult;
+ Guchar cSrc0, cDest0, cResult0;
+ SplashColorPtr destColorPtr;
+ Guchar *destAlphaPtr;
+ SplashColorPtr softMaskPtr;
+ int cSrcStride, x, lastX;
+
+ if (cSrcPtr) {
+ cSrcStride = 1;
+ } else {
+ cSrcPtr = pipe->cSrcVal;
+ cSrcStride = 0;
+ }
+ for (; x0 <= x1; ++x0) {
+ if (*shapePtr) {
+ break;
+ }
+ cSrcPtr += cSrcStride;
+ ++shapePtr;
+ }
+ if (x0 > x1) {
+ return;
+ }
+ updateModX(x0);
+ updateModY(y);
+ lastX = x0;
+
+ useDestRow(y);
+
+ destColorPtr = &bitmap->data[y * bitmap->rowSize + x0];
+ destAlphaPtr = &bitmap->alpha[y * bitmap->alphaRowSize + x0];
+ softMaskPtr = &state->softMask->data[y * state->softMask->rowSize + x0];
+
+ for (x = x0; x <= x1; ++x) {
+
+ //----- shape
+ shape = *shapePtr;
+ if (!shape) {
+ ++destColorPtr;
+ ++destAlphaPtr;
+ ++softMaskPtr;
+ cSrcPtr += cSrcStride;
+ ++shapePtr;
+ continue;
+ }
+ lastX = x;
+
+ //----- read source color
+ cSrc0 = state->grayTransfer[cSrcPtr[0]];
+
+ //----- source alpha
+ aSrc = div255(*softMaskPtr++ * shape);
+
+ //----- special case for aSrc = 255
+ if (aSrc == 255) {
+ aResult = 255;
+ cResult0 = cSrc0;
+ } else {
+
+ //----- read destination alpha
+ aDest = *destAlphaPtr;
+
+ //----- special case for aDest = 0
+ if (aDest == 0) {
+ aResult = aSrc;
+ cResult0 = cSrc0;
+ } else {
+
+ //----- read destination pixel
+ cDest0 = destColorPtr[0];
+
+ //----- result alpha and non-isolated group element correction
+ aResult = (Guchar)(aSrc + aDest - div255(aSrc * aDest));
+ alphaI = aResult;
+
+ //----- result color
+ cResult0 = (Guchar)(((alphaI - aSrc) * cDest0 + aSrc * cSrc0) / alphaI);
+ }
+ }
+
+ //----- write destination pixel
+ destColorPtr[0] = cResult0;
+ ++destColorPtr;
+ *destAlphaPtr++ = aResult;
+
+ cSrcPtr += cSrcStride;
+ ++shapePtr;
+ }
+
+ updateModX(lastX);
+}
+
+// special case:
+// !pipe->pattern && aInput == 255 && state->softMask && usesShape &&
+// !state->inNonIsolatedGroup && !state->inKnockoutGroup &&
+// !nonIsolatedGroup && state->overprintMask == 0xffffffff &&
+// !state->blendFunc &&
+// bitmap->mode == splashModeRGB8 && bitmap->alpha
+void Splash::pipeRunSoftMaskRGB8(SplashPipe *pipe, int x0, int x1, int y,
+ Guchar *shapePtr, SplashColorPtr cSrcPtr) {
+ Guchar shape, aSrc, aDest, alphaI, aResult;
+ Guchar cSrc0, cSrc1, cSrc2;
+ Guchar cDest0, cDest1, cDest2;
+ Guchar cResult0, cResult1, cResult2;
+ SplashColorPtr destColorPtr;
+ Guchar *destAlphaPtr;
+ SplashColorPtr softMaskPtr;
+ int cSrcStride, x, lastX;
+
+ if (cSrcPtr) {
+ cSrcStride = 3;
+ } else {
+ cSrcPtr = pipe->cSrcVal;
+ cSrcStride = 0;
+ }
+ for (; x0 <= x1; ++x0) {
+ if (*shapePtr) {
+ break;
+ }
+ cSrcPtr += cSrcStride;
+ ++shapePtr;
+ }
+ if (x0 > x1) {
+ return;
+ }
+ updateModX(x0);
+ updateModY(y);
+ lastX = x0;
+
+ useDestRow(y);
+
+ destColorPtr = &bitmap->data[y * bitmap->rowSize + x0 * 3];
+ destAlphaPtr = &bitmap->alpha[y * bitmap->alphaRowSize + x0];
+ softMaskPtr = &state->softMask->data[y * state->softMask->rowSize + x0];
+
+ for (x = x0; x <= x1; ++x) {
+
+ //----- shape
+ shape = *shapePtr;
+ if (!shape) {
+ destColorPtr += 3;
+ ++destAlphaPtr;
+ ++softMaskPtr;
+ cSrcPtr += cSrcStride;
+ ++shapePtr;
+ continue;
+ }
+ lastX = x;
+
+ //----- read source color
+ cSrc0 = state->rgbTransferR[cSrcPtr[0]];
+ cSrc1 = state->rgbTransferG[cSrcPtr[1]];
+ cSrc2 = state->rgbTransferB[cSrcPtr[2]];
+
+ //----- source alpha
+ aSrc = div255(*softMaskPtr++ * shape);
+
+ //----- special case for aSrc = 255
+ if (aSrc == 255) {
+ aResult = 255;
+ cResult0 = cSrc0;
+ cResult1 = cSrc1;
+ cResult2 = cSrc2;
+ } else {
+
+ //----- read destination alpha
+ aDest = *destAlphaPtr;
+
+ //----- special case for aDest = 0
+ if (aDest == 0) {
+ aResult = aSrc;
+ cResult0 = cSrc0;
+ cResult1 = cSrc1;
+ cResult2 = cSrc2;
+ } else {
+
+ //----- read destination pixel
+ cDest0 = destColorPtr[0];
+ cDest1 = destColorPtr[1];
+ cDest2 = destColorPtr[2];
+
+ //----- result alpha and non-isolated group element correction
+ aResult = (Guchar)(aSrc + aDest - div255(aSrc * aDest));
+ alphaI = aResult;
+
+ //----- result color
+ cResult0 = (Guchar)(((alphaI - aSrc) * cDest0 + aSrc * cSrc0) / alphaI);
+ cResult1 = (Guchar)(((alphaI - aSrc) * cDest1 + aSrc * cSrc1) / alphaI);
+ cResult2 = (Guchar)(((alphaI - aSrc) * cDest2 + aSrc * cSrc2) / alphaI);
+ }
+ }
+
+ //----- write destination pixel
+ destColorPtr[0] = cResult0;
+ destColorPtr[1] = cResult1;
+ destColorPtr[2] = cResult2;
+ destColorPtr += 3;
+ *destAlphaPtr++ = aResult;
+
+ cSrcPtr += cSrcStride;
+ ++shapePtr;
+ }
+
+ updateModX(lastX);
+}
+
+// special case:
+// !pipe->pattern && aInput == 255 && state->softMask && usesShape &&
+// !state->inNonIsolatedGroup && !state->inKnockoutGroup &&
+// !nonIsolatedGroup && state->overprintMask == 0xffffffff &&
+// !state->blendFunc &&
+// bitmap->mode == splashModeBGR8 && bitmap->alpha
+void Splash::pipeRunSoftMaskBGR8(SplashPipe *pipe, int x0, int x1, int y,
+ Guchar *shapePtr, SplashColorPtr cSrcPtr) {
+ Guchar shape, aSrc, aDest, alphaI, aResult;
+ Guchar cSrc0, cSrc1, cSrc2;
+ Guchar cDest0, cDest1, cDest2;
+ Guchar cResult0, cResult1, cResult2;
+ SplashColorPtr destColorPtr;
+ Guchar *destAlphaPtr;
+ SplashColorPtr softMaskPtr;
+ int cSrcStride, x, lastX;
+
+ if (cSrcPtr) {
+ cSrcStride = 3;
+ } else {
+ cSrcPtr = pipe->cSrcVal;
+ cSrcStride = 0;
+ }
+ for (; x0 <= x1; ++x0) {
+ if (*shapePtr) {
+ break;
+ }
+ cSrcPtr += cSrcStride;
+ ++shapePtr;
+ }
+ if (x0 > x1) {
+ return;
+ }
+ updateModX(x0);
+ updateModY(y);
+ lastX = x0;
+
+ useDestRow(y);
+
+ destColorPtr = &bitmap->data[y * bitmap->rowSize + x0 * 3];
+ destAlphaPtr = &bitmap->alpha[y * bitmap->alphaRowSize + x0];
+ softMaskPtr = &state->softMask->data[y * state->softMask->rowSize + x0];
+
+ for (x = x0; x <= x1; ++x) {
+
+ //----- shape
+ shape = *shapePtr;
+ if (!shape) {
+ destColorPtr += 3;
+ ++destAlphaPtr;
+ ++softMaskPtr;
+ cSrcPtr += cSrcStride;
+ ++shapePtr;
+ continue;
+ }
+ lastX = x;
+
+ //----- read source color
+ cSrc0 = state->rgbTransferR[cSrcPtr[0]];
+ cSrc1 = state->rgbTransferG[cSrcPtr[1]];
+ cSrc2 = state->rgbTransferB[cSrcPtr[2]];
+
+ //----- source alpha
+ aSrc = div255(*softMaskPtr++ * shape);
+
+ //----- special case for aSrc = 255
+ if (aSrc == 255) {
+ aResult = 255;
+ cResult0 = cSrc0;
+ cResult1 = cSrc1;
+ cResult2 = cSrc2;
+ } else {
+
+ //----- read destination alpha
+ aDest = *destAlphaPtr;
+
+ //----- special case for aDest = 0
+ if (aDest == 0) {
+ aResult = aSrc;
+ cResult0 = cSrc0;
+ cResult1 = cSrc1;
+ cResult2 = cSrc2;
+ } else {
+
+ //----- read destination pixel
+ cDest0 = destColorPtr[2];
+ cDest1 = destColorPtr[1];
+ cDest2 = destColorPtr[0];
+
+ //----- result alpha and non-isolated group element correction
+ aResult = (Guchar)(aSrc + aDest - div255(aSrc * aDest));
+ alphaI = aResult;
+
+ //----- result color
+ cResult0 = (Guchar)(((alphaI - aSrc) * cDest0 + aSrc * cSrc0) / alphaI);
+ cResult1 = (Guchar)(((alphaI - aSrc) * cDest1 + aSrc * cSrc1) / alphaI);
+ cResult2 = (Guchar)(((alphaI - aSrc) * cDest2 + aSrc * cSrc2) / alphaI);
+ }
+ }
+
+ //----- write destination pixel
+ destColorPtr[2] = cResult0;
+ destColorPtr[1] = cResult1;
+ destColorPtr[0] = cResult2;
+ destColorPtr += 3;
+ *destAlphaPtr++ = aResult;
+
+ cSrcPtr += cSrcStride;
+ ++shapePtr;
+ }
+
+ updateModX(lastX);
+}
+
+#if SPLASH_CMYK
+// special case:
+// !pipe->pattern && aInput == 255 && state->softMask && usesShape &&
+// !state->inNonIsolatedGroup && !state->inKnockoutGroup &&
+// !nonIsolatedGroup && state->overprintMask == 0xffffffff &&
+// !state->blendFunc &&
+// bitmap->mode == splashModeCMYK8 && bitmap->alpha
+void Splash::pipeRunSoftMaskCMYK8(SplashPipe *pipe, int x0, int x1, int y,
+ Guchar *shapePtr, SplashColorPtr cSrcPtr) {
+ Guchar shape, aSrc, aDest, alphaI, aResult;
+ Guchar cSrc0, cSrc1, cSrc2, cSrc3;
+ Guchar cDest0, cDest1, cDest2, cDest3;
+ Guchar cResult0, cResult1, cResult2, cResult3;
+ SplashColorPtr destColorPtr;
+ Guchar *destAlphaPtr;
+ SplashColorPtr softMaskPtr;
+ int cSrcStride, x, lastX;
+
+ if (cSrcPtr) {
+ cSrcStride = 4;
+ } else {
+ cSrcPtr = pipe->cSrcVal;
+ cSrcStride = 0;
+ }
+ for (; x0 <= x1; ++x0) {
+ if (*shapePtr) {
+ break;
+ }
+ cSrcPtr += cSrcStride;
+ ++shapePtr;
+ }
+ if (x0 > x1) {
+ return;
+ }
+ updateModX(x0);
+ updateModY(y);
+ lastX = x0;
+
+ useDestRow(y);
+
+ destColorPtr = &bitmap->data[y * bitmap->rowSize + x0 * 4];
+ destAlphaPtr = &bitmap->alpha[y * bitmap->alphaRowSize + x0];
+ softMaskPtr = &state->softMask->data[y * state->softMask->rowSize + x0];
+
+ for (x = x0; x <= x1; ++x) {
+
+ //----- shape
+ shape = *shapePtr;
+ if (!shape) {
+ destColorPtr += 4;
+ ++destAlphaPtr;
+ ++softMaskPtr;
+ cSrcPtr += cSrcStride;
+ ++shapePtr;
+ continue;
+ }
+ lastX = x;
+
+ //----- read destination pixel
+ cDest0 = destColorPtr[0];
+ cDest1 = destColorPtr[1];
+ cDest2 = destColorPtr[2];
+ cDest3 = destColorPtr[3];
+
+ //----- read destination alpha
+ aDest = *destAlphaPtr;
+
+ //----- overprint
+ cSrc0 = state->cmykTransferC[cSrcPtr[0]];
+ cSrc1 = state->cmykTransferM[cSrcPtr[1]];
+ cSrc2 = state->cmykTransferY[cSrcPtr[2]];
+ cSrc3 = state->cmykTransferK[cSrcPtr[3]];
+
+ //----- source alpha
+ aSrc = div255(*softMaskPtr++ * shape);
+
+ //----- special case for aSrc = 255
+ if (aSrc == 255) {
+ aResult = 255;
+ cResult0 = cSrc0;
+ cResult1 = cSrc1;
+ cResult2 = cSrc2;
+ cResult3 = cSrc3;
+ } else {
+
+ //----- special case for aDest = 0
+ if (aDest == 0) {
+ aResult = aSrc;
+ cResult0 = cSrc0;
+ cResult1 = cSrc1;
+ cResult2 = cSrc2;
+ cResult3 = cSrc3;
+ } else {
+
+ //----- result alpha and non-isolated group element correction
+ aResult = (Guchar)(aSrc + aDest - div255(aSrc * aDest));
+ alphaI = aResult;
+
+ //----- result color
+ cResult0 = (Guchar)(((alphaI - aSrc) * cDest0 + aSrc * cSrc0) / alphaI);
+ cResult1 = (Guchar)(((alphaI - aSrc) * cDest1 + aSrc * cSrc1) / alphaI);
+ cResult2 = (Guchar)(((alphaI - aSrc) * cDest2 + aSrc * cSrc2) / alphaI);
+ cResult3 = (Guchar)(((alphaI - aSrc) * cDest3 + aSrc * cSrc3) / alphaI);
+ }
+ }
+
+ //----- write destination pixel
+ destColorPtr[0] = cResult0;
+ destColorPtr[1] = cResult1;
+ destColorPtr[2] = cResult2;
+ destColorPtr[3] = cResult3;
+ destColorPtr += 4;
+ *destAlphaPtr++ = aResult;
+
+ cSrcPtr += cSrcStride;
+ ++shapePtr;
+ }
+
+ updateModX(lastX);
+}
+#endif
+
+
+void Splash::pipeRunNonIsoMono8(SplashPipe *pipe, int x0, int x1, int y,
+ Guchar *shapePtr, SplashColorPtr cSrcPtr) {
+ Guchar shape, aSrc, aDest, alphaI, alpha0, aResult;
+ Guchar cSrc0, cDest0, cResult0;
+ SplashColorPtr destColorPtr;
+ Guchar *destAlphaPtr;
+ Guchar *alpha0Ptr;
+ int cSrcStride, x, lastX;
+
+ if (cSrcPtr) {
+ cSrcStride = 1;
+ } else {
+ cSrcPtr = pipe->cSrcVal;
+ cSrcStride = 0;
+ }
+ for (; x0 <= x1; ++x0) {
+ if (*shapePtr) {
+ break;
+ }
+ cSrcPtr += cSrcStride;
+ ++shapePtr;
+ }
+ if (x0 > x1) {
+ return;
+ }
+ updateModX(x0);
+ updateModY(y);
+ lastX = x0;
+
+ useDestRow(y);
+
+ destColorPtr = &bitmap->data[y * bitmap->rowSize + x0];
+ destAlphaPtr = &bitmap->alpha[y * bitmap->alphaRowSize + x0];
+ alpha0Ptr = &groupBackBitmap->alpha[(groupBackY + y)
+ * groupBackBitmap->alphaRowSize +
+ (groupBackX + x0)];
+
+ for (x = x0; x <= x1; ++x) {
+
+ //----- shape
+ shape = *shapePtr;
+ if (!shape) {
+ destColorPtr += 1;
+ ++destAlphaPtr;
+ ++alpha0Ptr;
+ cSrcPtr += cSrcStride;
+ ++shapePtr;
+ continue;
+ }
+ lastX = x;
+
+ //----- read destination pixel
+ cDest0 = destColorPtr[0];
+ aDest = *destAlphaPtr;
+
+ //----- source color
+ cSrc0 = state->grayTransfer[cSrcPtr[0]];
+
+ //----- source alpha
+ aSrc = div255(pipe->aInput * shape);
+
+ //----- result alpha and non-isolated group element correction
+ aResult = (Guchar)(aSrc + aDest - div255(aSrc * aDest));
+ alpha0 = *alpha0Ptr++;
+ alphaI = (Guchar)(aResult + alpha0 - div255(aResult * alpha0));
+
+ //----- result color
+ if (alphaI == 0) {
+ cResult0 = 0;
+ } else {
+ cResult0 = (Guchar)(((alphaI - aSrc) * cDest0 + aSrc * cSrc0) / alphaI);
+ }
+
+ //----- write destination pixel
+ *destColorPtr++ = cResult0;
+ *destAlphaPtr++ = aResult;
+
+ cSrcPtr += cSrcStride;
+ ++shapePtr;
+ } // for (x ...)
+
+ updateModX(lastX);
+}
+
+void Splash::pipeRunNonIsoRGB8(SplashPipe *pipe, int x0, int x1, int y,
+ Guchar *shapePtr, SplashColorPtr cSrcPtr) {
+ Guchar shape, aSrc, aDest, alphaI, alpha0, aResult;
+ Guchar cSrc0, cSrc1, cSrc2;
+ Guchar cDest0, cDest1, cDest2;
+ Guchar cResult0, cResult1, cResult2;
+ SplashColorPtr destColorPtr;
+ Guchar *destAlphaPtr;
+ Guchar *alpha0Ptr;
+ int cSrcStride, x, lastX;
+
+ if (cSrcPtr) {
+ cSrcStride = 3;
+ } else {
+ cSrcPtr = pipe->cSrcVal;
+ cSrcStride = 0;
+ }
+ for (; x0 <= x1; ++x0) {
+ if (*shapePtr) {
+ break;
+ }
+ cSrcPtr += cSrcStride;
+ ++shapePtr;
+ }
+ if (x0 > x1) {
+ return;
+ }
+ updateModX(x0);
+ updateModY(y);
+ lastX = x0;
+
+ useDestRow(y);
+
+ destColorPtr = &bitmap->data[y * bitmap->rowSize + x0 * 3];
+ destAlphaPtr = &bitmap->alpha[y * bitmap->alphaRowSize + x0];
+ alpha0Ptr = &groupBackBitmap->alpha[(groupBackY + y)
+ * groupBackBitmap->alphaRowSize +
+ (groupBackX + x0)];
+
+ for (x = x0; x <= x1; ++x) {
+
+ //----- shape
+ shape = *shapePtr;
+ if (!shape) {
+ destColorPtr += 3;
+ ++destAlphaPtr;
+ ++alpha0Ptr;
+ cSrcPtr += cSrcStride;
+ ++shapePtr;
+ continue;
+ }
+ lastX = x;
+
+ //----- read destination pixel
+ cDest0 = destColorPtr[0];
+ cDest1 = destColorPtr[1];
+ cDest2 = destColorPtr[2];
+ aDest = *destAlphaPtr;
+
+ //----- source color
+ cSrc0 = state->rgbTransferR[cSrcPtr[0]];
+ cSrc1 = state->rgbTransferG[cSrcPtr[1]];
+ cSrc2 = state->rgbTransferB[cSrcPtr[2]];
+
+ //----- source alpha
+ aSrc = div255(pipe->aInput * shape);
+
+ //----- result alpha and non-isolated group element correction
+ aResult = (Guchar)(aSrc + aDest - div255(aSrc * aDest));
+ alpha0 = *alpha0Ptr++;
+ alphaI = (Guchar)(aResult + alpha0 - div255(aResult * alpha0));
+
+ //----- result color
+ if (alphaI == 0) {
+ cResult0 = 0;
+ cResult1 = 0;
+ cResult2 = 0;
+ } else {
+ cResult0 = (Guchar)(((alphaI - aSrc) * cDest0 + aSrc * cSrc0) / alphaI);
+ cResult1 = (Guchar)(((alphaI - aSrc) * cDest1 + aSrc * cSrc1) / alphaI);
+ cResult2 = (Guchar)(((alphaI - aSrc) * cDest2 + aSrc * cSrc2) / alphaI);
+ }
+
+ //----- write destination pixel
+ destColorPtr[0] = cResult0;
+ destColorPtr[1] = cResult1;
+ destColorPtr[2] = cResult2;
+ destColorPtr += 3;
+ *destAlphaPtr++ = aResult;
+
+ cSrcPtr += cSrcStride;
+ ++shapePtr;
+ } // for (x ...)
+
+ updateModX(lastX);
+}
+
+void Splash::pipeRunNonIsoBGR8(SplashPipe *pipe, int x0, int x1, int y,
+ Guchar *shapePtr, SplashColorPtr cSrcPtr) {
+ Guchar shape, aSrc, aDest, alphaI, alpha0, aResult;
+ Guchar cSrc0, cSrc1, cSrc2;
+ Guchar cDest0, cDest1, cDest2;
+ Guchar cResult0, cResult1, cResult2;
+ SplashColorPtr destColorPtr;
+ Guchar *destAlphaPtr;
+ Guchar *alpha0Ptr;
+ int cSrcStride, x, lastX;
+
+ if (cSrcPtr) {
+ cSrcStride = 3;
+ } else {
+ cSrcPtr = pipe->cSrcVal;
+ cSrcStride = 0;
+ }
+ for (; x0 <= x1; ++x0) {
+ if (*shapePtr) {
+ break;
+ }
+ cSrcPtr += cSrcStride;
+ ++shapePtr;
+ }
+ if (x0 > x1) {
+ return;
+ }
+ updateModX(x0);
+ updateModY(y);
+ lastX = x0;
+
+ useDestRow(y);
+
+ destColorPtr = &bitmap->data[y * bitmap->rowSize + x0 * 3];
+ destAlphaPtr = &bitmap->alpha[y * bitmap->alphaRowSize + x0];
+ alpha0Ptr = &groupBackBitmap->alpha[(groupBackY + y)
+ * groupBackBitmap->alphaRowSize +
+ (groupBackX + x0)];
+
+ for (x = x0; x <= x1; ++x) {
+
+ //----- shape
+ shape = *shapePtr;
+ if (!shape) {
+ destColorPtr += 3;
+ ++destAlphaPtr;
+ ++alpha0Ptr;
+ cSrcPtr += cSrcStride;
+ ++shapePtr;
+ continue;
+ }
+ lastX = x;
+
+ //----- read destination pixel
+ cDest0 = destColorPtr[2];
+ cDest1 = destColorPtr[1];
+ cDest2 = destColorPtr[0];
+ aDest = *destAlphaPtr;
+
+ //----- source color
+ cSrc0 = state->rgbTransferR[cSrcPtr[0]];
+ cSrc1 = state->rgbTransferG[cSrcPtr[1]];
+ cSrc2 = state->rgbTransferB[cSrcPtr[2]];
+
+ //----- source alpha
+ aSrc = div255(pipe->aInput * shape);
+
+ //----- result alpha and non-isolated group element correction
+ aResult = (Guchar)(aSrc + aDest - div255(aSrc * aDest));
+ alpha0 = *alpha0Ptr++;
+ alphaI = (Guchar)(aResult + alpha0 - div255(aResult * alpha0));
+
+ //----- result color
+ if (alphaI == 0) {
+ cResult0 = 0;
+ cResult1 = 0;
+ cResult2 = 0;
+ } else {
+ cResult0 = (Guchar)(((alphaI - aSrc) * cDest0 + aSrc * cSrc0) / alphaI);
+ cResult1 = (Guchar)(((alphaI - aSrc) * cDest1 + aSrc * cSrc1) / alphaI);
+ cResult2 = (Guchar)(((alphaI - aSrc) * cDest2 + aSrc * cSrc2) / alphaI);
+ }
+
+ //----- write destination pixel
+ destColorPtr[0] = cResult2;
+ destColorPtr[1] = cResult1;
+ destColorPtr[2] = cResult0;
+ destColorPtr += 3;
+ *destAlphaPtr++ = aResult;
+
+ cSrcPtr += cSrcStride;
+ ++shapePtr;
+ } // for (x ...)
+
+ updateModX(lastX);
+}
+
+#if SPLASH_CMYK
+void Splash::pipeRunNonIsoCMYK8(SplashPipe *pipe, int x0, int x1, int y,
+ Guchar *shapePtr, SplashColorPtr cSrcPtr) {
+ Guchar shape, aSrc, aDest, alphaI, alpha0, aResult, aPrev;
+ Guchar cSrc0, cSrc1, cSrc2, cSrc3;
+ Guchar cDest0, cDest1, cDest2, cDest3;
+ Guchar cResult0, cResult1, cResult2, cResult3;
+ SplashColorPtr destColorPtr;
+ Guchar *destAlphaPtr;
+ Guchar *alpha0Ptr;
+ int cSrcStride, x, lastX;
+
+ if (cSrcPtr) {
+ cSrcStride = 4;
+ } else {
+ cSrcPtr = pipe->cSrcVal;
+ cSrcStride = 0;
+ }
+ for (; x0 <= x1; ++x0) {
+ if (*shapePtr) {
+ break;
+ }
+ cSrcPtr += cSrcStride;
+ ++shapePtr;
+ }
+ if (x0 > x1) {
+ return;
+ }
+ updateModX(x0);
+ updateModY(y);
+ lastX = x0;
+
+ useDestRow(y);
+
+ destColorPtr = &bitmap->data[y * bitmap->rowSize + x0 * 4];
+ destAlphaPtr = &bitmap->alpha[y * bitmap->alphaRowSize + x0];
+ alpha0Ptr = &groupBackBitmap->alpha[(groupBackY + y)
+ * groupBackBitmap->alphaRowSize +
+ (groupBackX + x0)];
+
+ for (x = x0; x <= x1; ++x) {
+
+ //----- shape
+ shape = *shapePtr;
+ if (!shape) {
+ destColorPtr += 4;
+ ++destAlphaPtr;
+ ++alpha0Ptr;
+ cSrcPtr += cSrcStride;
+ ++shapePtr;
+ continue;
+ }
+ lastX = x;
+
+ //----- read destination pixel
+ cDest0 = destColorPtr[0];
+ cDest1 = destColorPtr[1];
+ cDest2 = destColorPtr[2];
+ cDest3 = destColorPtr[3];
+ aDest = *destAlphaPtr;
+
+ //----- overprint
+ aPrev = (Guchar)(*alpha0Ptr + aDest - div255(*alpha0Ptr * aDest));
+ if (state->overprintMask & 0x01) {
+ cSrc0 = state->cmykTransferC[cSrcPtr[0]];
+ } else {
+ cSrc0 = div255(aPrev * cDest0);
+ }
+ if (state->overprintMask & 0x02) {
+ cSrc1 = state->cmykTransferM[cSrcPtr[1]];
+ } else {
+ cSrc1 = div255(aPrev * cDest1);
+ }
+ if (state->overprintMask & 0x04) {
+ cSrc2 = state->cmykTransferY[cSrcPtr[2]];
+ } else {
+ cSrc2 = div255(aPrev * cDest2);
+ }
+ if (state->overprintMask & 0x08) {
+ cSrc3 = state->cmykTransferK[cSrcPtr[3]];
+ } else {
+ cSrc3 = div255(aPrev * cDest3);
+ }
+
+ //----- source alpha
+ aSrc = div255(pipe->aInput * shape);
+
+ //----- result alpha and non-isolated group element correction
+ aResult = (Guchar)(aSrc + aDest - div255(aSrc * aDest));
+ alpha0 = *alpha0Ptr++;
+ alphaI = (Guchar)(aResult + alpha0 - div255(aResult * alpha0));
+
+ //----- result color
+ if (alphaI == 0) {
+ cResult0 = 0;
+ cResult1 = 0;
+ cResult2 = 0;
+ cResult3 = 0;
+ } else {
+ cResult0 = (Guchar)(((alphaI - aSrc) * cDest0 + aSrc * cSrc0) / alphaI);
+ cResult1 = (Guchar)(((alphaI - aSrc) * cDest1 + aSrc * cSrc1) / alphaI);
+ cResult2 = (Guchar)(((alphaI - aSrc) * cDest2 + aSrc * cSrc2) / alphaI);
+ cResult3 = (Guchar)(((alphaI - aSrc) * cDest3 + aSrc * cSrc3) / alphaI);
+ }
+
+ //----- write destination pixel
+ destColorPtr[0] = cResult0;
+ destColorPtr[1] = cResult1;
+ destColorPtr[2] = cResult2;
+ destColorPtr[3] = cResult3;
+ destColorPtr += 4;
+ *destAlphaPtr++ = aResult;
+
+ cSrcPtr += cSrcStride;
+ ++shapePtr;
+ } // for (x ...)
+
+ updateModX(lastX);
+}
+#endif
+
+
+void Splash::useDestRow(int y) {
+ int y0, y1, yy;
+
+ if (groupDestInitMode == splashGroupDestPreInit) {
+ return;
+ }
+ if (groupDestInitYMin > groupDestInitYMax) {
+ y0 = y1 = y;
+ groupDestInitYMin = groupDestInitYMax = y;
+ } else if (y < groupDestInitYMin) {
+ y0 = y;
+ y1 = groupDestInitYMin - 1;
+ groupDestInitYMin = y;
+ } else if (y > groupDestInitYMax) {
+ y0 = groupDestInitYMax + 1;
+ y1 = y;
+ groupDestInitYMax = y;
+ } else {
+ return;
+ }
+ for (yy = y0; yy <= y1; ++yy) {
+ if (groupDestInitMode == splashGroupDestInitZero) {
+ // same as clear(color=0, alpha=0)
+ memset(bitmap->data + bitmap->rowSize * yy, 0,
+ bitmap->rowSize < 0 ? -bitmap->rowSize : bitmap->rowSize);
+ if (bitmap->alpha) {
+ memset(bitmap->alpha + bitmap->alphaRowSize * yy, 0,
+ bitmap->alphaRowSize);
+ }
+ } else { // (groupDestInitMode == splashGroupDestInitCopy)
+ // same as blitTransparent
+ copyGroupBackdropRow(yy);
+ }
+ }
+}
+
+void Splash::copyGroupBackdropRow(int y) {
+ SplashColorPtr p, q;
+ Guchar mask, srcMask;
+ int x;
+
+ if (groupBackBitmap->mode != bitmap->mode) {
+ return;
+ }
+
+ if (bitmap->mode == splashModeMono1) {
+ p = &bitmap->data[y * bitmap->rowSize];
+ mask = (Guchar)0x80;
+ q = &groupBackBitmap->data[(groupBackY + y) * groupBackBitmap->rowSize
+ + (groupBackX >> 3)];
+ srcMask = (Guchar)(0x80 >> (groupBackX & 7));
+ for (x = 0; x < bitmap->width; ++x) {
+ if (*q & srcMask) {
+ *p |= mask;
+ } else {
+ *p &= (Guchar)~mask;
+ }
+ if (!(mask = (Guchar)(mask >> 1))) {
+ mask = 0x80;
+ ++p;
+ }
+ if (!(srcMask = (Guchar)(srcMask >> 1))) {
+ srcMask = 0x80;
+ ++q;
+ }
+ }
+ } else {
+ p = &bitmap->data[y * bitmap->rowSize];
+ q = &groupBackBitmap->data[(groupBackY + y) * groupBackBitmap->rowSize
+ + bitmapComps * groupBackX];
+ memcpy(p, q, bitmapComps * bitmap->width);
+ }
+
+ if (bitmap->alpha) {
+ memset(&bitmap->alpha[y * bitmap->alphaRowSize], 0, bitmap->width);
+ }
+}
+
+//------------------------------------------------------------------------
+
+// Transform a point from user space to device space.
+inline void Splash::transform(SplashCoord *matrix,
+ SplashCoord xi, SplashCoord yi,
+ SplashCoord *xo, SplashCoord *yo) {
+ // [ m[0] m[1] 0 ]
+ // [xo yo 1] = [xi yi 1] * [ m[2] m[3] 0 ]
+ // [ m[4] m[5] 1 ]
+ *xo = xi * matrix[0] + yi * matrix[2] + matrix[4];
+ *yo = xi * matrix[1] + yi * matrix[3] + matrix[5];
+}
+
+//------------------------------------------------------------------------
+// SplashImageCache
+//------------------------------------------------------------------------
+
+SplashImageCache::SplashImageCache() {
+ tag = NULL;
+ width = 0;
+ height = 0;
+ mode = splashModeRGB8;
+ alpha = gFalse;
+ interpolate = gFalse;
+ colorData = NULL;
+ alphaData = NULL;
+ refCount = 1;
+}
+
+SplashImageCache::~SplashImageCache() {
+ if (tag) {
+ delete tag;
+ }
+ gfree(colorData);
+ gfree(alphaData);
+}
+
+GBool SplashImageCache::match(GString *aTag, int aWidth, int aHeight,
+ SplashColorMode aMode, GBool aAlpha,
+ GBool aInterpolate) {
+ return aTag && tag && !aTag->cmp(tag) &&
+ aWidth == width && aHeight == height &&
+ aMode == mode && aAlpha == alpha &&
+ aInterpolate == interpolate;
+}
+
+void SplashImageCache::reset(GString *aTag, int aWidth, int aHeight,
+ SplashColorMode aMode, GBool aAlpha,
+ GBool aInterpolate) {
+ if (tag) {
+ delete tag;
+ }
+ if (aTag) {
+ tag = aTag->copy();
+ } else {
+ tag = NULL;
+ }
+ width = aWidth;
+ height = aHeight;
+ mode = aMode;
+ alpha = aAlpha;
+ interpolate = aInterpolate;
+ gfree(colorData);
+ colorData = NULL;
+ gfree(alphaData);
+ alphaData = NULL;
+}
+
+void SplashImageCache::incRefCount() {
+ ++refCount;
+}
+
+void SplashImageCache::decRefCount() {
+ --refCount;
+ if (refCount == 0) {
+ delete this;
+ }
+}
+
+//------------------------------------------------------------------------
+// ImageScaler
+//------------------------------------------------------------------------
+
+// Abstract base class.
+class ImageScaler {
+public:
+
+ ImageScaler() {}
+ virtual ~ImageScaler() {}
+
+ // Compute the next line of the scaled image. This can be called up
+ // to [scaledHeight] times.
+ virtual void nextLine() = 0;
+
+ // Retrieve the color and alpha data generated by the most recent
+ // call to nextLine().
+ virtual Guchar *colorData() = 0;
+ virtual Guchar *alphaData() = 0;
+};
+
+//------------------------------------------------------------------------
+// BasicImageScaler
+//------------------------------------------------------------------------
+
+// The actual image scaler.
+class BasicImageScaler: public ImageScaler {
+public:
+
+ BasicImageScaler(SplashImageSource aSrc, void *aSrcData,
+ int aSrcWidth, int aSrcHeight, int aNComps, GBool aHasAlpha,
+ int aScaledWidth, int aScaledHeight, GBool aInterpolate);
+ virtual ~BasicImageScaler();
+ virtual void nextLine();
+ virtual Guchar *colorData() { return colorLine; }
+ virtual Guchar *alphaData() { return alphaLine; }
+
+protected:
+
+ void vertDownscaleHorizDownscale();
+ void vertDownscaleHorizUpscaleNoInterp();
+ void vertDownscaleHorizUpscaleInterp();
+ void vertUpscaleHorizDownscaleNoInterp();
+ void vertUpscaleHorizDownscaleInterp();
+ void vertUpscaleHorizUpscaleNoInterp();
+ void vertUpscaleHorizUpscaleInterp();
+
+ // source image data function
+ SplashImageSource src;
+ void *srcData;
+
+ // source image size
+ int srcWidth;
+ int srcHeight;
+
+ // scaled image size
+ int scaledWidth;
+ int scaledHeight;
+
+ // number of color and alpha components
+ int nComps;
+ GBool hasAlpha;
+
+ // params/state for vertical scaling
+ int yp, yq;
+ int yt, yn;
+ int ySrcCur, yScaledCur;
+ SplashCoord yInvScale;
+
+ // params for horizontal scaling
+ int xp, xq;
+ SplashCoord xInvScale;
+
+ // scaling function
+ void (BasicImageScaler::*scalingFunc)();
+
+ // temporary buffers for vertical scaling
+ Guchar *colorTmpBuf0;
+ Guchar *colorTmpBuf1;
+ Guchar *colorTmpBuf2;
+ Guchar *alphaTmpBuf0;
+ Guchar *alphaTmpBuf1;
+ Guchar *alphaTmpBuf2;
+ Guint *colorAccBuf;
+ Guint *alphaAccBuf;
+
+ // output of horizontal scaling
+ Guchar *colorLine;
+ Guchar *alphaLine;
+};
+
+BasicImageScaler::BasicImageScaler(SplashImageSource aSrc, void *aSrcData,
+ int aSrcWidth, int aSrcHeight,
+ int aNComps, GBool aHasAlpha,
+ int aScaledWidth, int aScaledHeight,
+ GBool aInterpolate) {
+ colorTmpBuf0 = NULL;
+ colorTmpBuf1 = NULL;
+ colorTmpBuf2 = NULL;
+ alphaTmpBuf0 = NULL;
+ alphaTmpBuf1 = NULL;
+ alphaTmpBuf2 = NULL;
+ colorAccBuf = NULL;
+ alphaAccBuf = NULL;
+ colorLine = NULL;
+ alphaLine = NULL;
+
+ src = aSrc;
+ srcData = aSrcData;
+ srcWidth = aSrcWidth;
+ srcHeight = aSrcHeight;
+ scaledWidth = aScaledWidth;
+ scaledHeight = aScaledHeight;
+ nComps = aNComps;
+ hasAlpha = aHasAlpha;
+
+ // select scaling function; allocate buffers
+ if (scaledHeight <= srcHeight) {
+ // vertical downscaling
+ yp = srcHeight / scaledHeight;
+ yq = srcHeight % scaledHeight;
+ yt = 0;
+ colorTmpBuf0 = (Guchar *)gmallocn(srcWidth, nComps);
+ colorAccBuf = (Guint *)gmallocn(srcWidth, nComps * (int)sizeof(Guint));
+ if (hasAlpha) {
+ alphaTmpBuf0 = (Guchar *)gmalloc(srcWidth);
+ alphaAccBuf = (Guint *)gmallocn(srcWidth, sizeof(Guint));
+ }
+ if (scaledWidth <= srcWidth) {
+ scalingFunc = &BasicImageScaler::vertDownscaleHorizDownscale;
+ } else {
+ if (aInterpolate) {
+ scalingFunc = &BasicImageScaler::vertDownscaleHorizUpscaleInterp;
+ } else {
+ scalingFunc = &BasicImageScaler::vertDownscaleHorizUpscaleNoInterp;
+ }
+ }
+ } else {
+ // vertical upscaling
+ yp = scaledHeight / srcHeight;
+ yq = scaledHeight % srcHeight;
+ yt = 0;
+ yn = 0;
+ if (aInterpolate) {
+ yInvScale = (SplashCoord)srcHeight / (SplashCoord)scaledHeight;
+ colorTmpBuf0 = (Guchar *)gmallocn(srcWidth, nComps);
+ colorTmpBuf1 = (Guchar *)gmallocn(srcWidth, nComps);
+ if (hasAlpha) {
+ alphaTmpBuf0 = (Guchar *)gmalloc(srcWidth);
+ alphaTmpBuf1 = (Guchar *)gmalloc(srcWidth);
+ }
+ ySrcCur = 0;
+ yScaledCur = 0;
+ if (scaledWidth <= srcWidth) {
+ scalingFunc = &BasicImageScaler::vertUpscaleHorizDownscaleInterp;
+ } else {
+ colorTmpBuf2 = (Guchar *)gmallocn(srcWidth, nComps);
+ if (hasAlpha) {
+ alphaTmpBuf2 = (Guchar *)gmalloc(srcWidth);
+ }
+ scalingFunc = &BasicImageScaler::vertUpscaleHorizUpscaleInterp;
+ }
+ } else {
+ colorTmpBuf0 = (Guchar *)gmallocn(srcWidth, nComps);
+ if (hasAlpha) {
+ alphaTmpBuf0 = (Guchar *)gmalloc(srcWidth);
+ }
+ if (scaledWidth <= srcWidth) {
+ scalingFunc = &BasicImageScaler::vertUpscaleHorizDownscaleNoInterp;
+ } else {
+ scalingFunc = &BasicImageScaler::vertUpscaleHorizUpscaleNoInterp;
+ }
+ }
+ }
+ if (scaledWidth <= srcWidth) {
+ xp = srcWidth / scaledWidth;
+ xq = srcWidth % scaledWidth;
+ } else {
+ xp = scaledWidth / srcWidth;
+ xq = scaledWidth % srcWidth;
+ if (aInterpolate) {
+ xInvScale = (SplashCoord)srcWidth / (SplashCoord)scaledWidth;
+ }
+ }
+ colorLine = (Guchar *)gmallocn(scaledWidth, nComps);
+ if (hasAlpha) {
+ alphaLine = (Guchar *)gmalloc(scaledWidth);
+ }
+}
+
+BasicImageScaler::~BasicImageScaler() {
+ gfree(colorTmpBuf0);
+ gfree(colorTmpBuf1);
+ gfree(colorTmpBuf2);
+ gfree(alphaTmpBuf0);
+ gfree(alphaTmpBuf1);
+ gfree(alphaTmpBuf2);
+ gfree(colorAccBuf);
+ gfree(alphaAccBuf);
+ gfree(colorLine);
+ gfree(alphaLine);
+}
+
+void BasicImageScaler::nextLine() {
+ (this->*scalingFunc)();
+}
+
+void BasicImageScaler::vertDownscaleHorizDownscale() {
+ //--- vert downscale
+ int yStep = yp;
+ yt += yq;
+ if (yt >= scaledHeight) {
+ yt -= scaledHeight;
+ ++yStep;
+ }
+ memset(colorAccBuf, 0, (srcWidth * nComps) * sizeof(Guint));
+ if (hasAlpha) {
+ memset(alphaAccBuf, 0, srcWidth * sizeof(Guint));
+ }
+ int nRowComps = srcWidth * nComps;
+ for (int i = 0; i < yStep; ++i) {
+ (*src)(srcData, colorTmpBuf0, alphaTmpBuf0);
+ for (int j = 0; j < nRowComps; ++j) {
+ colorAccBuf[j] += colorTmpBuf0[j];
+ }
+ if (hasAlpha) {
+ for (int j = 0; j < srcWidth; ++j) {
+ alphaAccBuf[j] += alphaTmpBuf0[j];
+ }
+ }
+ }
+
+ //--- horiz downscale
+ int colorAcc[splashMaxColorComps];
+ int xt = 0;
+ int unscaledColorIdx = 0;
+ int unscaledAlphaIdx = 0;
+ int scaledColorIdx = 0;
+
+ for (int scaledIdx = 0; scaledIdx < scaledWidth; ++scaledIdx) {
+ int xStep = xp;
+ xt += xq;
+ if (xt >= scaledWidth) {
+ xt -= scaledWidth;
+ ++xStep;
+ }
+
+ for (int j = 0; j < nComps; ++j) {
+ colorAcc[j] = 0;
+ }
+ for (int i = 0; i < xStep; ++i) {
+ for (int j = 0; j < nComps; ++j) {
+ colorAcc[j] += colorAccBuf[unscaledColorIdx + j];
+ }
+ unscaledColorIdx += nComps;
+ }
+ int nPixels = yStep * xStep;
+ for (int j = 0; j < nComps; ++j) {
+ colorLine[scaledColorIdx + j] = (Guchar)(colorAcc[j] / nPixels);
+ }
+ scaledColorIdx += nComps;
+
+ if (hasAlpha) {
+ int alphaAcc = 0;
+ for (int i = 0; i < xStep; ++i) {
+ alphaAcc += alphaAccBuf[unscaledAlphaIdx];
+ ++unscaledAlphaIdx;
+ }
+ alphaLine[scaledIdx] = (Guchar)(alphaAcc / nPixels);
+ }
+ }
+}
+
+void BasicImageScaler::vertDownscaleHorizUpscaleNoInterp() {
+ //--- vert downscale
+ int yStep = yp;
+ yt += yq;
+ if (yt >= scaledHeight) {
+ yt -= scaledHeight;
+ ++yStep;
+ }
+ memset(colorAccBuf, 0, (srcWidth * nComps) * sizeof(Guint));
+ if (hasAlpha) {
+ memset(alphaAccBuf, 0, srcWidth * sizeof(Guint));
+ }
+ int nRowComps = srcWidth * nComps;
+ for (int i = 0; i < yStep; ++i) {
+ (*src)(srcData, colorTmpBuf0, alphaTmpBuf0);
+ for (int j = 0; j < nRowComps; ++j) {
+ colorAccBuf[j] += colorTmpBuf0[j];
+ }
+ if (hasAlpha) {
+ for (int j = 0; j < srcWidth; ++j) {
+ alphaAccBuf[j] += alphaTmpBuf0[j];
+ }
+ }
+ }
+
+ //--- horiz upscale
+ Guchar colorBuf[splashMaxColorComps];
+ int xt = 0;
+ int scaledColorIdx = 0;
+ int srcColorIdx = 0;
+ int scaledAlphaIdx = 0;
+ for (int srcIdx = 0; srcIdx < srcWidth; ++srcIdx) {
+ int xStep = xp;
+ xt += xq;
+ if (xt >= srcWidth) {
+ xt -= srcWidth;
+ ++xStep;
+ }
+ for (int j = 0; j < nComps; ++j) {
+ colorBuf[j] = (Guchar)(colorAccBuf[srcColorIdx + j] / yStep);
+ }
+ srcColorIdx += nComps;
+ for (int i = 0; i < xStep; ++i) {
+ for (int j = 0; j < nComps; ++j) {
+ colorLine[scaledColorIdx + j] = colorBuf[j];
+ }
+ scaledColorIdx += nComps;
+ }
+ if (hasAlpha) {
+ Guchar alphaBuf = (Guchar)(alphaAccBuf[srcIdx] / yStep);
+ for (int i = 0; i < xStep; ++i) {
+ alphaLine[scaledAlphaIdx] = alphaBuf;
+ ++scaledAlphaIdx;
+ }
+ }
+ }
+}
+
+void BasicImageScaler::vertDownscaleHorizUpscaleInterp() {
+ //--- vert downscale
+ int yStep = yp;
+ yt += yq;
+ if (yt >= scaledHeight) {
+ yt -= scaledHeight;
+ ++yStep;
+ }
+ memset(colorAccBuf, 0, (srcWidth * nComps) * sizeof(Guint));
+ if (hasAlpha) {
+ memset(alphaAccBuf, 0, srcWidth * sizeof(Guint));
+ }
+ int nRowComps = srcWidth * nComps;
+ for (int i = 0; i < yStep; ++i) {
+ (*src)(srcData, colorTmpBuf0, alphaTmpBuf0);
+ for (int j = 0; j < nRowComps; ++j) {
+ colorAccBuf[j] += colorTmpBuf0[j];
+ }
+ if (hasAlpha) {
+ for (int j = 0; j < srcWidth; ++j) {
+ alphaAccBuf[j] += alphaTmpBuf0[j];
+ }
+ }
+ }
+ for (int j = 0; j < srcWidth * nComps; ++j) {
+ colorAccBuf[j] /= yStep;
+ }
+ if (hasAlpha) {
+ for (int j = 0; j < srcWidth; ++j) {
+ alphaAccBuf[j] /= yStep;
+ }
+ }
+
+ //--- horiz upscale
+ int scaledColorIdx = 0;
+ for (int scaledIdx = 0; scaledIdx < scaledWidth; ++scaledIdx) {
+ SplashCoord xs = ((SplashCoord)scaledIdx + 0.5) * xInvScale;
+ int x0 = splashFloor(xs - 0.5);
+ int x1 = x0 + 1;
+ SplashCoord s0 = (SplashCoord)x1 + 0.5 - xs;
+ SplashCoord s1 = (SplashCoord)1 - s0;
+ if (x0 < 0) {
+ x0 = 0;
+ }
+ if (x1 >= srcWidth) {
+ x1 = srcWidth - 1;
+ }
+ for (int j = 0; j < nComps; ++j) {
+ colorLine[scaledColorIdx + j] =
+ (Guchar)(int)(s0 * colorAccBuf[x0 * nComps + j] +
+ s1 * colorAccBuf[x1 * nComps + j]);
+ }
+ scaledColorIdx += nComps;
+ if (hasAlpha) {
+ alphaLine[scaledIdx] = (Guchar)(int)(s0 * alphaAccBuf[x0] +
+ s1 * alphaAccBuf[x1]);
+ }
+ }
+}
+
+void BasicImageScaler::vertUpscaleHorizDownscaleNoInterp() {
+ //--- vert upscale
+ if (yn == 0) {
+ yn = yp;
+ yt += yq;
+ if (yt >= srcHeight) {
+ yt -= srcHeight;
+ ++yn;
+ }
+ (*src)(srcData, colorTmpBuf0, alphaTmpBuf0);
+ }
+ --yn;
+
+ //--- horiz downscale
+ int colorAcc[splashMaxColorComps];
+ int xt = 0;
+ int unscaledColorIdx = 0;
+ int unscaledAlphaIdx = 0;
+ int scaledColorIdx = 0;
+ for (int scaledIdx = 0; scaledIdx < scaledWidth; ++scaledIdx) {
+ int xStep = xp;
+ xt += xq;
+ if (xt >= scaledWidth) {
+ xt -= scaledWidth;
+ ++xStep;
+ }
+
+ for (int j = 0; j < nComps; ++j) {
+ colorAcc[j] = 0;
+ }
+ for (int i = 0; i < xStep; ++i) {
+ for (int j = 0; j < nComps; ++j) {
+ colorAcc[j] += colorTmpBuf0[unscaledColorIdx + j];
+ }
+ unscaledColorIdx += nComps;
+ }
+ for (int j = 0; j < nComps; ++j) {
+ colorLine[scaledColorIdx + j] = (Guchar)(colorAcc[j] / xStep);
+ }
+ scaledColorIdx += nComps;
+
+ if (hasAlpha) {
+ int alphaAcc = 0;
+ for (int i = 0; i < xStep; ++i) {
+ alphaAcc += alphaTmpBuf0[unscaledAlphaIdx];
+ ++unscaledAlphaIdx;
+ }
+ alphaLine[scaledIdx] = (Guchar)(alphaAcc / xStep);
+ }
+ }
+}
+
+void BasicImageScaler::vertUpscaleHorizDownscaleInterp() {
+ //--- vert upscale
+ if (ySrcCur == 0) {
+ (*src)(srcData, colorTmpBuf0, alphaTmpBuf0);
+ (*src)(srcData, colorTmpBuf1, alphaTmpBuf1);
+ ySrcCur = 1;
+ }
+ SplashCoord ys = ((SplashCoord)yScaledCur + 0.5) * yInvScale;
+ int y0 = splashFloor(ys - 0.5);
+ int y1 = y0 + 1;
+ SplashCoord vs0 = (SplashCoord)y1 + 0.5 - ys;
+ SplashCoord vs1 = (SplashCoord)1 - vs0;
+ if (y1 > ySrcCur && ySrcCur < srcHeight - 1) {
+ Guchar *t = colorTmpBuf0;
+ colorTmpBuf0 = colorTmpBuf1;
+ colorTmpBuf1 = t;
+ if (hasAlpha) {
+ t = alphaTmpBuf0;
+ alphaTmpBuf0 = alphaTmpBuf1;
+ alphaTmpBuf1 = t;
+ }
+ (*src)(srcData, colorTmpBuf1, alphaTmpBuf1);
+ ++ySrcCur;
+ }
+ Guchar *color0 = colorTmpBuf0;
+ Guchar *color1 = colorTmpBuf1;
+ Guchar *alpha0 = alphaTmpBuf0;
+ Guchar *alpha1 = alphaTmpBuf1;
+ if (y0 < 0) {
+ y0 = 0;
+ color1 = color0;
+ alpha1 = alpha0;
+ }
+ if (y1 >= srcHeight) {
+ y1 = srcHeight - 1;
+ color0 = color1;
+ alpha0 = alpha1;
+ }
+ ++yScaledCur;
+
+ //--- horiz downscale
+ int colorAcc[splashMaxColorComps];
+ int xt = 0;
+ int unscaledColorIdx = 0;
+ int unscaledAlphaIdx = 0;
+ int scaledColorIdx = 0;
+ for (int scaledIdx = 0; scaledIdx < scaledWidth; ++scaledIdx) {
+ int xStep = xp;
+ xt += xq;
+ if (xt >= scaledWidth) {
+ xt -= scaledWidth;
+ ++xStep;
+ }
+
+ for (int j = 0; j < nComps; ++j) {
+ colorAcc[j] = 0;
+ }
+ for (int i = 0; i < xStep; ++i) {
+ for (int j = 0; j < nComps; ++j) {
+ colorAcc[j] += (int)(vs0 * (int)color0[unscaledColorIdx + j] +
+ vs1 * (int)color1[unscaledColorIdx + j]);
+ }
+ unscaledColorIdx += nComps;
+ }
+ for (int j = 0; j < nComps; ++j) {
+ colorLine[scaledColorIdx + j] = (Guchar)(colorAcc[j] / xStep);
+ }
+ scaledColorIdx += nComps;
+
+ if (hasAlpha) {
+ int alphaAcc = 0;
+ for (int i = 0; i < xStep; ++i) {
+ alphaAcc += (int)(vs0 * (int)alpha0[unscaledAlphaIdx] +
+ vs1 * (int)alpha1[unscaledAlphaIdx]);
+ ++unscaledAlphaIdx;
+ }
+ alphaLine[scaledIdx] = (Guchar)(alphaAcc / xStep);
+ }
+ }
+}
+
+void BasicImageScaler::vertUpscaleHorizUpscaleNoInterp() {
+ //--- vert upscale
+ if (yn == 0) {
+ yn = yp;
+ yt += yq;
+ if (yt >= srcHeight) {
+ yt -= srcHeight;
+ ++yn;
+ }
+ (*src)(srcData, colorTmpBuf0, alphaTmpBuf0);
+ }
+ --yn;
+
+ //--- horiz upscale
+ int xt = 0;
+ int scaledColorIdx = 0;
+ int srcColorIdx = 0;
+ int scaledAlphaIdx = 0;
+ for (int srcIdx = 0; srcIdx < srcWidth; ++srcIdx) {
+ int xStep = xp;
+ xt += xq;
+ if (xt >= srcWidth) {
+ xt -= srcWidth;
+ ++xStep;
+ }
+ for (int i = 0; i < xStep; ++i) {
+ for (int j = 0; j < nComps; ++j) {
+ colorLine[scaledColorIdx + j] = colorTmpBuf0[srcColorIdx + j];
+ }
+ scaledColorIdx += nComps;
+ }
+ srcColorIdx += nComps;
+ if (hasAlpha) {
+ Guchar alphaBuf = alphaTmpBuf0[srcIdx];
+ for (int i = 0; i < xStep; ++i) {
+ alphaLine[scaledAlphaIdx] = alphaBuf;
+ ++scaledAlphaIdx;
+ }
+ }
+ }
+}
+
+void BasicImageScaler::vertUpscaleHorizUpscaleInterp() {
+ //--- vert upscale
+ if (ySrcCur == 0) {
+ (*src)(srcData, colorTmpBuf0, alphaTmpBuf0);
+ (*src)(srcData, colorTmpBuf1, alphaTmpBuf1);
+ ySrcCur = 1;
+ }
+ SplashCoord ys = ((SplashCoord)yScaledCur + 0.5) * yInvScale;
+ int y0 = splashFloor(ys - 0.5);
+ int y1 = y0 + 1;
+ SplashCoord vs0 = (SplashCoord)y1 + 0.5 - ys;
+ SplashCoord vs1 = (SplashCoord)1 - vs0;
+ if (y1 > ySrcCur && ySrcCur < srcHeight - 1) {
+ Guchar *t = colorTmpBuf0;
+ colorTmpBuf0 = colorTmpBuf1;
+ colorTmpBuf1 = t;
+ if (hasAlpha) {
+ t = alphaTmpBuf0;
+ alphaTmpBuf0 = alphaTmpBuf1;
+ alphaTmpBuf1 = t;
+ }
+ (*src)(srcData, colorTmpBuf1, alphaTmpBuf1);
+ ++ySrcCur;
+ }
+ Guchar *color0 = colorTmpBuf0;
+ Guchar *color1 = colorTmpBuf1;
+ Guchar *alpha0 = alphaTmpBuf0;
+ Guchar *alpha1 = alphaTmpBuf1;
+ if (y0 < 0) {
+ y0 = 0;
+ color1 = color0;
+ alpha1 = alpha0;
+ }
+ if (y1 >= srcHeight) {
+ y1 = srcHeight - 1;
+ color0 = color1;
+ alpha0 = alpha1;
+ }
+ ++yScaledCur;
+ for (int srcIdx = 0; srcIdx < srcWidth * nComps; ++srcIdx) {
+ colorTmpBuf2[srcIdx] = (Guchar)(int)(vs0 * (int)color0[srcIdx] +
+ vs1 * (int)color1[srcIdx]);
+ }
+ if (hasAlpha) {
+ for (int srcIdx = 0; srcIdx < srcWidth; ++srcIdx) {
+ alphaTmpBuf2[srcIdx] = (Guchar)(int)(vs0 * (int)alpha0[srcIdx] +
+ vs1 * (int)alpha1[srcIdx]);
+ }
+ }
+
+ //--- horiz upscale
+ int scaledColorIdx = 0;
+ for (int scaledIdx = 0; scaledIdx < scaledWidth; ++scaledIdx) {
+ SplashCoord xs = ((SplashCoord)scaledIdx + 0.5) * xInvScale;
+ int x0 = splashFloor(xs - 0.5);
+ int x1 = x0 + 1;
+ SplashCoord hs0 = (SplashCoord)x1 + 0.5 - xs;
+ SplashCoord hs1 = (SplashCoord)1 - hs0;
+ if (x0 < 0) {
+ x0 = 0;
+ }
+ if (x1 >= srcWidth) {
+ x1 = srcWidth - 1;
+ }
+ for (int j = 0; j < nComps; ++j) {
+ colorLine[scaledColorIdx + j] =
+ (Guchar)(int)(hs0 * (int)colorTmpBuf2[x0 * nComps + j] +
+ hs1 * (int)colorTmpBuf2[x1 * nComps + j]);
+ }
+ scaledColorIdx += nComps;
+ if (hasAlpha) {
+ alphaLine[scaledIdx] = (Guchar)(int)(hs0 * (int)alphaTmpBuf2[x0] +
+ hs1 * (int)alphaTmpBuf2[x1]);
+ }
+ }
+}
+
+//------------------------------------------------------------------------
+// SavingImageScaler
+//------------------------------------------------------------------------
+
+// Wrapper around BasicImageScaler that saves the scaled image for use
+// by ReplayImageScaler.
+class SavingImageScaler: public BasicImageScaler {
+public:
+
+ SavingImageScaler(SplashImageSource aSrc, void *aSrcData,
+ int aSrcWidth, int aSrcHeight, int aNComps, GBool aHasAlpha,
+ int aScaledWidth, int aScaledHeight, GBool aInterpolate,
+ Guchar *aColorCache, Guchar *aAlphaCache);
+ virtual void nextLine();
+
+private:
+
+ Guchar *colorPtr;
+ Guchar *alphaPtr;
+};
+
+SavingImageScaler::SavingImageScaler(SplashImageSource aSrc, void *aSrcData,
+ int aSrcWidth, int aSrcHeight,
+ int aNComps, GBool aHasAlpha,
+ int aScaledWidth, int aScaledHeight,
+ GBool aInterpolate,
+ Guchar *aColorCache, Guchar *aAlphaCache):
+ BasicImageScaler(aSrc, aSrcData, aSrcWidth, aSrcHeight, aNComps, aHasAlpha,
+ aScaledWidth, aScaledHeight, aInterpolate)
+{
+ colorPtr = aColorCache;
+ alphaPtr = aAlphaCache;
+}
+
+void SavingImageScaler::nextLine() {
+ BasicImageScaler::nextLine();
+ memcpy(colorPtr, colorData(), scaledWidth * nComps);
+ colorPtr += scaledWidth * nComps;
+ if (hasAlpha) {
+ memcpy(alphaPtr, alphaData(), scaledWidth);
+ alphaPtr += scaledWidth;
+ }
+}
+
+//------------------------------------------------------------------------
+// ReplayImageScaler
+//------------------------------------------------------------------------
+
+// "Replay" a scaled image saved by SavingImageScaler.
+class ReplayImageScaler: public ImageScaler {
+public:
+
+ ReplayImageScaler(int aNComps, GBool aHasAlpha,
+ int aScaledWidth,
+ Guchar *aColorCache, Guchar *aAlphaCache);
+ virtual void nextLine();
+ virtual Guchar *colorData() { return colorLine; }
+ virtual Guchar *alphaData() { return alphaLine; }
+
+private:
+
+ int nComps;
+ GBool hasAlpha;
+ int scaledWidth;
+ Guchar *colorPtr;
+ Guchar *alphaPtr;
+ Guchar *colorLine;
+ Guchar *alphaLine;
+};
+
+ReplayImageScaler::ReplayImageScaler(int aNComps, GBool aHasAlpha,
+ int aScaledWidth,
+ Guchar *aColorCache, Guchar *aAlphaCache) {
+ nComps = aNComps;
+ hasAlpha = aHasAlpha;
+ scaledWidth = aScaledWidth;
+ colorPtr = aColorCache;
+ alphaPtr = aAlphaCache;
+ colorLine = NULL;
+ alphaLine = NULL;
+}
+
+void ReplayImageScaler::nextLine() {
+ colorLine = colorPtr;
+ alphaLine = alphaPtr;
+ colorPtr += scaledWidth * nComps;
+ if (hasAlpha) {
+ alphaPtr += scaledWidth;
+ }
+}
+
+//------------------------------------------------------------------------
+// ImageMaskScaler
+//------------------------------------------------------------------------
+
+class ImageMaskScaler {
+public:
+
+ // Set up a MaskScaler to scale from [srcWidth]x[srcHeight] to
+ // [scaledWidth]x[scaledHeight]. The [interpolate] flag controls
+ // filtering on upsampling, and the [antialias] flag controls
+ // filtering on downsampling.
+ ImageMaskScaler(SplashImageMaskSource aSrc, void *aSrcData,
+ int aSrcWidth, int aSrcHeight,
+ int aScaledWidth, int aScaledHeight,
+ GBool aInterpolate, GBool aAntialias);
+
+ ~ImageMaskScaler();
+
+ // Compute the next line of the scaled image mask. This can be
+ // called up to [scaledHeight] times.
+ void nextLine();
+
+ // Retrieve the data generated by the most recent call to
+ // nextLine().
+ Guchar *data() { return line; }
+
+private:
+
+ void vertDownscaleHorizDownscale();
+ void vertDownscaleHorizDownscaleThresh();
+ void vertDownscaleHorizUpscaleNoInterp();
+ void vertDownscaleHorizUpscaleInterp();
+ void vertDownscaleHorizUpscaleThresh();
+ void vertUpscaleHorizDownscaleNoInterp();
+ void vertUpscaleHorizDownscaleInterp();
+ void vertUpscaleHorizDownscaleThresh();
+ void vertUpscaleHorizUpscaleNoInterp();
+ void vertUpscaleHorizUpscaleInterp();
+
+ // source image data function
+ SplashImageMaskSource src;
+ void *srcData;
+
+ // source image size
+ int srcWidth;
+ int srcHeight;
+
+ // scaled image size
+ int scaledWidth;
+ int scaledHeight;
+
+ // params/state for vertical scaling
+ int yp, yq;
+ int yt, yn;
+ int ySrcCur, yScaledCur;
+ SplashCoord yInvScale;
+
+ // params for horizontal scaling
+ int xp, xq;
+ SplashCoord xInvScale;
+
+ // vertical and horizontal scaling functions
+ void (ImageMaskScaler::*scalingFunc)();
+
+ // temporary buffers for vertical scaling
+ Guchar *tmpBuf0;
+ Guchar *tmpBuf1;
+ Guchar *tmpBuf2;
+ Guint *accBuf;
+
+ // output of horizontal scaling
+ Guchar *line;
+};
+
+ImageMaskScaler::ImageMaskScaler(SplashImageMaskSource aSrc, void *aSrcData,
+ int aSrcWidth, int aSrcHeight,
+ int aScaledWidth, int aScaledHeight,
+ GBool aInterpolate, GBool aAntialias) {
+ tmpBuf0 = NULL;
+ tmpBuf1 = NULL;
+ tmpBuf2 = NULL;
+ accBuf = NULL;
+ line = NULL;
+
+ src = aSrc;
+ srcData = aSrcData;
+ srcWidth = aSrcWidth;
+ srcHeight = aSrcHeight;
+ scaledWidth = aScaledWidth;
+ scaledHeight = aScaledHeight;
+
+ // select scaling function; allocate buffers
+ if (scaledHeight <= srcHeight) {
+ // vertical downscaling
+ yp = srcHeight / scaledHeight;
+ yq = srcHeight % scaledHeight;
+ yt = 0;
+ tmpBuf0 = (Guchar *)gmalloc(srcWidth);
+ accBuf = (Guint *)gmallocn(srcWidth, sizeof(Guint));
+ if (scaledWidth <= srcWidth) {
+ if (!aAntialias) {
+ scalingFunc = &ImageMaskScaler::vertDownscaleHorizDownscaleThresh;
+ } else {
+ scalingFunc = &ImageMaskScaler::vertDownscaleHorizDownscale;
+ }
+ } else {
+ if (!aAntialias) {
+ scalingFunc = &ImageMaskScaler::vertDownscaleHorizUpscaleThresh;
+ } else if (aInterpolate) {
+ scalingFunc = &ImageMaskScaler::vertDownscaleHorizUpscaleInterp;
+ } else {
+ scalingFunc = &ImageMaskScaler::vertDownscaleHorizUpscaleNoInterp;
+ }
+ }
+ } else {
+ // vertical upscaling
+ yp = scaledHeight / srcHeight;
+ yq = scaledHeight % srcHeight;
+ yt = 0;
+ yn = 0;
+ if (!aAntialias) {
+ tmpBuf0 = (Guchar *)gmalloc(srcWidth);
+ if (scaledWidth <= srcWidth) {
+ scalingFunc = &ImageMaskScaler::vertUpscaleHorizDownscaleThresh;
+ } else {
+ scalingFunc = &ImageMaskScaler::vertUpscaleHorizUpscaleNoInterp;
+ }
+ } else if (aInterpolate) {
+ yInvScale = (SplashCoord)srcHeight / (SplashCoord)scaledHeight;
+ tmpBuf0 = (Guchar *)gmalloc(srcWidth);
+ tmpBuf1 = (Guchar *)gmalloc(srcWidth);
+ ySrcCur = 0;
+ yScaledCur = 0;
+ if (scaledWidth <= srcWidth) {
+ scalingFunc = &ImageMaskScaler::vertUpscaleHorizDownscaleInterp;
+ } else {
+ tmpBuf2 = (Guchar *)gmalloc(srcWidth);
+ scalingFunc = &ImageMaskScaler::vertUpscaleHorizUpscaleInterp;
+ }
+ } else {
+ tmpBuf0 = (Guchar *)gmalloc(srcWidth);
+ if (scaledWidth <= srcWidth) {
+ scalingFunc = &ImageMaskScaler::vertUpscaleHorizDownscaleNoInterp;
+ } else {
+ scalingFunc = &ImageMaskScaler::vertUpscaleHorizUpscaleNoInterp;
+ }
+ }
+ }
+ if (scaledWidth <= srcWidth) {
+ xp = srcWidth / scaledWidth;
+ xq = srcWidth % scaledWidth;
+ } else {
+ xp = scaledWidth / srcWidth;
+ xq = scaledWidth % srcWidth;
+ if (aInterpolate) {
+ xInvScale = (SplashCoord)srcWidth / (SplashCoord)scaledWidth;
+ }
+ }
+ line = (Guchar *)gmalloc(scaledWidth);
+}
+
+ImageMaskScaler::~ImageMaskScaler() {
+ gfree(tmpBuf0);
+ gfree(tmpBuf1);
+ gfree(tmpBuf2);
+ gfree(accBuf);
+ gfree(line);
+}
+
+void ImageMaskScaler::nextLine() {
+ (this->*scalingFunc)();
+}
+
+void ImageMaskScaler::vertDownscaleHorizDownscale() {
+ //--- vert downscale
+ int yStep = yp;
+ yt += yq;
+ if (yt >= scaledHeight) {
+ yt -= scaledHeight;
+ ++yStep;
+ }
+ memset(accBuf, 0, srcWidth * sizeof(Guint));
+ for (int i = 0; i < yStep; ++i) {
+ (*src)(srcData, tmpBuf0);
+ for (int j = 0; j < srcWidth; ++j) {
+ accBuf[j] += tmpBuf0[j];
+ }
+ }
+
+ //--- horiz downscale
+ int acc;
+ int xt = 0;
+ int unscaledIdx = 0;
+ for (int scaledIdx = 0; scaledIdx < scaledWidth; ++scaledIdx) {
+ int xStep = xp;
+ xt += xq;
+ if (xt >= scaledWidth) {
+ xt -= scaledWidth;
+ ++xStep;
+ }
+
+ acc = 0;
+ for (int i = 0; i < xStep; ++i) {
+ acc += accBuf[unscaledIdx];
+ ++unscaledIdx;
+ }
+ line[scaledIdx] = (Guchar)((255 * acc) / (xStep * yStep));
+ }
+}
+
+void ImageMaskScaler::vertDownscaleHorizDownscaleThresh() {
+ //--- vert downscale
+ int yStep = yp;
+ yt += yq;
+ if (yt >= scaledHeight) {
+ yt -= scaledHeight;
+ ++yStep;
+ }
+ memset(accBuf, 0, srcWidth * sizeof(Guint));
+ for (int i = 0; i < yStep; ++i) {
+ (*src)(srcData, tmpBuf0);
+ for (int j = 0; j < srcWidth; ++j) {
+ accBuf[j] += tmpBuf0[j];
+ }
+ }
+
+ //--- horiz downscale
+ int acc;
+ int xt = 0;
+ int unscaledIdx = 0;
+ for (int scaledIdx = 0; scaledIdx < scaledWidth; ++scaledIdx) {
+ int xStep = xp;
+ xt += xq;
+ if (xt >= scaledWidth) {
+ xt -= scaledWidth;
+ ++xStep;
+ }
+
+ acc = 0;
+ for (int i = 0; i < xStep; ++i) {
+ acc += accBuf[unscaledIdx];
+ ++unscaledIdx;
+ }
+ line[scaledIdx] = acc > ((xStep * yStep) >> 1) ? (Guchar)255 : (Guchar)0;
+ }
+}
+
+void ImageMaskScaler::vertDownscaleHorizUpscaleNoInterp() {
+ //--- vert downscale
+ int yStep = yp;
+ yt += yq;
+ if (yt >= scaledHeight) {
+ yt -= scaledHeight;
+ ++yStep;
+ }
+ memset(accBuf, 0, srcWidth * sizeof(Guint));
+ for (int i = 0; i < yStep; ++i) {
+ (*src)(srcData, tmpBuf0);
+ for (int j = 0; j < srcWidth; ++j) {
+ accBuf[j] += tmpBuf0[j];
+ }
+ }
+
+ //--- horiz upscale
+ int xt = 0;
+ int scaledIdx = 0;
+ for (int srcIdx = 0; srcIdx < srcWidth; ++srcIdx) {
+ int xStep = xp;
+ xt += xq;
+ if (xt >= srcWidth) {
+ xt -= srcWidth;
+ ++xStep;
+ }
+ Guchar buf = (Guchar)((255 * accBuf[srcIdx]) / yStep);
+ for (int i = 0; i < xStep; ++i) {
+ line[scaledIdx] = buf;
+ ++scaledIdx;
+ }
+ }
+}
+
+void ImageMaskScaler::vertDownscaleHorizUpscaleInterp() {
+ //--- vert downscale
+ int yStep = yp;
+ yt += yq;
+ if (yt >= scaledHeight) {
+ yt -= scaledHeight;
+ ++yStep;
+ }
+ memset(accBuf, 0, srcWidth * sizeof(Guint));
+ for (int i = 0; i < yStep; ++i) {
+ (*src)(srcData, tmpBuf0);
+ for (int j = 0; j < srcWidth; ++j) {
+ accBuf[j] += tmpBuf0[j];
+ }
+ }
+ for (int j = 0; j < srcWidth; ++j) {
+ accBuf[j] = (255 * accBuf[j]) / yStep;
+ }
+
+ //--- horiz upscale
+ for (int scaledIdx = 0; scaledIdx < scaledWidth; ++scaledIdx) {
+ SplashCoord xs = ((SplashCoord)scaledIdx + 0.5) * xInvScale;
+ int x0 = splashFloor(xs - 0.5);
+ int x1 = x0 + 1;
+ SplashCoord s0 = (SplashCoord)x1 + 0.5 - xs;
+ SplashCoord s1 = (SplashCoord)1 - s0;
+ if (x0 < 0) {
+ x0 = 0;
+ }
+ if (x1 >= srcWidth) {
+ x1 = srcWidth - 1;
+ }
+ line[scaledIdx] = (Guchar)(int)(s0 * accBuf[x0] + s1 * accBuf[x1]);
+ }
+}
+
+void ImageMaskScaler::vertDownscaleHorizUpscaleThresh() {
+ //--- vert downscale
+ int yStep = yp;
+ yt += yq;
+ if (yt >= scaledHeight) {
+ yt -= scaledHeight;
+ ++yStep;
+ }
+ memset(accBuf, 0, srcWidth * sizeof(Guint));
+ for (int i = 0; i < yStep; ++i) {
+ (*src)(srcData, tmpBuf0);
+ for (int j = 0; j < srcWidth; ++j) {
+ accBuf[j] += tmpBuf0[j];
+ }
+ }
+
+ //--- horiz upscale
+ int xt = 0;
+ int scaledIdx = 0;
+ for (int srcIdx = 0; srcIdx < srcWidth; ++srcIdx) {
+ int xStep = xp;
+ xt += xq;
+ if (xt >= srcWidth) {
+ xt -= srcWidth;
+ ++xStep;
+ }
+ Guchar buf = accBuf[srcIdx] > (Guint)(yStep >> 1) ? (Guchar)255 : (Guchar)0;
+ for (int i = 0; i < xStep; ++i) {
+ line[scaledIdx] = buf;
+ ++scaledIdx;
+ }
+ }
+}
+
+void ImageMaskScaler::vertUpscaleHorizDownscaleNoInterp() {
+ //--- vert upscale
+ if (yn == 0) {
+ yn = yp;
+ yt += yq;
+ if (yt >= srcHeight) {
+ yt -= srcHeight;
+ ++yn;
+ }
+ (*src)(srcData, tmpBuf0);
+ }
+ --yn;
+
+ //--- horiz downscale
+ int acc;
+ int xt = 0;
+ int unscaledIdx = 0;
+ for (int scaledIdx = 0; scaledIdx < scaledWidth; ++scaledIdx) {
+ int xStep = xp;
+ xt += xq;
+ if (xt >= scaledWidth) {
+ xt -= scaledWidth;
+ ++xStep;
+ }
+
+ acc = 0;
+ for (int i = 0; i < xStep; ++i) {
+ acc += tmpBuf0[unscaledIdx];
+ ++unscaledIdx;
+ }
+ line[scaledIdx] = (Guchar)((255 * acc) / xStep);
+ }
+}
+
+void ImageMaskScaler::vertUpscaleHorizDownscaleInterp() {
+ //--- vert upscale
+ if (ySrcCur == 0) {
+ (*src)(srcData, tmpBuf0);
+ (*src)(srcData, tmpBuf1);
+ ySrcCur = 1;
+ }
+ SplashCoord ys = ((SplashCoord)yScaledCur + 0.5) * yInvScale;
+ int y0 = splashFloor(ys - 0.5);
+ int y1 = y0 + 1;
+ SplashCoord vs0 = (SplashCoord)y1 + 0.5 - ys;
+ SplashCoord vs1 = (SplashCoord)1 - vs0;
+ if (y1 > ySrcCur && ySrcCur < srcHeight - 1) {
+ Guchar *t = tmpBuf0;
+ tmpBuf0 = tmpBuf1;
+ tmpBuf1 = t;
+ (*src)(srcData, tmpBuf1);
+ ++ySrcCur;
+ }
+ Guchar *mask0 = tmpBuf0;
+ Guchar *mask1 = tmpBuf1;
+ if (y0 < 0) {
+ y0 = 0;
+ mask1 = mask0;
+ }
+ if (y1 >= srcHeight) {
+ y1 = srcHeight - 1;
+ mask0 = mask1;
+ }
+ ++yScaledCur;
+
+ //--- horiz downscale
+ int acc;
+ int xt = 0;
+ int unscaledIdx = 0;
+ for (int scaledIdx = 0; scaledIdx < scaledWidth; ++scaledIdx) {
+ int xStep = xp;
+ xt += xq;
+ if (xt >= scaledWidth) {
+ xt -= scaledWidth;
+ ++xStep;
+ }
+
+ acc = 0;
+ for (int i = 0; i < xStep; ++i) {
+ acc += (int)(vs0 * (int)mask0[unscaledIdx] +
+ vs1 * (int)mask1[unscaledIdx]);
+ ++unscaledIdx;
+ }
+ line[scaledIdx] = (Guchar)((255 * acc) / xStep);
+ }
+}
+
+void ImageMaskScaler::vertUpscaleHorizDownscaleThresh() {
+ //--- vert upscale
+ if (yn == 0) {
+ yn = yp;
+ yt += yq;
+ if (yt >= srcHeight) {
+ yt -= srcHeight;
+ ++yn;
+ }
+ (*src)(srcData, tmpBuf0);
+ }
+ --yn;
+
+ //--- horiz downscale
+ int acc;
+ int xt = 0;
+ int unscaledIdx = 0;
+ for (int scaledIdx = 0; scaledIdx < scaledWidth; ++scaledIdx) {
+ int xStep = xp;
+ xt += xq;
+ if (xt >= scaledWidth) {
+ xt -= scaledWidth;
+ ++xStep;
+ }
+
+ acc = 0;
+ for (int i = 0; i < xStep; ++i) {
+ acc += tmpBuf0[unscaledIdx];
+ ++unscaledIdx;
+ }
+ line[scaledIdx] = acc > (xStep >> 1) ? (Guchar)255 : (Guchar)0;
+ }
+}
+
+void ImageMaskScaler::vertUpscaleHorizUpscaleNoInterp() {
+ //--- vert upscale
+ if (yn == 0) {
+ yn = yp;
+ yt += yq;
+ if (yt >= srcHeight) {
+ yt -= srcHeight;
+ ++yn;
+ }
+ (*src)(srcData, tmpBuf0);
+ }
+ --yn;
+
+ //--- horiz upscale
+ int xt = 0;
+ int scaledIdx = 0;
+ for (int srcIdx = 0; srcIdx < srcWidth; ++srcIdx) {
+ int xStep = xp;
+ xt += xq;
+ if (xt >= srcWidth) {
+ xt -= srcWidth;
+ ++xStep;
+ }
+ Guchar buf = (Guchar)(255 * tmpBuf0[srcIdx]);
+ for (int i = 0; i < xStep; ++i) {
+ line[scaledIdx] = buf;
+ ++scaledIdx;
+ }
+ }
+}
+
+void ImageMaskScaler::vertUpscaleHorizUpscaleInterp() {
+ //--- vert upscale
+ if (ySrcCur == 0) {
+ (*src)(srcData, tmpBuf0);
+ (*src)(srcData, tmpBuf1);
+ ySrcCur = 1;
+ }
+ SplashCoord ys = ((SplashCoord)yScaledCur + 0.5) * yInvScale;
+ int y0 = splashFloor(ys - 0.5);
+ int y1 = y0 + 1;
+ SplashCoord vs0 = (SplashCoord)255 * ((SplashCoord)y1 + 0.5 - ys);
+ SplashCoord vs1 = (SplashCoord)255 - vs0;
+ if (y1 > ySrcCur && ySrcCur < srcHeight - 1) {
+ Guchar *t = tmpBuf0;
+ tmpBuf0 = tmpBuf1;
+ tmpBuf1 = t;
+ (*src)(srcData, tmpBuf1);
+ ++ySrcCur;
+ }
+ Guchar *mask0 = tmpBuf0;
+ Guchar *mask1 = tmpBuf1;
+ if (y0 < 0) {
+ y0 = 0;
+ mask1 = mask0;
+ }
+ if (y1 >= srcHeight) {
+ y1 = srcHeight - 1;
+ mask0 = mask1;
+ }
+ ++yScaledCur;
+ for (int srcIdx = 0; srcIdx < srcWidth; ++srcIdx) {
+ tmpBuf2[srcIdx] = (Guchar)(int)(vs0 * (int)mask0[srcIdx] +
+ vs1 * (int)mask1[srcIdx]);
+ }
+
+ //--- horiz upscale
+ for (int scaledIdx = 0; scaledIdx < scaledWidth; ++scaledIdx) {
+ SplashCoord xs = ((SplashCoord)scaledIdx + 0.5) * xInvScale;
+ int x0 = splashFloor(xs - 0.5);
+ int x1 = x0 + 1;
+ SplashCoord hs0 = (SplashCoord)x1 + 0.5 - xs;
+ SplashCoord hs1 = (SplashCoord)1 - hs0;
+ if (x0 < 0) {
+ x0 = 0;
+ }
+ if (x1 >= srcWidth) {
+ x1 = srcWidth - 1;
+ }
+ line[scaledIdx] = (Guchar)(int)(hs0 * (int)tmpBuf2[x0] +
+ hs1 * (int)tmpBuf2[x1]);
+ }
+}
+
+//------------------------------------------------------------------------
+// Splash
+//------------------------------------------------------------------------
+
+Splash::Splash(SplashBitmap *bitmapA, GBool vectorAntialiasA,
+ SplashImageCache *imageCacheA,
+ SplashScreenParams *screenParams) {
+ bitmap = bitmapA;
+ bitmapComps = splashColorModeNComps[bitmap->mode];
+ vectorAntialias = vectorAntialiasA;
+ inShading = gFalse;
+ state = new SplashState(bitmap->width, bitmap->height, vectorAntialias,
+ screenParams);
+ scanBuf = (Guchar *)gmalloc(bitmap->width);
+ if (bitmap->mode == splashModeMono1) {
+ scanBuf2 = (Guchar *)gmalloc(bitmap->width);
+ } else {
+ scanBuf2 = NULL;
+ }
+ groupBackBitmap = NULL;
+ groupDestInitMode = splashGroupDestPreInit;
+ overprintMaskBitmap = NULL;
+ minLineWidth = 0;
+ clearModRegion();
+ debugMode = gFalse;
+
+ if (imageCacheA) {
+ imageCache = imageCacheA;
+ imageCache->incRefCount();
+ } else {
+ imageCache = new SplashImageCache();
+ }
+}
+
+Splash::Splash(SplashBitmap *bitmapA, GBool vectorAntialiasA,
+ SplashImageCache *imageCacheA, SplashScreen *screenA) {
+ bitmap = bitmapA;
+ bitmapComps = splashColorModeNComps[bitmap->mode];
+ vectorAntialias = vectorAntialiasA;
+ inShading = gFalse;
+ state = new SplashState(bitmap->width, bitmap->height, vectorAntialias,
+ screenA);
+ scanBuf = (Guchar *)gmalloc(bitmap->width);
+ if (bitmap->mode == splashModeMono1) {
+ scanBuf2 = (Guchar *)gmalloc(bitmap->width);
+ } else {
+ scanBuf2 = NULL;
+ }
+ groupBackBitmap = NULL;
+ groupDestInitMode = splashGroupDestPreInit;
+ overprintMaskBitmap = NULL;
+ minLineWidth = 0;
+ clearModRegion();
+ debugMode = gFalse;
+
+ if (imageCacheA) {
+ imageCache = imageCacheA;
+ imageCache->incRefCount();
+ } else {
+ imageCache = new SplashImageCache();
+ }
+}
+
+Splash::~Splash() {
+ imageCache->decRefCount();
+
+ while (state->next) {
+ restoreState();
+ }
+ delete state;
+ gfree(scanBuf);
+ gfree(scanBuf2);
+}
+
+//------------------------------------------------------------------------
+// state read
+//------------------------------------------------------------------------
+
+SplashCoord *Splash::getMatrix() {
+ return state->matrix;
+}
+
+SplashPattern *Splash::getStrokePattern() {
+ return state->strokePattern;
+}
+
+SplashPattern *Splash::getFillPattern() {
+ return state->fillPattern;
+}
+
+SplashScreen *Splash::getScreen() {
+ return state->screen;
+}
+
+SplashBlendFunc Splash::getBlendFunc() {
+ return state->blendFunc;
+}
+
+SplashCoord Splash::getStrokeAlpha() {
+ return state->strokeAlpha;
+}
+
+SplashCoord Splash::getFillAlpha() {
+ return state->fillAlpha;
+}
+
+SplashCoord Splash::getLineWidth() {
+ return state->lineWidth;
+}
+
+int Splash::getLineCap() {
+ return state->lineCap;
+}
+
+int Splash::getLineJoin() {
+ return state->lineJoin;
+}
+
+SplashCoord Splash::getMiterLimit() {
+ return state->miterLimit;
+}
+
+SplashCoord Splash::getFlatness() {
+ return state->flatness;
+}
+
+SplashCoord *Splash::getLineDash() {
+ return state->lineDash;
+}
+
+int Splash::getLineDashLength() {
+ return state->lineDashLength;
+}
+
+SplashCoord Splash::getLineDashPhase() {
+ return state->lineDashPhase;
+}
+
+SplashStrokeAdjustMode Splash::getStrokeAdjust() {
+ return state->strokeAdjust;
+}
+
+SplashClip *Splash::getClip() {
+ return state->clip;
+}
+
+SplashBitmap *Splash::getSoftMask() {
+ return state->softMask;
+}
+
+GBool Splash::getInNonIsolatedGroup() {
+ return state->inNonIsolatedGroup;
+}
+
+GBool Splash::getInKnockoutGroup() {
+ return state->inKnockoutGroup;
+}
+
+//------------------------------------------------------------------------
+// state write
+//------------------------------------------------------------------------
+
+void Splash::setMatrix(SplashCoord *matrix) {
+ memcpy(state->matrix, matrix, 6 * sizeof(SplashCoord));
+}
+
+void Splash::setStrokePattern(SplashPattern *strokePattern) {
+ state->setStrokePattern(strokePattern);
+}
+
+void Splash::setFillPattern(SplashPattern *fillPattern) {
+ state->setFillPattern(fillPattern);
+}
+
+void Splash::setScreen(SplashScreen *screen) {
+ state->setScreen(screen);
+}
+
+void Splash::setBlendFunc(SplashBlendFunc func) {
+ state->blendFunc = func;
+}
+
+void Splash::setStrokeAlpha(SplashCoord alpha) {
+ state->strokeAlpha = alpha;
+}
+
+void Splash::setFillAlpha(SplashCoord alpha) {
+ state->fillAlpha = alpha;
+}
+
+void Splash::setLineWidth(SplashCoord lineWidth) {
+ state->lineWidth = lineWidth;
+}
+
+void Splash::setLineCap(int lineCap) {
+ if (lineCap >= 0 && lineCap <= 2) {
+ state->lineCap = lineCap;
+ } else {
+ state->lineCap = 0;
+ }
+}
+
+void Splash::setLineJoin(int lineJoin) {
+ if (lineJoin >= 0 && lineJoin <= 2) {
+ state->lineJoin = lineJoin;
+ } else {
+ state->lineJoin = 0;
+ }
+}
+
+void Splash::setMiterLimit(SplashCoord miterLimit) {
+ state->miterLimit = miterLimit;
+}
+
+void Splash::setFlatness(SplashCoord flatness) {
+ if (flatness < 1) {
+ state->flatness = 1;
+ } else {
+ state->flatness = flatness;
+ }
+}
+
+void Splash::setLineDash(SplashCoord *lineDash, int lineDashLength,
+ SplashCoord lineDashPhase) {
+ state->setLineDash(lineDash, lineDashLength, lineDashPhase);
+}
+
+void Splash::setStrokeAdjust(SplashStrokeAdjustMode strokeAdjust) {
+ state->strokeAdjust = strokeAdjust;
+}
+
+void Splash::clipResetToRect(SplashCoord x0, SplashCoord y0,
+ SplashCoord x1, SplashCoord y1) {
+ state->clipResetToRect(x0, y0, x1, y1);
+}
+
+SplashError Splash::clipToRect(SplashCoord x0, SplashCoord y0,
+ SplashCoord x1, SplashCoord y1) {
+ return state->clipToRect(x0, y0, x1, y1);
+}
+
+SplashError Splash::clipToPath(SplashPath *path, GBool eo) {
+ return state->clipToPath(path, eo);
+}
+
+void Splash::setSoftMask(SplashBitmap *softMask, GBool deleteBitmap) {
+ state->setSoftMask(softMask, deleteBitmap);
+}
+
+void Splash::setInTransparencyGroup(SplashBitmap *groupBackBitmapA,
+ int groupBackXA, int groupBackYA,
+ SplashGroupDestInitMode groupDestInitModeA,
+ GBool nonIsolated, GBool knockout) {
+ groupBackBitmap = groupBackBitmapA;
+ groupBackX = groupBackXA;
+ groupBackY = groupBackYA;
+ groupDestInitMode = groupDestInitModeA;
+ groupDestInitYMin = 1;
+ groupDestInitYMax = 0;
+ state->inNonIsolatedGroup = nonIsolated;
+ state->inKnockoutGroup = knockout;
+}
+
+void Splash::forceDeferredInit(int y, int h) {
+ useDestRow(y);
+ useDestRow(y + h - 1);
+}
+
+// Check that alpha is 0 in the specified rectangle.
+// NB: This doesn't work correctly in a non-isolated group, because
+// the rasterizer temporarily stores alpha_g instead of alpha.
+GBool Splash::checkTransparentRect(int x, int y, int w, int h) {
+ if (state->inNonIsolatedGroup) {
+ return gFalse;
+ }
+
+
+ if (!bitmap->alpha) {
+ return gFalse;
+ }
+ int yy0, yy1;
+ if (groupDestInitMode == splashGroupDestPreInit) {
+ yy0 = y;
+ yy1 = y + h - 1;
+ } else {
+ // both splashGroupDestInitZero and splashGroupDestInitCopy set
+ // alpha to zero, so anything outside of groupDestInit[YMin,YMax]
+ // will have alpha=0
+ yy0 = (y > groupDestInitYMin) ? y : groupDestInitYMin;
+ yy1 = (y + h - 1 < groupDestInitYMax) ? y + h - 1 : groupDestInitYMax;
+ }
+ Guchar *alphaP = &bitmap->alpha[yy0 * bitmap->alphaRowSize + x];
+ for (int yy = yy0; yy <= yy1; ++yy) {
+ for (int xx = 0; xx < w; ++xx) {
+ if (alphaP[xx] != 0) {
+ return gFalse;
+ }
+ }
+ alphaP += bitmap->getAlphaRowSize();
+ }
+ return gTrue;
+}
+
+void Splash::setTransfer(Guchar *red, Guchar *green, Guchar *blue,
+ Guchar *gray) {
+ state->setTransfer(red, green, blue, gray);
+}
+
+void Splash::setOverprintMask(Guint overprintMask) {
+ state->overprintMask = overprintMask;
+}
+
+
+void Splash::setEnablePathSimplification(GBool en) {
+ state->enablePathSimplification = en;
+}
+
+//------------------------------------------------------------------------
+// state save/restore
+//------------------------------------------------------------------------
+
+void Splash::saveState() {
+ SplashState *newState;
+
+ newState = state->copy();
+ newState->next = state;
+ state = newState;
+}
+
+SplashError Splash::restoreState() {
+ SplashState *oldState;
+
+ if (!state->next) {
+ return splashErrNoSave;
+ }
+ oldState = state;
+ state = state->next;
+ delete oldState;
+ return splashOk;
+}
+
+//------------------------------------------------------------------------
+// drawing operations
+//------------------------------------------------------------------------
+
+void Splash::clear(SplashColorPtr color, Guchar alpha) {
+ SplashColorPtr row, p;
+ Guchar mono;
+ int x, y;
+
+ switch (bitmap->mode) {
+ case splashModeMono1:
+ mono = (color[0] & 0x80) ? 0xff : 0x00;
+ if (bitmap->rowSize < 0) {
+ memset(bitmap->data + bitmap->rowSize * (bitmap->height - 1),
+ mono, -bitmap->rowSize * bitmap->height);
+ } else {
+ memset(bitmap->data, mono, bitmap->rowSize * bitmap->height);
+ }
+ break;
+ case splashModeMono8:
+ if (bitmap->rowSize < 0) {
+ memset(bitmap->data + bitmap->rowSize * (bitmap->height - 1),
+ color[0], -bitmap->rowSize * bitmap->height);
+ } else {
+ memset(bitmap->data, color[0], bitmap->rowSize * bitmap->height);
+ }
+ break;
+ case splashModeRGB8:
+ if (color[0] == color[1] && color[1] == color[2]) {
+ if (bitmap->rowSize < 0) {
+ memset(bitmap->data + bitmap->rowSize * (bitmap->height - 1),
+ color[0], -bitmap->rowSize * bitmap->height);
+ } else {
+ memset(bitmap->data, color[0], bitmap->rowSize * bitmap->height);
+ }
+ } else {
+ row = bitmap->data;
+ for (y = 0; y < bitmap->height; ++y) {
+ p = row;
+ for (x = 0; x < bitmap->width; ++x) {
+ *p++ = color[0];
+ *p++ = color[1];
+ *p++ = color[2];
+ }
+ row += bitmap->rowSize;
+ }
+ }
+ break;
+ case splashModeBGR8:
+ if (color[0] == color[1] && color[1] == color[2]) {
+ if (bitmap->rowSize < 0) {
+ memset(bitmap->data + bitmap->rowSize * (bitmap->height - 1),
+ color[0], -bitmap->rowSize * bitmap->height);
+ } else {
+ memset(bitmap->data, color[0], bitmap->rowSize * bitmap->height);
+ }
+ } else {
+ row = bitmap->data;
+ for (y = 0; y < bitmap->height; ++y) {
+ p = row;
+ for (x = 0; x < bitmap->width; ++x) {
+ *p++ = color[2];
+ *p++ = color[1];
+ *p++ = color[0];
+ }
+ row += bitmap->rowSize;
+ }
+ }
+ break;
+#if SPLASH_CMYK
+ case splashModeCMYK8:
+ if (color[0] == color[1] && color[1] == color[2] && color[2] == color[3]) {
+ if (bitmap->rowSize < 0) {
+ memset(bitmap->data + bitmap->rowSize * (bitmap->height - 1),
+ color[0], -bitmap->rowSize * bitmap->height);
+ } else {
+ memset(bitmap->data, color[0], bitmap->rowSize * bitmap->height);
+ }
+ } else {
+ row = bitmap->data;
+ for (y = 0; y < bitmap->height; ++y) {
+ p = row;
+ for (x = 0; x < bitmap->width; ++x) {
+ *p++ = color[0];
+ *p++ = color[1];
+ *p++ = color[2];
+ *p++ = color[3];
+ }
+ row += bitmap->rowSize;
+ }
+ }
+ break;
+#endif
+ }
+
+ if (bitmap->alpha) {
+ memset(bitmap->alpha, alpha, bitmap->alphaRowSize * bitmap->height);
+ }
+
+ updateModX(0);
+ updateModY(0);
+ updateModX(bitmap->width - 1);
+ updateModY(bitmap->height - 1);
+}
+
+SplashError Splash::stroke(SplashPath *path) {
+ SplashPath *path2, *dPath;
+ SplashCoord t0, t1, t2, t3, w, w2, lineDashMax, lineDashTotal;
+ int lineCap, lineJoin, i;
+
+ if (debugMode) {
+ printf("stroke [dash:%d] [width:%.2f]:\n",
+ state->lineDashLength, (double)state->lineWidth);
+ dumpPath(path);
+ }
+ opClipRes = splashClipAllOutside;
+ if (path->length == 0) {
+ return splashErrEmptyPath;
+ }
+ path2 = flattenPath(path, state->matrix, state->flatness);
+
+ // Compute an approximation of the transformed line width.
+ // Given a CTM of [m0 m1],
+ // [m2 m3]
+ // if |m0|*|m3| >= |m1|*|m2| then use min{|m0|,|m3|}, else
+ // use min{|m1|,|m2|}.
+ // This handles the common cases -- [s 0 ] and [0 s] --
+ // [0 +/-s] [+/-s 0]
+ // well, and still does something reasonable for the uncommon
+ // case transforms.
+ t0 = splashAbs(state->matrix[0]);
+ t1 = splashAbs(state->matrix[1]);
+ t2 = splashAbs(state->matrix[2]);
+ t3 = splashAbs(state->matrix[3]);
+ if (t0 * t3 >= t1 * t2) {
+ w = (t0 < t3) ? t0 : t3;
+ } else {
+ w = (t1 < t2) ? t1 : t2;
+ }
+ w2 = w * state->lineWidth;
+
+ // construct the dashed path
+ if (state->lineDashLength > 0) {
+
+ // check the maximum transformed dash element length (using the
+ // same approximation as for line width) -- if it's less than 0.1
+ // pixel, don't apply the dash pattern; this avoids a huge
+ // performance/memory hit with PDF files that use absurd dash
+ // patterns like [0.0007 0.0003]
+ lineDashTotal = 0;
+ lineDashMax = 0;
+ for (i = 0; i < state->lineDashLength; ++i) {
+ lineDashTotal += state->lineDash[i];
+ if (state->lineDash[i] > lineDashMax) {
+ lineDashMax = state->lineDash[i];
+ }
+ }
+ // Acrobat simply draws nothing if the dash array is [0]
+ if (lineDashTotal == 0) {
+ delete path2;
+ return splashOk;
+ }
+ if (w * lineDashMax > 0.1) {
+
+ dPath = makeDashedPath(path2);
+ delete path2;
+ path2 = dPath;
+ if (path2->length == 0) {
+ delete path2;
+ return splashErrEmptyPath;
+ }
+ }
+ }
+
+ // round caps on narrow lines look bad, and can't be
+ // stroke-adjusted, so use projecting caps instead (but we can't do
+ // this if there are zero-length dashes or segments, because those
+ // turn into round dots)
+ lineCap = state->lineCap;
+ lineJoin = state->lineJoin;
+ if (state->strokeAdjust == splashStrokeAdjustCAD &&
+ w2 < 3.5) {
+ if (lineCap == splashLineCapRound &&
+ !state->lineDashContainsZeroLengthDashes() &&
+ !path->containsZeroLengthSubpaths()) {
+ lineCap = splashLineCapProjecting;
+ }
+ if (lineJoin == splashLineJoinRound) {
+ lineJoin = splashLineJoinBevel;
+ }
+ }
+
+ // if there is a min line width set, and the transformed line width
+ // is smaller, use the min line width
+ if (w > 0 && w2 < minLineWidth) {
+ strokeWide(path2, minLineWidth / w, splashLineCapButt, splashLineJoinBevel);
+ } else if (bitmap->mode == splashModeMono1 || !vectorAntialias) {
+ // in monochrome mode or if antialiasing is disabled, use 0-width
+ // lines for any transformed line width <= 1 -- lines less than 1
+ // pixel wide look too fat without antialiasing
+ if (w2 < 1.001) {
+ strokeNarrow(path2);
+ } else {
+ strokeWide(path2, state->lineWidth, lineCap, lineJoin);
+ }
+ } else {
+ // in gray and color modes, only use 0-width lines if the line
+ // width is explicitly set to 0
+ if (state->lineWidth == 0) {
+ strokeNarrow(path2);
+ } else {
+ strokeWide(path2, state->lineWidth, lineCap, lineJoin);
+ }
+ }
+
+ delete path2;
+ return splashOk;
+}
+
+void Splash::strokeNarrow(SplashPath *path) {
+ SplashPipe pipe;
+ SplashXPath *xPath;
+ SplashXPathSeg *seg;
+ int x0, x1, y0, y1, xa, xb, y;
+ SplashCoord dxdy;
+ SplashClipResult clipRes;
+ int nClipRes[3];
+ int i;
+
+ nClipRes[0] = nClipRes[1] = nClipRes[2] = 0;
+
+ xPath = new SplashXPath(path, state->matrix, state->flatness, gFalse,
+ state->enablePathSimplification,
+ state->strokeAdjust);
+
+ pipeInit(&pipe, state->strokePattern,
+ (Guchar)splashRound(state->strokeAlpha * 255),
+ gTrue, gFalse);
+
+ for (i = 0, seg = xPath->segs; i < xPath->length; ++i, ++seg) {
+ if (seg->y0 <= seg->y1) {
+ y0 = splashFloor(seg->y0);
+ y1 = splashFloor(seg->y1);
+ x0 = splashFloor(seg->x0);
+ x1 = splashFloor(seg->x1);
+ } else {
+ y0 = splashFloor(seg->y1);
+ y1 = splashFloor(seg->y0);
+ x0 = splashFloor(seg->x1);
+ x1 = splashFloor(seg->x0);
+ }
+ if ((clipRes = state->clip->testRect(x0 <= x1 ? x0 : x1, y0,
+ x0 <= x1 ? x1 : x0, y1,
+ state->strokeAdjust))
+ != splashClipAllOutside) {
+ if (y0 == y1) {
+ if (x0 <= x1) {
+ drawStrokeSpan(&pipe, x0, x1, y0, clipRes == splashClipAllInside);
+ } else {
+ drawStrokeSpan(&pipe, x1, x0, y0, clipRes == splashClipAllInside);
+ }
+ } else {
+ dxdy = seg->dxdy;
+ y = state->clip->getYMinI(state->strokeAdjust);
+ if (y0 < y) {
+ y0 = y;
+ x0 = splashFloor(seg->x0 + ((SplashCoord)y0 - seg->y0) * dxdy);
+ }
+ y = state->clip->getYMaxI(state->strokeAdjust);
+ if (y1 > y) {
+ y1 = y;
+ x1 = splashFloor(seg->x0 + ((SplashCoord)y1 - seg->y0) * dxdy);
+ }
+ if (x0 <= x1) {
+ xa = x0;
+ for (y = y0; y <= y1; ++y) {
+ if (y < y1) {
+ xb = splashFloor(seg->x0 +
+ ((SplashCoord)y + 1 - seg->y0) * dxdy);
+ } else {
+ xb = x1 + 1;
+ }
+ if (xa == xb) {
+ drawStrokeSpan(&pipe, xa, xa, y, clipRes == splashClipAllInside);
+ } else {
+ drawStrokeSpan(&pipe, xa, xb - 1, y,
+ clipRes == splashClipAllInside);
+ }
+ xa = xb;
+ }
+ } else {
+ xa = x0;
+ for (y = y0; y <= y1; ++y) {
+ if (y < y1) {
+ xb = splashFloor(seg->x0 +
+ ((SplashCoord)y + 1 - seg->y0) * dxdy);
+ } else {
+ xb = x1 - 1;
+ }
+ if (xa == xb) {
+ drawStrokeSpan(&pipe, xa, xa, y, clipRes == splashClipAllInside);
+ } else {
+ drawStrokeSpan(&pipe, xb + 1, xa, y,
+ clipRes == splashClipAllInside);
+ }
+ xa = xb;
+ }
+ }
+ }
+ }
+ ++nClipRes[clipRes];
+ }
+ if (nClipRes[splashClipPartial] ||
+ (nClipRes[splashClipAllInside] && nClipRes[splashClipAllOutside])) {
+ opClipRes = splashClipPartial;
+ } else if (nClipRes[splashClipAllInside]) {
+ opClipRes = splashClipAllInside;
+ } else {
+ opClipRes = splashClipAllOutside;
+ }
+
+ delete xPath;
+}
+
+void Splash::drawStrokeSpan(SplashPipe *pipe, int x0, int x1, int y,
+ GBool noClip) {
+ int x;
+
+ x = state->clip->getXMinI(state->strokeAdjust);
+ if (x > x0) {
+ x0 = x;
+ }
+ x = state->clip->getXMaxI(state->strokeAdjust);
+ if (x < x1) {
+ x1 = x;
+ }
+ if (x0 > x1) {
+ return;
+ }
+ for (x = x0; x <= x1; ++x) {
+ scanBuf[x] = 0xff;
+ }
+ if (!noClip) {
+ if (!state->clip->clipSpanBinary(scanBuf, y, x0, x1, state->strokeAdjust)) {
+ return;
+ }
+ }
+ (this->*pipe->run)(pipe, x0, x1, y, scanBuf + x0, NULL);
+}
+
+void Splash::strokeWide(SplashPath *path, SplashCoord w,
+ int lineCap, int lineJoin) {
+ SplashPath *path2;
+
+ path2 = makeStrokePath(path, w, lineCap, lineJoin, gFalse);
+ fillWithPattern(path2, gFalse, state->strokePattern, state->strokeAlpha);
+ delete path2;
+}
+
+SplashPath *Splash::flattenPath(SplashPath *path, SplashCoord *matrix,
+ SplashCoord flatness) {
+ SplashPath *fPath;
+ SplashCoord flatness2;
+ Guchar flag;
+ int i;
+
+ fPath = new SplashPath();
+#if USE_FIXEDPOINT
+ flatness2 = flatness;
+#else
+ flatness2 = flatness * flatness;
+#endif
+ i = 0;
+ while (i < path->length) {
+ flag = path->flags[i];
+ if (flag & splashPathFirst) {
+ fPath->moveTo(path->pts[i].x, path->pts[i].y);
+ ++i;
+ } else {
+ if (flag & splashPathCurve) {
+ flattenCurve(path->pts[i-1].x, path->pts[i-1].y,
+ path->pts[i ].x, path->pts[i ].y,
+ path->pts[i+1].x, path->pts[i+1].y,
+ path->pts[i+2].x, path->pts[i+2].y,
+ matrix, flatness2, fPath);
+ i += 3;
+ } else {
+ fPath->lineTo(path->pts[i].x, path->pts[i].y);
+ ++i;
+ }
+ if (path->flags[i-1] & splashPathClosed) {
+ fPath->close();
+ }
+ }
+ }
+ return fPath;
+}
+
+void Splash::flattenCurve(SplashCoord x0, SplashCoord y0,
+ SplashCoord x1, SplashCoord y1,
+ SplashCoord x2, SplashCoord y2,
+ SplashCoord x3, SplashCoord y3,
+ SplashCoord *matrix, SplashCoord flatness2,
+ SplashPath *fPath) {
+ SplashCoord cx[splashMaxCurveSplits + 1][3];
+ SplashCoord cy[splashMaxCurveSplits + 1][3];
+ int cNext[splashMaxCurveSplits + 1];
+ SplashCoord xl0, xl1, xl2, xr0, xr1, xr2, xr3, xx1, xx2, xh;
+ SplashCoord yl0, yl1, yl2, yr0, yr1, yr2, yr3, yy1, yy2, yh;
+ SplashCoord dx, dy, mx, my, tx, ty, d1, d2;
+ int p1, p2, p3;
+
+ // initial segment
+ p1 = 0;
+ p2 = splashMaxCurveSplits;
+ cx[p1][0] = x0; cy[p1][0] = y0;
+ cx[p1][1] = x1; cy[p1][1] = y1;
+ cx[p1][2] = x2; cy[p1][2] = y2;
+ cx[p2][0] = x3; cy[p2][0] = y3;
+ cNext[p1] = p2;
+
+ while (p1 < splashMaxCurveSplits) {
+
+ // get the next segment
+ xl0 = cx[p1][0]; yl0 = cy[p1][0];
+ xx1 = cx[p1][1]; yy1 = cy[p1][1];
+ xx2 = cx[p1][2]; yy2 = cy[p1][2];
+ p2 = cNext[p1];
+ xr3 = cx[p2][0]; yr3 = cy[p2][0];
+
+ // compute the distances (in device space) from the control points
+ // to the midpoint of the straight line (this is a bit of a hack,
+ // but it's much faster than computing the actual distances to the
+ // line)
+ transform(matrix, (xl0 + xr3) * 0.5, (yl0 + yr3) * 0.5, &mx, &my);
+ transform(matrix, xx1, yy1, &tx, &ty);
+#if USE_FIXEDPOINT
+ d1 = splashDist(tx, ty, mx, my);
+#else
+ dx = tx - mx;
+ dy = ty - my;
+ d1 = dx*dx + dy*dy;
+#endif
+ transform(matrix, xx2, yy2, &tx, &ty);
+#if USE_FIXEDPOINT
+ d2 = splashDist(tx, ty, mx, my);
+#else
+ dx = tx - mx;
+ dy = ty - my;
+ d2 = dx*dx + dy*dy;
+#endif
+
+ // if the curve is flat enough, or no more subdivisions are
+ // allowed, add the straight line segment
+ if (p2 - p1 == 1 || (d1 <= flatness2 && d2 <= flatness2)) {
+ fPath->lineTo(xr3, yr3);
+ p1 = p2;
+
+ // otherwise, subdivide the curve
+ } else {
+ xl1 = splashAvg(xl0, xx1);
+ yl1 = splashAvg(yl0, yy1);
+ xh = splashAvg(xx1, xx2);
+ yh = splashAvg(yy1, yy2);
+ xl2 = splashAvg(xl1, xh);
+ yl2 = splashAvg(yl1, yh);
+ xr2 = splashAvg(xx2, xr3);
+ yr2 = splashAvg(yy2, yr3);
+ xr1 = splashAvg(xh, xr2);
+ yr1 = splashAvg(yh, yr2);
+ xr0 = splashAvg(xl2, xr1);
+ yr0 = splashAvg(yl2, yr1);
+ // add the new subdivision points
+ p3 = (p1 + p2) / 2;
+ cx[p1][1] = xl1; cy[p1][1] = yl1;
+ cx[p1][2] = xl2; cy[p1][2] = yl2;
+ cNext[p1] = p3;
+ cx[p3][0] = xr0; cy[p3][0] = yr0;
+ cx[p3][1] = xr1; cy[p3][1] = yr1;
+ cx[p3][2] = xr2; cy[p3][2] = yr2;
+ cNext[p3] = p2;
+ }
+ }
+}
+
+SplashPath *Splash::makeDashedPath(SplashPath *path) {
+ SplashPath *dPath;
+ SplashCoord lineDashTotal;
+ SplashCoord lineDashStartPhase, lineDashDist, segLen;
+ SplashCoord x0, y0, x1, y1, xa, ya;
+ GBool lineDashStartOn, lineDashEndOn, lineDashOn, newPath;
+ int lineDashStartIdx, lineDashIdx, subpathStart, nDashes;
+ int i, j, k;
+
+ lineDashTotal = 0;
+ for (i = 0; i < state->lineDashLength; ++i) {
+ lineDashTotal += state->lineDash[i];
+ }
+ // Acrobat simply draws nothing if the dash array is [0]
+ if (lineDashTotal == 0) {
+ return new SplashPath();
+ }
+ lineDashStartPhase = state->lineDashPhase;
+ if (lineDashStartPhase > lineDashTotal * 2) {
+ i = splashFloor(lineDashStartPhase / (lineDashTotal * 2));
+ lineDashStartPhase -= lineDashTotal * i * 2;
+ } else if (lineDashStartPhase < 0) {
+ i = splashCeil(-lineDashStartPhase / (lineDashTotal * 2));
+ lineDashStartPhase += lineDashTotal * i * 2;
+ }
+ i = splashFloor(lineDashStartPhase / lineDashTotal);
+ lineDashStartPhase -= (SplashCoord)i * lineDashTotal;
+ lineDashStartOn = gTrue;
+ lineDashStartIdx = 0;
+ if (lineDashStartPhase > 0) {
+ while (lineDashStartPhase >= state->lineDash[lineDashStartIdx]) {
+ lineDashStartOn = !lineDashStartOn;
+ lineDashStartPhase -= state->lineDash[lineDashStartIdx];
+ if (++lineDashStartIdx == state->lineDashLength) {
+ lineDashStartIdx = 0;
+ }
+ }
+ }
+
+ dPath = new SplashPath();
+
+ // process each subpath
+ i = 0;
+ while (i < path->length) {
+
+ // find the end of the subpath
+ for (j = i;
+ j < path->length - 1 && !(path->flags[j] & splashPathLast);
+ ++j) ;
+
+ // initialize the dash parameters
+ lineDashOn = lineDashStartOn;
+ lineDashEndOn = lineDashStartOn;
+ lineDashIdx = lineDashStartIdx;
+ lineDashDist = state->lineDash[lineDashIdx] - lineDashStartPhase;
+ subpathStart = dPath->length;
+ nDashes = 0;
+
+ // process each segment of the subpath
+ newPath = gTrue;
+ for (k = i; k < j; ++k) {
+
+ // grab the segment
+ x0 = path->pts[k].x;
+ y0 = path->pts[k].y;
+ x1 = path->pts[k+1].x;
+ y1 = path->pts[k+1].y;
+ segLen = splashDist(x0, y0, x1, y1);
+
+ // process the segment
+ while (segLen > 0) {
+
+ // Special case for zero-length dash segments: draw a very
+ // short -- but not zero-length -- segment. This ensures that
+ // we get the correct behavior with butt and projecting line
+ // caps. The PS/PDF specs imply that zero-length segments are
+ // not drawn unless the line cap is round, but Acrobat and
+ // Ghostscript both draw very short segments (for butt caps)
+ // and squares (for projecting caps).
+ if (lineDashDist == 0) {
+ if (lineDashOn) {
+ if (newPath) {
+ dPath->moveTo(x0, y0);
+ newPath = gFalse;
+ ++nDashes;
+ }
+ xa = x0 + ((SplashCoord)0.001 / segLen) * (x1 - x0);
+ ya = y0 + ((SplashCoord)0.001 / segLen) * (y1 - y0);
+ dPath->lineTo(xa, ya);
+ }
+
+ } else if (lineDashDist >= segLen) {
+ if (lineDashOn) {
+ if (newPath) {
+ dPath->moveTo(x0, y0);
+ newPath = gFalse;
+ ++nDashes;
+ }
+ dPath->lineTo(x1, y1);
+ }
+ lineDashDist -= segLen;
+ segLen = 0;
+
+ } else {
+ xa = x0 + (lineDashDist / segLen) * (x1 - x0);
+ ya = y0 + (lineDashDist / segLen) * (y1 - y0);
+ if (lineDashOn) {
+ if (newPath) {
+ dPath->moveTo(x0, y0);
+ newPath = gFalse;
+ ++nDashes;
+ }
+ dPath->lineTo(xa, ya);
+ }
+ x0 = xa;
+ y0 = ya;
+ segLen -= lineDashDist;
+ lineDashDist = 0;
+ }
+
+ lineDashEndOn = lineDashOn;
+
+ // get the next entry in the dash array
+ if (lineDashDist <= 0) {
+ lineDashOn = !lineDashOn;
+ if (++lineDashIdx == state->lineDashLength) {
+ lineDashIdx = 0;
+ }
+ lineDashDist = state->lineDash[lineDashIdx];
+ newPath = gTrue;
+ }
+ }
+ }
+
+ // in a closed subpath, where the dash pattern is "on" at both the
+ // start and end of the subpath, we need to merge the start and
+ // end to get a proper line join
+ if ((path->flags[j] & splashPathClosed) &&
+ lineDashStartOn &&
+ lineDashEndOn) {
+ if (nDashes == 1) {
+ dPath->close();
+ } else if (nDashes > 1) {
+ k = subpathStart;
+ do {
+ ++k;
+ dPath->lineTo(dPath->pts[k].x, dPath->pts[k].y);
+ } while (!(dPath->flags[k] & splashPathLast));
+ ++k;
+ memmove(&dPath->pts[subpathStart], &dPath->pts[k],
+ (dPath->length - k) * sizeof(SplashPathPoint));
+ memmove(&dPath->flags[subpathStart], &dPath->flags[k],
+ (dPath->length - k) * sizeof(Guchar));
+ dPath->length -= k - subpathStart;
+ dPath->curSubpath -= k - subpathStart;
+ }
+ }
+
+ i = j + 1;
+ }
+
+ return dPath;
+}
+
+SplashError Splash::fill(SplashPath *path, GBool eo) {
+ if (debugMode) {
+ printf("fill [eo:%d]:\n", eo);
+ dumpPath(path);
+ }
+ return fillWithPattern(path, eo, state->fillPattern, state->fillAlpha);
+}
+
+SplashError Splash::fillWithPattern(SplashPath *path, GBool eo,
+ SplashPattern *pattern,
+ SplashCoord alpha) {
+ SplashPipe pipe;
+ SplashPath *path2;
+ SplashXPath *xPath;
+ SplashXPathScanner *scanner;
+ int xMin, yMin, xMax, xMin2, xMax2, yMax, y, t;
+ SplashClipResult clipRes;
+
+ if (path->length == 0) {
+ return splashErrEmptyPath;
+ }
+ if (pathAllOutside(path)) {
+ opClipRes = splashClipAllOutside;
+ return splashOk;
+ }
+
+ path2 = tweakFillPath(path);
+
+ xPath = new SplashXPath(path2, state->matrix, state->flatness, gTrue,
+ state->enablePathSimplification,
+ state->strokeAdjust);
+ if (path2 != path) {
+ delete path2;
+ }
+ xMin = xPath->getXMin();
+ yMin = xPath->getYMin();
+ xMax = xPath->getXMax();
+ yMax = xPath->getYMax();
+ if (xMin > xMax || yMin > yMax) {
+ delete xPath;
+ return splashOk;
+ }
+ scanner = new SplashXPathScanner(xPath, eo, yMin, yMax);
+
+ // check clipping
+ if ((clipRes = state->clip->testRect(xMin, yMin, xMax, yMax,
+ state->strokeAdjust))
+ != splashClipAllOutside) {
+
+ if ((t = state->clip->getXMinI(state->strokeAdjust)) > xMin) {
+ xMin = t;
+ }
+ if ((t = state->clip->getXMaxI(state->strokeAdjust)) < xMax) {
+ xMax = t;
+ }
+ if ((t = state->clip->getYMinI(state->strokeAdjust)) > yMin) {
+ yMin = t;
+ }
+ if ((t = state->clip->getYMaxI(state->strokeAdjust)) < yMax) {
+ yMax = t;
+ }
+ if (xMin > xMax || yMin > yMax) {
+ delete scanner;
+ delete xPath;
+ return splashOk;
+ }
+
+ pipeInit(&pipe, pattern, (Guchar)splashRound(alpha * 255),
+ gTrue, gFalse);
+
+ // draw the spans
+ if (vectorAntialias && !inShading) {
+ for (y = yMin; y <= yMax; ++y) {
+ scanner->getSpan(scanBuf, y, xMin, xMax, &xMin2, &xMax2);
+ if (xMin2 <= xMax2) {
+ if (clipRes != splashClipAllInside) {
+ state->clip->clipSpan(scanBuf, y, xMin2, xMax2,
+ state->strokeAdjust);
+ }
+ (this->*pipe.run)(&pipe, xMin2, xMax2, y, scanBuf + xMin2, NULL);
+ }
+ }
+ } else {
+ for (y = yMin; y <= yMax; ++y) {
+ scanner->getSpanBinary(scanBuf, y, xMin, xMax, &xMin2, &xMax2);
+ if (xMin2 <= xMax2) {
+ if (clipRes != splashClipAllInside) {
+ state->clip->clipSpanBinary(scanBuf, y, xMin2, xMax2,
+ state->strokeAdjust);
+ }
+ (this->*pipe.run)(&pipe, xMin2, xMax2, y, scanBuf + xMin2, NULL);
+ }
+ }
+ }
+ }
+ opClipRes = clipRes;
+
+ delete scanner;
+ delete xPath;
+ return splashOk;
+}
+
+// Applies various tweaks to a fill path:
+// (1) add stroke adjust hints to a filled rectangle
+// (2) applies a minimum width to a zero-width filled rectangle (so
+// stroke adjustment works correctly
+// (3) convert a degenerate fill ('moveto lineto fill' and 'moveto
+// lineto closepath fill') to a minimum-width filled rectangle
+//
+// These tweaks only apply to paths with a single subpath.
+//
+// Returns either the unchanged input path or a new path (in which
+// case the returned path must be deleted by the caller).
+SplashPath *Splash::tweakFillPath(SplashPath *path) {
+ SplashPath *path2;
+ SplashCoord xx0, yy0, xx1, yy1, dx, dy, d, wx, wy, w;
+ int n;
+
+ if (state->strokeAdjust == splashStrokeAdjustOff || path->hints) {
+ return path;
+ }
+
+ n = path->getLength();
+ if (!((n == 2) ||
+ (n == 3 &&
+ path->flags[1] == 0) ||
+ (n == 4 &&
+ path->flags[1] == 0 &&
+ path->flags[2] == 0) ||
+ (n == 5 &&
+ path->flags[1] == 0 &&
+ path->flags[2] == 0 &&
+ path->flags[3] == 0))) {
+ return path;
+ }
+
+ path2 = path;
+
+ // degenerate fill (2 or 3 points) or rectangle of (nearly) zero
+ // width --> replace with a min-width rectangle and hint
+ if (n == 2 ||
+ (n == 3 && (path->flags[0] & splashPathClosed)) ||
+ (n == 3 && (splashAbs(path->pts[0].x - path->pts[2].x) < 0.001 &&
+ splashAbs(path->pts[0].y - path->pts[2].y) < 0.001)) ||
+ ((n == 4 ||
+ (n == 5 && (path->flags[0] & splashPathClosed))) &&
+ ((splashAbs(path->pts[0].x - path->pts[1].x) < 0.001 &&
+ splashAbs(path->pts[0].y - path->pts[1].y) < 0.001 &&
+ splashAbs(path->pts[2].x - path->pts[3].x) < 0.001 &&
+ splashAbs(path->pts[2].y - path->pts[3].y) < 0.001) ||
+ (splashAbs(path->pts[0].x - path->pts[3].x) < 0.001 &&
+ splashAbs(path->pts[0].y - path->pts[3].y) < 0.001 &&
+ splashAbs(path->pts[1].x - path->pts[2].x) < 0.001 &&
+ splashAbs(path->pts[1].y - path->pts[2].y) < 0.001)))) {
+ wx = state->matrix[0] + state->matrix[2];
+ wy = state->matrix[1] + state->matrix[3];
+ w = splashSqrt(wx*wx + wy*wy);
+ if (w < 0.001) {
+ w = 0;
+ } else {
+ // min width is 0.1 -- this constant is minWidth * sqrt(2)
+ w = (SplashCoord)0.1414 / w;
+ }
+ xx0 = path->pts[0].x;
+ yy0 = path->pts[0].y;
+ if (n <= 3) {
+ xx1 = path->pts[1].x;
+ yy1 = path->pts[1].y;
+ } else {
+ xx1 = path->pts[2].x;
+ yy1 = path->pts[2].y;
+ }
+ dx = xx1 - xx0;
+ dy = yy1 - yy0;
+ d = splashSqrt(dx * dx + dy * dy);
+ if (d < 0.001) {
+ d = 0;
+ } else {
+ d = w / d;
+ }
+ dx *= d;
+ dy *= d;
+ path2 = new SplashPath();
+ path2->moveTo(xx0 + dy, yy0 - dx);
+ path2->lineTo(xx1 + dy, yy1 - dx);
+ path2->lineTo(xx1 - dy, yy1 + dx);
+ path2->lineTo(xx0 - dy, yy0 + dx);
+ path2->close(gTrue);
+ path2->addStrokeAdjustHint(0, 2, 0, 4);
+ path2->addStrokeAdjustHint(1, 3, 0, 4);
+
+ // unclosed rectangle --> close and hint
+ } else if (n == 4 && !(path->flags[0] & splashPathClosed)) {
+ path2->close(gTrue);
+ path2->addStrokeAdjustHint(0, 2, 0, 4);
+ path2->addStrokeAdjustHint(1, 3, 0, 4);
+
+ // closed rectangle --> hint
+ } else if (n == 5 && (path->flags[0] & splashPathClosed)) {
+ path2->addStrokeAdjustHint(0, 2, 0, 4);
+ path2->addStrokeAdjustHint(1, 3, 0, 4);
+ }
+
+ return path2;
+}
+
+GBool Splash::pathAllOutside(SplashPath *path) {
+ SplashCoord xMin1, yMin1, xMax1, yMax1;
+ SplashCoord xMin2, yMin2, xMax2, yMax2;
+ SplashCoord x, y;
+ int xMinI, yMinI, xMaxI, yMaxI;
+ int i;
+
+ xMin1 = xMax1 = path->pts[0].x;
+ yMin1 = yMax1 = path->pts[0].y;
+ for (i = 1; i < path->length; ++i) {
+ if (path->pts[i].x < xMin1) {
+ xMin1 = path->pts[i].x;
+ } else if (path->pts[i].x > xMax1) {
+ xMax1 = path->pts[i].x;
+ }
+ if (path->pts[i].y < yMin1) {
+ yMin1 = path->pts[i].y;
+ } else if (path->pts[i].y > yMax1) {
+ yMax1 = path->pts[i].y;
+ }
+ }
+
+ transform(state->matrix, xMin1, yMin1, &x, &y);
+ xMin2 = xMax2 = x;
+ yMin2 = yMax2 = y;
+ transform(state->matrix, xMin1, yMax1, &x, &y);
+ if (x < xMin2) {
+ xMin2 = x;
+ } else if (x > xMax2) {
+ xMax2 = x;
+ }
+ if (y < yMin2) {
+ yMin2 = y;
+ } else if (y > yMax2) {
+ yMax2 = y;
+ }
+ transform(state->matrix, xMax1, yMin1, &x, &y);
+ if (x < xMin2) {
+ xMin2 = x;
+ } else if (x > xMax2) {
+ xMax2 = x;
+ }
+ if (y < yMin2) {
+ yMin2 = y;
+ } else if (y > yMax2) {
+ yMax2 = y;
+ }
+ transform(state->matrix, xMax1, yMax1, &x, &y);
+ if (x < xMin2) {
+ xMin2 = x;
+ } else if (x > xMax2) {
+ xMax2 = x;
+ }
+ if (y < yMin2) {
+ yMin2 = y;
+ } else if (y > yMax2) {
+ yMax2 = y;
+ }
+ // sanity-check the coordinates - xMinI/yMinI/xMaxI/yMaxI are
+ // 32-bit integers, so coords need to be < 2^31
+ SplashXPath::clampCoords(&xMin2, &yMin2);
+ SplashXPath::clampCoords(&xMax2, &yMax2);
+ xMinI = splashFloor(xMin2);
+ yMinI = splashFloor(yMin2);
+ xMaxI = splashFloor(xMax2);
+ yMaxI = splashFloor(yMax2);
+
+ return state->clip->testRect(xMinI, yMinI, xMaxI, yMaxI,
+ state->strokeAdjust) ==
+ splashClipAllOutside;
+}
+
+SplashError Splash::fillChar(SplashCoord x, SplashCoord y,
+ int c, SplashFont *font) {
+ SplashGlyphBitmap glyph;
+ SplashCoord xt, yt;
+ int x0, y0, xFrac, yFrac;
+ SplashError err;
+
+ if (debugMode) {
+ printf("fillChar: x=%.2f y=%.2f c=%3d=0x%02x='%c'\n",
+ (double)x, (double)y, c, c, c);
+ }
+ transform(state->matrix, x, y, &xt, &yt);
+ x0 = splashFloor(xt);
+ xFrac = splashFloor((xt - x0) * splashFontFraction);
+ y0 = splashFloor(yt);
+ yFrac = splashFloor((yt - y0) * splashFontFraction);
+ if (!font->getGlyph(c, xFrac, yFrac, &glyph)) {
+ return splashErrNoGlyph;
+ }
+ err = fillGlyph2(x0, y0, &glyph);
+ if (glyph.freeData) {
+ gfree(glyph.data);
+ }
+ return err;
+}
+
+SplashError Splash::fillGlyph(SplashCoord x, SplashCoord y,
+ SplashGlyphBitmap *glyph) {
+ SplashCoord xt, yt;
+ int x0, y0;
+
+ transform(state->matrix, x, y, &xt, &yt);
+ x0 = splashFloor(xt);
+ y0 = splashFloor(yt);
+ return fillGlyph2(x0, y0, glyph);
+}
+
+SplashError Splash::fillGlyph2(int x0, int y0, SplashGlyphBitmap *glyph) {
+ SplashPipe pipe;
+ SplashClipResult clipRes;
+ Guchar alpha;
+ Guchar *p;
+ int xMin, yMin, xMax, yMax;
+ int x, y, xg, yg, xx, t;
+
+ xg = x0 - glyph->x;
+ yg = y0 - glyph->y;
+ xMin = xg;
+ xMax = xg + glyph->w - 1;
+ yMin = yg;
+ yMax = yg + glyph->h - 1;
+ if ((clipRes = state->clip->testRect(xMin, yMin, xMax, yMax,
+ state->strokeAdjust))
+ != splashClipAllOutside) {
+ pipeInit(&pipe, state->fillPattern,
+ (Guchar)splashRound(state->fillAlpha * 255),
+ gTrue, gFalse);
+ if (clipRes == splashClipAllInside) {
+ if (glyph->aa) {
+ p = glyph->data;
+ for (y = yMin; y <= yMax; ++y) {
+ (this->*pipe.run)(&pipe, xMin, xMax, y,
+ glyph->data + (y - yMin) * glyph->w, NULL);
+ }
+ } else {
+ p = glyph->data;
+ for (y = yMin; y <= yMax; ++y) {
+ for (x = xMin; x <= xMax; x += 8) {
+ alpha = *p++;
+ for (xx = 0; xx < 8 && x + xx <= xMax; ++xx) {
+ scanBuf[x + xx] = (alpha & 0x80) ? 0xff : 0x00;
+ alpha = (Guchar)(alpha << 1);
+ }
+ }
+ (this->*pipe.run)(&pipe, xMin, xMax, y, scanBuf + xMin, NULL);
+ }
+ }
+ } else {
+ if ((t = state->clip->getXMinI(state->strokeAdjust)) > xMin) {
+ xMin = t;
+ }
+ if ((t = state->clip->getXMaxI(state->strokeAdjust)) < xMax) {
+ xMax = t;
+ }
+ if ((t = state->clip->getYMinI(state->strokeAdjust)) > yMin) {
+ yMin = t;
+ }
+ if ((t = state->clip->getYMaxI(state->strokeAdjust)) < yMax) {
+ yMax = t;
+ }
+ if (xMin <= xMax && yMin <= yMax) {
+ if (glyph->aa) {
+ for (y = yMin; y <= yMax; ++y) {
+ p = glyph->data + (y - yg) * glyph->w + (xMin - xg);
+ memcpy(scanBuf + xMin, p, xMax - xMin + 1);
+ state->clip->clipSpan(scanBuf, y, xMin, xMax,
+ state->strokeAdjust);
+ (this->*pipe.run)(&pipe, xMin, xMax, y, scanBuf + xMin, NULL);
+ }
+ } else {
+ for (y = yMin; y <= yMax; ++y) {
+ p = glyph->data + (y - yg) * ((glyph->w + 7) >> 3)
+ + ((xMin - xg) >> 3);
+ alpha = *p++;
+ xx = (xMin - xg) & 7;
+ alpha = (Guchar)(alpha << xx);
+ for (x = xMin; xx < 8 && x <= xMax; ++x, ++xx) {
+ scanBuf[x] = (alpha & 0x80) ? 255 : 0;
+ alpha = (Guchar)(alpha << 1);
+ }
+ for (; x <= xMax; x += 8) {
+ alpha = *p++;
+ for (xx = 0; xx < 8 && x + xx <= xMax; ++xx) {
+ scanBuf[x + xx] = (alpha & 0x80) ? 255 : 0;
+ alpha = (Guchar)(alpha << 1);
+ }
+ }
+ state->clip->clipSpanBinary(scanBuf, y, xMin, xMax,
+ state->strokeAdjust);
+ (this->*pipe.run)(&pipe, xMin, xMax, y, scanBuf + xMin, NULL);
+ }
+ }
+ }
+ }
+ }
+ opClipRes = clipRes;
+
+ return splashOk;
+}
+
+void Splash::getImageBounds(SplashCoord xyMin, SplashCoord xyMax,
+ int *xyMinI, int *xyMaxI) {
+ if (state->strokeAdjust == splashStrokeAdjustOff) {
+ // make sure the coords fit in 32-bit ints
+#if USE_FIXEDPOINT
+ if (xyMin < -32767) {
+ xyMin = -32767;
+ } else if (xyMin > 32767) {
+ xyMin = 32767;
+ }
+ if (xyMax < -32767) {
+ xyMax = -32767;
+ } else if (xyMax > 32767) {
+ xyMax = 32767;
+ }
+#else
+ if (xyMin < -1e9) {
+ xyMin = -1e9;
+ } else if (xyMin > 1e9) {
+ xyMin = 1e9;
+ }
+ if (xyMax < -1e9) {
+ xyMax = -1e9;
+ } else if (xyMax > 1e9) {
+ xyMax = 1e9;
+ }
+#endif
+ *xyMinI = splashFloor(xyMin);
+ *xyMaxI = splashFloor(xyMax);
+ if (*xyMaxI <= *xyMinI) {
+ *xyMaxI = *xyMinI + 1;
+ }
+ } else {
+ splashStrokeAdjust(xyMin, xyMax, xyMinI, xyMaxI, state->strokeAdjust);
+ }
+}
+
+struct SplashDrawImageMaskRowData {
+ SplashPipe pipe;
+};
+
+// The glyphMode flag is not currently used, but may be useful if the
+// stroke adjustment behavior is changed.
+SplashError Splash::fillImageMask(GString *imageTag,
+ SplashImageMaskSource src, void *srcData,
+ int w, int h, SplashCoord *mat,
+ GBool glyphMode, GBool interpolate,
+ GBool antialias) {
+ if (debugMode) {
+ printf("fillImageMask: w=%d h=%d mat=[%.2f %.2f %.2f %.2f %.2f %.2f]\n",
+ w, h, (double)mat[0], (double)mat[1], (double)mat[2],
+ (double)mat[3], (double)mat[4], (double)mat[5]);
+ }
+
+ //--- check for singular matrix
+ if (!splashCheckDet(mat[0], mat[1], mat[2], mat[3], 0.000001)) {
+ return splashErrSingularMatrix;
+ }
+
+ //--- compute image bbox, check clipping
+ GBool flipsOnly = splashAbs(mat[1]) <= 0.0001 && splashAbs(mat[2]) <= 0.0001;
+ GBool rot90Only = splashAbs(mat[0]) <= 0.0001 && splashAbs(mat[3]) <= 0.0001;
+ GBool horizFlip = gFalse;
+ GBool vertFlip = gFalse;
+ int xMin, yMin, xMax, yMax;
+ if (flipsOnly) {
+ horizFlip = mat[0] < 0;
+ vertFlip = mat[3] < 0;
+ if (horizFlip) {
+ getImageBounds(mat[0] + mat[4], mat[4], &xMin, &xMax);
+ } else {
+ getImageBounds(mat[4], mat[0] + mat[4], &xMin, &xMax);
+ }
+ if (vertFlip) {
+ getImageBounds(mat[3] + mat[5], mat[5], &yMin, &yMax);
+ } else {
+ getImageBounds(mat[5], mat[3] + mat[5], &yMin, &yMax);
+ }
+ } else if (rot90Only) {
+ horizFlip = mat[2] < 0;
+ vertFlip = mat[1] < 0;
+ if (horizFlip) {
+ getImageBounds(mat[2] + mat[4], mat[4], &xMin, &xMax);
+ } else {
+ getImageBounds(mat[4], mat[2] + mat[4], &xMin, &xMax);
+ }
+ if (vertFlip) {
+ getImageBounds(mat[1] + mat[5], mat[5], &yMin, &yMax);
+ } else {
+ getImageBounds(mat[5], mat[1] + mat[5], &yMin, &yMax);
+ }
+ } else {
+ int xx = splashRound(mat[4]); // (0,0)
+ int yy = splashRound(mat[5]);
+ xMin = xMax = xx;
+ yMin = yMax = yy;
+ xx = splashRound(mat[0] + mat[4]); // (1,0)
+ yy = splashRound(mat[1] + mat[5]);
+ if (xx < xMin) {
+ xMin = xx;
+ } else if (xx > xMax) {
+ xMax = xx;
+ }
+ if (yy < yMin) {
+ yMin = yy;
+ } else if (yy > yMax) {
+ yMax = yy;
+ }
+ xx = splashRound(mat[2] + mat[4]); // (0,1)
+ yy = splashRound(mat[3] + mat[5]);
+ if (xx < xMin) {
+ xMin = xx;
+ } else if (xx > xMax) {
+ xMax = xx;
+ }
+ if (yy < yMin) {
+ yMin = yy;
+ } else if (yy > yMax) {
+ yMax = yy;
+ }
+ xx = splashRound(mat[0] + mat[2] + mat[4]); // (1,1)
+ yy = splashRound(mat[1] + mat[3] + mat[5]);
+ if (xx < xMin) {
+ xMin = xx;
+ } else if (xx > xMax) {
+ xMax = xx;
+ }
+ if (yy < yMin) {
+ yMin = yy;
+ } else if (yy > yMax) {
+ yMax = yy;
+ }
+ if (xMax <= xMin) {
+ xMax = xMin + 1;
+ }
+ if (yMax <= yMin) {
+ yMax = yMin + 1;
+ }
+ }
+ SplashClipResult clipRes =
+ state->clip->testRect(xMin, yMin, xMax - 1, yMax - 1,
+ state->strokeAdjust);
+ // If the scaled mask is much wider and/or taller than the clip
+ // region, we use the "arbitrary" scaling path, to avoid a
+ // potentially very slow loop in the flips-only path (which scans
+ // the full width and height of the scaled mask, regardless of the
+ // clip region).
+ int clipW = state->clip->getXMaxI(state->strokeAdjust)
+ - state->clip->getXMinI(state->strokeAdjust);
+ int clipH = state->clip->getYMaxI(state->strokeAdjust)
+ - state->clip->getYMinI(state->strokeAdjust);
+ GBool veryLarge = ((xMax - xMin) / 8 > clipW && xMax - xMin > 1000) ||
+ ((yMax - yMin) / 8 > clipH && yMax - yMin > 1000);
+
+ //--- set up the SplashDrawImageMaskRowData object and the pipes
+ SplashDrawImageMaskRowData dd;
+ pipeInit(&dd.pipe, state->fillPattern,
+ (Guchar)splashRound(state->fillAlpha * 255),
+ gTrue, gFalse);
+
+ //--- choose the drawRow function
+ SplashDrawImageMaskRowFunc drawRowFunc;
+ if (clipRes == splashClipAllInside) {
+ drawRowFunc = &Splash::drawImageMaskRowNoClip;
+ } else {
+ if (antialias) {
+ drawRowFunc = &Splash::drawImageMaskRowClipAA;
+ } else {
+ drawRowFunc = &Splash::drawImageMaskRowClipNoAA;
+ }
+ }
+
+ //--- horizontal/vertical flips only
+ if (flipsOnly && !veryLarge) {
+ if (clipRes != splashClipAllOutside) {
+ int scaledWidth = xMax - xMin;
+ int scaledHeight = yMax - yMin;
+ ImageMaskScaler scaler(src, srcData, w, h,
+ scaledWidth, scaledHeight, interpolate, antialias);
+ Guchar *tmpLine = NULL;
+ if (horizFlip) {
+ tmpLine = (Guchar *)gmalloc(scaledWidth);
+ }
+ if (vertFlip) {
+ if (horizFlip) { // bottom-up, mirrored
+ for (int y = 0; y < scaledHeight; ++y) {
+ scaler.nextLine();
+ mirrorImageMaskRow(scaler.data(), tmpLine, scaledWidth);
+ (this->*drawRowFunc)(&dd, tmpLine,
+ xMin, yMax - 1 - y, scaledWidth);
+ }
+ } else { // bottom-up
+ for (int y = 0; y < scaledHeight; ++y) {
+ scaler.nextLine();
+ (this->*drawRowFunc)(&dd, scaler.data(),
+ xMin, yMax - 1 - y, scaledWidth);
+ }
+ }
+ } else {
+ if (horizFlip) { // top-down, mirrored
+ for (int y = 0; y < scaledHeight; ++y) {
+ scaler.nextLine();
+ mirrorImageMaskRow(scaler.data(), tmpLine, scaledWidth);
+ (this->*drawRowFunc)(&dd, tmpLine,
+ xMin, yMin + y, scaledWidth);
+ }
+ } else { // top-down
+ for (int y = 0; y < scaledHeight; ++y) {
+ scaler.nextLine();
+ (this->*drawRowFunc)(&dd, scaler.data(),
+ xMin, yMin + y, scaledWidth);
+ }
+ }
+ }
+ gfree(tmpLine);
+ }
+
+ //--- 90/270 rotation
+ } else if (rot90Only && !veryLarge) {
+ if (clipRes != splashClipAllOutside) {
+
+ // scale the mask
+ int scaledWidth = yMax - yMin;
+ int scaledHeight = xMax - xMin;
+ ImageMaskScaler scaler(src, srcData, w, h,
+ scaledWidth, scaledHeight, interpolate, antialias);
+ Guchar *scaledMask = (Guchar *)gmallocn(scaledHeight, scaledWidth);
+ Guchar *ptr = scaledMask;
+ for (int y = 0; y < scaledHeight; ++y) {
+ scaler.nextLine();
+ memcpy(ptr, scaler.data(), scaledWidth);
+ ptr += scaledWidth;
+ }
+
+ // draw it
+ Guchar *tmpLine = (Guchar *)gmalloc(scaledHeight);
+ for (int y = 0; y < scaledWidth; ++y) {
+ if (vertFlip) {
+ ptr = scaledMask + (scaledWidth - 1 - y);
+ } else {
+ ptr = scaledMask + y;
+ }
+ if (horizFlip) {
+ ptr += (scaledHeight - 1) * scaledWidth;
+ for (int x = 0; x < scaledHeight; ++x) {
+ tmpLine[x] = *ptr;
+ ptr -= scaledWidth;
+ }
+ } else {
+ for (int x = 0; x < scaledHeight; ++x) {
+ tmpLine[x] = *ptr;
+ ptr += scaledWidth;
+ }
+ }
+ (this->*drawRowFunc)(&dd, tmpLine, xMin, yMin + y, scaledHeight);
+ }
+
+ gfree(tmpLine);
+ gfree(scaledMask);
+ }
+
+ //--- arbitrary transform
+ } else {
+ // estimate of size of scaled image
+ int scaledWidth = splashRound(splashSqrt(mat[0] * mat[0]
+ + mat[1] * mat[1]));
+ int scaledHeight = splashRound(splashSqrt(mat[2] * mat[2]
+ + mat[3] * mat[3]));
+ if (scaledWidth < 1) {
+ scaledWidth = 1;
+ }
+ if (scaledHeight < 1) {
+ scaledHeight = 1;
+ }
+ GBool downscaling = gTrue;
+ if (veryLarge || (scaledWidth >= w && scaledHeight >= h)) {
+ downscaling = gFalse;
+ scaledWidth = w;
+ scaledHeight = h;
+ }
+
+ // compute mapping from device space to scaled image space
+ SplashCoord mat1[6];
+ mat1[0] = mat[0] / scaledWidth;
+ mat1[1] = mat[1] / scaledWidth;
+ mat1[2] = mat[2] / scaledHeight;
+ mat1[3] = mat[3] / scaledHeight;
+ mat1[4] = mat[4];
+ mat1[5] = mat[5];
+ SplashCoord det = mat1[0] * mat1[3] - mat1[1] * mat1[2];
+ if (splashAbs(det) < 1e-6) {
+ // this should be caught by the singular matrix check in drawImage
+ return splashErrSingularMatrix;
+ }
+ SplashCoord invMat[6];
+ invMat[0] = mat1[3] / det;
+ invMat[1] = -mat1[1] / det;
+ invMat[2] = -mat1[2] / det;
+ invMat[3] = mat1[0] / det;
+ // the extra "+ 0.5 * (...)" terms are here because the
+ // drawImageArbitrary(No)Interp functions multiply by pixel
+ // centers, (x + 0.5, y + 0.5)
+ invMat[4] = (mat1[2] * mat1[5] - mat1[3] * mat1[4]) / det
+ + (invMat[0] + invMat[2]) * 0.5;
+ invMat[5] = (mat1[1] * mat1[4] - mat1[0] * mat1[5]) / det
+ + (invMat[1] + invMat[3]) * 0.5;
+
+ // if downscaling: store the downscaled image mask
+ // if upscaling: store the unscaled image mask
+ Guchar *scaledMask = (Guchar *)gmallocn(scaledHeight, scaledWidth);
+ if (downscaling) {
+ ImageMaskScaler scaler(src, srcData, w, h,
+ scaledWidth, scaledHeight, interpolate, antialias);
+ Guchar *ptr = scaledMask;
+ for (int y = 0; y < scaledHeight; ++y) {
+ scaler.nextLine();
+ memcpy(ptr, scaler.data(), scaledWidth);
+ ptr += scaledWidth;
+ }
+ } else {
+ Guchar *ptr = scaledMask;
+ for (int y = 0; y < scaledHeight; ++y) {
+ (*src)(srcData, ptr);
+ for (int x = 0; x < scaledWidth; ++x) {
+ *ptr = (Guchar)(*ptr * 255);
+ ++ptr;
+ }
+ }
+ }
+
+ // draw it
+ if (interpolate && antialias) {
+ drawImageMaskArbitraryInterp(scaledMask,
+ &dd, drawRowFunc, invMat,
+ scaledWidth, scaledHeight,
+ xMin, yMin, xMax, yMax);
+ } else {
+ drawImageMaskArbitraryNoInterp(scaledMask,
+ &dd, drawRowFunc, invMat,
+ scaledWidth, scaledHeight,
+ xMin, yMin, xMax, yMax);
+ }
+
+ // free the downscaled/unscaled image
+ gfree(scaledMask);
+ }
+
+ return splashOk;
+}
+
+void Splash::drawImageMaskArbitraryNoInterp(
+ Guchar *scaledMask,
+ SplashDrawImageMaskRowData *dd,
+ SplashDrawImageMaskRowFunc drawRowFunc,
+ SplashCoord *invMat,
+ int scaledWidth, int scaledHeight,
+ int xMin, int yMin, int xMax, int yMax) {
+ int tt = state->clip->getXMinI(state->strokeAdjust);
+ if (tt > xMin) {
+ xMin = tt;
+ }
+ tt = state->clip->getXMaxI(state->strokeAdjust) + 1;
+ if (tt < xMax) {
+ xMax = tt;
+ }
+ tt = state->clip->getYMinI(state->strokeAdjust);
+ if (tt > yMin) {
+ yMin = tt;
+ }
+ tt = state->clip->getYMaxI(state->strokeAdjust) + 1;
+ if (tt < yMax) {
+ yMax = tt;
+ }
+ if (xMax <= xMin || yMax <= yMin) {
+ return;
+ }
+
+ Guchar *buf = (Guchar *)gmalloc(xMax - xMin);
+
+ for (int y = yMin; y < yMax; ++y) {
+ int rowMin = xMax;
+ int rowMax = 0;
+ for (int x = xMin; x < xMax; ++x) {
+ // note: invMat includes a "+0.5" factor so that this is really
+ // a multiply by (x+0.5, y+0.5)
+ int xx = splashFloor((SplashCoord)x * invMat[0]
+ + (SplashCoord)y * invMat[2] + invMat[4]);
+ int yy = splashFloor((SplashCoord)x * invMat[1]
+ + (SplashCoord)y * invMat[3] + invMat[5]);
+ if (xx >= 0 && xx < scaledWidth &&
+ yy >= 0 && yy < scaledHeight) {
+ Guchar *p = scaledMask + (yy * scaledWidth + xx);
+ Guchar *q = buf + (x - xMin);
+ *q = *p;
+ if (x < rowMin) {
+ rowMin = x;
+ }
+ rowMax = x + 1;
+ }
+ }
+ if (rowMin < rowMax) {
+ (this->*drawRowFunc)(dd, buf + (rowMin - xMin),
+ rowMin, y, rowMax - rowMin);
+ }
+ }
+
+ gfree(buf);
+}
+
+void Splash::drawImageMaskArbitraryInterp(
+ Guchar *scaledMask,
+ SplashDrawImageMaskRowData *dd,
+ SplashDrawImageMaskRowFunc drawRowFunc,
+ SplashCoord *invMat,
+ int scaledWidth, int scaledHeight,
+ int xMin, int yMin, int xMax, int yMax) {
+ int tt = state->clip->getXMinI(state->strokeAdjust);
+ if (tt > xMin) {
+ xMin = tt;
+ }
+ tt = state->clip->getXMaxI(state->strokeAdjust) + 1;
+ if (tt < xMax) {
+ xMax = tt;
+ }
+ tt = state->clip->getYMinI(state->strokeAdjust);
+ if (tt > yMin) {
+ yMin = tt;
+ }
+ tt = state->clip->getYMaxI(state->strokeAdjust) + 1;
+ if (tt < yMax) {
+ yMax = tt;
+ }
+ if (xMax <= xMin || yMax <= yMin) {
+ return;
+ }
+
+ Guchar *buf = (Guchar *)gmalloc(xMax - xMin);
+
+ for (int y = yMin; y < yMax; ++y) {
+ int rowMin = xMax;
+ int rowMax = 0;
+ for (int x = xMin; x < xMax; ++x) {
+ // note: invMat includes a "+0.5" factor so that this is really
+ // a multiply by (x+0.5, y+0.5)
+ SplashCoord xs = (SplashCoord)x * invMat[0]
+ + (SplashCoord)y * invMat[2] + invMat[4];
+ SplashCoord ys = (SplashCoord)x * invMat[1]
+ + (SplashCoord)y * invMat[3] + invMat[5];
+ int x0 = splashFloor(xs - 0.5);
+ int x1 = x0 + 1;
+ int y0 = splashFloor(ys - 0.5);
+ int y1 = y0 + 1;
+ if (x1 >= 0 && x0 < scaledWidth && y1 >= 0 && y0 < scaledHeight) {
+ SplashCoord sx0 = (SplashCoord)x1 + 0.5 - xs;
+ SplashCoord sx1 = (SplashCoord)1 - sx0;
+ SplashCoord sy0 = (SplashCoord)y1 + 0.5 - ys;
+ SplashCoord sy1 = (SplashCoord)1 - sy0;
+ if (x0 < 0) {
+ x0 = 0;
+ }
+ if (x1 >= scaledWidth) {
+ x1 = scaledWidth - 1;
+ }
+ if (y0 < 0) {
+ y0 = 0;
+ }
+ if (y1 >= scaledHeight) {
+ y1 = scaledHeight - 1;
+ }
+ Guchar *p00 = scaledMask + (y0 * scaledWidth + x0);
+ Guchar *p10 = scaledMask + (y0 * scaledWidth + x1);
+ Guchar *p01 = scaledMask + (y1 * scaledWidth + x0);
+ Guchar *p11 = scaledMask + (y1 * scaledWidth + x1);
+ Guchar *q = buf + (x - xMin);
+ *q = (Guchar)(int)(sx0 * (sy0 * (int)*p00 + sy1 * (int)*p01) +
+ sx1 * (sy0 * (int)*p10 + sy1 * (int)*p11));
+ if (x < rowMin) {
+ rowMin = x;
+ }
+ rowMax = x + 1;
+ }
+ }
+ if (rowMin < rowMax) {
+ (this->*drawRowFunc)(dd, buf + (rowMin - xMin),
+ rowMin, y, rowMax - rowMin);
+ }
+ }
+
+ gfree(buf);
+}
+
+void Splash::mirrorImageMaskRow(Guchar *maskIn, Guchar *maskOut, int width) {
+ Guchar *p, *q;
+
+ p = maskIn;
+ q = maskOut + (width - 1);
+ for (int i = 0; i < width; ++i) {
+ *q = *p;
+ ++p;
+ --q;
+ }
+}
+
+void Splash::drawImageMaskRowNoClip(SplashDrawImageMaskRowData *data,
+ Guchar *maskData,
+ int x, int y, int width) {
+ (this->*data->pipe.run)(&data->pipe, x, x + width - 1, y, maskData, NULL);
+}
+
+void Splash::drawImageMaskRowClipNoAA(SplashDrawImageMaskRowData *data,
+ Guchar *maskData,
+ int x, int y, int width) {
+ if (y < 0 || y >= bitmap->height) {
+ return;
+ }
+ if (x < 0) {
+ maskData -= x;
+ width += x;
+ x = 0;
+ }
+ if (x + width > bitmap->width) {
+ width = bitmap->width - x;
+ }
+ if (width <= 0) {
+ return;
+ }
+ memcpy(scanBuf + x, maskData, width);
+ state->clip->clipSpanBinary(scanBuf, y, x, x + width - 1,
+ state->strokeAdjust);
+ (this->*data->pipe.run)(&data->pipe, x, x + width - 1, y,
+ scanBuf + x, NULL);
+}
+
+void Splash::drawImageMaskRowClipAA(SplashDrawImageMaskRowData *data,
+ Guchar *maskData,
+ int x, int y, int width) {
+ if (y < 0 || y >= bitmap->height) {
+ return;
+ }
+ if (x < 0) {
+ maskData -= x;
+ width += x;
+ x = 0;
+ }
+ if (x + width > bitmap->width) {
+ width = bitmap->width - x;
+ }
+ if (width <= 0) {
+ return;
+ }
+ memcpy(scanBuf + x, maskData, width);
+ state->clip->clipSpan(scanBuf, y, x, x + width - 1, state->strokeAdjust);
+ (this->*data->pipe.run)(&data->pipe, x, x + width - 1, y,
+ scanBuf + x, NULL);
+}
+
+struct SplashDrawImageRowData {
+ int nComps;
+ GBool srcAlpha;
+ SplashPipe pipe;
+};
+
+SplashError Splash::drawImage(GString *imageTag,
+ SplashImageSource src, void *srcData,
+ SplashColorMode srcMode, GBool srcAlpha,
+ int w, int h, SplashCoord *mat,
+ GBool interpolate) {
+ if (debugMode) {
+ printf("drawImage: srcMode=%d srcAlpha=%d w=%d h=%d mat=[%.2f %.2f %.2f %.2f %.2f %.2f]\n",
+ srcMode, srcAlpha, w, h, (double)mat[0], (double)mat[1], (double)mat[2],
+ (double)mat[3], (double)mat[4], (double)mat[5]);
+ }
+
+ //--- check color modes
+ GBool ok = gFalse;
+ int nComps = 0;
+ switch (bitmap->mode) {
+ case splashModeMono1:
+ case splashModeMono8:
+ ok = srcMode == splashModeMono8;
+ nComps = 1;
+ break;
+ case splashModeRGB8:
+ case splashModeBGR8:
+ ok = srcMode == splashModeRGB8;
+ nComps = 3;
+ break;
+#if SPLASH_CMYK
+ case splashModeCMYK8:
+ ok = srcMode == splashModeCMYK8;
+ nComps = 4;
+ break;
+#endif
+ default:
+ ok = gFalse;
+ break;
+ }
+ if (!ok) {
+ return splashErrModeMismatch;
+ }
+
+ //--- check for singular matrix
+ if (!splashCheckDet(mat[0], mat[1], mat[2], mat[3], 0.000001)) {
+ return splashErrSingularMatrix;
+ }
+
+ //--- compute image bbox, check clipping
+ GBool flipsOnly = splashAbs(mat[1]) <= 0.0001 && splashAbs(mat[2]) <= 0.0001;
+ GBool rot90Only = splashAbs(mat[0]) <= 0.0001 && splashAbs(mat[3]) <= 0.0001;
+ GBool horizFlip = gFalse;
+ GBool vertFlip = gFalse;
+ int xMin, yMin, xMax, yMax;
+ if (flipsOnly) {
+ horizFlip = mat[0] < 0;
+ vertFlip = mat[3] < 0;
+ if (horizFlip) {
+ getImageBounds(mat[0] + mat[4], mat[4], &xMin, &xMax);
+ } else {
+ getImageBounds(mat[4], mat[0] + mat[4], &xMin, &xMax);
+ }
+ if (vertFlip) {
+ getImageBounds(mat[3] + mat[5], mat[5], &yMin, &yMax);
+ } else {
+ getImageBounds(mat[5], mat[3] + mat[5], &yMin, &yMax);
+ }
+ } else if (rot90Only) {
+ horizFlip = mat[2] < 0;
+ vertFlip = mat[1] < 0;
+ if (horizFlip) {
+ getImageBounds(mat[2] + mat[4], mat[4], &xMin, &xMax);
+ } else {
+ getImageBounds(mat[4], mat[2] + mat[4], &xMin, &xMax);
+ }
+ if (vertFlip) {
+ getImageBounds(mat[1] + mat[5], mat[5], &yMin, &yMax);
+ } else {
+ getImageBounds(mat[5], mat[1] + mat[5], &yMin, &yMax);
+ }
+ } else {
+ int xx = splashRound(mat[4]); // (0,0)
+ int yy = splashRound(mat[5]);
+ xMin = xMax = xx;
+ yMin = yMax = yy;
+ xx = splashRound(mat[0] + mat[4]); // (1,0)
+ yy = splashRound(mat[1] + mat[5]);
+ if (xx < xMin) {
+ xMin = xx;
+ } else if (xx > xMax) {
+ xMax = xx;
+ }
+ if (yy < yMin) {
+ yMin = yy;
+ } else if (yy > yMax) {
+ yMax = yy;
+ }
+ xx = splashRound(mat[2] + mat[4]); // (0,1)
+ yy = splashRound(mat[3] + mat[5]);
+ if (xx < xMin) {
+ xMin = xx;
+ } else if (xx > xMax) {
+ xMax = xx;
+ }
+ if (yy < yMin) {
+ yMin = yy;
+ } else if (yy > yMax) {
+ yMax = yy;
+ }
+ xx = splashRound(mat[0] + mat[2] + mat[4]); // (1,1)
+ yy = splashRound(mat[1] + mat[3] + mat[5]);
+ if (xx < xMin) {
+ xMin = xx;
+ } else if (xx > xMax) {
+ xMax = xx;
+ }
+ if (yy < yMin) {
+ yMin = yy;
+ } else if (yy > yMax) {
+ yMax = yy;
+ }
+ if (xMax <= xMin) {
+ xMax = xMin + 1;
+ }
+ if (yMax <= yMin) {
+ yMax = yMin + 1;
+ }
+ }
+ SplashClipResult clipRes =
+ state->clip->testRect(xMin, yMin, xMax - 1, yMax - 1,
+ state->strokeAdjust);
+ // If the scaled image is much wider and/or taller than the clip
+ // region, we use the arbitrary transform path, to avoid a
+ // potentially very slow loop in the flips-only path (which scans
+ // the full width and height of the scaled image, regardless of the
+ // clip region).
+ int clipW = state->clip->getXMaxI(state->strokeAdjust)
+ - state->clip->getXMinI(state->strokeAdjust);
+ int clipH = state->clip->getYMaxI(state->strokeAdjust)
+ - state->clip->getYMinI(state->strokeAdjust);
+ GBool veryLarge = ((xMax - xMin) / 8 > clipW && xMax - xMin > 1000) ||
+ ((yMax - yMin) / 8 > clipH && yMax - yMin > 1000);
+
+ //--- set up the SplashDrawImageRowData object and the pipes
+ SplashDrawImageRowData dd;
+ dd.nComps = nComps;
+ dd.srcAlpha = srcAlpha;
+ pipeInit(&dd.pipe, NULL,
+ (Guchar)splashRound(state->fillAlpha * 255),
+ clipRes != splashClipAllInside || srcAlpha,
+ gFalse);
+
+ //--- choose the drawRow function
+ SplashDrawImageRowFunc drawRowFunc;
+ if (clipRes == splashClipAllInside) {
+ if (srcAlpha) {
+ drawRowFunc = &Splash::drawImageRowNoClipAlpha;
+ } else {
+ drawRowFunc = &Splash::drawImageRowNoClipNoAlpha;
+ }
+ } else {
+ if (srcAlpha) {
+ if (vectorAntialias) {
+ drawRowFunc = &Splash::drawImageRowClipAlphaAA;
+ } else {
+ drawRowFunc = &Splash::drawImageRowClipAlphaNoAA;
+ }
+ } else {
+ if (vectorAntialias) {
+ drawRowFunc = &Splash::drawImageRowClipNoAlphaAA;
+ } else {
+ drawRowFunc = &Splash::drawImageRowClipNoAlphaNoAA;
+ }
+ }
+ }
+
+ //--- horizontal/vertical flips only
+ if (flipsOnly && !veryLarge) {
+ if (clipRes != splashClipAllOutside) {
+ int scaledWidth = xMax - xMin;
+ int scaledHeight = yMax - yMin;
+ ImageScaler *scaler = getImageScaler(imageTag, src, srcData,
+ w, h, nComps,
+ scaledWidth, scaledHeight,
+ srcMode, srcAlpha, interpolate);
+ Guchar *tmpLine = NULL;
+ Guchar *tmpAlphaLine = NULL;
+ if (horizFlip) {
+ tmpLine = (Guchar *)gmallocn(scaledWidth, nComps);
+ if (srcAlpha) {
+ tmpAlphaLine = (Guchar *)gmalloc(scaledWidth);
+ }
+ }
+ if (vertFlip) {
+ if (horizFlip) { // bottom-up, mirrored
+ for (int y = 0; y < scaledHeight; ++y) {
+ scaler->nextLine();
+ mirrorImageRow(scaler->colorData(), scaler->alphaData(),
+ tmpLine, tmpAlphaLine,
+ scaledWidth, nComps, srcAlpha);
+ (this->*drawRowFunc)(&dd, tmpLine, tmpAlphaLine,
+ xMin, yMax - 1 - y, scaledWidth);
+ }
+ } else { // bottom-up
+ for (int y = 0; y < scaledHeight; ++y) {
+ scaler->nextLine();
+ (this->*drawRowFunc)(&dd, scaler->colorData(), scaler->alphaData(),
+ xMin, yMax - 1 - y, scaledWidth);
+ }
+ }
+ } else {
+ if (horizFlip) { // top-down, mirrored
+ for (int y = 0; y < scaledHeight; ++y) {
+ scaler->nextLine();
+ mirrorImageRow(scaler->colorData(), scaler->alphaData(),
+ tmpLine, tmpAlphaLine,
+ scaledWidth, nComps, srcAlpha);
+ (this->*drawRowFunc)(&dd, tmpLine, tmpAlphaLine,
+ xMin, yMin + y, scaledWidth);
+ }
+ } else { // top-down
+ for (int y = 0; y < scaledHeight; ++y) {
+ scaler->nextLine();
+ (this->*drawRowFunc)(&dd, scaler->colorData(), scaler->alphaData(),
+ xMin, yMin + y, scaledWidth);
+ }
+ }
+ }
+ gfree(tmpLine);
+ gfree(tmpAlphaLine);
+ delete scaler;
+ }
+
+ //--- 90/270 rotation
+ } else if (rot90Only && !veryLarge) {
+ if (clipRes != splashClipAllOutside) {
+
+ // scale the image
+ int scaledWidth = yMax - yMin;
+ int scaledHeight = xMax - xMin;
+ Guchar *scaledColor, *scaledAlpha;
+ GBool freeScaledImage;
+ getScaledImage(imageTag, src, srcData, w, h, nComps,
+ scaledWidth, scaledHeight, srcMode, srcAlpha, interpolate,
+ &scaledColor, &scaledAlpha, &freeScaledImage);
+
+ // draw it
+ Guchar *tmpLine = (Guchar *)gmallocn(scaledHeight, nComps);
+ Guchar *tmpAlphaLine = NULL;
+ if (srcAlpha) {
+ tmpAlphaLine = (Guchar *)gmalloc(scaledHeight);
+ }
+ for (int y = 0; y < scaledWidth; ++y) {
+ Guchar *ptr, *alphaPtr;
+ if (vertFlip) {
+ ptr = scaledColor + (scaledWidth - 1 - y) * nComps;
+ if (srcAlpha) {
+ alphaPtr = scaledAlpha + (scaledWidth - 1 - y);
+ }
+ } else {
+ ptr = scaledColor + y * nComps;
+ if (srcAlpha) {
+ alphaPtr = scaledAlpha + y;
+ }
+ }
+ if (horizFlip) {
+ ptr += (scaledHeight - 1) * scaledWidth * nComps;
+ Guchar *q = tmpLine;
+ for (int x = 0; x < scaledHeight; ++x) {
+ for (int i = 0; i < nComps; ++i) {
+ *q++ = ptr[i];
+ }
+ ptr -= scaledWidth * nComps;
+ }
+ if (srcAlpha) {
+ alphaPtr += (scaledHeight - 1) * scaledWidth;
+ q = tmpAlphaLine;
+ for (int x = 0; x < scaledHeight; ++x) {
+ *q++ = *alphaPtr;
+ alphaPtr -= scaledWidth;
+ }
+ }
+ } else {
+ Guchar *q = tmpLine;
+ for (int x = 0; x < scaledHeight; ++x) {
+ for (int i = 0; i < nComps; ++i) {
+ *q++ = ptr[i];
+ }
+ ptr += scaledWidth * nComps;
+ }
+ if (srcAlpha) {
+ q = tmpAlphaLine;
+ for (int x = 0; x < scaledHeight; ++x) {
+ *q++ = *alphaPtr;
+ alphaPtr += scaledWidth;
+ }
+ }
+ }
+ (this->*drawRowFunc)(&dd, tmpLine, tmpAlphaLine,
+ xMin, yMin + y, scaledHeight);
+ }
+
+ gfree(tmpLine);
+ gfree(tmpAlphaLine);
+ if (freeScaledImage) {
+ gfree(scaledColor);
+ gfree(scaledAlpha);
+ }
+ }
+
+ //--- arbitrary transform
+ } else {
+ // estimate of size of scaled image
+ int scaledWidth = splashRound(splashSqrt(mat[0] * mat[0]
+ + mat[1] * mat[1]));
+ int scaledHeight = splashRound(splashSqrt(mat[2] * mat[2]
+ + mat[3] * mat[3]));
+ if (scaledWidth < 1) {
+ scaledWidth = 1;
+ }
+ if (scaledHeight < 1) {
+ scaledHeight = 1;
+ }
+ if (veryLarge || (scaledWidth >= w && scaledHeight >= h)) {
+ scaledWidth = w;
+ scaledHeight = h;
+ }
+
+ // compute mapping from device space to scaled image space
+ SplashCoord mat1[6];
+ mat1[0] = mat[0] / scaledWidth;
+ mat1[1] = mat[1] / scaledWidth;
+ mat1[2] = mat[2] / scaledHeight;
+ mat1[3] = mat[3] / scaledHeight;
+ mat1[4] = mat[4];
+ mat1[5] = mat[5];
+ SplashCoord det = mat1[0] * mat1[3] - mat1[1] * mat1[2];
+ if (splashAbs(det) < 1e-6) {
+ // this should be caught by the singular matrix check in drawImage
+ return splashErrSingularMatrix;
+ }
+ SplashCoord invMat[6];
+ invMat[0] = mat1[3] / det;
+ invMat[1] = -mat1[1] / det;
+ invMat[2] = -mat1[2] / det;
+ invMat[3] = mat1[0] / det;
+ // the extra "+ 0.5 * (...)" terms are here because the
+ // drawImageArbitrary(No)Interp functions multiply by pixel
+ // centers, (x + 0.5, y + 0.5)
+ invMat[4] = (mat1[2] * mat1[5] - mat1[3] * mat1[4]) / det
+ + (invMat[0] + invMat[2]) * 0.5;
+ invMat[5] = (mat1[1] * mat1[4] - mat1[0] * mat1[5]) / det
+ + (invMat[1] + invMat[3]) * 0.5;
+
+ Guchar *scaledColor, *scaledAlpha;
+ GBool freeScaledImage;
+ getScaledImage(imageTag, src, srcData, w, h, nComps,
+ scaledWidth, scaledHeight, srcMode, srcAlpha, interpolate,
+ &scaledColor, &scaledAlpha, &freeScaledImage);
+
+ // draw it
+ if (interpolate) {
+ drawImageArbitraryInterp(scaledColor, scaledAlpha,
+ &dd, drawRowFunc, invMat,
+ scaledWidth, scaledHeight,
+ xMin, yMin, xMax, yMax,
+ nComps, srcAlpha);
+ } else {
+ drawImageArbitraryNoInterp(scaledColor, scaledAlpha,
+ &dd, drawRowFunc, invMat,
+ scaledWidth, scaledHeight,
+ xMin, yMin, xMax, yMax,
+ nComps, srcAlpha);
+ }
+
+ // free the downscaled/unscaled image
+ if (freeScaledImage) {
+ gfree(scaledColor);
+ gfree(scaledAlpha);
+ }
+ }
+
+ return splashOk;
+}
+
+ImageScaler *Splash::getImageScaler(GString *imageTag,
+ SplashImageSource src, void *srcData,
+ int w, int h, int nComps,
+ int scaledWidth, int scaledHeight,
+ SplashColorMode srcMode,
+ GBool srcAlpha, GBool interpolate) {
+ // Notes:
+ //
+ // * If the scaled image is more than 8 Mpixels, we don't cache it.
+ //
+ // * Caching is done on the third consecutive use (second
+ // consecutive reuse) of an image; this avoids overhead on the
+ // common case of single-use images.
+
+ if (scaledWidth < 8000000 / scaledHeight &&
+ imageCache->match(imageTag, scaledWidth, scaledHeight,
+ srcMode, srcAlpha, interpolate)) {
+ if (imageCache->colorData) {
+ return new ReplayImageScaler(nComps, srcAlpha, scaledWidth,
+ imageCache->colorData,
+ imageCache->alphaData);
+ } else {
+ int lineSize;
+ if (scaledWidth < INT_MAX / nComps) {
+ lineSize = scaledWidth * nComps;
+ } else {
+ lineSize = -1;
+ }
+ imageCache->colorData = (Guchar *)gmallocn(scaledHeight, lineSize);
+ if (srcAlpha) {
+ imageCache->alphaData = (Guchar *)gmallocn(scaledHeight, scaledWidth);
+ }
+ return new SavingImageScaler(src, srcData,
+ w, h, nComps, srcAlpha,
+ scaledWidth, scaledHeight,
+ interpolate,
+ imageCache->colorData,
+ imageCache->alphaData);
+ }
+ } else {
+ imageCache->reset(imageTag, scaledWidth, scaledHeight,
+ srcMode, srcAlpha, interpolate);
+ return new BasicImageScaler(src, srcData,
+ w, h, nComps, srcAlpha,
+ scaledWidth, scaledHeight,
+ interpolate);
+ }
+}
+
+void Splash::getScaledImage(GString *imageTag,
+ SplashImageSource src, void *srcData,
+ int w, int h, int nComps,
+ int scaledWidth, int scaledHeight,
+ SplashColorMode srcMode,
+ GBool srcAlpha, GBool interpolate,
+ Guchar **scaledColor, Guchar **scaledAlpha,
+ GBool *freeScaledImage) {
+ // Notes:
+ //
+ // * If the scaled image is more than 8 Mpixels, we don't cache it.
+ //
+ // * This buffers the whole image anyway, so there's no reason to
+ // skip caching on the first reuse.
+
+ if (scaledWidth >= 8000000 / scaledHeight) {
+ int lineSize;
+ if (scaledWidth < INT_MAX / nComps) {
+ lineSize = scaledWidth * nComps;
+ } else {
+ lineSize = -1;
+ }
+ *scaledColor = (Guchar *)gmallocn(scaledHeight, lineSize);
+ if (srcAlpha) {
+ *scaledAlpha = (Guchar *)gmallocn(scaledHeight, scaledWidth);
+ } else {
+ *scaledAlpha = NULL;
+ }
+ *freeScaledImage = gTrue;
+ if (scaledWidth == w && scaledHeight == h) {
+ Guchar *colorPtr = *scaledColor;
+ Guchar *alphaPtr = *scaledAlpha;
+ for (int y = 0; y < scaledHeight; ++y) {
+ (*src)(srcData, colorPtr, alphaPtr);
+ colorPtr += scaledWidth * nComps;
+ if (srcAlpha) {
+ alphaPtr += scaledWidth;
+ }
+ }
+ } else {
+ BasicImageScaler scaler(src, srcData, w, h, nComps, srcAlpha,
+ scaledWidth, scaledHeight, interpolate);
+ Guchar *colorPtr = *scaledColor;
+ Guchar *alphaPtr = *scaledAlpha;
+ for (int y = 0; y < scaledHeight; ++y) {
+ scaler.nextLine();
+ memcpy(colorPtr, scaler.colorData(), scaledWidth * nComps);
+ colorPtr += scaledWidth * nComps;
+ if (srcAlpha) {
+ memcpy(alphaPtr, scaler.alphaData(), scaledWidth);
+ alphaPtr += scaledWidth;
+ }
+ }
+ }
+ } else {
+ if (!imageCache->match(imageTag, scaledWidth, scaledHeight,
+ srcMode, srcAlpha, interpolate) ||
+ !imageCache->colorData) {
+ imageCache->reset(imageTag, scaledWidth, scaledHeight,
+ srcMode, srcAlpha, interpolate);
+ int lineSize;
+ if (scaledWidth < INT_MAX / nComps) {
+ lineSize = scaledWidth * nComps;
+ } else {
+ lineSize = -1;
+ }
+ imageCache->colorData = (Guchar *)gmallocn(scaledHeight, lineSize);
+ if (srcAlpha) {
+ imageCache->alphaData = (Guchar *)gmallocn(scaledHeight, scaledWidth);
+ }
+ if (scaledWidth == w && scaledHeight == h) {
+ Guchar *colorPtr = imageCache->colorData;
+ Guchar *alphaPtr = imageCache->alphaData;
+ for (int y = 0; y < scaledHeight; ++y) {
+ (*src)(srcData, colorPtr, alphaPtr);
+ colorPtr += scaledWidth * nComps;
+ if (srcAlpha) {
+ alphaPtr += scaledWidth;
+ }
+ }
+ } else {
+ SavingImageScaler scaler(src, srcData, w, h, nComps, srcAlpha,
+ scaledWidth, scaledHeight, interpolate,
+ imageCache->colorData, imageCache->alphaData);
+ Guchar *colorPtr = imageCache->colorData;
+ Guchar *alphaPtr = imageCache->alphaData;
+ for (int y = 0; y < scaledHeight; ++y) {
+ scaler.nextLine();
+ memcpy(colorPtr, scaler.colorData(), scaledWidth * nComps);
+ colorPtr += scaledWidth * nComps;
+ if (srcAlpha) {
+ memcpy(alphaPtr, scaler.alphaData(), scaledWidth);
+ alphaPtr += scaledWidth;
+ }
+ }
+ }
+ }
+ *scaledColor = imageCache->colorData;
+ *scaledAlpha = imageCache->alphaData;
+ *freeScaledImage = gFalse;
+ }
+}
+
+void Splash::drawImageArbitraryNoInterp(Guchar *scaledColor,
+ Guchar *scaledAlpha,
+ SplashDrawImageRowData *dd,
+ SplashDrawImageRowFunc drawRowFunc,
+ SplashCoord *invMat,
+ int scaledWidth, int scaledHeight,
+ int xMin, int yMin, int xMax, int yMax,
+ int nComps, GBool srcAlpha) {
+ int tt = state->clip->getXMinI(state->strokeAdjust);
+ if (tt > xMin) {
+ xMin = tt;
+ }
+ tt = state->clip->getXMaxI(state->strokeAdjust) + 1;
+ if (tt < xMax) {
+ xMax = tt;
+ }
+ tt = state->clip->getYMinI(state->strokeAdjust);
+ if (tt > yMin) {
+ yMin = tt;
+ }
+ tt = state->clip->getYMaxI(state->strokeAdjust) + 1;
+ if (tt < yMax) {
+ yMax = tt;
+ }
+ if (xMax <= xMin || yMax <= yMin) {
+ return;
+ }
+
+ Guchar *colorBuf = (Guchar *)gmallocn(xMax - xMin, nComps);
+ Guchar *alphaBuf = NULL;
+ if (srcAlpha) {
+ alphaBuf = (Guchar *)gmalloc(xMax - xMin);
+ }
+
+ for (int y = yMin; y < yMax; ++y) {
+ int rowMin = xMax;
+ int rowMax = 0;
+ for (int x = xMin; x < xMax; ++x) {
+ // note: invMat includes a "+0.5" factor so that this is really
+ // a multiply by (x+0.5, y+0.5)
+ int xx = splashFloor((SplashCoord)x * invMat[0]
+ + (SplashCoord)y * invMat[2] + invMat[4]);
+ int yy = splashFloor((SplashCoord)x * invMat[1]
+ + (SplashCoord)y * invMat[3] + invMat[5]);
+ if (xx >= 0 && xx < scaledWidth &&
+ yy >= 0 && yy < scaledHeight) {
+ Guchar *p = scaledColor + (yy * scaledWidth + xx) * nComps;
+ Guchar *q = colorBuf + (x - xMin) * nComps;
+ for (int i = 0; i < nComps; ++i) {
+ *q++ = *p++;
+ }
+ if (srcAlpha) {
+ alphaBuf[x - xMin] = scaledAlpha[yy * scaledWidth + xx];
+ }
+ if (x < rowMin) {
+ rowMin = x;
+ }
+ rowMax = x + 1;
+ }
+ }
+ if (rowMin < rowMax) {
+ (this->*drawRowFunc)(dd,
+ colorBuf + (rowMin - xMin) * nComps,
+ alphaBuf + (rowMin - xMin),
+ rowMin, y, rowMax - rowMin);
+ }
+ }
+
+ gfree(colorBuf);
+ gfree(alphaBuf);
+}
+
+void Splash::drawImageArbitraryInterp(Guchar *scaledColor, Guchar *scaledAlpha,
+ SplashDrawImageRowData *dd,
+ SplashDrawImageRowFunc drawRowFunc,
+ SplashCoord *invMat,
+ int scaledWidth, int scaledHeight,
+ int xMin, int yMin, int xMax, int yMax,
+ int nComps, GBool srcAlpha) {
+ int tt = state->clip->getXMinI(state->strokeAdjust);
+ if (tt > xMin) {
+ xMin = tt;
+ }
+ tt = state->clip->getXMaxI(state->strokeAdjust) + 1;
+ if (tt < xMax) {
+ xMax = tt;
+ }
+ tt = state->clip->getYMinI(state->strokeAdjust);
+ if (tt > yMin) {
+ yMin = tt;
+ }
+ tt = state->clip->getYMaxI(state->strokeAdjust) + 1;
+ if (tt < yMax) {
+ yMax = tt;
+ }
+ if (xMax <= xMin || yMax <= yMin) {
+ return;
+ }
+
+ Guchar *colorBuf = (Guchar *)gmallocn(xMax - xMin, nComps);
+ Guchar *alphaBuf = NULL;
+ if (srcAlpha) {
+ alphaBuf = (Guchar *)gmalloc(xMax - xMin);
+ }
+
+ for (int y = yMin; y < yMax; ++y) {
+ int rowMin = xMax;
+ int rowMax = 0;
+ for (int x = xMin; x < xMax; ++x) {
+ // note: invMat includes a "+0.5" factor so that this is really
+ // a multiply by (x+0.5, y+0.5)
+ SplashCoord xs = (SplashCoord)x * invMat[0]
+ + (SplashCoord)y * invMat[2] + invMat[4];
+ SplashCoord ys = (SplashCoord)x * invMat[1]
+ + (SplashCoord)y * invMat[3] + invMat[5];
+ int x0 = splashFloor(xs - 0.5);
+ int x1 = x0 + 1;
+ int y0 = splashFloor(ys - 0.5);
+ int y1 = y0 + 1;
+ if (x1 >= 0 && x0 < scaledWidth && y1 >= 0 && y0 < scaledHeight) {
+ SplashCoord sx0 = (SplashCoord)x1 + 0.5 - xs;
+ SplashCoord sx1 = (SplashCoord)1 - sx0;
+ SplashCoord sy0 = (SplashCoord)y1 + 0.5 - ys;
+ SplashCoord sy1 = (SplashCoord)1 - sy0;
+ if (x0 < 0) {
+ x0 = 0;
+ }
+ if (x1 >= scaledWidth) {
+ x1 = scaledWidth - 1;
+ }
+ if (y0 < 0) {
+ y0 = 0;
+ }
+ if (y1 >= scaledHeight) {
+ y1 = scaledHeight - 1;
+ }
+ Guchar *p00 = scaledColor + (y0 * scaledWidth + x0) * nComps;
+ Guchar *p10 = scaledColor + (y0 * scaledWidth + x1) * nComps;
+ Guchar *p01 = scaledColor + (y1 * scaledWidth + x0) * nComps;
+ Guchar *p11 = scaledColor + (y1 * scaledWidth + x1) * nComps;
+ Guchar *q = colorBuf + (x - xMin) * nComps;
+ for (int i = 0; i < nComps; ++i) {
+ *q++ = (Guchar)(int)(sx0 * (sy0 * (int)*p00++ + sy1 * (int)*p01++) +
+ sx1 * (sy0 * (int)*p10++ + sy1 * (int)*p11++));
+ }
+ if (srcAlpha) {
+ p00 = scaledAlpha + (y0 * scaledWidth + x0);
+ p10 = scaledAlpha + (y0 * scaledWidth + x1);
+ p01 = scaledAlpha + (y1 * scaledWidth + x0);
+ p11 = scaledAlpha + (y1 * scaledWidth + x1);
+ q = alphaBuf + (x - xMin);
+ *q = (Guchar)(int)(sx0 * (sy0 * (int)*p00 + sy1 * (int)*p01) +
+ sx1 * (sy0 * (int)*p10 + sy1 * (int)*p11));
+ }
+ if (x < rowMin) {
+ rowMin = x;
+ }
+ rowMax = x + 1;
+ }
+ }
+ if (rowMin < rowMax) {
+ (this->*drawRowFunc)(dd,
+ colorBuf + (rowMin - xMin) * nComps,
+ alphaBuf + (rowMin - xMin),
+ rowMin, y, rowMax - rowMin);
+ }
+ }
+
+ gfree(colorBuf);
+ gfree(alphaBuf);
+}
+
+void Splash::mirrorImageRow(Guchar *colorIn, Guchar *alphaIn,
+ Guchar *colorOut, Guchar *alphaOut,
+ int width, int nComps, GBool srcAlpha) {
+ Guchar *p, *q;
+
+ p = colorIn;
+ q = colorOut + (width - 1) * nComps;
+ for (int i = 0; i < width; ++i) {
+ for (int j = 0; j < nComps; ++j) {
+ q[j] = p[j];
+ }
+ p += nComps;
+ q -= nComps;
+ }
+
+ if (srcAlpha) {
+ p = alphaIn;
+ q = alphaOut + (width - 1);
+ for (int i = 0; i < width; ++i) {
+ *q = *p;
+ ++p;
+ --q;
+ }
+ }
+}
+
+void Splash::drawImageRowNoClipNoAlpha(SplashDrawImageRowData *data,
+ Guchar *colorData, Guchar *alphaData,
+ int x, int y, int width) {
+ (this->*data->pipe.run)(&data->pipe, x, x + width - 1, y, NULL, colorData);
+}
+
+void Splash::drawImageRowNoClipAlpha(SplashDrawImageRowData *data,
+ Guchar *colorData, Guchar *alphaData,
+ int x, int y, int width) {
+ (this->*data->pipe.run)(&data->pipe, x, x + width - 1, y,
+ alphaData, colorData);
+}
+
+void Splash::drawImageRowClipNoAlphaNoAA(SplashDrawImageRowData *data,
+ Guchar *colorData,
+ Guchar *alphaData,
+ int x, int y, int width) {
+ if (y < 0 || y >= bitmap->height) {
+ return;
+ }
+ if (x < 0) {
+ colorData -= x * data->nComps;
+ width += x;
+ x = 0;
+ }
+ if (x + width > bitmap->width) {
+ width = bitmap->width - x;
+ }
+ if (width <= 0) {
+ return;
+ }
+ memset(scanBuf + x, 0xff, width);
+ state->clip->clipSpanBinary(scanBuf, y, x, x + width - 1,
+ state->strokeAdjust);
+ (this->*data->pipe.run)(&data->pipe, x, x + width - 1, y,
+ scanBuf + x, colorData);
+}
+
+void Splash::drawImageRowClipNoAlphaAA(SplashDrawImageRowData *data,
+ Guchar *colorData,
+ Guchar *alphaData,
+ int x, int y, int width) {
+ if (y < 0 || y >= bitmap->height) {
+ return;
+ }
+ if (x < 0) {
+ colorData -= x * data->nComps;
+ width += x;
+ x = 0;
+ }
+ if (x + width > bitmap->width) {
+ width = bitmap->width - x;
+ }
+ if (width <= 0) {
+ return;
+ }
+ memset(scanBuf + x, 0xff, width);
+ state->clip->clipSpan(scanBuf, y, x, x + width - 1, state->strokeAdjust);
+ (this->*data->pipe.run)(&data->pipe, x, x + width - 1, y,
+ scanBuf + x, colorData);
+}
+
+void Splash::drawImageRowClipAlphaNoAA(SplashDrawImageRowData *data,
+ Guchar *colorData,
+ Guchar *alphaData,
+ int x, int y, int width) {
+ if (y < 0 || y >= bitmap->height) {
+ return;
+ }
+ if (x < 0) {
+ colorData -= x * data->nComps;
+ alphaData -= x;
+ width += x;
+ x = 0;
+ }
+ if (x + width > bitmap->width) {
+ width = bitmap->width - x;
+ }
+ if (width <= 0) {
+ return;
+ }
+ memcpy(scanBuf + x, alphaData, width);
+ state->clip->clipSpanBinary(scanBuf, y, x, x + width - 1,
+ state->strokeAdjust);
+ (this->*data->pipe.run)(&data->pipe, x, x + width - 1, y,
+ scanBuf + x, colorData);
+}
+
+void Splash::drawImageRowClipAlphaAA(SplashDrawImageRowData *data,
+ Guchar *colorData,
+ Guchar *alphaData,
+ int x, int y, int width) {
+ if (y < 0 || y >= bitmap->height) {
+ return;
+ }
+ if (x < 0) {
+ colorData -= x * data->nComps;
+ alphaData -= x;
+ width += x;
+ x = 0;
+ }
+ if (x + width > bitmap->width) {
+ width = bitmap->width - x;
+ }
+ if (width <= 0) {
+ return;
+ }
+ memcpy(scanBuf + x, alphaData, width);
+ state->clip->clipSpan(scanBuf, y, x, x + width - 1, state->strokeAdjust);
+ (this->*data->pipe.run)(&data->pipe, x, x + width - 1, y,
+ scanBuf + x, colorData);
+}
+
+SplashError Splash::composite(SplashBitmap *src, int xSrc, int ySrc,
+ int xDest, int yDest, int w, int h,
+ GBool noClip, GBool nonIsolated) {
+ SplashPipe pipe;
+ Guchar *mono1Ptr, *lineBuf, *linePtr;
+ Guchar mono1Mask, b;
+ int x0, x1, x, y0, y1, y, t;
+
+ if (!(src->mode == bitmap->mode ||
+ (src->mode == splashModeMono8 && bitmap->mode == splashModeMono1) ||
+ (src->mode == splashModeRGB8 && bitmap->mode == splashModeBGR8))) {
+ return splashErrModeMismatch;
+ }
+
+ pipeInit(&pipe, NULL,
+ (Guchar)splashRound(state->fillAlpha * 255),
+ !noClip || src->alpha != NULL, nonIsolated);
+ if (src->mode == splashModeMono1) {
+ // in mono1 mode, pipeRun expects the source to be in mono8
+ // format, so we need to extract the source color values into
+ // scanBuf, expanding them from mono1 to mono8
+ if (noClip) {
+ if (src->alpha) {
+ for (y = 0; y < h; ++y) {
+ mono1Ptr = src->data + (ySrc + y) * src->rowSize + (xSrc >> 3);
+ mono1Mask = (Guchar)(0x80 >> (xSrc & 7));
+ for (x = 0; x < w; ++x) {
+ scanBuf[x] = (*mono1Ptr & mono1Mask) ? 0xff : 0x00;
+ mono1Ptr += mono1Mask & 1;
+ mono1Mask = (Guchar)((mono1Mask << 7) | (mono1Mask >> 1));
+ }
+ // this uses shape instead of alpha, which isn't technically
+ // correct, but works out the same
+ (this->*pipe.run)(&pipe, xDest, xDest + w - 1, yDest + y,
+ src->alpha +
+ (ySrc + y) * src->alphaRowSize + xSrc,
+ scanBuf);
+ }
+ } else {
+ for (y = 0; y < h; ++y) {
+ mono1Ptr = src->data + (ySrc + y) * src->rowSize + (xSrc >> 3);
+ mono1Mask = (Guchar)(0x80 >> (xSrc & 7));
+ for (x = 0; x < w; ++x) {
+ scanBuf[x] = (*mono1Ptr & mono1Mask) ? 0xff : 0x00;
+ mono1Ptr += mono1Mask & 1;
+ mono1Mask = (Guchar)((mono1Mask << 7) | (mono1Mask >> 1));
+ }
+ (this->*pipe.run)(&pipe, xDest, xDest + w - 1, yDest + y,
+ NULL,
+ scanBuf);
+ }
+ }
+ } else {
+ x0 = xDest;
+ if ((t = state->clip->getXMinI(state->strokeAdjust)) > x0) {
+ x0 = t;
+ }
+ x1 = xDest + w;
+ if ((t = state->clip->getXMaxI(state->strokeAdjust) + 1) < x1) {
+ x1 = t;
+ }
+ y0 = yDest;
+ if ((t = state->clip->getYMinI(state->strokeAdjust)) > y0) {
+ y0 = t;
+ }
+ y1 = yDest + h;
+ if ((t = state->clip->getYMaxI(state->strokeAdjust) + 1) < y1) {
+ y1 = t;
+ }
+ if (x0 < x1 && y0 < y1) {
+ if (src->alpha) {
+ for (y = y0; y < y1; ++y) {
+ mono1Ptr = src->data
+ + (ySrc + y - yDest) * src->rowSize
+ + ((xSrc + x0 - xDest) >> 3);
+ mono1Mask = (Guchar)(0x80 >> ((xSrc + x0 - xDest) & 7));
+ for (x = x0; x < x1; ++x) {
+ scanBuf[x] = (*mono1Ptr & mono1Mask) ? 0xff : 0x00;
+ mono1Ptr += mono1Mask & 1;
+ mono1Mask = (Guchar)((mono1Mask << 7) | (mono1Mask >> 1));
+ }
+ memcpy(scanBuf2 + x0,
+ src->alpha + (ySrc + y - yDest) * src->alphaRowSize +
+ (xSrc + x0 - xDest),
+ x1 - x0);
+ if (!state->clip->clipSpanBinary(scanBuf2, y, x0, x1 - 1,
+ state->strokeAdjust)) {
+ continue;
+ }
+ // this uses shape instead of alpha, which isn't technically
+ // correct, but works out the same
+ (this->*pipe.run)(&pipe, x0, x1 - 1, y,
+ scanBuf2 + x0,
+ scanBuf + x0);
+ }
+ } else {
+ for (y = y0; y < y1; ++y) {
+ mono1Ptr = src->data
+ + (ySrc + y - yDest) * src->rowSize
+ + ((xSrc + x0 - xDest) >> 3);
+ mono1Mask = (Guchar)(0x80 >> ((xSrc + x0 - xDest) & 7));
+ for (x = x0; x < x1; ++x) {
+ scanBuf[x] = (*mono1Ptr & mono1Mask) ? 0xff : 0x00;
+ mono1Ptr += mono1Mask & 1;
+ mono1Mask = (Guchar)((mono1Mask << 7) | (mono1Mask >> 1));
+ }
+ memset(scanBuf2 + x0, 0xff, x1 - x0);
+ if (!state->clip->clipSpanBinary(scanBuf2, y, x0, x1 - 1,
+ state->strokeAdjust)) {
+ continue;
+ }
+ (this->*pipe.run)(&pipe, x0, x1 - 1, y,
+ scanBuf2 + x0,
+ scanBuf + x0);
+ }
+ }
+ }
+ }
+
+ } else if (src->mode == splashModeBGR8) {
+ // in BGR8 mode, pipeRun expects the source to be in RGB8 format,
+ // so we need to swap bytes
+ lineBuf = (Guchar *)gmallocn(w, 3);
+ if (noClip) {
+ if (src->alpha) {
+ for (y = 0; y < h; ++y) {
+ memcpy(lineBuf,
+ src->data + (ySrc + y) * src->rowSize + xSrc * 3,
+ w * 3);
+ for (x = 0, linePtr = lineBuf; x < w; ++x, linePtr += 3) {
+ b = linePtr[0];
+ linePtr[0] = linePtr[2];
+ linePtr[2] = b;
+ }
+ // this uses shape instead of alpha, which isn't technically
+ // correct, but works out the same
+ (this->*pipe.run)(&pipe, xDest, xDest + w - 1, yDest + y,
+ src->alpha +
+ (ySrc + y) * src->alphaRowSize + xSrc,
+ lineBuf);
+ }
+ } else {
+ for (y = 0; y < h; ++y) {
+ memcpy(lineBuf,
+ src->data + (ySrc + y) * src->rowSize + xSrc * 3,
+ w * 3);
+ for (x = 0, linePtr = lineBuf; x < w; ++x, linePtr += 3) {
+ b = linePtr[0];
+ linePtr[0] = linePtr[2];
+ linePtr[2] = b;
+ }
+ (this->*pipe.run)(&pipe, xDest, xDest + w - 1, yDest + y,
+ NULL, lineBuf);
+ }
+ }
+ } else {
+ x0 = xDest;
+ if ((t = state->clip->getXMinI(state->strokeAdjust)) > x0) {
+ x0 = t;
+ }
+ x1 = xDest + w;
+ if ((t = state->clip->getXMaxI(state->strokeAdjust) + 1) < x1) {
+ x1 = t;
+ }
+ y0 = yDest;
+ if ((t = state->clip->getYMinI(state->strokeAdjust)) > y0) {
+ y0 = t;
+ }
+ y1 = yDest + h;
+ if ((t = state->clip->getYMaxI(state->strokeAdjust) + 1) < y1) {
+ y1 = t;
+ }
+ if (x0 < x1 && y0 < y1) {
+ if (src->alpha) {
+ for (y = y0; y < y1; ++y) {
+ memcpy(scanBuf + x0,
+ src->alpha + (ySrc + y - yDest) * src->alphaRowSize +
+ (xSrc + x0 - xDest),
+ x1 - x0);
+ state->clip->clipSpan(scanBuf, y, x0, x1 - 1, state->strokeAdjust);
+ memcpy(lineBuf,
+ src->data +
+ (ySrc + y - yDest) * src->rowSize +
+ (xSrc + x0 - xDest) * 3,
+ (x1 - x0) * 3);
+ for (x = 0, linePtr = lineBuf; x < x1 - x0; ++x, linePtr += 3) {
+ b = linePtr[0];
+ linePtr[0] = linePtr[2];
+ linePtr[2] = b;
+ }
+ // this uses shape instead of alpha, which isn't technically
+ // correct, but works out the same
+ (this->*pipe.run)(&pipe, x0, x1 - 1, y,
+ scanBuf + x0, lineBuf);
+ }
+ } else {
+ for (y = y0; y < y1; ++y) {
+ memset(scanBuf + x0, 0xff, x1 - x0);
+ state->clip->clipSpan(scanBuf, y, x0, x1 - 1, state->strokeAdjust);
+ memcpy(lineBuf,
+ src->data +
+ (ySrc + y - yDest) * src->rowSize +
+ (xSrc + x0 - xDest) * 3,
+ (x1 - x0) * 3);
+ for (x = 0, linePtr = lineBuf; x < x1 - x0; ++x, linePtr += 3) {
+ b = linePtr[0];
+ linePtr[0] = linePtr[2];
+ linePtr[2] = b;
+ }
+ (this->*pipe.run)(&pipe, x0, x1 - 1, yDest + y,
+ scanBuf + x0,
+ src->data +
+ (ySrc + y - yDest) * src->rowSize +
+ (xSrc + x0 - xDest) * bitmapComps);
+ }
+ }
+ }
+ }
+ gfree(lineBuf);
+
+ } else { // src->mode not mono1 or BGR8
+ if (noClip) {
+ if (src->alpha) {
+ for (y = 0; y < h; ++y) {
+ // this uses shape instead of alpha, which isn't technically
+ // correct, but works out the same
+ (this->*pipe.run)(&pipe, xDest, xDest + w - 1, yDest + y,
+ src->alpha +
+ (ySrc + y) * src->alphaRowSize + xSrc,
+ src->data + (ySrc + y) * src->rowSize +
+ xSrc * bitmapComps);
+ }
+ } else {
+ for (y = 0; y < h; ++y) {
+ (this->*pipe.run)(&pipe, xDest, xDest + w - 1, yDest + y,
+ NULL,
+ src->data + (ySrc + y) * src->rowSize +
+ xSrc * bitmapComps);
+ }
+ }
+ } else {
+ x0 = xDest;
+ if ((t = state->clip->getXMinI(state->strokeAdjust)) > x0) {
+ x0 = t;
+ }
+ x1 = xDest + w;
+ if ((t = state->clip->getXMaxI(state->strokeAdjust) + 1) < x1) {
+ x1 = t;
+ }
+ y0 = yDest;
+ if ((t = state->clip->getYMinI(state->strokeAdjust)) > y0) {
+ y0 = t;
+ }
+ y1 = yDest + h;
+ if ((t = state->clip->getYMaxI(state->strokeAdjust) + 1) < y1) {
+ y1 = t;
+ }
+ if (x0 < x1 && y0 < y1) {
+ if (src->alpha) {
+ for (y = y0; y < y1; ++y) {
+ memcpy(scanBuf + x0,
+ src->alpha + (ySrc + y - yDest) * src->alphaRowSize +
+ (xSrc + x0 - xDest),
+ x1 - x0);
+ state->clip->clipSpan(scanBuf, y, x0, x1 - 1, state->strokeAdjust);
+ // this uses shape instead of alpha, which isn't technically
+ // correct, but works out the same
+ (this->*pipe.run)(&pipe, x0, x1 - 1, y,
+ scanBuf + x0,
+ src->data +
+ (ySrc + y - yDest) * src->rowSize +
+ (xSrc + x0 - xDest) * bitmapComps);
+ }
+ } else {
+ for (y = y0; y < y1; ++y) {
+ memset(scanBuf + x0, 0xff, x1 - x0);
+ state->clip->clipSpan(scanBuf, y, x0, x1 - 1, state->strokeAdjust);
+ (this->*pipe.run)(&pipe, x0, x1 - 1, yDest + y,
+ scanBuf + x0,
+ src->data +
+ (ySrc + y - yDest) * src->rowSize +
+ (xSrc + x0 - xDest) * bitmapComps);
+ }
+ }
+ }
+ }
+ }
+
+ return splashOk;
+}
+
+SplashError Splash::compositeWithOverprint(SplashBitmap *src,
+ Guint *srcOverprintMaskBitmap,
+ int xSrc, int ySrc,
+ int xDest, int yDest, int w, int h,
+ GBool noClip, GBool nonIsolated) {
+ SplashPipe pipe;
+ int x0, x1, y0, y1, y, t;
+
+ if (!(src->mode == bitmap->mode ||
+ (src->mode == splashModeMono8 && bitmap->mode == splashModeMono1) ||
+ (src->mode == splashModeRGB8 && bitmap->mode == splashModeBGR8))) {
+ return splashErrModeMismatch;
+ }
+
+ pipeInit(&pipe, NULL,
+ (Guchar)splashRound(state->fillAlpha * 255),
+ !noClip || src->alpha != NULL, nonIsolated, gTrue);
+
+ if (noClip) {
+ if (src->alpha) {
+ for (y = 0; y < h; ++y) {
+ pipe.srcOverprintMaskPtr = srcOverprintMaskBitmap + y * w + xSrc;
+ // this uses shape instead of alpha, which isn't technically
+ // correct, but works out the same
+ (this->*pipe.run)(&pipe, xDest, xDest + w - 1, yDest + y,
+ src->alpha +
+ (ySrc + y) * src->alphaRowSize + xSrc,
+ src->data + (ySrc + y) * src->rowSize +
+ xSrc * bitmapComps);
+ }
+ } else {
+ for (y = 0; y < h; ++y) {
+ pipe.srcOverprintMaskPtr = srcOverprintMaskBitmap + y * w + xSrc;
+ (this->*pipe.run)(&pipe, xDest, xDest + w - 1, yDest + y,
+ NULL,
+ src->data + (ySrc + y) * src->rowSize +
+ xSrc * bitmapComps);
+ }
+ }
+ } else {
+ x0 = xDest;
+ if ((t = state->clip->getXMinI(state->strokeAdjust)) > x0) {
+ x0 = t;
+ }
+ x1 = xDest + w;
+ if ((t = state->clip->getXMaxI(state->strokeAdjust) + 1) < x1) {
+ x1 = t;
+ }
+ y0 = yDest;
+ if ((t = state->clip->getYMinI(state->strokeAdjust)) > y0) {
+ y0 = t;
+ }
+ y1 = yDest + h;
+ if ((t = state->clip->getYMaxI(state->strokeAdjust) + 1) < y1) {
+ y1 = t;
+ }
+ if (x0 < x1 && y0 < y1) {
+ if (src->alpha) {
+ for (y = y0; y < y1; ++y) {
+ memcpy(scanBuf + x0,
+ src->alpha + (ySrc + y - yDest) * src->alphaRowSize +
+ (xSrc + x0 - xDest),
+ x1 - x0);
+ state->clip->clipSpan(scanBuf, y, x0, x1 - 1, state->strokeAdjust);
+ pipe.srcOverprintMaskPtr = srcOverprintMaskBitmap
+ + (ySrc + y - yDest) * w
+ + (xSrc + x0 - xDest);
+ // this uses shape instead of alpha, which isn't technically
+ // correct, but works out the same
+ (this->*pipe.run)(&pipe, x0, x1 - 1, y,
+ scanBuf + x0,
+ src->data +
+ (ySrc + y - yDest) * src->rowSize +
+ (xSrc + x0 - xDest) * bitmapComps);
+ }
+ } else {
+ for (y = y0; y < y1; ++y) {
+ memset(scanBuf + x0, 0xff, x1 - x0);
+ state->clip->clipSpan(scanBuf, y, x0, x1 - 1, state->strokeAdjust);
+ pipe.srcOverprintMaskPtr = srcOverprintMaskBitmap
+ + (ySrc + y - yDest) * w
+ + (xSrc + x0 - xDest);
+ (this->*pipe.run)(&pipe, x0, x1 - 1, y,
+ scanBuf + x0,
+ src->data +
+ (ySrc + y - yDest) * src->rowSize +
+ (xSrc + x0 - xDest) * bitmapComps);
+ }
+ }
+ }
+ }
+
+ return splashOk;
+}
+
+void Splash::compositeBackground(SplashColorPtr color) {
+ SplashColorPtr p;
+ Guchar *q;
+ Guchar alpha, alpha1, c, color0, color1, color2, mask;
+#if SPLASH_CMYK
+ Guchar color3;
+#endif
+ int x, y;
+
+ switch (bitmap->mode) {
+ case splashModeMono1:
+ color0 = color[0];
+ for (y = 0; y < bitmap->height; ++y) {
+ p = &bitmap->data[y * bitmap->rowSize];
+ q = &bitmap->alpha[y * bitmap->alphaRowSize];
+ mask = 0x80;
+ for (x = 0; x < bitmap->width; ++x) {
+ alpha = *q++;
+ if (alpha == 0) {
+ if (color0 & 0x80) {
+ *p |= mask;
+ } else {
+ *p &= (Guchar)~mask;
+ }
+ } else if (alpha != 255) {
+ alpha1 = (Guchar)(255 - alpha);
+ c = (*p & mask) ? 0xff : 0x00;
+ c = div255(alpha1 * color0 + alpha * c);
+ if (c & 0x80) {
+ *p |= mask;
+ } else {
+ *p &= (Guchar)~mask;
+ }
+ }
+ if (!(mask = (Guchar)(mask >> 1))) {
+ mask = 0x80;
+ ++p;
+ }
+ }
+ }
+ break;
+ case splashModeMono8:
+ color0 = color[0];
+ for (y = 0; y < bitmap->height; ++y) {
+ p = &bitmap->data[y * bitmap->rowSize];
+ q = &bitmap->alpha[y * bitmap->alphaRowSize];
+ for (x = 0; x < bitmap->width; ++x) {
+ alpha = *q++;
+ if (alpha == 0) {
+ p[0] = color0;
+ } else if (alpha != 255) {
+ alpha1 = (Guchar)(255 - alpha);
+ p[0] = div255(alpha1 * color0 + alpha * p[0]);
+ }
+ ++p;
+ }
+ }
+ break;
+ case splashModeRGB8:
+ case splashModeBGR8:
+ color0 = color[0];
+ color1 = color[1];
+ color2 = color[2];
+ for (y = 0; y < bitmap->height; ++y) {
+ p = &bitmap->data[y * bitmap->rowSize];
+ q = &bitmap->alpha[y * bitmap->alphaRowSize];
+ for (x = 0; x < bitmap->width; ++x) {
+ alpha = *q++;
+ if (alpha == 0) {
+ p[0] = color0;
+ p[1] = color1;
+ p[2] = color2;
+ } else if (alpha != 255) {
+ alpha1 = (Guchar)(255 - alpha);
+ p[0] = div255(alpha1 * color0 + alpha * p[0]);
+ p[1] = div255(alpha1 * color1 + alpha * p[1]);
+ p[2] = div255(alpha1 * color2 + alpha * p[2]);
+ }
+ p += 3;
+ }
+ }
+ break;
+#if SPLASH_CMYK
+ case splashModeCMYK8:
+ color0 = color[0];
+ color1 = color[1];
+ color2 = color[2];
+ color3 = color[3];
+ for (y = 0; y < bitmap->height; ++y) {
+ p = &bitmap->data[y * bitmap->rowSize];
+ q = &bitmap->alpha[y * bitmap->alphaRowSize];
+ for (x = 0; x < bitmap->width; ++x) {
+ alpha = *q++;
+ if (alpha == 0) {
+ p[0] = color0;
+ p[1] = color1;
+ p[2] = color2;
+ p[3] = color3;
+ } else if (alpha != 255) {
+ alpha1 = (Guchar)(255 - alpha);
+ p[0] = div255(alpha1 * color0 + alpha * p[0]);
+ p[1] = div255(alpha1 * color1 + alpha * p[1]);
+ p[2] = div255(alpha1 * color2 + alpha * p[2]);
+ p[3] = div255(alpha1 * color3 + alpha * p[3]);
+ }
+ p += 4;
+ }
+ }
+ break;
+#endif
+ }
+ memset(bitmap->alpha, 255, bitmap->alphaRowSize * bitmap->height);
+}
+
+SplashError Splash::blitTransparent(SplashBitmap *src, int xSrc, int ySrc,
+ int xDest, int yDest, int w, int h) {
+ SplashColorPtr p, q;
+ Guchar mask, srcMask;
+ int x, y;
+
+ if (src->mode != bitmap->mode) {
+ return splashErrModeMismatch;
+ }
+
+ switch (bitmap->mode) {
+ case splashModeMono1:
+ for (y = 0; y < h; ++y) {
+ p = &bitmap->data[(yDest + y) * bitmap->rowSize + (xDest >> 3)];
+ mask = (Guchar)(0x80 >> (xDest & 7));
+ q = &src->data[(ySrc + y) * src->rowSize + (xSrc >> 3)];
+ srcMask = (Guchar)(0x80 >> (xSrc & 7));
+ for (x = 0; x < w; ++x) {
+ if (*q & srcMask) {
+ *p |= mask;
+ } else {
+ *p &= (Guchar)~mask;
+ }
+ if (!(mask = (Guchar)(mask >> 1))) {
+ mask = 0x80;
+ ++p;
+ }
+ if (!(srcMask = (Guchar)(srcMask >> 1))) {
+ srcMask = 0x80;
+ ++q;
+ }
+ }
+ }
+ break;
+ case splashModeMono8:
+ for (y = 0; y < h; ++y) {
+ p = &bitmap->data[(yDest + y) * bitmap->rowSize + xDest];
+ q = &src->data[(ySrc + y) * src->rowSize + xSrc];
+ memcpy(p, q, w);
+ }
+ break;
+ case splashModeRGB8:
+ case splashModeBGR8:
+ for (y = 0; y < h; ++y) {
+ p = &bitmap->data[(yDest + y) * bitmap->rowSize + 3 * xDest];
+ q = &src->data[(ySrc + y) * src->rowSize + 3 * xSrc];
+ memcpy(p, q, 3 * w);
+ }
+ break;
+#if SPLASH_CMYK
+ case splashModeCMYK8:
+ for (y = 0; y < h; ++y) {
+ p = &bitmap->data[(yDest + y) * bitmap->rowSize + 4 * xDest];
+ q = &src->data[(ySrc + y) * src->rowSize + 4 * xSrc];
+ memcpy(p, q, 4 * w);
+ }
+ break;
+#endif
+ }
+
+ if (bitmap->alpha) {
+ for (y = 0; y < h; ++y) {
+ q = &bitmap->alpha[(yDest + y) * bitmap->alphaRowSize + xDest];
+ memset(q, 0, w);
+ }
+ }
+
+ return splashOk;
+}
+
+SplashError Splash::blitCorrectedAlpha(SplashBitmap *dest, int xSrc, int ySrc,
+ int xDest, int yDest, int w, int h) {
+ SplashColorPtr p, q;
+ Guchar *alpha0Ptr;
+ Guchar alpha0, aSrc, mask, srcMask;
+ int x, y;
+
+ if (bitmap->mode != dest->mode ||
+ !bitmap->alpha ||
+ !dest->alpha ||
+ !groupBackBitmap) {
+ return splashErrModeMismatch;
+ }
+
+ switch (bitmap->mode) {
+ case splashModeMono1:
+ for (y = 0; y < h; ++y) {
+ p = &dest->data[(yDest + y) * dest->rowSize + (xDest >> 3)];
+ mask = (Guchar)(0x80 >> (xDest & 7));
+ q = &bitmap->data[(ySrc + y) * bitmap->rowSize + (xSrc >> 3)];
+ srcMask = (Guchar)(0x80 >> (xSrc & 7));
+ for (x = 0; x < w; ++x) {
+ if (*q & srcMask) {
+ *p |= mask;
+ } else {
+ *p &= (Guchar)~mask;
+ }
+ if (!(mask = (Guchar)(mask >> 1))) {
+ mask = 0x80;
+ ++p;
+ }
+ if (!(srcMask = (Guchar)(srcMask >> 1))) {
+ srcMask = 0x80;
+ ++q;
+ }
+ }
+ }
+ break;
+ case splashModeMono8:
+ for (y = 0; y < h; ++y) {
+ p = &dest->data[(yDest + y) * dest->rowSize + xDest];
+ q = &bitmap->data[(ySrc + y) * bitmap->rowSize + xSrc];
+ memcpy(p, q, w);
+ }
+ break;
+ case splashModeRGB8:
+ case splashModeBGR8:
+ for (y = 0; y < h; ++y) {
+ p = &dest->data[(yDest + y) * dest->rowSize + 3 * xDest];
+ q = &bitmap->data[(ySrc + y) * bitmap->rowSize + 3 * xSrc];
+ memcpy(p, q, 3 * w);
+ }
+ break;
+#if SPLASH_CMYK
+ case splashModeCMYK8:
+ for (y = 0; y < h; ++y) {
+ p = &dest->data[(yDest + y) * dest->rowSize + 4 * xDest];
+ q = &bitmap->data[(ySrc + y) * bitmap->rowSize + 4 * xSrc];
+ memcpy(p, q, 4 * w);
+ }
+ break;
+#endif
+ }
+
+ for (y = 0; y < h; ++y) {
+ p = &dest->alpha[(yDest + y) * dest->alphaRowSize + xDest];
+ q = &bitmap->alpha[(ySrc + y) * bitmap->alphaRowSize + xSrc];
+ alpha0Ptr = &groupBackBitmap->alpha[(groupBackY + ySrc + y)
+ * groupBackBitmap->alphaRowSize +
+ (groupBackX + xSrc)];
+ for (x = 0; x < w; ++x) {
+ alpha0 = *alpha0Ptr++;
+ aSrc = *q++;
+ *p++ = (Guchar)(alpha0 + aSrc - div255(alpha0 * aSrc));
+ }
+ }
+
+ return splashOk;
+}
+
+SplashPath *Splash::makeStrokePath(SplashPath *path, SplashCoord w,
+ int lineCap, int lineJoin,
+ GBool flatten) {
+ SplashPath *pathIn, *dashPath, *pathOut;
+ SplashCoord d, dx, dy, wdx, wdy, dxNext, dyNext, wdxNext, wdyNext;
+ SplashCoord crossprod, dotprod, miter, m;
+ SplashCoord angle, angleNext, dAngle, xc, yc;
+ SplashCoord dxJoin, dyJoin, dJoin, kappa;
+ SplashCoord cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4;
+ GBool first, last, closed;
+ int subpathStart0, subpathStart1, seg, i0, i1, j0, j1, k0, k1;
+ int left0, left1, left2, right0, right1, right2, join0, join1, join2;
+ int leftFirst, rightFirst, firstPt;
+
+ pathOut = new SplashPath();
+
+ if (path->length == 0) {
+ return pathOut;
+ }
+
+ if (flatten) {
+ pathIn = flattenPath(path, state->matrix, state->flatness);
+ if (state->lineDashLength > 0) {
+ dashPath = makeDashedPath(pathIn);
+ delete pathIn;
+ pathIn = dashPath;
+ if (pathIn->length == 0) {
+ delete pathIn;
+ return pathOut;
+ }
+ }
+ } else {
+ pathIn = path;
+ }
+
+ subpathStart0 = subpathStart1 = 0; // make gcc happy
+ seg = 0; // make gcc happy
+ closed = gFalse; // make gcc happy
+ left0 = left1 = right0 = right1 = join0 = join1 = 0; // make gcc happy
+ leftFirst = rightFirst = firstPt = 0; // make gcc happy
+
+ i0 = 0;
+ for (i1 = i0;
+ !(pathIn->flags[i1] & splashPathLast) &&
+ i1 + 1 < pathIn->length &&
+ pathIn->pts[i1+1].x == pathIn->pts[i1].x &&
+ pathIn->pts[i1+1].y == pathIn->pts[i1].y;
+ ++i1) ;
+
+ while (i1 < pathIn->length) {
+ if ((first = pathIn->flags[i0] & splashPathFirst)) {
+ subpathStart0 = i0;
+ subpathStart1 = i1;
+ seg = 0;
+ closed = pathIn->flags[i0] & splashPathClosed;
+ }
+ j0 = i1 + 1;
+ if (j0 < pathIn->length) {
+ for (j1 = j0;
+ !(pathIn->flags[j1] & splashPathLast) &&
+ j1 + 1 < pathIn->length &&
+ pathIn->pts[j1+1].x == pathIn->pts[j1].x &&
+ pathIn->pts[j1+1].y == pathIn->pts[j1].y;
+ ++j1) ;
+ } else {
+ j1 = j0;
+ }
+ if (pathIn->flags[i1] & splashPathLast) {
+ if (first && lineCap == splashLineCapRound) {
+ // special case: zero-length subpath with round line caps -->
+ // draw a circle
+ pathOut->moveTo(pathIn->pts[i0].x + (SplashCoord)0.5 * w,
+ pathIn->pts[i0].y);
+ pathOut->curveTo(pathIn->pts[i0].x + (SplashCoord)0.5 * w,
+ pathIn->pts[i0].y + bezierCircle2 * w,
+ pathIn->pts[i0].x + bezierCircle2 * w,
+ pathIn->pts[i0].y + (SplashCoord)0.5 * w,
+ pathIn->pts[i0].x,
+ pathIn->pts[i0].y + (SplashCoord)0.5 * w);
+ pathOut->curveTo(pathIn->pts[i0].x - bezierCircle2 * w,
+ pathIn->pts[i0].y + (SplashCoord)0.5 * w,
+ pathIn->pts[i0].x - (SplashCoord)0.5 * w,
+ pathIn->pts[i0].y + bezierCircle2 * w,
+ pathIn->pts[i0].x - (SplashCoord)0.5 * w,
+ pathIn->pts[i0].y);
+ pathOut->curveTo(pathIn->pts[i0].x - (SplashCoord)0.5 * w,
+ pathIn->pts[i0].y - bezierCircle2 * w,
+ pathIn->pts[i0].x - bezierCircle2 * w,
+ pathIn->pts[i0].y - (SplashCoord)0.5 * w,
+ pathIn->pts[i0].x,
+ pathIn->pts[i0].y - (SplashCoord)0.5 * w);
+ pathOut->curveTo(pathIn->pts[i0].x + bezierCircle2 * w,
+ pathIn->pts[i0].y - (SplashCoord)0.5 * w,
+ pathIn->pts[i0].x + (SplashCoord)0.5 * w,
+ pathIn->pts[i0].y - bezierCircle2 * w,
+ pathIn->pts[i0].x + (SplashCoord)0.5 * w,
+ pathIn->pts[i0].y);
+ pathOut->close();
+ }
+ i0 = j0;
+ i1 = j1;
+ continue;
+ }
+ last = pathIn->flags[j1] & splashPathLast;
+ if (last) {
+ k0 = subpathStart1 + 1;
+ } else {
+ k0 = j1 + 1;
+ }
+ for (k1 = k0;
+ !(pathIn->flags[k1] & splashPathLast) &&
+ k1 + 1 < pathIn->length &&
+ pathIn->pts[k1+1].x == pathIn->pts[k1].x &&
+ pathIn->pts[k1+1].y == pathIn->pts[k1].y;
+ ++k1) ;
+
+ // compute the deltas for segment (i1, j0)
+#if USE_FIXEDPOINT
+ // the 1/d value can be small, which introduces significant
+ // inaccuracies in fixed point mode
+ d = splashDist(pathIn->pts[i1].x, pathIn->pts[i1].y,
+ pathIn->pts[j0].x, pathIn->pts[j0].y);
+ dx = (pathIn->pts[j0].x - pathIn->pts[i1].x) / d;
+ dy = (pathIn->pts[j0].y - pathIn->pts[i1].y) / d;
+#else
+ d = (SplashCoord)1 / splashDist(pathIn->pts[i1].x, pathIn->pts[i1].y,
+ pathIn->pts[j0].x, pathIn->pts[j0].y);
+ dx = d * (pathIn->pts[j0].x - pathIn->pts[i1].x);
+ dy = d * (pathIn->pts[j0].y - pathIn->pts[i1].y);
+#endif
+ wdx = (SplashCoord)0.5 * w * dx;
+ wdy = (SplashCoord)0.5 * w * dy;
+
+ // draw the start cap
+ if (i0 == subpathStart0) {
+ firstPt = pathOut->length;
+ }
+ if (first && !closed) {
+ switch (lineCap) {
+ case splashLineCapButt:
+ pathOut->moveTo(pathIn->pts[i0].x - wdy, pathIn->pts[i0].y + wdx);
+ pathOut->lineTo(pathIn->pts[i0].x + wdy, pathIn->pts[i0].y - wdx);
+ break;
+ case splashLineCapRound:
+ pathOut->moveTo(pathIn->pts[i0].x - wdy, pathIn->pts[i0].y + wdx);
+ pathOut->curveTo(pathIn->pts[i0].x - wdy - bezierCircle * wdx,
+ pathIn->pts[i0].y + wdx - bezierCircle * wdy,
+ pathIn->pts[i0].x - wdx - bezierCircle * wdy,
+ pathIn->pts[i0].y - wdy + bezierCircle * wdx,
+ pathIn->pts[i0].x - wdx,
+ pathIn->pts[i0].y - wdy);
+ pathOut->curveTo(pathIn->pts[i0].x - wdx + bezierCircle * wdy,
+ pathIn->pts[i0].y - wdy - bezierCircle * wdx,
+ pathIn->pts[i0].x + wdy - bezierCircle * wdx,
+ pathIn->pts[i0].y - wdx - bezierCircle * wdy,
+ pathIn->pts[i0].x + wdy,
+ pathIn->pts[i0].y - wdx);
+ break;
+ case splashLineCapProjecting:
+ pathOut->moveTo(pathIn->pts[i0].x - wdx - wdy,
+ pathIn->pts[i0].y + wdx - wdy);
+ pathOut->lineTo(pathIn->pts[i0].x - wdx + wdy,
+ pathIn->pts[i0].y - wdx - wdy);
+ break;
+ }
+ } else {
+ pathOut->moveTo(pathIn->pts[i0].x - wdy, pathIn->pts[i0].y + wdx);
+ pathOut->lineTo(pathIn->pts[i0].x + wdy, pathIn->pts[i0].y - wdx);
+ }
+
+ // draw the left side of the segment rectangle and the end cap
+ left2 = pathOut->length - 1;
+ if (last && !closed) {
+ switch (lineCap) {
+ case splashLineCapButt:
+ pathOut->lineTo(pathIn->pts[j0].x + wdy, pathIn->pts[j0].y - wdx);
+ pathOut->lineTo(pathIn->pts[j0].x - wdy, pathIn->pts[j0].y + wdx);
+ break;
+ case splashLineCapRound:
+ pathOut->lineTo(pathIn->pts[j0].x + wdy, pathIn->pts[j0].y - wdx);
+ pathOut->curveTo(pathIn->pts[j0].x + wdy + bezierCircle * wdx,
+ pathIn->pts[j0].y - wdx + bezierCircle * wdy,
+ pathIn->pts[j0].x + wdx + bezierCircle * wdy,
+ pathIn->pts[j0].y + wdy - bezierCircle * wdx,
+ pathIn->pts[j0].x + wdx,
+ pathIn->pts[j0].y + wdy);
+ pathOut->curveTo(pathIn->pts[j0].x + wdx - bezierCircle * wdy,
+ pathIn->pts[j0].y + wdy + bezierCircle * wdx,
+ pathIn->pts[j0].x - wdy + bezierCircle * wdx,
+ pathIn->pts[j0].y + wdx + bezierCircle * wdy,
+ pathIn->pts[j0].x - wdy,
+ pathIn->pts[j0].y + wdx);
+ break;
+ case splashLineCapProjecting:
+ pathOut->lineTo(pathIn->pts[j0].x + wdy + wdx,
+ pathIn->pts[j0].y - wdx + wdy);
+ pathOut->lineTo(pathIn->pts[j0].x - wdy + wdx,
+ pathIn->pts[j0].y + wdx + wdy);
+ break;
+ }
+ } else {
+ pathOut->lineTo(pathIn->pts[j0].x + wdy, pathIn->pts[j0].y - wdx);
+ pathOut->lineTo(pathIn->pts[j0].x - wdy, pathIn->pts[j0].y + wdx);
+ }
+
+ // draw the right side of the segment rectangle
+ // (NB: if stroke adjustment is enabled, the closepath operation MUST
+ // add a segment because this segment is used for a hint)
+ right2 = pathOut->length - 1;
+ pathOut->close(state->strokeAdjust != splashStrokeAdjustOff);
+
+ // draw the join
+ join2 = pathOut->length;
+ if (!last || closed) {
+
+ // compute the deltas for segment (j1, k0)
+#if USE_FIXEDPOINT
+ // the 1/d value can be small, which introduces significant
+ // inaccuracies in fixed point mode
+ d = splashDist(pathIn->pts[j1].x, pathIn->pts[j1].y,
+ pathIn->pts[k0].x, pathIn->pts[k0].y);
+ dxNext = (pathIn->pts[k0].x - pathIn->pts[j1].x) / d;
+ dyNext = (pathIn->pts[k0].y - pathIn->pts[j1].y) / d;
+#else
+ d = (SplashCoord)1 / splashDist(pathIn->pts[j1].x, pathIn->pts[j1].y,
+ pathIn->pts[k0].x, pathIn->pts[k0].y);
+ dxNext = d * (pathIn->pts[k0].x - pathIn->pts[j1].x);
+ dyNext = d * (pathIn->pts[k0].y - pathIn->pts[j1].y);
+#endif
+ wdxNext = (SplashCoord)0.5 * w * dxNext;
+ wdyNext = (SplashCoord)0.5 * w * dyNext;
+
+ // compute the join parameters
+ crossprod = dx * dyNext - dy * dxNext;
+ dotprod = -(dx * dxNext + dy * dyNext);
+ if (dotprod > 0.9999) {
+ // avoid a divide-by-zero -- set miter to something arbitrary
+ // such that sqrt(miter) will exceed miterLimit (and m is never
+ // used in that situation)
+ // (note: the comparison value (0.9999) has to be less than
+ // 1-epsilon, where epsilon is the smallest value
+ // representable in the fixed point format)
+ miter = (state->miterLimit + 1) * (state->miterLimit + 1);
+ m = 0;
+ } else {
+ miter = (SplashCoord)2 / ((SplashCoord)1 - dotprod);
+ if (miter < 1) {
+ // this can happen because of floating point inaccuracies
+ miter = 1;
+ }
+ m = splashSqrt(miter - 1);
+ }
+
+ // round join
+ if (lineJoin == splashLineJoinRound) {
+ // join angle < 180
+ if (crossprod < 0) {
+ angle = atan2((double)dx, (double)-dy);
+ angleNext = atan2((double)dxNext, (double)-dyNext);
+ if (angle < angleNext) {
+ angle += 2 * M_PI;
+ }
+ dAngle = (angle - angleNext) / M_PI;
+ if (dAngle < 0.501) {
+ // span angle is <= 90 degrees -> draw a single arc
+ kappa = dAngle * bezierCircle * w;
+ cx1 = pathIn->pts[j0].x - wdy + kappa * dx;
+ cy1 = pathIn->pts[j0].y + wdx + kappa * dy;
+ cx2 = pathIn->pts[j0].x - wdyNext - kappa * dxNext;
+ cy2 = pathIn->pts[j0].y + wdxNext - kappa * dyNext;
+ pathOut->moveTo(pathIn->pts[j0].x, pathIn->pts[j0].y);
+ pathOut->lineTo(pathIn->pts[j0].x - wdyNext,
+ pathIn->pts[j0].y + wdxNext);
+ pathOut->curveTo(cx2, cy2, cx1, cy1,
+ pathIn->pts[j0].x - wdy,
+ pathIn->pts[j0].y + wdx);
+ } else {
+ // span angle is > 90 degrees -> split into two arcs
+ dJoin = splashDist(-wdy, wdx, -wdyNext, wdxNext);
+ if (dJoin > 0) {
+ dxJoin = (-wdyNext + wdy) / dJoin;
+ dyJoin = (wdxNext - wdx) / dJoin;
+ xc = pathIn->pts[j0].x
+ + (SplashCoord)0.5 * w
+ * cos((double)((SplashCoord)0.5 * (angle + angleNext)));
+ yc = pathIn->pts[j0].y
+ + (SplashCoord)0.5 * w
+ * sin((double)((SplashCoord)0.5 * (angle + angleNext)));
+ kappa = dAngle * bezierCircle2 * w;
+ cx1 = pathIn->pts[j0].x - wdy + kappa * dx;
+ cy1 = pathIn->pts[j0].y + wdx + kappa * dy;
+ cx2 = xc - kappa * dxJoin;
+ cy2 = yc - kappa * dyJoin;
+ cx3 = xc + kappa * dxJoin;
+ cy3 = yc + kappa * dyJoin;
+ cx4 = pathIn->pts[j0].x - wdyNext - kappa * dxNext;
+ cy4 = pathIn->pts[j0].y + wdxNext - kappa * dyNext;
+ pathOut->moveTo(pathIn->pts[j0].x, pathIn->pts[j0].y);
+ pathOut->lineTo(pathIn->pts[j0].x - wdyNext,
+ pathIn->pts[j0].y + wdxNext);
+ pathOut->curveTo(cx4, cy4, cx3, cy3, xc, yc);
+ pathOut->curveTo(cx2, cy2, cx1, cy1,
+ pathIn->pts[j0].x - wdy,
+ pathIn->pts[j0].y + wdx);
+ }
+ }
+
+ // join angle >= 180
+ } else {
+ angle = atan2((double)-dx, (double)dy);
+ angleNext = atan2((double)-dxNext, (double)dyNext);
+ if (angleNext < angle) {
+ angleNext += 2 * M_PI;
+ }
+ dAngle = (angleNext - angle) / M_PI;
+ if (dAngle < 0.501) {
+ // span angle is <= 90 degrees -> draw a single arc
+ kappa = dAngle * bezierCircle * w;
+ cx1 = pathIn->pts[j0].x + wdy + kappa * dx;
+ cy1 = pathIn->pts[j0].y - wdx + kappa * dy;
+ cx2 = pathIn->pts[j0].x + wdyNext - kappa * dxNext;
+ cy2 = pathIn->pts[j0].y - wdxNext - kappa * dyNext;
+ pathOut->moveTo(pathIn->pts[j0].x, pathIn->pts[j0].y);
+ pathOut->lineTo(pathIn->pts[j0].x + wdy,
+ pathIn->pts[j0].y - wdx);
+ pathOut->curveTo(cx1, cy1, cx2, cy2,
+ pathIn->pts[j0].x + wdyNext,
+ pathIn->pts[j0].y - wdxNext);
+ } else {
+ // span angle is > 90 degrees -> split into two arcs
+ dJoin = splashDist(wdy, -wdx, wdyNext, -wdxNext);
+ if (dJoin > 0) {
+ dxJoin = (wdyNext - wdy) / dJoin;
+ dyJoin = (-wdxNext + wdx) / dJoin;
+ xc = pathIn->pts[j0].x
+ + (SplashCoord)0.5 * w
+ * cos((double)((SplashCoord)0.5 * (angle + angleNext)));
+ yc = pathIn->pts[j0].y
+ + (SplashCoord)0.5 * w
+ * sin((double)((SplashCoord)0.5 * (angle + angleNext)));
+ kappa = dAngle * bezierCircle2 * w;
+ cx1 = pathIn->pts[j0].x + wdy + kappa * dx;
+ cy1 = pathIn->pts[j0].y - wdx + kappa * dy;
+ cx2 = xc - kappa * dxJoin;
+ cy2 = yc - kappa * dyJoin;
+ cx3 = xc + kappa * dxJoin;
+ cy3 = yc + kappa * dyJoin;
+ cx4 = pathIn->pts[j0].x + wdyNext - kappa * dxNext;
+ cy4 = pathIn->pts[j0].y - wdxNext - kappa * dyNext;
+ pathOut->moveTo(pathIn->pts[j0].x, pathIn->pts[j0].y);
+ pathOut->lineTo(pathIn->pts[j0].x + wdy,
+ pathIn->pts[j0].y - wdx);
+ pathOut->curveTo(cx1, cy1, cx2, cy2, xc, yc);
+ pathOut->curveTo(cx3, cy3, cx4, cy4,
+ pathIn->pts[j0].x + wdyNext,
+ pathIn->pts[j0].y - wdxNext);
+ }
+ }
+ }
+
+ } else {
+ pathOut->moveTo(pathIn->pts[j0].x, pathIn->pts[j0].y);
+
+ // join angle < 180
+ if (crossprod < 0) {
+ pathOut->lineTo(pathIn->pts[j0].x - wdyNext,
+ pathIn->pts[j0].y + wdxNext);
+ // miter join inside limit
+ if (lineJoin == splashLineJoinMiter &&
+ splashSqrt(miter) <= state->miterLimit) {
+ pathOut->lineTo(pathIn->pts[j0].x - wdy + wdx * m,
+ pathIn->pts[j0].y + wdx + wdy * m);
+ pathOut->lineTo(pathIn->pts[j0].x - wdy,
+ pathIn->pts[j0].y + wdx);
+ // bevel join or miter join outside limit
+ } else {
+ pathOut->lineTo(pathIn->pts[j0].x - wdy,
+ pathIn->pts[j0].y + wdx);
+ }
+
+ // join angle >= 180
+ } else {
+ pathOut->lineTo(pathIn->pts[j0].x + wdy,
+ pathIn->pts[j0].y - wdx);
+ // miter join inside limit
+ if (lineJoin == splashLineJoinMiter &&
+ splashSqrt(miter) <= state->miterLimit) {
+ pathOut->lineTo(pathIn->pts[j0].x + wdy + wdx * m,
+ pathIn->pts[j0].y - wdx + wdy * m);
+ pathOut->lineTo(pathIn->pts[j0].x + wdyNext,
+ pathIn->pts[j0].y - wdxNext);
+ // bevel join or miter join outside limit
+ } else {
+ pathOut->lineTo(pathIn->pts[j0].x + wdyNext,
+ pathIn->pts[j0].y - wdxNext);
+ }
+ }
+ }
+
+ pathOut->close();
+ }
+
+ // add stroke adjustment hints
+ if (state->strokeAdjust != splashStrokeAdjustOff) {
+
+ // subpath with one segment
+ if (seg == 0 && last) {
+ switch (lineCap) {
+ case splashLineCapButt:
+ pathOut->addStrokeAdjustHint(firstPt, left2 + 1,
+ firstPt, pathOut->length - 1);
+ break;
+ case splashLineCapProjecting:
+ pathOut->addStrokeAdjustHint(firstPt, left2 + 1,
+ firstPt, pathOut->length - 1, gTrue);
+ break;
+ case splashLineCapRound:
+ break;
+ }
+ pathOut->addStrokeAdjustHint(left2, right2,
+ firstPt, pathOut->length - 1);
+ } else {
+
+ // start of subpath
+ if (seg == 1) {
+
+ // start cap
+ if (!closed) {
+ switch (lineCap) {
+ case splashLineCapButt:
+ pathOut->addStrokeAdjustHint(firstPt, left1 + 1,
+ firstPt, firstPt + 1);
+ pathOut->addStrokeAdjustHint(firstPt, left1 + 1,
+ right1 + 1, right1 + 1);
+ break;
+ case splashLineCapProjecting:
+ pathOut->addStrokeAdjustHint(firstPt, left1 + 1,
+ firstPt, firstPt + 1, gTrue);
+ pathOut->addStrokeAdjustHint(firstPt, left1 + 1,
+ right1 + 1, right1 + 1, gTrue);
+ break;
+ case splashLineCapRound:
+ break;
+ }
+ }
+
+ // first segment
+ pathOut->addStrokeAdjustHint(left1, right1, firstPt, left2);
+ pathOut->addStrokeAdjustHint(left1, right1, right2 + 1, right2 + 1);
+ }
+
+ // middle of subpath
+ if (seg > 1) {
+ pathOut->addStrokeAdjustHint(left1, right1, left0 + 1, right0);
+ pathOut->addStrokeAdjustHint(left1, right1, join0, left2);
+ pathOut->addStrokeAdjustHint(left1, right1, right2 + 1, right2 + 1);
+ }
+
+ // end of subpath
+ if (last) {
+
+ if (closed) {
+ // first segment
+ pathOut->addStrokeAdjustHint(leftFirst, rightFirst,
+ left2 + 1, right2);
+ pathOut->addStrokeAdjustHint(leftFirst, rightFirst,
+ join2, pathOut->length - 1);
+
+ // last segment
+ pathOut->addStrokeAdjustHint(left2, right2,
+ left1 + 1, right1);
+ pathOut->addStrokeAdjustHint(left2, right2,
+ join1, pathOut->length - 1);
+ pathOut->addStrokeAdjustHint(left2, right2,
+ leftFirst - 1, leftFirst);
+ pathOut->addStrokeAdjustHint(left2, right2,
+ rightFirst + 1, rightFirst + 1);
+
+ } else {
+
+ // last segment
+ pathOut->addStrokeAdjustHint(left2, right2,
+ left1 + 1, right1);
+ pathOut->addStrokeAdjustHint(left2, right2,
+ join1, pathOut->length - 1);
+
+ // end cap
+ switch (lineCap) {
+ case splashLineCapButt:
+ pathOut->addStrokeAdjustHint(left2 - 1, left2 + 1,
+ left2 + 1, left2 + 2);
+ break;
+ case splashLineCapProjecting:
+ pathOut->addStrokeAdjustHint(left2 - 1, left2 + 1,
+ left2 + 1, left2 + 2, gTrue);
+ break;
+ case splashLineCapRound:
+ break;
+ }
+ }
+ }
+ }
+
+ left0 = left1;
+ left1 = left2;
+ right0 = right1;
+ right1 = right2;
+ join0 = join1;
+ join1 = join2;
+ if (seg == 0) {
+ leftFirst = left2;
+ rightFirst = right2;
+ }
+ }
+
+ i0 = j0;
+ i1 = j1;
+ ++seg;
+ }
+
+ if (pathIn != path) {
+ delete pathIn;
+ }
+
+ return pathOut;
+}
+
+SplashClipResult Splash::limitRectToClipRect(int *xMin, int *yMin,
+ int *xMax, int *yMax) {
+ int t;
+
+ if ((t = state->clip->getXMinI(state->strokeAdjust)) > *xMin) {
+ *xMin = t;
+ }
+ if ((t = state->clip->getXMaxI(state->strokeAdjust) + 1) < *xMax) {
+ *xMax = t;
+ }
+ if ((t = state->clip->getYMinI(state->strokeAdjust)) > *yMin) {
+ *yMin = t;
+ }
+ if ((t = state->clip->getYMaxI(state->strokeAdjust) + 1) < *yMax) {
+ *yMax = t;
+ }
+ if (*xMin >= *xMax || *yMin >= *yMax) {
+ return splashClipAllOutside;
+ }
+ return state->clip->testRect(*xMin, *yMin, *xMax - 1, *yMax - 1,
+ state->strokeAdjust);
+}
+
+void Splash::dumpPath(SplashPath *path) {
+ int i;
+
+ for (i = 0; i < path->length; ++i) {
+ printf(" %3d: x=%8.2f y=%8.2f%s%s%s%s\n",
+ i, (double)path->pts[i].x, (double)path->pts[i].y,
+ (path->flags[i] & splashPathFirst) ? " first" : "",
+ (path->flags[i] & splashPathLast) ? " last" : "",
+ (path->flags[i] & splashPathClosed) ? " closed" : "",
+ (path->flags[i] & splashPathCurve) ? " curve" : "");
+ }
+ if (path->hintsLength == 0) {
+ printf(" no hints\n");
+ } else {
+ for (i = 0; i < path->hintsLength; ++i) {
+ printf(" hint %3d: ctrl0=%d ctrl1=%d pts=%d..%d\n",
+ i, path->hints[i].ctrl0, path->hints[i].ctrl1,
+ path->hints[i].firstPt, path->hints[i].lastPt);
+ }
+ }
+}
+
+void Splash::dumpXPath(SplashXPath *path) {
+ int i;
+
+ for (i = 0; i < path->length; ++i) {
+ printf(" %4d: x0=%8.2f y0=%8.2f x1=%8.2f y1=%8.2f count=%d\n",
+ i, (double)path->segs[i].x0, (double)path->segs[i].y0,
+ (double)path->segs[i].x1, (double)path->segs[i].y1,
+ path->segs[i].count);
+ }
+}
+
diff --git a/splash/Splash.h b/splash/Splash.h
new file mode 100644
index 0000000..9622b07
--- /dev/null
+++ b/splash/Splash.h
@@ -0,0 +1,537 @@
+//========================================================================
+//
+// Splash.h
+//
+// Copyright 2003-2013 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef SPLASH_H
+#define SPLASH_H
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include "SplashTypes.h"
+#include "SplashClip.h"
+
+class GString;
+class Splash;
+class SplashBitmap;
+struct SplashGlyphBitmap;
+class SplashState;
+class SplashPattern;
+class SplashScreen;
+class SplashPath;
+class SplashXPath;
+class SplashFont;
+struct SplashPipe;
+struct SplashDrawImageMaskRowData;
+class ImageScaler;
+typedef void (Splash::*SplashDrawImageMaskRowFunc)(
+ SplashDrawImageMaskRowData *data,
+ Guchar *maskData,
+ int x, int y, int width);
+struct SplashDrawImageRowData;
+typedef void (Splash::*SplashDrawImageRowFunc)(SplashDrawImageRowData *data,
+ Guchar *colorData,
+ Guchar *alphaData,
+ int x, int y, int width);
+
+//------------------------------------------------------------------------
+
+// Retrieves the next line of pixels in an image mask. Normally,
+// fills in *<line> and returns true. If the image stream is
+// exhausted, returns false.
+typedef GBool (*SplashImageMaskSource)(void *data, Guchar *pixel);
+
+// Retrieves the next line of pixels in an image. Normally, fills in
+// *<line> and returns true. If the image stream is exhausted,
+// returns false.
+typedef GBool (*SplashImageSource)(void *data, SplashColorPtr colorLine,
+ Guchar *alphaLine);
+
+
+//------------------------------------------------------------------------
+
+enum SplashPipeResultColorCtrl {
+ splashPipeResultColorNoAlphaBlendMono,
+ splashPipeResultColorNoAlphaBlendRGB,
+#if SPLASH_CMYK
+ splashPipeResultColorNoAlphaBlendCMYK,
+#endif
+ splashPipeResultColorAlphaNoBlendMono,
+ splashPipeResultColorAlphaNoBlendRGB,
+#if SPLASH_CMYK
+ splashPipeResultColorAlphaNoBlendCMYK,
+#endif
+ splashPipeResultColorAlphaBlendMono,
+ splashPipeResultColorAlphaBlendRGB
+#if SPLASH_CMYK
+ ,
+ splashPipeResultColorAlphaBlendCMYK
+#endif
+};
+
+//------------------------------------------------------------------------
+
+// Transparency group destination bitmap initialization control.
+enum SplashGroupDestInitMode {
+ splashGroupDestPreInit, // dest is already initialized
+ splashGroupDestInitZero, // initialize to zero (isolated group)
+ splashGroupDestInitCopy // copy backdrop (non-isolated group)
+};
+
+//------------------------------------------------------------------------
+// SplashImageCache
+//------------------------------------------------------------------------
+
+// This holds a cached image, and is shared by multiple Splash objects
+// in the same thread.
+class SplashImageCache {
+public:
+
+ SplashImageCache();
+ ~SplashImageCache();
+ GBool match(GString *aTag, int aWidth, int aHeight,
+ SplashColorMode aMode, GBool aAlpha,
+ GBool aInterpolate);
+ void reset(GString *aTag, int aWidth, int aHeight,
+ SplashColorMode aMode, GBool aAlpha,
+ GBool aInterpolate);
+ void incRefCount();
+ void decRefCount();
+
+ GString *tag;
+ int width;
+ int height;
+ SplashColorMode mode;
+ GBool alpha;
+ GBool interpolate;
+ Guchar *colorData;
+ Guchar *alphaData;
+
+ int refCount;
+};
+
+//------------------------------------------------------------------------
+// Splash
+//------------------------------------------------------------------------
+
+class Splash {
+public:
+
+ // Create a new rasterizer object.
+ Splash(SplashBitmap *bitmapA, GBool vectorAntialiasA,
+ SplashImageCache *imageCacheA,
+ SplashScreenParams *screenParams = NULL);
+ Splash(SplashBitmap *bitmapA, GBool vectorAntialiasA,
+ SplashImageCache *imageCacheA, SplashScreen *screenA);
+
+ ~Splash();
+
+ //----- state read
+
+ SplashCoord *getMatrix();
+ SplashPattern *getStrokePattern();
+ SplashPattern *getFillPattern();
+ SplashScreen *getScreen();
+ SplashBlendFunc getBlendFunc();
+ SplashCoord getStrokeAlpha();
+ SplashCoord getFillAlpha();
+ SplashCoord getLineWidth();
+ int getLineCap();
+ int getLineJoin();
+ SplashCoord getMiterLimit();
+ SplashCoord getFlatness();
+ SplashCoord *getLineDash();
+ int getLineDashLength();
+ SplashCoord getLineDashPhase();
+ SplashStrokeAdjustMode getStrokeAdjust();
+ SplashClip *getClip();
+ SplashBitmap *getSoftMask();
+ GBool getInNonIsolatedGroup();
+ GBool getInKnockoutGroup();
+
+ //----- state write
+
+ void setMatrix(SplashCoord *matrix);
+ void setStrokePattern(SplashPattern *strokeColor);
+ void setFillPattern(SplashPattern *fillColor);
+ void setScreen(SplashScreen *screen);
+ void setBlendFunc(SplashBlendFunc func);
+ void setStrokeAlpha(SplashCoord alpha);
+ void setFillAlpha(SplashCoord alpha);
+ void setLineWidth(SplashCoord lineWidth);
+ void setLineCap(int lineCap);
+ void setLineJoin(int lineJoin);
+ void setMiterLimit(SplashCoord miterLimit);
+ void setFlatness(SplashCoord flatness);
+ // the <lineDash> array will be copied
+ void setLineDash(SplashCoord *lineDash, int lineDashLength,
+ SplashCoord lineDashPhase);
+ void setStrokeAdjust(SplashStrokeAdjustMode strokeAdjust);
+ // NB: uses transformed coordinates.
+ void clipResetToRect(SplashCoord x0, SplashCoord y0,
+ SplashCoord x1, SplashCoord y1);
+ // NB: uses transformed coordinates.
+ SplashError clipToRect(SplashCoord x0, SplashCoord y0,
+ SplashCoord x1, SplashCoord y1);
+ // NB: uses untransformed coordinates.
+ SplashError clipToPath(SplashPath *path, GBool eo);
+ void setSoftMask(SplashBitmap *softMask, GBool deleteBitmap = gTrue);
+ void setInTransparencyGroup(SplashBitmap *groupBackBitmapA,
+ int groupBackXA, int groupBackYA,
+ SplashGroupDestInitMode groupDestInitModeA,
+ GBool nonIsolated, GBool knockout);
+ void forceDeferredInit(int y, int h);
+ GBool checkTransparentRect(int x, int y, int w, int h);
+ void setTransfer(Guchar *red, Guchar *green, Guchar *blue, Guchar *gray);
+ void setOverprintMask(Guint overprintMask);
+ void setEnablePathSimplification(GBool en);
+
+ //----- state save/restore
+
+ void saveState();
+ SplashError restoreState();
+
+ //----- drawing operations
+
+ // Fill the bitmap with <color>. This is not subject to clipping.
+ void clear(SplashColorPtr color, Guchar alpha = 0x00);
+
+ // Stroke a path using the current stroke pattern.
+ SplashError stroke(SplashPath *path);
+
+ // Fill a path using the current fill pattern.
+ SplashError fill(SplashPath *path, GBool eo);
+
+ // Draw a character, using the current fill pattern.
+ SplashError fillChar(SplashCoord x, SplashCoord y, int c, SplashFont *font);
+
+ // Draw a glyph, using the current fill pattern. This function does
+ // not free any data, i.e., it ignores glyph->freeData.
+ SplashError fillGlyph(SplashCoord x, SplashCoord y,
+ SplashGlyphBitmap *glyph);
+
+ // Draws an image mask using the fill color. This will read <h>
+ // lines of <w> pixels from <src>, starting with the top line. "1"
+ // pixels will be drawn with the current fill color; "0" pixels are
+ // transparent. The matrix:
+ // [ mat[0] mat[1] 0 ]
+ // [ mat[2] mat[3] 0 ]
+ // [ mat[4] mat[5] 1 ]
+ // maps a unit square to the desired destination for the image, in
+ // PostScript style:
+ // [x' y' 1] = [x y 1] * mat
+ // Note that the Splash y axis points downward, and the image source
+ // is assumed to produce pixels in raster order, starting from the
+ // top line. If [interpolate] is false, no filtering is done when
+ // upsampling. If [antialias] is false, no filtering is done when
+ // upsampling (overriding the [interpolate] flag), and threshold
+ // filtering is done when downsampling.
+ SplashError fillImageMask(GString *imageTag,
+ SplashImageMaskSource src, void *srcData,
+ int w, int h, SplashCoord *mat,
+ GBool glyphMode, GBool interpolate,
+ GBool antialias);
+
+ // Draw an image. This will read <h> lines of <w> pixels from
+ // <src>, starting with the top line. These pixels are assumed to
+ // be in the source mode, <srcMode>. If <srcAlpha> is true, the
+ // alpha values returned by <src> are used; otherwise they are
+ // ignored. The following combinations of source and target modes
+ // are supported:
+ // source target
+ // ------ ------
+ // Mono8 Mono1 -- with dithering
+ // Mono8 Mono8
+ // RGB8 RGB8
+ // BGR8 RGB8
+ // CMYK8 CMYK8
+ // The matrix behaves as for fillImageMask.
+ SplashError drawImage(GString *imageTag,
+ SplashImageSource src, void *srcData,
+ SplashColorMode srcMode, GBool srcAlpha,
+ int w, int h, SplashCoord *mat,
+ GBool interpolate);
+
+ // Composite a rectangular region from <src> onto this Splash
+ // object.
+ SplashError composite(SplashBitmap *src, int xSrc, int ySrc,
+ int xDest, int yDest, int w, int h,
+ GBool noClip, GBool nonIsolated);
+
+ // Composite a rectangular region from <src> onto this Splash
+ // object, using <srcOverprintMaskBitmap> as the overprint mask per
+ // pixel. This is only supported for CMYK and DeviceN bitmaps.
+ SplashError compositeWithOverprint(SplashBitmap *src,
+ Guint *srcOverprintMaskBitmap,
+ int xSrc, int ySrc,
+ int xDest, int yDest, int w, int h,
+ GBool noClip, GBool nonIsolated);
+
+ // Composite this Splash object onto a background color. The
+ // background alpha is assumed to be 1.
+ void compositeBackground(SplashColorPtr color);
+
+ // Copy a rectangular region from <src> onto the bitmap belonging to
+ // this Splash object. The destination alpha values are all set to
+ // zero.
+ SplashError blitTransparent(SplashBitmap *src, int xSrc, int ySrc,
+ int xDest, int yDest, int w, int h);
+
+ // Copy a rectangular region from the bitmap belonging to this
+ // Splash object to <dest>. The alpha values are corrected for a
+ // non-isolated group.
+ SplashError blitCorrectedAlpha(SplashBitmap *dest, int xSrc, int ySrc,
+ int xDest, int yDest, int w, int h);
+
+ //----- misc
+
+ // Construct a path for a stroke, given the path to be stroked and
+ // the line width <w>. All other stroke parameters are taken from
+ // the current state. If <flatten> is true, this function will
+ // first flatten the path and handle the linedash.
+ SplashPath *makeStrokePath(SplashPath *path, SplashCoord w,
+ int lineCap, int lineJoin,
+ GBool flatten = gTrue);
+
+ // Reduce the size of a rectangle as much as possible by moving any
+ // edges that are completely outside the clip region. Returns the
+ // clipping status of the resulting rectangle.
+ SplashClipResult limitRectToClipRect(int *xMin, int *yMin,
+ int *xMax, int *yMax);
+
+ // Return the associated bitmap.
+ SplashBitmap *getBitmap() { return bitmap; }
+
+ // Enable writing the per-pixel overprint mask to a separate bitmap.
+ void setOverprintMaskBitmap(Guint *overprintMaskBitmapA)
+ { overprintMaskBitmap = overprintMaskBitmapA; }
+
+ // Set the minimum line width.
+ void setMinLineWidth(SplashCoord w) { minLineWidth = w; }
+
+ // Get a bounding box which includes all modifications since the
+ // last call to clearModRegion.
+ void getModRegion(int *xMin, int *yMin, int *xMax, int *yMax)
+ { *xMin = modXMin; *yMin = modYMin; *xMax = modXMax; *yMax = modYMax; }
+
+ // Clear the modified region bounding box.
+ void clearModRegion();
+
+ // Get clipping status for the last drawing operation subject to
+ // clipping.
+ SplashClipResult getClipRes() { return opClipRes; }
+
+ // Toggle debug mode on or off.
+ void setDebugMode(GBool debugModeA) { debugMode = debugModeA; }
+
+ SplashImageCache *getImageCache() { return imageCache; }
+
+#if 1 //~tmp: turn off anti-aliasing temporarily
+ void setInShading(GBool sh) { inShading = sh; }
+#endif
+
+
+private:
+
+ void pipeInit(SplashPipe *pipe, SplashPattern *pattern,
+ Guchar aInput, GBool usesShape,
+ GBool nonIsolatedGroup, GBool usesSrcOverprint = gFalse);
+ void pipeRun(SplashPipe *pipe, int x0, int x1, int y,
+ Guchar *shapePtr, SplashColorPtr cSrcPtr);
+ void pipeRunSimpleMono1(SplashPipe *pipe, int x0, int x1, int y,
+ Guchar *shapePtr, SplashColorPtr cSrcPtr);
+ void pipeRunSimpleMono8(SplashPipe *pipe, int x0, int x1, int y,
+ Guchar *shapePtr, SplashColorPtr cSrcPtr);
+ void pipeRunSimpleRGB8(SplashPipe *pipe, int x0, int x1, int y,
+ Guchar *shapePtr, SplashColorPtr cSrcPtr);
+ void pipeRunSimpleBGR8(SplashPipe *pipe, int x0, int x1, int y,
+ Guchar *shapePtr, SplashColorPtr cSrcPtr);
+#if SPLASH_CMYK
+ void pipeRunSimpleCMYK8(SplashPipe *pipe, int x0, int x1, int y,
+ Guchar *shapePtr, SplashColorPtr cSrcPtr);
+#endif
+ void pipeRunShapeMono1(SplashPipe *pipe, int x0, int x1, int y,
+ Guchar *shapePtr, SplashColorPtr cSrcPtr);
+ void pipeRunShapeMono8(SplashPipe *pipe, int x0, int x1, int y,
+ Guchar *shapePtr, SplashColorPtr cSrcPtr);
+ void pipeRunShapeRGB8(SplashPipe *pipe, int x0, int x1, int y,
+ Guchar *shapePtr, SplashColorPtr cSrcPtr);
+ void pipeRunShapeBGR8(SplashPipe *pipe, int x0, int x1, int y,
+ Guchar *shapePtr, SplashColorPtr cSrcPtr);
+#if SPLASH_CMYK
+ void pipeRunShapeCMYK8(SplashPipe *pipe, int x0, int x1, int y,
+ Guchar *shapePtr, SplashColorPtr cSrcPtr);
+#endif
+ void pipeRunShapeNoAlphaMono8(SplashPipe *pipe, int x0, int x1, int y,
+ Guchar *shapePtr, SplashColorPtr cSrcPtr);
+ void pipeRunAAMono1(SplashPipe *pipe, int x0, int x1, int y,
+ Guchar *shapePtr, SplashColorPtr cSrcPtr);
+ void pipeRunAAMono8(SplashPipe *pipe, int x0, int x1, int y,
+ Guchar *shapePtr, SplashColorPtr cSrcPtr);
+ void pipeRunAARGB8(SplashPipe *pipe, int x0, int x1, int y,
+ Guchar *shapePtr, SplashColorPtr cSrcPtr);
+ void pipeRunAABGR8(SplashPipe *pipe, int x0, int x1, int y,
+ Guchar *shapePtr, SplashColorPtr cSrcPtr);
+#if SPLASH_CMYK
+ void pipeRunAACMYK8(SplashPipe *pipe, int x0, int x1, int y,
+ Guchar *shapePtr, SplashColorPtr cSrcPtr);
+#endif
+ void pipeRunSoftMaskMono8(SplashPipe *pipe, int x0, int x1, int y,
+ Guchar *shapePtr, SplashColorPtr cSrcPtr);
+ void pipeRunSoftMaskRGB8(SplashPipe *pipe, int x0, int x1, int y,
+ Guchar *shapePtr, SplashColorPtr cSrcPtr);
+ void pipeRunSoftMaskBGR8(SplashPipe *pipe, int x0, int x1, int y,
+ Guchar *shapePtr, SplashColorPtr cSrcPtr);
+#if SPLASH_CMYK
+ void pipeRunSoftMaskCMYK8(SplashPipe *pipe, int x0, int x1, int y,
+ Guchar *shapePtr, SplashColorPtr cSrcPtr);
+#endif
+ void pipeRunNonIsoMono8(SplashPipe *pipe, int x0, int x1, int y,
+ Guchar *shapePtr, SplashColorPtr cSrcPtr);
+ void pipeRunNonIsoRGB8(SplashPipe *pipe, int x0, int x1, int y,
+ Guchar *shapePtr, SplashColorPtr cSrcPtr);
+ void pipeRunNonIsoBGR8(SplashPipe *pipe, int x0, int x1, int y,
+ Guchar *shapePtr, SplashColorPtr cSrcPtr);
+#if SPLASH_CMYK
+ void pipeRunNonIsoCMYK8(SplashPipe *pipe, int x0, int x1, int y,
+ Guchar *shapePtr, SplashColorPtr cSrcPtr);
+#endif
+ void useDestRow(int y);
+ void copyGroupBackdropRow(int y);
+ void transform(SplashCoord *matrix, SplashCoord xi, SplashCoord yi,
+ SplashCoord *xo, SplashCoord *yo);
+ void updateModX(int x);
+ void updateModY(int y);
+ void strokeNarrow(SplashPath *path);
+ void drawStrokeSpan(SplashPipe *pipe, int x0, int x1, int y, GBool noClip);
+ void strokeWide(SplashPath *path, SplashCoord w,
+ int lineCap, int lineJoin);
+ SplashPath *flattenPath(SplashPath *path, SplashCoord *matrix,
+ SplashCoord flatness);
+ void flattenCurve(SplashCoord x0, SplashCoord y0,
+ SplashCoord x1, SplashCoord y1,
+ SplashCoord x2, SplashCoord y2,
+ SplashCoord x3, SplashCoord y3,
+ SplashCoord *matrix, SplashCoord flatness2,
+ SplashPath *fPath);
+ SplashPath *makeDashedPath(SplashPath *xPath);
+ SplashError fillWithPattern(SplashPath *path, GBool eo,
+ SplashPattern *pattern, SplashCoord alpha);
+ SplashPath *tweakFillPath(SplashPath *path);
+ GBool pathAllOutside(SplashPath *path);
+ SplashError fillGlyph2(int x0, int y0, SplashGlyphBitmap *glyph);
+ void getImageBounds(SplashCoord xyMin, SplashCoord xyMax,
+ int *xyMinI, int *xyMaxI);
+ void drawImageMaskArbitraryNoInterp(Guchar *scaledMask,
+ SplashDrawImageMaskRowData *dd,
+ SplashDrawImageMaskRowFunc drawRowFunc,
+ SplashCoord *invMat,
+ int scaledWidth, int scaledHeight,
+ int xMin, int yMin, int xMax, int yMax);
+ void drawImageMaskArbitraryInterp(Guchar *scaledMask,
+ SplashDrawImageMaskRowData *dd,
+ SplashDrawImageMaskRowFunc drawRowFunc,
+ SplashCoord *invMat,
+ int scaledWidth, int scaledHeight,
+ int xMin, int yMin, int xMax, int yMax);
+ void mirrorImageMaskRow(Guchar *maskIn, Guchar *maskOut, int width);
+ void drawImageMaskRowNoClip(SplashDrawImageMaskRowData *data,
+ Guchar *maskData,
+ int x, int y, int width);
+ void drawImageMaskRowClipNoAA(SplashDrawImageMaskRowData *data,
+ Guchar *maskData,
+ int x, int y, int width);
+ void drawImageMaskRowClipAA(SplashDrawImageMaskRowData *data,
+ Guchar *maskData,
+ int x, int y, int width);
+ ImageScaler *getImageScaler(GString *imageTag,
+ SplashImageSource src, void *srcData,
+ int w, int h, int nComps,
+ int scaledWidth, int scaledHeight,
+ SplashColorMode srcMode,
+ GBool srcAlpha, GBool interpolate);
+ void getScaledImage(GString *imageTag,
+ SplashImageSource src, void *srcData,
+ int w, int h, int nComps,
+ int scaledWidth, int scaledHeight,
+ SplashColorMode srcMode,
+ GBool srcAlpha, GBool interpolate,
+ Guchar **scaledColor, Guchar **scaledAlpha,
+ GBool *freeScaledImage);
+ void drawImageArbitraryNoInterp(Guchar *scaledColor, Guchar *scaledAlpha,
+ SplashDrawImageRowData *dd,
+ SplashDrawImageRowFunc drawRowFunc,
+ SplashCoord *invMat,
+ int scaledWidth, int scaledHeight,
+ int xMin, int yMin, int xMax, int yMax,
+ int nComps, GBool srcAlpha);
+ void drawImageArbitraryInterp(Guchar *scaledColor, Guchar *scaledAlpha,
+ SplashDrawImageRowData *dd,
+ SplashDrawImageRowFunc drawRowFunc,
+ SplashCoord *invMat,
+ int scaledWidth, int scaledHeight,
+ int xMin, int yMin, int xMax, int yMax,
+ int nComps, GBool srcAlpha);
+ void mirrorImageRow(Guchar *colorIn, Guchar *alphaIn,
+ Guchar *colorOut, Guchar *alphaOut,
+ int width, int nComps, GBool srcAlpha);
+ void drawImageRowNoClipNoAlpha(SplashDrawImageRowData *data,
+ Guchar *colorData, Guchar *alphaData,
+ int x, int y, int width);
+ void drawImageRowNoClipAlpha(SplashDrawImageRowData *data,
+ Guchar *colorData, Guchar *alphaData,
+ int x, int y, int width);
+ void drawImageRowClipNoAlphaNoAA(SplashDrawImageRowData *data,
+ Guchar *colorData,
+ Guchar *alphaData,
+ int x, int y, int width);
+ void drawImageRowClipNoAlphaAA(SplashDrawImageRowData *data,
+ Guchar *colorData,
+ Guchar *alphaData,
+ int x, int y, int width);
+ void drawImageRowClipAlphaNoAA(SplashDrawImageRowData *data,
+ Guchar *colorData,
+ Guchar *alphaData,
+ int x, int y, int width);
+ void drawImageRowClipAlphaAA(SplashDrawImageRowData *data,
+ Guchar *colorData,
+ Guchar *alphaData,
+ int x, int y, int width);
+ void dumpPath(SplashPath *path);
+ void dumpXPath(SplashXPath *path);
+
+
+ static SplashPipeResultColorCtrl pipeResultColorNoAlphaBlend[];
+ static SplashPipeResultColorCtrl pipeResultColorAlphaNoBlend[];
+ static SplashPipeResultColorCtrl pipeResultColorAlphaBlend[];
+ static int pipeNonIsoGroupCorrection[];
+
+ SplashBitmap *bitmap;
+ int bitmapComps;
+ SplashState *state;
+ Guchar *scanBuf;
+ Guchar *scanBuf2;
+ SplashBitmap // for transparency groups, this is the bitmap
+ *groupBackBitmap; // containing the alpha0/color0 values
+ int groupBackX, groupBackY; // offset within groupBackBitmap
+ SplashGroupDestInitMode groupDestInitMode;
+ int groupDestInitYMin, groupDestInitYMax;
+ Guint *overprintMaskBitmap;
+ SplashCoord minLineWidth;
+ int modXMin, modYMin, modXMax, modYMax;
+ SplashClipResult opClipRes;
+ GBool vectorAntialias;
+ GBool inShading;
+ GBool debugMode;
+
+ SplashImageCache *imageCache;
+};
+
+#endif
diff --git a/splash/SplashBitmap.cc b/splash/SplashBitmap.cc
new file mode 100644
index 0000000..db341d7
--- /dev/null
+++ b/splash/SplashBitmap.cc
@@ -0,0 +1,288 @@
+//========================================================================
+//
+// SplashBitmap.cc
+//
+// Copyright 2003-2013 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stdio.h>
+#include <limits.h>
+#include "gmem.h"
+#include "gmempp.h"
+#include "gfile.h"
+#include "Trace.h"
+#include "SplashErrorCodes.h"
+#include "SplashBitmap.h"
+
+//------------------------------------------------------------------------
+// SplashBitmap
+//------------------------------------------------------------------------
+
+SplashBitmap::SplashBitmap(int widthA, int heightA, int rowPad,
+ SplashColorMode modeA, GBool alphaA,
+ GBool topDown, SplashBitmap *parentA) {
+ // NB: this code checks that rowSize fits in a signed 32-bit
+ // integer, because some code (outside this class) makes that
+ // assumption
+ width = widthA;
+ height = heightA;
+ mode = modeA;
+ switch (mode) {
+ case splashModeMono1:
+ if (width <= 0) {
+ gMemError("invalid bitmap width");
+ }
+ rowSize = (width + 7) >> 3;
+ break;
+ case splashModeMono8:
+ if (width <= 0) {
+ gMemError("invalid bitmap width");
+ }
+ rowSize = width;
+ break;
+ case splashModeRGB8:
+ case splashModeBGR8:
+ if (width <= 0 || width > INT_MAX / 3) {
+ gMemError("invalid bitmap width");
+ }
+ rowSize = (SplashBitmapRowSize)width * 3;
+ break;
+#if SPLASH_CMYK
+ case splashModeCMYK8:
+ if (width <= 0 || width > INT_MAX / 4) {
+ gMemError("invalid bitmap width");
+ }
+ rowSize = (SplashBitmapRowSize)width * 4;
+ break;
+#endif
+ }
+ rowSize += rowPad - 1;
+ rowSize -= rowSize % rowPad;
+
+ traceAlloc(this, "alloc bitmap: %d x %d x %d %s -> %lld bytes",
+ width, height, splashColorModeNComps[mode],
+ alphaA ? "with alpha" : "without alpha",
+ height * rowSize + (alphaA ? height * width : 0));
+
+ parent = parentA;
+ oldData = NULL;
+ oldAlpha = NULL;
+ oldRowSize = 0;
+ oldAlphaRowSize = 0;
+ oldHeight = 0;
+ if (parent && parent->oldData &&
+ parent->oldRowSize == rowSize &&
+ parent->oldHeight == height) {
+ data = parent->oldData;
+ parent->oldData = NULL;
+ traceMessage("reusing bitmap memory");
+ } else {
+ data = (SplashColorPtr)gmallocn64(height, rowSize);
+ traceMessage("not reusing bitmap memory"
+ " (parent=%p parent->oldData=%p same-size=%d)",
+ parent, parent ? parent->oldData : NULL,
+ parent ? (parent->oldRowSize == rowSize &&
+ parent->oldHeight == height) : 0);
+ }
+ if (!topDown) {
+ data += (height - 1) * rowSize;
+ rowSize = -rowSize;
+ }
+ if (alphaA) {
+ alphaRowSize = width;
+ if (parent && parent->oldAlpha &&
+ parent->oldAlphaRowSize == alphaRowSize &&
+ parent->oldHeight == height) {
+ alpha = parent->oldAlpha;
+ parent->oldAlpha = NULL;
+ } else {
+ alpha = (Guchar *)gmallocn64(height, alphaRowSize);
+ }
+ } else {
+ alphaRowSize = 0;
+ alpha = NULL;
+ }
+}
+
+SplashBitmap::~SplashBitmap() {
+ traceFree(this, "free bitmap");
+ if (data && rowSize < 0) {
+ rowSize = -rowSize;
+ data -= (height - 1) * rowSize;
+ }
+ if (parent && rowSize > 4000000 / height) {
+ gfree(parent->oldData);
+ gfree(parent->oldAlpha);
+ parent->oldData = data;
+ parent->oldAlpha = alpha;
+ parent->oldRowSize = rowSize;
+ parent->oldAlphaRowSize = alphaRowSize;
+ parent->oldHeight = height;
+ } else {
+ gfree(data);
+ gfree(alpha);
+ }
+ gfree(oldData);
+ gfree(oldAlpha);
+}
+
+SplashError SplashBitmap::writePNMFile(char *fileName) {
+ FILE *f;
+ SplashError err;
+
+ if (!(f = openFile(fileName, "wb"))) {
+ return splashErrOpenFile;
+ }
+ err = writePNMFile(f);
+ fclose(f);
+ return err;
+}
+
+SplashError SplashBitmap::writePNMFile(FILE *f) {
+ SplashColorPtr row, p;
+ int x, y;
+
+ switch (mode) {
+
+ case splashModeMono1:
+ fprintf(f, "P4\n%d %d\n", width, height);
+ row = data;
+ for (y = 0; y < height; ++y) {
+ p = row;
+ for (x = 0; x < width; x += 8) {
+ fputc(*p ^ 0xff, f);
+ ++p;
+ }
+ row += rowSize;
+ }
+ break;
+
+ case splashModeMono8:
+ fprintf(f, "P5\n%d %d\n255\n", width, height);
+ row = data;
+ for (y = 0; y < height; ++y) {
+ fwrite(row, 1, width, f);
+ row += rowSize;
+ }
+ break;
+
+ case splashModeRGB8:
+ fprintf(f, "P6\n%d %d\n255\n", width, height);
+ row = data;
+ for (y = 0; y < height; ++y) {
+ fwrite(row, 1, 3 * width, f);
+ row += rowSize;
+ }
+ break;
+
+ case splashModeBGR8:
+ fprintf(f, "P6\n%d %d\n255\n", width, height);
+ row = data;
+ for (y = 0; y < height; ++y) {
+ p = row;
+ for (x = 0; x < width; ++x) {
+ fputc(splashBGR8R(p), f);
+ fputc(splashBGR8G(p), f);
+ fputc(splashBGR8B(p), f);
+ p += 3;
+ }
+ row += rowSize;
+ }
+ break;
+
+#if SPLASH_CMYK
+ case splashModeCMYK8:
+ fprintf(f, "P7\n");
+ fprintf(f, "WIDTH %d\n", width);
+ fprintf(f, "HEIGHT %d\n", height);
+ fprintf(f, "DEPTH 4\n");
+ fprintf(f, "MAXVAL 255\n");
+ fprintf(f, "TUPLTYPE CMYK\n");
+ fprintf(f, "ENDHDR\n");
+ row = data;
+ for (y = 0; y < height; ++y) {
+ fwrite(row, 1, 4 * width, f);
+ row += rowSize;
+ }
+ break;
+#endif
+
+ }
+
+ return splashOk;
+}
+
+SplashError SplashBitmap::writeAlphaPGMFile(char *fileName) {
+ FILE *f;
+
+ if (!alpha) {
+ return splashErrModeMismatch;
+ }
+ if (!(f = openFile(fileName, "wb"))) {
+ return splashErrOpenFile;
+ }
+ fprintf(f, "P5\n%d %d\n255\n", width, height);
+ fwrite(alpha, 1, width * height, f);
+ fclose(f);
+ return splashOk;
+}
+
+
+void SplashBitmap::getPixel(int x, int y, SplashColorPtr pixel) {
+ SplashColorPtr p;
+
+ if (y < 0 || y >= height || x < 0 || x >= width) {
+ return;
+ }
+ switch (mode) {
+ case splashModeMono1:
+ p = &data[y * rowSize + (x >> 3)];
+ pixel[0] = (p[0] & (0x80 >> (x & 7))) ? 0xff : 0x00;
+ break;
+ case splashModeMono8:
+ p = &data[y * rowSize + x];
+ pixel[0] = p[0];
+ break;
+ case splashModeRGB8:
+ p = &data[y * rowSize + 3 * x];
+ pixel[0] = p[0];
+ pixel[1] = p[1];
+ pixel[2] = p[2];
+ break;
+ case splashModeBGR8:
+ p = &data[y * rowSize + 3 * x];
+ pixel[0] = p[2];
+ pixel[1] = p[1];
+ pixel[2] = p[0];
+ break;
+#if SPLASH_CMYK
+ case splashModeCMYK8:
+ p = &data[y * rowSize + 4 * x];
+ pixel[0] = p[0];
+ pixel[1] = p[1];
+ pixel[2] = p[2];
+ pixel[3] = p[3];
+ break;
+#endif
+ }
+}
+
+Guchar SplashBitmap::getAlpha(int x, int y) {
+ return alpha[y * (size_t)width + x];
+}
+
+SplashColorPtr SplashBitmap::takeData() {
+ SplashColorPtr data2;
+
+ data2 = data;
+ data = NULL;
+ return data2;
+}
+
diff --git a/splash/SplashBitmap.h b/splash/SplashBitmap.h
new file mode 100644
index 0000000..54975a3
--- /dev/null
+++ b/splash/SplashBitmap.h
@@ -0,0 +1,98 @@
+//========================================================================
+//
+// SplashBitmap.h
+//
+// Copyright 2003-2013 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef SPLASHBITMAP_H
+#define SPLASHBITMAP_H
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include <stdio.h>
+#include <limits.h>
+// older compilers won't define SIZE_MAX in stdint.h without this
+#ifndef __STDC_LIMIT_MACROS
+# define __STDC_LIMIT_MACROS 1
+#endif
+#include <stdint.h>
+#include "SplashTypes.h"
+
+//------------------------------------------------------------------------
+
+// ssize_t isn't well-defined, so define our own
+#if SIZE_MAX == UINT_MAX
+ typedef int SplashBitmapRowSize;
+# define SplashBitmapRowSizeMax INT_MAX
+#else
+ typedef long long SplashBitmapRowSize;
+# define SplashBitmapRowSizeMax LLONG_MAX
+#endif
+
+//------------------------------------------------------------------------
+// SplashBitmap
+//------------------------------------------------------------------------
+
+class SplashBitmap {
+public:
+
+ // Create a new bitmap. It will have <widthA> x <heightA> pixels in
+ // color mode <modeA>. Rows will be padded out to a multiple of
+ // <rowPad> bytes. If <topDown> is false, the bitmap will be stored
+ // upside-down, i.e., with the last row first in memory.
+ SplashBitmap(int widthA, int heightA, int rowPad,
+ SplashColorMode modeA, GBool alphaA,
+ GBool topDown, SplashBitmap *parentA);
+
+ ~SplashBitmap();
+
+ int getWidth() { return width; }
+ int getHeight() { return height; }
+ SplashBitmapRowSize getRowSize() { return rowSize; }
+ size_t getAlphaRowSize() { return alphaRowSize; }
+ SplashColorMode getMode() { return mode; }
+ SplashColorPtr getDataPtr() { return data; }
+ Guchar *getAlphaPtr() { return alpha; }
+
+ SplashError writePNMFile(char *fileName);
+ SplashError writePNMFile(FILE *f);
+ SplashError writeAlphaPGMFile(char *fileName);
+
+ void getPixel(int x, int y, SplashColorPtr pixel);
+ Guchar getAlpha(int x, int y);
+
+ // Caller takes ownership of the bitmap data. The SplashBitmap
+ // object is no longer valid -- the next call should be to the
+ // destructor.
+ SplashColorPtr takeData();
+
+private:
+
+ int width, height; // size of bitmap
+ SplashBitmapRowSize rowSize; // size of one row of data, in bytes
+ // - negative for bottom-up bitmaps
+ size_t alphaRowSize; // size of one row of alpha, in bytes
+ SplashColorMode mode; // color mode
+ SplashColorPtr data; // pointer to row zero of the color data
+ Guchar *alpha; // pointer to row zero of the alpha data
+ // (always top-down)
+
+ // save the last-allocated (large) bitmap data and reuse if possible
+ SplashBitmap *parent;
+ SplashColorPtr oldData;
+ Guchar *oldAlpha;
+ SplashBitmapRowSize oldRowSize;
+ size_t oldAlphaRowSize;
+ int oldHeight;
+
+ friend class Splash;
+};
+
+
+#endif
diff --git a/splash/SplashClip.cc b/splash/SplashClip.cc
new file mode 100644
index 0000000..bf7b802
--- /dev/null
+++ b/splash/SplashClip.cc
@@ -0,0 +1,521 @@
+//========================================================================
+//
+// SplashClip.cc
+//
+// Copyright 2003-2013 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include "gmem.h"
+#include "gmempp.h"
+#include "SplashErrorCodes.h"
+#include "SplashPath.h"
+#include "SplashXPath.h"
+#include "SplashXPathScanner.h"
+#include "SplashClip.h"
+
+//------------------------------------------------------------------------
+
+// Compute x * y / 255, where x and y are in [0, 255].
+static inline Guchar mul255(Guchar x, Guchar y) {
+ int z;
+
+ z = (int)x * (int)y;
+ return (Guchar)((z + (z >> 8) + 0x80) >> 8);
+}
+
+//------------------------------------------------------------------------
+// SplashClip
+//------------------------------------------------------------------------
+
+SplashClip::SplashClip(int hardXMinA, int hardYMinA,
+ int hardXMaxA, int hardYMaxA) {
+ int w;
+
+ hardXMin = hardXMinA;
+ hardYMin = hardYMinA;
+ hardXMax = hardXMaxA;
+ hardYMax = hardYMaxA;
+ xMin = hardXMin;
+ yMin = hardYMin;
+ xMax = hardXMax;
+ yMax = hardYMax;
+ intBoundsValid = gFalse;
+ paths = NULL;
+ eo = NULL;
+ scanners = NULL;
+ length = size = 0;
+ isSimple = gTrue;
+ prev = NULL;
+ if ((w = hardXMax + 1) <= 0) {
+ w = 1;
+ }
+ buf = (Guchar *)gmalloc(w);
+}
+
+SplashClip::SplashClip(SplashClip *clip) {
+ int w;
+
+ hardXMin = clip->hardXMin;
+ hardYMin = clip->hardYMin;
+ hardXMax = clip->hardXMax;
+ hardYMax = clip->hardYMax;
+ xMin = clip->xMin;
+ yMin = clip->yMin;
+ xMax = clip->xMax;
+ yMax = clip->yMax;
+ xMinI = clip->xMinI;
+ yMinI = clip->yMinI;
+ xMaxI = clip->xMaxI;
+ yMaxI = clip->yMaxI;
+ intBoundsValid = clip->intBoundsValid;
+ intBoundsStrokeAdjust = clip->intBoundsStrokeAdjust;
+ paths = NULL;
+ eo = NULL;
+ scanners = NULL;
+ length = size = 0;
+ isSimple = clip->isSimple;
+ prev = clip;
+ if ((w = splashCeil(xMax)) <= 0) {
+ w = 1;
+ }
+ buf = (Guchar *)gmalloc(w);
+}
+
+SplashClip::~SplashClip() {
+ int i;
+
+ for (i = 0; i < length; ++i) {
+ delete scanners[i];
+ delete paths[i];
+ }
+ gfree(paths);
+ gfree(eo);
+ gfree(scanners);
+ gfree(buf);
+}
+
+void SplashClip::grow(int nPaths) {
+ if (length + nPaths > size) {
+ if (size == 0) {
+ size = 32;
+ }
+ while (size < length + nPaths) {
+ size *= 2;
+ }
+ paths = (SplashXPath **)greallocn(paths, size, sizeof(SplashXPath *));
+ eo = (Guchar *)greallocn(eo, size, sizeof(Guchar));
+ scanners = (SplashXPathScanner **)
+ greallocn(scanners, size, sizeof(SplashXPathScanner *));
+ }
+}
+
+void SplashClip::resetToRect(SplashCoord x0, SplashCoord y0,
+ SplashCoord x1, SplashCoord y1) {
+ int w, i;
+
+ for (i = 0; i < length; ++i) {
+ delete paths[i];
+ delete scanners[i];
+ }
+ gfree(paths);
+ gfree(eo);
+ gfree(scanners);
+ gfree(buf);
+ paths = NULL;
+ eo = NULL;
+ scanners = NULL;
+ length = size = 0;
+ isSimple = gTrue;
+ prev = NULL;
+
+ if (x0 < x1) {
+ xMin = x0;
+ xMax = x1;
+ } else {
+ xMin = x1;
+ xMax = x0;
+ }
+ if (y0 < y1) {
+ yMin = y0;
+ yMax = y1;
+ } else {
+ yMin = y1;
+ yMax = y0;
+ }
+ intBoundsValid = gFalse;
+ if ((w = splashCeil(xMax)) <= 0) {
+ w = 1;
+ }
+ buf = (Guchar *)gmalloc(w);
+}
+
+SplashError SplashClip::clipToRect(SplashCoord x0, SplashCoord y0,
+ SplashCoord x1, SplashCoord y1) {
+ if (x0 < x1) {
+ if (x0 > xMin) {
+ xMin = x0;
+ intBoundsValid = gFalse;
+ }
+ if (x1 < xMax) {
+ xMax = x1;
+ intBoundsValid = gFalse;
+ }
+ } else {
+ if (x1 > xMin) {
+ xMin = x1;
+ intBoundsValid = gFalse;
+ }
+ if (x0 < xMax) {
+ xMax = x0;
+ intBoundsValid = gFalse;
+ }
+ }
+ if (y0 < y1) {
+ if (y0 > yMin) {
+ yMin = y0;
+ intBoundsValid = gFalse;
+ }
+ if (y1 < yMax) {
+ yMax = y1;
+ intBoundsValid = gFalse;
+ }
+ } else {
+ if (y1 > yMin) {
+ yMin = y1;
+ intBoundsValid = gFalse;
+ }
+ if (y0 < yMax) {
+ yMax = y0;
+ intBoundsValid = gFalse;
+ }
+ }
+ return splashOk;
+}
+
+SplashError SplashClip::clipToPath(SplashPath *path, SplashCoord *matrix,
+ SplashCoord flatness, GBool eoA,
+ GBool enablePathSimplification,
+ SplashStrokeAdjustMode strokeAdjust) {
+ SplashXPath *xPath;
+ SplashCoord t;
+
+ xPath = new SplashXPath(path, matrix, flatness, gTrue,
+ enablePathSimplification,
+ strokeAdjust);
+
+ // check for an empty path
+ if (xPath->length == 0) {
+ xMin = yMin = 1;
+ xMax = yMax = 0;
+ intBoundsValid = gFalse;
+ delete xPath;
+ return splashOk;
+ }
+
+ // check for a rectangle
+ if (xPath->isRect) {
+ clipToRect(xPath->rectX0, xPath->rectY0, xPath->rectX1, xPath->rectY1);
+ delete xPath;
+ return splashOk;
+ }
+
+ grow(1);
+ paths[length] = xPath;
+ eo[length] = (Guchar)eoA;
+ if ((t = xPath->getXMin()) > xMin) {
+ xMin = t;
+ }
+ if ((t = xPath->getYMin()) > yMin) {
+ yMin = t;
+ }
+ if ((t = xPath->getXMax() + 1) < xMax) {
+ xMax = t;
+ }
+ if ((t = xPath->getYMax() + 1) < yMax) {
+ yMax = t;
+ }
+ intBoundsValid = gFalse;
+ scanners[length] = new SplashXPathScanner(xPath, eoA, splashFloor(yMin),
+ splashCeil(yMax) - 1);
+ ++length;
+ isSimple = gFalse;
+
+ return splashOk;
+}
+
+SplashClipResult SplashClip::testRect(int rectXMin, int rectYMin,
+ int rectXMax, int rectYMax,
+ SplashStrokeAdjustMode strokeAdjust) {
+ // In general, this function tests the rectangle:
+ // x = [rectXMin, rectXMax + 1) (note: coords are ints)
+ // y = [rectYMin, rectYMax + 1)
+ // against the clipping region:
+ // x = [xMin, xMax) (note: coords are fp)
+ // y = [yMin, yMax)
+
+ if (strokeAdjust != splashStrokeAdjustOff && isSimple) {
+ // special case for stroke adjustment with a simple clipping
+ // rectangle -- the clipping region is:
+ // x = [xMinI, xMaxI + 1)
+ // y = [yMinI, yMaxI + 1)
+ updateIntBounds(strokeAdjust);
+ if (xMinI > xMaxI || yMinI > yMaxI) {
+ return splashClipAllOutside;
+ }
+ if (rectXMax + 1 <= xMinI ||
+ rectXMin >= xMaxI + 1 ||
+ rectYMax + 1 <= yMinI ||
+ rectYMin >= yMaxI + 1) {
+ return splashClipAllOutside;
+ }
+ if (rectXMin >= xMinI &&
+ rectXMax <= xMaxI &&
+ rectYMin >= yMinI &&
+ rectYMax <= yMaxI) {
+ return splashClipAllInside;
+ }
+ } else {
+ if (xMin >= xMax || yMin >= yMax) {
+ return splashClipAllOutside;
+ }
+ if ((SplashCoord)(rectXMax + 1) <= xMin ||
+ (SplashCoord)rectXMin >= xMax ||
+ (SplashCoord)(rectYMax + 1) <= yMin ||
+ (SplashCoord)rectYMin >= yMax) {
+ return splashClipAllOutside;
+ }
+ if (isSimple &&
+ (SplashCoord)rectXMin >= xMin &&
+ (SplashCoord)(rectXMax + 1) <= xMax &&
+ (SplashCoord)rectYMin >= yMin &&
+ (SplashCoord)(rectYMax + 1) <= yMax) {
+ return splashClipAllInside;
+ }
+ }
+ return splashClipPartial;
+}
+
+void SplashClip::clipSpan(Guchar *line, int y, int x0, int x1,
+ SplashStrokeAdjustMode strokeAdjust) {
+ SplashClip *clip;
+ SplashCoord d;
+ int x0a, x1a, x0b, x1b, x, i;
+
+ updateIntBounds(strokeAdjust);
+
+ //--- clip to the integer rectangle
+
+ if (y < yMinI || y > yMaxI ||
+ x1 < xMinI || x0 > xMaxI) {
+ memset(line + x0, 0, x1 - x0 + 1);
+ return;
+ }
+
+ if (x0 > xMinI) {
+ x0a = x0;
+ } else {
+ x0a = xMinI;
+ memset(line + x0, 0, x0a - x0);
+ }
+
+ if (x1 < xMaxI) {
+ x1a = x1;
+ } else {
+ x1a = xMaxI;
+ memset(line + x1a + 1, 0, x1 - x1a);
+ }
+
+ if (x0a > x1a) {
+ return;
+ }
+
+ //--- clip to the floating point rectangle
+ // (if stroke adjustment is disabled)
+
+ if (strokeAdjust == splashStrokeAdjustOff) {
+
+ // clip left edge (xMin)
+ if (x0a == xMinI) {
+ d = (SplashCoord)(xMinI + 1) - xMin;
+ line[x0a] = (Guchar)(int)((SplashCoord)line[x0a] * d);
+ }
+
+ // clip right edge (xMax)
+ if (x1a == xMaxI) {
+ d = xMax - (SplashCoord)xMaxI;
+ line[x1a] = (Guchar)(int)((SplashCoord)line[x1a] * d);
+ }
+
+ // clip top edge (yMin)
+ if (y == yMinI) {
+ d = (SplashCoord)(yMinI + 1) - yMin;
+ for (x = x0a; x <= x1a; ++x) {
+ line[x] = (Guchar)(int)((SplashCoord)line[x] * d);
+ }
+ }
+
+ // clip bottom edge (yMax)
+ if (y == yMaxI) {
+ d = yMax - (SplashCoord)yMaxI;
+ for (x = x0a; x <= x1a; ++x) {
+ line[x] = (Guchar)(int)((SplashCoord)line[x] * d);
+ }
+ }
+ }
+
+ if (isSimple) {
+ return;
+ }
+
+ //--- clip to the paths
+
+ for (clip = this; clip; clip = clip->prev) {
+ for (i = 0; i < clip->length; ++i) {
+ clip->scanners[i]->getSpan(buf, y, x0a, x1a, &x0b, &x1b);
+ if (x0a < x0b) {
+ memset(line + x0a, 0, x0b - x0a);
+ }
+ for (x = x0b; x <= x1b; ++x) {
+ line[x] = mul255(line[x], buf[x]);
+ }
+ if (x1b < x1a) {
+ memset(line + x1b + 1, 0, x1a - x1b);
+ }
+ }
+ }
+}
+
+GBool SplashClip::clipSpanBinary(Guchar *line, int y, int x0, int x1,
+ SplashStrokeAdjustMode strokeAdjust) {
+ SplashClip *clip;
+ int x0a, x1a, x0b, x1b, x, i;
+ Guchar any;
+
+ updateIntBounds(strokeAdjust);
+
+ if (y < yMinI || y > yMaxI ||
+ x1 < xMinI || x0 > xMaxI) {
+ if (x0 <= x1) {
+ memset(line + x0, 0, x1 - x0 + 1);
+ }
+ return gFalse;
+ }
+
+ if (x0 > xMinI) {
+ x0a = x0;
+ } else {
+ x0a = xMinI;
+ memset(line + x0, 0, x0a - x0);
+ }
+
+ if (x1 < xMaxI) {
+ x1a = x1;
+ } else {
+ x1a = xMaxI;
+ memset(line + x1a + 1, 0, x1 - x1a);
+ }
+
+ if (x0a > x1a) {
+ return gFalse;
+ }
+
+ if (isSimple) {
+ for (x = x0a; x <= x1a; ++x) {
+ if (line[x]) {
+ return gTrue;
+ }
+ }
+ return gFalse;
+ }
+
+ any = 0;
+ for (clip = this; clip; clip = clip->prev) {
+ for (i = 0; i < clip->length; ++i) {
+ clip->scanners[i]->getSpanBinary(buf, y, x0a, x1a, &x0b, &x1b);
+ if (x0a < x0b) {
+ memset(line + x0a, 0, x0b - x0a);
+ }
+ for (x = x0b; x <= x1b; ++x) {
+ line[x] &= buf[x];
+ any |= line[x];
+ }
+ if (x1b < x1a) {
+ memset(line + x1b + 1, 0, x1a - x1b);
+ }
+ }
+ }
+
+ return any != 0;
+}
+
+int SplashClip::getXMinI(SplashStrokeAdjustMode strokeAdjust) {
+ updateIntBounds(strokeAdjust);
+ return xMinI;
+}
+
+int SplashClip::getXMaxI(SplashStrokeAdjustMode strokeAdjust) {
+ updateIntBounds(strokeAdjust);
+ return xMaxI;
+}
+
+int SplashClip::getYMinI(SplashStrokeAdjustMode strokeAdjust) {
+ updateIntBounds(strokeAdjust);
+ return yMinI;
+}
+
+int SplashClip::getYMaxI(SplashStrokeAdjustMode strokeAdjust) {
+ updateIntBounds(strokeAdjust);
+ return yMaxI;
+}
+
+int SplashClip::getNumPaths() {
+ SplashClip *clip;
+ int n;
+
+ n = 0;
+ for (clip = this; clip; clip = clip->prev) {
+ n += clip->length;
+ }
+ return n;
+}
+
+void SplashClip::updateIntBounds(SplashStrokeAdjustMode strokeAdjust) {
+ if (intBoundsValid && strokeAdjust == intBoundsStrokeAdjust) {
+ return;
+ }
+ if (strokeAdjust != splashStrokeAdjustOff && isSimple) {
+ splashStrokeAdjust(xMin, xMax, &xMinI, &xMaxI, strokeAdjust);
+ splashStrokeAdjust(yMin, yMax, &yMinI, &yMaxI, strokeAdjust);
+ } else {
+ xMinI = splashFloor(xMin);
+ yMinI = splashFloor(yMin);
+ xMaxI = splashCeil(xMax);
+ yMaxI = splashCeil(yMax);
+ }
+ if (xMinI < hardXMin) {
+ xMinI = hardXMin;
+ }
+ if (yMinI < hardYMin) {
+ yMinI = hardYMin;
+ }
+ if (xMaxI > hardXMax) {
+ xMaxI = hardXMax;
+ }
+ if (yMaxI > hardYMax) {
+ yMaxI = hardYMax;
+ }
+ // the clipping code uses [xMinI, xMaxI] instead of [xMinI, xMaxI)
+ --xMaxI;
+ --yMaxI;
+ intBoundsValid = gTrue;
+ intBoundsStrokeAdjust = strokeAdjust;
+}
diff --git a/splash/SplashClip.h b/splash/SplashClip.h
new file mode 100644
index 0000000..fb86ed8
--- /dev/null
+++ b/splash/SplashClip.h
@@ -0,0 +1,130 @@
+//========================================================================
+//
+// SplashClip.h
+//
+// Copyright 2003-2013 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef SPLASHCLIP_H
+#define SPLASHCLIP_H
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include "SplashTypes.h"
+#include "SplashMath.h"
+
+class SplashPath;
+class SplashXPath;
+class SplashXPathScanner;
+class SplashBitmap;
+
+//------------------------------------------------------------------------
+
+enum SplashClipResult {
+ splashClipAllInside,
+ splashClipAllOutside,
+ splashClipPartial
+};
+
+//------------------------------------------------------------------------
+// SplashClip
+//------------------------------------------------------------------------
+
+class SplashClip {
+public:
+
+ // Create a clip, for the given rectangle.
+ SplashClip(int hardXMinA, int hardYMinA,
+ int hardXMaxA, int hardYMaxA);
+
+ // Copy a clip.
+ SplashClip *copy() { return new SplashClip(this); }
+
+ ~SplashClip();
+
+ // Reset the clip to a rectangle.
+ void resetToRect(SplashCoord x0, SplashCoord y0,
+ SplashCoord x1, SplashCoord y1);
+
+ // Intersect the clip with a rectangle.
+ SplashError clipToRect(SplashCoord x0, SplashCoord y0,
+ SplashCoord x1, SplashCoord y1);
+
+ // Interesect the clip with <path>.
+ SplashError clipToPath(SplashPath *path, SplashCoord *matrix,
+ SplashCoord flatness, GBool eoA,
+ GBool enablePathSimplification,
+ SplashStrokeAdjustMode strokeAdjust);
+
+ // Tests a rectangle against the clipping region. Returns one of:
+ // - splashClipAllInside if the entire rectangle is inside the
+ // clipping region, i.e., all pixels in the rectangle are
+ // visible
+ // - splashClipAllOutside if the entire rectangle is outside the
+ // clipping region, i.e., all the pixels in the rectangle are
+ // clipped
+ // - splashClipPartial if the rectangle is part inside and part
+ // outside the clipping region
+ SplashClipResult testRect(int rectXMin, int rectYMin,
+ int rectXMax, int rectYMax,
+ SplashStrokeAdjustMode strokeAdjust);
+
+ // Clip a scan line. Modifies line[] by multiplying with clipping
+ // shape values for one scan line: ([x0, x1], y).
+ void clipSpan(Guchar *line, int y, int x0, int x1,
+ SplashStrokeAdjustMode strokeAdjust);
+
+ // Like clipSpan(), but uses the values 0 and 255 only.
+ // Returns true if there are any non-zero values in the result
+ // (i.e., returns false if the entire line is clipped out).
+ GBool clipSpanBinary(Guchar *line, int y, int x0, int x1,
+ SplashStrokeAdjustMode strokeAdjust);
+
+ // Get the rectangle part of the clip region.
+ SplashCoord getXMin() { return xMin; }
+ SplashCoord getXMax() { return xMax; }
+ SplashCoord getYMin() { return yMin; }
+ SplashCoord getYMax() { return yMax; }
+
+ // Get the rectangle part of the clip region, in integer coordinates.
+ int getXMinI(SplashStrokeAdjustMode strokeAdjust);
+ int getXMaxI(SplashStrokeAdjustMode strokeAdjust);
+ int getYMinI(SplashStrokeAdjustMode strokeAdjust);
+ int getYMaxI(SplashStrokeAdjustMode strokeAdjust);
+
+ // Get the number of arbitrary paths used by the clip region.
+ int getNumPaths();
+
+private:
+
+ SplashClip(SplashClip *clip);
+ void grow(int nPaths);
+ void updateIntBounds(SplashStrokeAdjustMode strokeAdjust);
+
+ int hardXMin, hardYMin, // coordinates cannot fall outside of
+ hardXMax, hardYMax; // [hardXMin, hardXMax), [hardYMin, hardYMax)
+
+ SplashCoord xMin, yMin, // current clip bounding rectangle
+ xMax, yMax; // (these coordinates may be adjusted if
+ // stroke adjustment is enabled)
+
+ int xMinI, yMinI, xMaxI, yMaxI;
+ GBool intBoundsValid; // true if xMinI, etc. are valid
+ GBool intBoundsStrokeAdjust; // value of strokeAdjust used to compute
+ // xMinI, etc.
+
+ SplashXPath **paths;
+ Guchar *eo;
+ SplashXPathScanner **scanners;
+ int length, size;
+ GBool isSimple;
+ SplashClip *prev;
+ Guchar *buf;
+};
+
+#endif
diff --git a/splash/SplashErrorCodes.h b/splash/SplashErrorCodes.h
new file mode 100644
index 0000000..ebe6091
--- /dev/null
+++ b/splash/SplashErrorCodes.h
@@ -0,0 +1,34 @@
+//========================================================================
+//
+// SplashErrorCodes.h
+//
+// Copyright 2003-2013 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef SPLASHERRORCODES_H
+#define SPLASHERRORCODES_H
+
+#include <aconf.h>
+
+//------------------------------------------------------------------------
+
+#define splashOk 0 // no error
+
+#define splashErrNoCurPt 1 // no current point
+
+#define splashErrEmptyPath 2 // zero points in path
+
+#define splashErrBogusPath 3 // only one point in subpath
+
+#define splashErrNoSave 4 // state stack is empty
+
+#define splashErrOpenFile 5 // couldn't open file
+
+#define splashErrNoGlyph 6 // couldn't get the requested glyph
+
+#define splashErrModeMismatch 7 // invalid combination of color modes
+
+#define splashErrSingularMatrix 8 // matrix is singular
+
+#endif
diff --git a/splash/SplashFTFont.cc b/splash/SplashFTFont.cc
new file mode 100644
index 0000000..9148144
--- /dev/null
+++ b/splash/SplashFTFont.cc
@@ -0,0 +1,460 @@
+//========================================================================
+//
+// SplashFTFont.cc
+//
+// Copyright 2003-2013 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <aconf.h>
+
+#if HAVE_FREETYPE_H
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <ft2build.h>
+#include FT_OUTLINE_H
+#include FT_SIZES_H
+#include FT_GLYPH_H
+#include "gmem.h"
+#include "gmempp.h"
+#include "SplashMath.h"
+#include "SplashGlyphBitmap.h"
+#include "SplashPath.h"
+#include "SplashFontEngine.h"
+#include "SplashFTFontEngine.h"
+#include "SplashFTFontFile.h"
+#include "SplashFTFont.h"
+
+//------------------------------------------------------------------------
+
+static int glyphPathMoveTo(const FT_Vector *pt, void *path);
+static int glyphPathLineTo(const FT_Vector *pt, void *path);
+static int glyphPathConicTo(const FT_Vector *ctrl, const FT_Vector *pt,
+ void *path);
+static int glyphPathCubicTo(const FT_Vector *ctrl1, const FT_Vector *ctrl2,
+ const FT_Vector *pt, void *path);
+
+//------------------------------------------------------------------------
+// SplashFTFont
+//------------------------------------------------------------------------
+
+SplashFTFont::SplashFTFont(SplashFTFontFile *fontFileA, SplashCoord *matA,
+ SplashCoord *textMatA):
+ SplashFont(fontFileA, matA, textMatA, fontFileA->engine->aa)
+{
+ FT_Face face;
+ int size, div;
+ int x, y;
+#if USE_FIXEDPOINT
+ SplashCoord scale;
+#endif
+
+ face = fontFileA->face;
+ if (FT_New_Size(face, &sizeObj)) {
+ return;
+ }
+ face->size = sizeObj;
+ size = splashRound(splashDist(0, 0, mat[2], mat[3]));
+ if (size < 1) {
+ size = 1;
+ }
+ if (FT_Set_Pixel_Sizes(face, 0, size)) {
+ return;
+ }
+ // if the textMat values are too small, FreeType's fixed point
+ // arithmetic doesn't work so well
+ textScale = splashDist(0, 0, textMat[2], textMat[3]) / size;
+ // avoid problems with singular (or close-to-singular) matrices
+ if (textScale < 0.00001) {
+ textScale = 0.00001;
+ }
+
+ div = face->bbox.xMax > 20000 ? 65536 : 1;
+
+#if USE_FIXEDPOINT
+ scale = (SplashCoord)1 / (SplashCoord)face->units_per_EM;
+
+ // transform the four corners of the font bounding box -- the min
+ // and max values form the bounding box of the transformed font
+ x = (int)(mat[0] * (scale * (face->bbox.xMin / div)) +
+ mat[2] * (scale * (face->bbox.yMin / div)));
+ xMin = xMax = x;
+ y = (int)(mat[1] * (scale * (face->bbox.xMin / div)) +
+ mat[3] * (scale * (face->bbox.yMin / div)));
+ yMin = yMax = y;
+ x = (int)(mat[0] * (scale * (face->bbox.xMin / div)) +
+ mat[2] * (scale * (face->bbox.yMax / div)));
+ if (x < xMin) {
+ xMin = x;
+ } else if (x > xMax) {
+ xMax = x;
+ }
+ y = (int)(mat[1] * (scale * (face->bbox.xMin / div)) +
+ mat[3] * (scale * (face->bbox.yMax / div)));
+ if (y < yMin) {
+ yMin = y;
+ } else if (y > yMax) {
+ yMax = y;
+ }
+ x = (int)(mat[0] * (scale * (face->bbox.xMax / div)) +
+ mat[2] * (scale * (face->bbox.yMin / div)));
+ if (x < xMin) {
+ xMin = x;
+ } else if (x > xMax) {
+ xMax = x;
+ }
+ y = (int)(mat[1] * (scale * (face->bbox.xMax / div)) +
+ mat[3] * (scale * (face->bbox.yMin / div)));
+ if (y < yMin) {
+ yMin = y;
+ } else if (y > yMax) {
+ yMax = y;
+ }
+ x = (int)(mat[0] * (scale * (face->bbox.xMax / div)) +
+ mat[2] * (scale * (face->bbox.yMax / div)));
+ if (x < xMin) {
+ xMin = x;
+ } else if (x > xMax) {
+ xMax = x;
+ }
+ y = (int)(mat[1] * (scale * (face->bbox.xMax / div)) +
+ mat[3] * (scale * (face->bbox.yMax / div)));
+ if (y < yMin) {
+ yMin = y;
+ } else if (y > yMax) {
+ yMax = y;
+ }
+#else // USE_FIXEDPOINT
+ // transform the four corners of the font bounding box -- the min
+ // and max values form the bounding box of the transformed font
+ x = (int)((mat[0] * (SplashCoord)face->bbox.xMin
+ + mat[2] * (SplashCoord)face->bbox.yMin) /
+ (div * face->units_per_EM));
+ xMin = xMax = x;
+ y = (int)((mat[1] * (SplashCoord)face->bbox.xMin
+ + mat[3] * (SplashCoord)face->bbox.yMin) /
+ (div * face->units_per_EM));
+ yMin = yMax = y;
+ x = (int)((mat[0] * (SplashCoord)face->bbox.xMin
+ + mat[2] * (SplashCoord)face->bbox.yMax) /
+ (div * face->units_per_EM));
+ if (x < xMin) {
+ xMin = x;
+ } else if (x > xMax) {
+ xMax = x;
+ }
+ y = (int)((mat[1] * (SplashCoord)face->bbox.xMin
+ + mat[3] * (SplashCoord)face->bbox.yMax) /
+ (div * face->units_per_EM));
+ if (y < yMin) {
+ yMin = y;
+ } else if (y > yMax) {
+ yMax = y;
+ }
+ x = (int)((mat[0] * (SplashCoord)face->bbox.xMax
+ + mat[2] * (SplashCoord)face->bbox.yMin) /
+ (div * face->units_per_EM));
+ if (x < xMin) {
+ xMin = x;
+ } else if (x > xMax) {
+ xMax = x;
+ }
+ y = (int)((mat[1] * (SplashCoord)face->bbox.xMax
+ + mat[3] * (SplashCoord)face->bbox.yMin) /
+ (div * face->units_per_EM));
+ if (y < yMin) {
+ yMin = y;
+ } else if (y > yMax) {
+ yMax = y;
+ }
+ x = (int)((mat[0] * (SplashCoord)face->bbox.xMax
+ + mat[2] * (SplashCoord)face->bbox.yMax) /
+ (div * face->units_per_EM));
+ if (x < xMin) {
+ xMin = x;
+ } else if (x > xMax) {
+ xMax = x;
+ }
+ y = (int)((mat[1] * (SplashCoord)face->bbox.xMax
+ + mat[3] * (SplashCoord)face->bbox.yMax) /
+ (div * face->units_per_EM));
+ if (y < yMin) {
+ yMin = y;
+ } else if (y > yMax) {
+ yMax = y;
+ }
+#endif // USE_FIXEDPOINT
+ // This is a kludge: some buggy PDF generators embed fonts with
+ // zero bounding boxes.
+ if (xMax == xMin) {
+ xMin = 0;
+ xMax = size;
+ }
+ if (yMax == yMin) {
+ yMin = 0;
+ yMax = (int)((SplashCoord)1.2 * size);
+ }
+
+ // compute the transform matrix
+#if USE_FIXEDPOINT
+ matrix.xx = (FT_Fixed)((mat[0] / size).get16Dot16());
+ matrix.yx = (FT_Fixed)((mat[1] / size).get16Dot16());
+ matrix.xy = (FT_Fixed)((mat[2] / size).get16Dot16());
+ matrix.yy = (FT_Fixed)((mat[3] / size).get16Dot16());
+ textMatrix.xx = (FT_Fixed)((textMat[0] / (textScale * size)).get16Dot16());
+ textMatrix.yx = (FT_Fixed)((textMat[1] / (textScale * size)).get16Dot16());
+ textMatrix.xy = (FT_Fixed)((textMat[2] / (textScale * size)).get16Dot16());
+ textMatrix.yy = (FT_Fixed)((textMat[3] / (textScale * size)).get16Dot16());
+#else
+ matrix.xx = (FT_Fixed)((mat[0] / size) * 65536);
+ matrix.yx = (FT_Fixed)((mat[1] / size) * 65536);
+ matrix.xy = (FT_Fixed)((mat[2] / size) * 65536);
+ matrix.yy = (FT_Fixed)((mat[3] / size) * 65536);
+ textMatrix.xx = (FT_Fixed)((textMat[0] / (textScale * size)) * 65536);
+ textMatrix.yx = (FT_Fixed)((textMat[1] / (textScale * size)) * 65536);
+ textMatrix.xy = (FT_Fixed)((textMat[2] / (textScale * size)) * 65536);
+ textMatrix.yy = (FT_Fixed)((textMat[3] / (textScale * size)) * 65536);
+#endif
+}
+
+SplashFTFont::~SplashFTFont() {
+}
+
+GBool SplashFTFont::getGlyph(int c, int xFrac, int yFrac,
+ SplashGlyphBitmap *bitmap) {
+ return SplashFont::getGlyph(c, xFrac, 0, bitmap);
+}
+
+GBool SplashFTFont::makeGlyph(int c, int xFrac, int yFrac,
+ SplashGlyphBitmap *bitmap) {
+ SplashFTFontFile *ff;
+ FT_Vector offset;
+ FT_GlyphSlot slot;
+ int gid;
+ FT_Int32 flags;
+ int rowSize;
+ Guchar *p, *q;
+ int i;
+
+ ff = (SplashFTFontFile *)fontFile;
+
+ ff->face->size = sizeObj;
+ offset.x = (FT_Pos)(int)((SplashCoord)xFrac * splashFontFractionMul * 64);
+ offset.y = 0;
+ FT_Set_Transform(ff->face, &matrix, &offset);
+ slot = ff->face->glyph;
+
+ if (ff->codeToGID && c < ff->codeToGIDLen) {
+ gid = ff->codeToGID[c];
+ } else {
+ gid = c;
+ }
+ if (ff->fontType == splashFontTrueType && gid < 0) {
+ // skip the TrueType notdef glyph
+ return gFalse;
+ }
+
+ // Set up the load flags:
+ // * disable bitmaps because they look ugly when scaled, rotated,
+ // etc.
+ // * disable autohinting because it can fail badly with font subsets
+ // that use invalid glyph names (the FreeType autohinter depends
+ // on the glyph name to figure out how to autohint the glyph)
+ // * but enable light autohinting for Type 1 fonts because regular
+ // hinting looks pretty bad, and the invalid glyph name issue
+ // seems to be very rare (Type 1 fonts are mostly used for
+ // substitution, in which case the full font is being used, which
+ // means we have the glyph names)
+ // This also sets the "pedantic" flag, running the FreeType hinter
+ // in paranoid mode. If that triggers any errors, we disable
+ // hinting below.
+ flags = FT_LOAD_NO_BITMAP | FT_LOAD_PEDANTIC;
+ if (ff->engine->flags & splashFTNoHinting) {
+ flags |= FT_LOAD_NO_HINTING;
+ } else if (ff->fontType == splashFontType1) {
+ flags |= FT_LOAD_TARGET_LIGHT;
+ } else {
+ flags |= FT_LOAD_NO_AUTOHINT;
+ }
+ if (FT_Load_Glyph(ff->face, (FT_UInt)gid, flags)) {
+ // fonts with broken hinting instructions can cause errors here;
+ // try again with no hinting (this is probably only relevant for
+ // TrueType fonts)
+ flags = FT_LOAD_NO_BITMAP | FT_LOAD_NO_HINTING;
+ if (FT_Load_Glyph(ff->face, (FT_UInt)gid, flags)) {
+ return gFalse;
+ }
+ }
+ if (FT_Render_Glyph(slot, aa ? FT_RENDER_MODE_NORMAL
+ : FT_RENDER_MODE_MONO)) {
+ return gFalse;
+ }
+ if (slot->bitmap.width == 0 || slot->bitmap.rows == 0) {
+ // this can happen if (a) the glyph is really tiny or (b) the
+ // metrics in the TrueType file are broken
+ return gFalse;
+ }
+
+ bitmap->x = -slot->bitmap_left;
+ bitmap->y = slot->bitmap_top;
+ bitmap->w = slot->bitmap.width;
+ bitmap->h = slot->bitmap.rows;
+ bitmap->aa = aa;
+ if (aa) {
+ rowSize = bitmap->w;
+ } else {
+ rowSize = (bitmap->w + 7) >> 3;
+ }
+ bitmap->data = (Guchar *)gmallocn(bitmap->h, rowSize);
+ bitmap->freeData = gTrue;
+ for (i = 0, p = bitmap->data, q = slot->bitmap.buffer;
+ i < bitmap->h;
+ ++i, p += rowSize, q += slot->bitmap.pitch) {
+ memcpy(p, q, rowSize);
+ }
+
+ return gTrue;
+}
+
+struct SplashFTFontPath {
+ SplashPath *path;
+ SplashCoord textScale;
+ GBool needClose;
+};
+
+SplashPath *SplashFTFont::getGlyphPath(int c) {
+ static FT_Outline_Funcs outlineFuncs = {
+#if FREETYPE_MINOR <= 1
+ (int (*)(FT_Vector *, void *))&glyphPathMoveTo,
+ (int (*)(FT_Vector *, void *))&glyphPathLineTo,
+ (int (*)(FT_Vector *, FT_Vector *, void *))&glyphPathConicTo,
+ (int (*)(FT_Vector *, FT_Vector *, FT_Vector *, void *))&glyphPathCubicTo,
+#else
+ &glyphPathMoveTo,
+ &glyphPathLineTo,
+ &glyphPathConicTo,
+ &glyphPathCubicTo,
+#endif
+ 0, 0
+ };
+ SplashFTFontFile *ff;
+ SplashFTFontPath path;
+ FT_GlyphSlot slot;
+ int gid;
+ FT_Glyph glyph;
+
+ ff = (SplashFTFontFile *)fontFile;
+ ff->face->size = sizeObj;
+ FT_Set_Transform(ff->face, &textMatrix, NULL);
+ slot = ff->face->glyph;
+ if (ff->codeToGID && c < ff->codeToGIDLen) {
+ gid = ff->codeToGID[c];
+ } else {
+ gid = c;
+ }
+ if (ff->fontType == splashFontTrueType && gid < 0) {
+ // skip the TrueType notdef glyph
+ return NULL;
+ }
+ if (FT_Load_Glyph(ff->face, (FT_UInt)gid, FT_LOAD_NO_BITMAP)) {
+ // fonts with broken hinting instructions can cause errors here;
+ // try again with no hinting (this is probably only relevant for
+ // TrueType fonts)
+ if (FT_Load_Glyph(ff->face, (FT_UInt)gid,
+ FT_LOAD_NO_BITMAP | FT_LOAD_NO_HINTING)) {
+ return NULL;
+ }
+ }
+ if (FT_Get_Glyph(slot, &glyph)) {
+ return NULL;
+ }
+ path.path = new SplashPath();
+ path.textScale = textScale;
+ path.needClose = gFalse;
+ FT_Outline_Decompose(&((FT_OutlineGlyph)glyph)->outline,
+ &outlineFuncs, &path);
+ if (path.needClose) {
+ path.path->close();
+ }
+ FT_Done_Glyph(glyph);
+ return path.path;
+}
+
+static int glyphPathMoveTo(const FT_Vector *pt, void *path) {
+ SplashFTFontPath *p = (SplashFTFontPath *)path;
+
+ if (p->needClose) {
+ p->path->close();
+ p->needClose = gFalse;
+ }
+ p->path->moveTo((SplashCoord)pt->x * p->textScale / 64.0,
+ (SplashCoord)pt->y * p->textScale / 64.0);
+ return 0;
+}
+
+static int glyphPathLineTo(const FT_Vector *pt, void *path) {
+ SplashFTFontPath *p = (SplashFTFontPath *)path;
+
+ p->path->lineTo((SplashCoord)pt->x * p->textScale / 64.0,
+ (SplashCoord)pt->y * p->textScale / 64.0);
+ p->needClose = gTrue;
+ return 0;
+}
+
+static int glyphPathConicTo(const FT_Vector *ctrl, const FT_Vector *pt,
+ void *path) {
+ SplashFTFontPath *p = (SplashFTFontPath *)path;
+ SplashCoord x0, y0, x1, y1, x2, y2, x3, y3, xc, yc;
+
+ if (!p->path->getCurPt(&x0, &y0)) {
+ return 0;
+ }
+ xc = (SplashCoord)ctrl->x * p->textScale / 64.0;
+ yc = (SplashCoord)ctrl->y * p->textScale / 64.0;
+ x3 = (SplashCoord)pt->x * p->textScale / 64.0;
+ y3 = (SplashCoord)pt->y * p->textScale / 64.0;
+
+ // A second-order Bezier curve is defined by two endpoints, p0 and
+ // p3, and one control point, pc:
+ //
+ // p(t) = (1-t)^2*p0 + t*(1-t)*pc + t^2*p3
+ //
+ // A third-order Bezier curve is defined by the same two endpoints,
+ // p0 and p3, and two control points, p1 and p2:
+ //
+ // p(t) = (1-t)^3*p0 + 3t*(1-t)^2*p1 + 3t^2*(1-t)*p2 + t^3*p3
+ //
+ // Applying some algebra, we can convert a second-order curve to a
+ // third-order curve:
+ //
+ // p1 = (1/3) * (p0 + 2pc)
+ // p2 = (1/3) * (2pc + p3)
+
+ x1 = (SplashCoord)(1.0 / 3.0) * (x0 + (SplashCoord)2 * xc);
+ y1 = (SplashCoord)(1.0 / 3.0) * (y0 + (SplashCoord)2 * yc);
+ x2 = (SplashCoord)(1.0 / 3.0) * ((SplashCoord)2 * xc + x3);
+ y2 = (SplashCoord)(1.0 / 3.0) * ((SplashCoord)2 * yc + y3);
+
+ p->path->curveTo(x1, y1, x2, y2, x3, y3);
+ p->needClose = gTrue;
+ return 0;
+}
+
+static int glyphPathCubicTo(const FT_Vector *ctrl1, const FT_Vector *ctrl2,
+ const FT_Vector *pt, void *path) {
+ SplashFTFontPath *p = (SplashFTFontPath *)path;
+
+ p->path->curveTo((SplashCoord)ctrl1->x * p->textScale / 64.0,
+ (SplashCoord)ctrl1->y * p->textScale / 64.0,
+ (SplashCoord)ctrl2->x * p->textScale / 64.0,
+ (SplashCoord)ctrl2->y * p->textScale / 64.0,
+ (SplashCoord)pt->x * p->textScale / 64.0,
+ (SplashCoord)pt->y * p->textScale / 64.0);
+ p->needClose = gTrue;
+ return 0;
+}
+
+#endif // HAVE_FREETYPE_H
diff --git a/splash/SplashFTFont.h b/splash/SplashFTFont.h
new file mode 100644
index 0000000..ac08b00
--- /dev/null
+++ b/splash/SplashFTFont.h
@@ -0,0 +1,60 @@
+//========================================================================
+//
+// SplashFTFont.h
+//
+// Copyright 2003-2013 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef SPLASHFTFONT_H
+#define SPLASHFTFONT_H
+
+#include <aconf.h>
+
+#if HAVE_FREETYPE_H
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include "SplashFont.h"
+
+class SplashFTFontFile;
+
+//------------------------------------------------------------------------
+// SplashFTFont
+//------------------------------------------------------------------------
+
+class SplashFTFont: public SplashFont {
+public:
+
+ SplashFTFont(SplashFTFontFile *fontFileA, SplashCoord *matA,
+ SplashCoord *textMatA);
+
+ virtual ~SplashFTFont();
+
+ // Munge xFrac and yFrac before calling SplashFont::getGlyph.
+ virtual GBool getGlyph(int c, int xFrac, int yFrac,
+ SplashGlyphBitmap *bitmap);
+
+ // Rasterize a glyph. The <xFrac> and <yFrac> values are the same
+ // as described for getGlyph.
+ virtual GBool makeGlyph(int c, int xFrac, int yFrac,
+ SplashGlyphBitmap *bitmap);
+
+ // Return the path for a glyph.
+ virtual SplashPath *getGlyphPath(int c);
+
+private:
+
+ FT_Size sizeObj;
+ FT_Matrix matrix;
+ FT_Matrix textMatrix;
+ SplashCoord textScale;
+};
+
+#endif // HAVE_FREETYPE_H
+
+#endif
diff --git a/splash/SplashFTFontEngine.cc b/splash/SplashFTFontEngine.cc
new file mode 100644
index 0000000..3393954
--- /dev/null
+++ b/splash/SplashFTFontEngine.cc
@@ -0,0 +1,392 @@
+//========================================================================
+//
+// SplashFTFontEngine.cc
+//
+// Copyright 2003-2013 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <aconf.h>
+
+#if HAVE_FREETYPE_H
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stdio.h>
+#ifndef _WIN32
+# include <unistd.h>
+#endif
+#include "gmem.h"
+#include "gmempp.h"
+#include "GString.h"
+#include "gfile.h"
+#include "FoFiTrueType.h"
+#include "FoFiType1C.h"
+#include "SplashFTFontFile.h"
+#include "SplashFTFontEngine.h"
+#include FT_MODULE_H
+#ifdef FT_CFF_DRIVER_H
+# include FT_CFF_DRIVER_H
+#endif
+
+#ifdef VMS
+#if (__VMS_VER < 70000000)
+extern "C" int unlink(char *filename);
+#endif
+#endif
+
+//------------------------------------------------------------------------
+
+static void fileWrite(void *stream, const char *data, int len) {
+ fwrite(data, 1, len, (FILE *)stream);
+}
+
+#if LOAD_FONTS_FROM_MEM
+static void gstringWrite(void *stream, const char *data, int len) {
+ ((GString *)stream)->append(data, len);
+}
+#endif
+
+//------------------------------------------------------------------------
+// SplashFTFontEngine
+//------------------------------------------------------------------------
+
+SplashFTFontEngine::SplashFTFontEngine(GBool aaA, Guint flagsA,
+ FT_Library libA) {
+ FT_Int major, minor, patch;
+
+ aa = aaA;
+ flags = flagsA;
+ lib = libA;
+
+ // as of FT 2.1.8, CID fonts are indexed by CID instead of GID
+ FT_Library_Version(lib, &major, &minor, &patch);
+ useCIDs = major > 2 ||
+ (major == 2 && (minor > 1 || (minor == 1 && patch > 7)));
+}
+
+SplashFTFontEngine *SplashFTFontEngine::init(GBool aaA, Guint flagsA) {
+ FT_Library libA;
+
+ if (FT_Init_FreeType(&libA)) {
+ return NULL;
+ }
+ return new SplashFTFontEngine(aaA, flagsA, libA);
+}
+
+SplashFTFontEngine::~SplashFTFontEngine() {
+ FT_Done_FreeType(lib);
+}
+
+SplashFontFile *SplashFTFontEngine::loadType1Font(SplashFontFileID *idA,
+#if LOAD_FONTS_FROM_MEM
+ GString *fontBuf,
+#else
+ char *fileName,
+ GBool deleteFile,
+#endif
+ const char **enc) {
+ return SplashFTFontFile::loadType1Font(this, idA, splashFontType1,
+#if LOAD_FONTS_FROM_MEM
+ fontBuf,
+#else
+ fileName, deleteFile,
+#endif
+ enc);
+}
+
+SplashFontFile *SplashFTFontEngine::loadType1CFont(SplashFontFileID *idA,
+#if LOAD_FONTS_FROM_MEM
+ GString *fontBuf,
+#else
+ char *fileName,
+ GBool deleteFile,
+#endif
+ const char **enc) {
+ return SplashFTFontFile::loadType1Font(this, idA, splashFontType1C,
+#if LOAD_FONTS_FROM_MEM
+ fontBuf,
+#else
+ fileName, deleteFile,
+#endif
+ enc);
+}
+
+SplashFontFile *SplashFTFontEngine::loadOpenTypeT1CFont(SplashFontFileID *idA,
+#if LOAD_FONTS_FROM_MEM
+ GString *fontBuf,
+#else
+ char *fileName,
+ GBool deleteFile,
+#endif
+ const char **enc) {
+ FoFiTrueType *ff;
+#if LOAD_FONTS_FROM_MEM
+ GString *fontBuf2;
+#else
+ GString *tmpFileName;
+ FILE *tmpFile;
+#endif
+ SplashFontFile *ret;
+
+#if LOAD_FONTS_FROM_MEM
+ if (!(ff = FoFiTrueType::make(fontBuf->getCString(), fontBuf->getLength(),
+ 0, gTrue))) {
+#else
+ if (!(ff = FoFiTrueType::load(fileName, 0, gTrue))) {
+#endif
+ return NULL;
+ }
+ if (ff->isHeadlessCFF()) {
+#if LOAD_FONTS_FROM_MEM
+ fontBuf2 = new GString();
+ ff->convertToType1(NULL, enc, gFalse, &gstringWrite, fontBuf2);
+ delete ff;
+ ret = SplashFTFontFile::loadType1Font(this, idA, splashFontType1,
+ fontBuf2, enc);
+ if (ret) {
+ delete fontBuf;
+ } else {
+ delete fontBuf2;
+ }
+#else
+ tmpFileName = NULL;
+ if (!openTempFile(&tmpFileName, &tmpFile, "wb", NULL)) {
+ delete ff;
+ return NULL;
+ }
+ ff->convertToType1(NULL, enc, gFalse, &fileWrite, tmpFile);
+ delete ff;
+ fclose(tmpFile);
+ ret = SplashFTFontFile::loadType1Font(this, idA, splashFontType1,
+ tmpFileName->getCString(),
+ gTrue, enc);
+ if (ret) {
+ if (deleteFile) {
+ unlink(fileName);
+ }
+ } else {
+ unlink(tmpFileName->getCString());
+ }
+ delete tmpFileName;
+#endif
+ } else {
+ delete ff;
+ ret = SplashFTFontFile::loadType1Font(this, idA, splashFontOpenTypeT1C,
+#if LOAD_FONTS_FROM_MEM
+ fontBuf,
+#else
+ fileName, deleteFile,
+#endif
+ enc);
+ }
+ return ret;
+}
+
+SplashFontFile *SplashFTFontEngine::loadCIDFont(SplashFontFileID *idA,
+#if LOAD_FONTS_FROM_MEM
+ GString *fontBuf,
+#else
+ char *fileName,
+ GBool deleteFile,
+#endif
+ int *codeToGID,
+ int codeToGIDLen) {
+ FoFiType1C *ff;
+ int *cidToGIDMap;
+ int nCIDs;
+ SplashFontFile *ret;
+
+ // check for a CFF font
+ if (codeToGID) {
+ cidToGIDMap = NULL;
+ nCIDs = 0;
+ } else if (useCIDs) {
+ cidToGIDMap = NULL;
+ nCIDs = 0;
+#if LOAD_FONTS_FROM_MEM
+ } else if ((ff = FoFiType1C::make(fontBuf->getCString(),
+ fontBuf->getLength()))) {
+#else
+ } else if ((ff = FoFiType1C::load(fileName))) {
+#endif
+ cidToGIDMap = ff->getCIDToGIDMap(&nCIDs);
+ delete ff;
+ } else {
+ cidToGIDMap = NULL;
+ nCIDs = 0;
+ }
+ ret = SplashFTFontFile::loadCIDFont(this, idA, splashFontCID,
+#if LOAD_FONTS_FROM_MEM
+ fontBuf,
+#else
+ fileName, deleteFile,
+#endif
+ codeToGID ? codeToGID : cidToGIDMap,
+ codeToGID ? codeToGIDLen : nCIDs);
+ if (!ret) {
+ gfree(cidToGIDMap);
+ }
+ return ret;
+}
+
+SplashFontFile *SplashFTFontEngine::loadOpenTypeCFFFont(SplashFontFileID *idA,
+#if LOAD_FONTS_FROM_MEM
+ GString *fontBuf,
+#else
+ char *fileName,
+ GBool deleteFile,
+#endif
+ int *codeToGID,
+ int codeToGIDLen) {
+ FoFiTrueType *ff;
+#if LOAD_FONTS_FROM_MEM
+ GString *fontBuf2;
+#else
+ GString *tmpFileName;
+ FILE *tmpFile;
+#endif
+ char *cffStart;
+ int cffLength;
+ int *cidToGIDMap;
+ int nCIDs;
+ SplashFontFile *ret;
+
+#if LOAD_FONTS_FROM_MEM
+ if (!(ff = FoFiTrueType::make(fontBuf->getCString(), fontBuf->getLength(),
+ 0, gTrue))) {
+#else
+ if (!(ff = FoFiTrueType::load(fileName, 0, gTrue))) {
+#endif
+ return NULL;
+ }
+ cidToGIDMap = NULL;
+ nCIDs = 0;
+ if (ff->isHeadlessCFF()) {
+ if (!ff->getCFFBlock(&cffStart, &cffLength)) {
+ return NULL;
+ }
+#if LOAD_FONTS_FROM_MEM
+ fontBuf2 = new GString(cffStart, cffLength);
+ if (!useCIDs) {
+ cidToGIDMap = ff->getCIDToGIDMap(&nCIDs);
+ }
+ ret = SplashFTFontFile::loadCIDFont(this, idA, splashFontOpenTypeCFF,
+ fontBuf2, cidToGIDMap, nCIDs);
+ if (ret) {
+ delete fontBuf;
+ } else {
+ delete fontBuf2;
+ }
+#else
+ tmpFileName = NULL;
+ if (!openTempFile(&tmpFileName, &tmpFile, "wb", NULL)) {
+ delete ff;
+ return NULL;
+ }
+ fwrite(cffStart, 1, cffLength, tmpFile);
+ fclose(tmpFile);
+ if (!useCIDs) {
+ cidToGIDMap = ff->getCIDToGIDMap(&nCIDs);
+ }
+ ret = SplashFTFontFile::loadCIDFont(this, idA, splashFontOpenTypeCFF,
+ tmpFileName->getCString(), gTrue,
+ cidToGIDMap, nCIDs);
+ if (ret) {
+ if (deleteFile) {
+ unlink(fileName);
+ }
+ } else {
+ unlink(tmpFileName->getCString());
+ }
+ delete tmpFileName;
+#endif
+ } else {
+ if (!codeToGID && !useCIDs && ff->isOpenTypeCFF()) {
+ cidToGIDMap = ff->getCIDToGIDMap(&nCIDs);
+ }
+ ret = SplashFTFontFile::loadCIDFont(this, idA, splashFontOpenTypeCFF,
+#if LOAD_FONTS_FROM_MEM
+ fontBuf,
+#else
+ fileName, deleteFile,
+#endif
+ codeToGID ? codeToGID : cidToGIDMap,
+ codeToGID ? codeToGIDLen : nCIDs);
+ }
+ delete ff;
+ if (!ret) {
+ gfree(cidToGIDMap);
+ }
+ return ret;
+}
+
+SplashFontFile *SplashFTFontEngine::loadTrueTypeFont(SplashFontFileID *idA,
+#if LOAD_FONTS_FROM_MEM
+ GString *fontBuf,
+#else
+ char *fileName,
+ GBool deleteFile,
+#endif
+ int fontNum,
+ int *codeToGID,
+ int codeToGIDLen) {
+ FoFiTrueType *ff;
+#if LOAD_FONTS_FROM_MEM
+ GString *fontBuf2;
+#else
+ GString *tmpFileName;
+ FILE *tmpFile;
+#endif
+ SplashFontFile *ret;
+
+#if LOAD_FONTS_FROM_MEM
+ if (!(ff = FoFiTrueType::make(fontBuf->getCString(), fontBuf->getLength(),
+ fontNum))) {
+#else
+ if (!(ff = FoFiTrueType::load(fileName, fontNum))) {
+#endif
+ return NULL;
+ }
+#if LOAD_FONTS_FROM_MEM
+ fontBuf2 = new GString;
+ ff->writeTTF(&gstringWrite, fontBuf2);
+#else
+ tmpFileName = NULL;
+ if (!openTempFile(&tmpFileName, &tmpFile, "wb", NULL)) {
+ delete ff;
+ return NULL;
+ }
+ ff->writeTTF(&fileWrite, tmpFile);
+ fclose(tmpFile);
+#endif
+ delete ff;
+ ret = SplashFTFontFile::loadTrueTypeFont(this, idA, splashFontTrueType,
+#if LOAD_FONTS_FROM_MEM
+ fontBuf2,
+#else
+ tmpFileName->getCString(), gTrue,
+#endif
+ 0, codeToGID, codeToGIDLen);
+#if LOAD_FONTS_FROM_MEM
+ if (ret) {
+ delete fontBuf;
+ } else {
+ delete fontBuf2;
+ }
+#else
+ if (ret) {
+ if (deleteFile) {
+ unlink(fileName);
+ }
+ } else {
+ unlink(tmpFileName->getCString());
+ }
+ delete tmpFileName;
+#endif
+ return ret;
+}
+
+#endif // HAVE_FREETYPE_H
diff --git a/splash/SplashFTFontEngine.h b/splash/SplashFTFontEngine.h
new file mode 100644
index 0000000..24db3c6
--- /dev/null
+++ b/splash/SplashFTFontEngine.h
@@ -0,0 +1,99 @@
+//========================================================================
+//
+// SplashFTFontEngine.h
+//
+// Copyright 2003-2013 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef SPLASHFTFONTENGINE_H
+#define SPLASHFTFONTENGINE_H
+
+#include <aconf.h>
+
+#if HAVE_FREETYPE_H
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include "gtypes.h"
+class GString;
+
+class SplashFontFile;
+class SplashFontFileID;
+
+//------------------------------------------------------------------------
+// SplashFTFontEngine
+//------------------------------------------------------------------------
+
+class SplashFTFontEngine {
+public:
+
+ static SplashFTFontEngine *init(GBool aaA, Guint flagsA);
+
+ ~SplashFTFontEngine();
+
+ // Load fonts.
+ SplashFontFile *loadType1Font(SplashFontFileID *idA,
+#if LOAD_FONTS_FROM_MEM
+ GString *fontBuf,
+#else
+ char *fileName, GBool deleteFile,
+#endif
+ const char **enc);
+ SplashFontFile *loadType1CFont(SplashFontFileID *idA,
+#if LOAD_FONTS_FROM_MEM
+ GString *fontBuf,
+#else
+ char *fileName, GBool deleteFile,
+#endif
+ const char **enc);
+ SplashFontFile *loadOpenTypeT1CFont(SplashFontFileID *idA,
+#if LOAD_FONTS_FROM_MEM
+ GString *fontBuf,
+#else
+ char *fileName, GBool deleteFile,
+#endif
+ const char **enc);
+ SplashFontFile *loadCIDFont(SplashFontFileID *idA,
+#if LOAD_FONTS_FROM_MEM
+ GString *fontBuf,
+#else
+ char *fileName, GBool deleteFile,
+#endif
+ int *codeToGID, int codeToGIDLen);
+ SplashFontFile *loadOpenTypeCFFFont(SplashFontFileID *idA,
+#if LOAD_FONTS_FROM_MEM
+ GString *fontBuf,
+#else
+ char *fileName, GBool deleteFile,
+#endif
+ int *codeToGID, int codeToGIDLen);
+ SplashFontFile *loadTrueTypeFont(SplashFontFileID *idA,
+#if LOAD_FONTS_FROM_MEM
+ GString *fontBuf,
+#else
+ char *fileName, GBool deleteFile,
+#endif
+ int fontNum,
+ int *codeToGID, int codeToGIDLen);
+
+private:
+
+ SplashFTFontEngine(GBool aaA, Guint flagsA, FT_Library libA);
+
+ GBool aa;
+ Guint flags;
+ FT_Library lib;
+ GBool useCIDs;
+
+ friend class SplashFTFontFile;
+ friend class SplashFTFont;
+};
+
+#endif // HAVE_FREETYPE_H
+
+#endif
diff --git a/splash/SplashFTFontFile.cc b/splash/SplashFTFontFile.cc
new file mode 100644
index 0000000..b5fd02a
--- /dev/null
+++ b/splash/SplashFTFontFile.cc
@@ -0,0 +1,171 @@
+//========================================================================
+//
+// SplashFTFontFile.cc
+//
+// Copyright 2003-2013 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <aconf.h>
+
+#if HAVE_FREETYPE_H
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include "gmem.h"
+#include "gmempp.h"
+#include "GString.h"
+#include "SplashFTFontEngine.h"
+#include "SplashFTFont.h"
+#include "SplashFTFontFile.h"
+
+//------------------------------------------------------------------------
+// SplashFTFontFile
+//------------------------------------------------------------------------
+
+SplashFontFile *SplashFTFontFile::loadType1Font(SplashFTFontEngine *engineA,
+ SplashFontFileID *idA,
+ SplashFontType fontTypeA,
+#if LOAD_FONTS_FROM_MEM
+ GString *fontBufA,
+#else
+ char *fileNameA,
+ GBool deleteFileA,
+#endif
+ const char **encA) {
+ FT_Face faceA;
+ int *codeToGIDA;
+ const char *name;
+ int i;
+
+#if LOAD_FONTS_FROM_MEM
+ if (FT_New_Memory_Face(engineA->lib, (FT_Byte *)fontBufA->getCString(),
+ fontBufA->getLength(), 0, &faceA)) {
+#else
+ if (FT_New_Face(engineA->lib, fileNameA, 0, &faceA)) {
+#endif
+ return NULL;
+ }
+ codeToGIDA = (int *)gmallocn(256, sizeof(int));
+ for (i = 0; i < 256; ++i) {
+ codeToGIDA[i] = 0;
+ if ((name = encA[i])) {
+ codeToGIDA[i] = (int)FT_Get_Name_Index(faceA, (char *)name);
+ }
+ }
+
+ return new SplashFTFontFile(engineA, idA, fontTypeA,
+#if LOAD_FONTS_FROM_MEM
+ fontBufA,
+#else
+ fileNameA, deleteFileA,
+#endif
+ faceA, codeToGIDA, 256);
+}
+
+SplashFontFile *SplashFTFontFile::loadCIDFont(SplashFTFontEngine *engineA,
+ SplashFontFileID *idA,
+ SplashFontType fontTypeA,
+#if LOAD_FONTS_FROM_MEM
+ GString *fontBufA,
+#else
+ char *fileNameA,
+ GBool deleteFileA,
+#endif
+ int *codeToGIDA,
+ int codeToGIDLenA) {
+ FT_Face faceA;
+
+#if LOAD_FONTS_FROM_MEM
+ if (FT_New_Memory_Face(engineA->lib, (FT_Byte *)fontBufA->getCString(),
+ fontBufA->getLength(), 0, &faceA)) {
+#else
+ if (FT_New_Face(engineA->lib, fileNameA, 0, &faceA)) {
+#endif
+ return NULL;
+ }
+
+ return new SplashFTFontFile(engineA, idA, fontTypeA,
+#if LOAD_FONTS_FROM_MEM
+ fontBufA,
+#else
+ fileNameA, deleteFileA,
+#endif
+ faceA, codeToGIDA, codeToGIDLenA);
+}
+
+SplashFontFile *SplashFTFontFile::loadTrueTypeFont(SplashFTFontEngine *engineA,
+ SplashFontFileID *idA,
+ SplashFontType fontTypeA,
+#if LOAD_FONTS_FROM_MEM
+ GString *fontBufA,
+#else
+ char *fileNameA,
+ GBool deleteFileA,
+#endif
+ int fontNum,
+ int *codeToGIDA,
+ int codeToGIDLenA) {
+ FT_Face faceA;
+
+#if LOAD_FONTS_FROM_MEM
+ if (FT_New_Memory_Face(engineA->lib, (FT_Byte *)fontBufA->getCString(),
+ fontBufA->getLength(), fontNum, &faceA)) {
+#else
+ if (FT_New_Face(engineA->lib, fileNameA, fontNum, &faceA)) {
+#endif
+ return NULL;
+ }
+
+ return new SplashFTFontFile(engineA, idA, fontTypeA,
+#if LOAD_FONTS_FROM_MEM
+ fontBufA,
+#else
+ fileNameA, deleteFileA,
+#endif
+ faceA, codeToGIDA, codeToGIDLenA);
+}
+
+SplashFTFontFile::SplashFTFontFile(SplashFTFontEngine *engineA,
+ SplashFontFileID *idA,
+ SplashFontType fontTypeA,
+#if LOAD_FONTS_FROM_MEM
+ GString *fontBufA,
+#else
+ char *fileNameA, GBool deleteFileA,
+#endif
+ FT_Face faceA,
+ int *codeToGIDA, int codeToGIDLenA):
+#if LOAD_FONTS_FROM_MEM
+ SplashFontFile(idA, fontTypeA, fontBufA)
+#else
+ SplashFontFile(idA, fontTypeA, fileNameA, deleteFileA)
+#endif
+{
+ engine = engineA;
+ face = faceA;
+ codeToGID = codeToGIDA;
+ codeToGIDLen = codeToGIDLenA;
+}
+
+SplashFTFontFile::~SplashFTFontFile() {
+ if (face) {
+ FT_Done_Face(face);
+ }
+ if (codeToGID) {
+ gfree(codeToGID);
+ }
+}
+
+SplashFont *SplashFTFontFile::makeFont(SplashCoord *mat,
+ SplashCoord *textMat) {
+ SplashFont *font;
+
+ font = new SplashFTFont(this, mat, textMat);
+ font->initCache();
+ return font;
+}
+
+#endif // HAVE_FREETYPE_H
diff --git a/splash/SplashFTFontFile.h b/splash/SplashFTFontFile.h
new file mode 100644
index 0000000..3a6b9b7
--- /dev/null
+++ b/splash/SplashFTFontFile.h
@@ -0,0 +1,95 @@
+//========================================================================
+//
+// SplashFTFontFile.h
+//
+// Copyright 2003-2013 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef SPLASHFTFONTFILE_H
+#define SPLASHFTFONTFILE_H
+
+#include <aconf.h>
+
+#if HAVE_FREETYPE_H
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include "SplashFontFile.h"
+
+class SplashFontFileID;
+class SplashFTFontEngine;
+
+//------------------------------------------------------------------------
+// SplashFTFontFile
+//------------------------------------------------------------------------
+
+class SplashFTFontFile: public SplashFontFile {
+public:
+
+ static SplashFontFile *loadType1Font(SplashFTFontEngine *engineA,
+ SplashFontFileID *idA,
+ SplashFontType fontTypeA,
+#if LOAD_FONTS_FROM_MEM
+ GString *fontBufA,
+#else
+ char *fileNameA, GBool deleteFileA,
+#endif
+ const char **encA);
+ static SplashFontFile *loadCIDFont(SplashFTFontEngine *engineA,
+ SplashFontFileID *idA,
+ SplashFontType fontTypeA,
+#if LOAD_FONTS_FROM_MEM
+ GString *fontBufA,
+#else
+ char *fileNameA, GBool deleteFileA,
+#endif
+ int *codeToGIDA, int codeToGIDLenA);
+ static SplashFontFile *loadTrueTypeFont(SplashFTFontEngine *engineA,
+ SplashFontFileID *idA,
+ SplashFontType fontTypeA,
+#if LOAD_FONTS_FROM_MEM
+ GString *fontBufA,
+#else
+ char *fileNameA,
+ GBool deleteFileA,
+#endif
+ int fontNum,
+ int *codeToGIDA,
+ int codeToGIDLenA);
+
+ virtual ~SplashFTFontFile();
+
+ // Create a new SplashFTFont, i.e., a scaled instance of this font
+ // file.
+ virtual SplashFont *makeFont(SplashCoord *mat,
+ SplashCoord *textMat);
+
+private:
+
+ SplashFTFontFile(SplashFTFontEngine *engineA,
+ SplashFontFileID *idA,
+ SplashFontType fontTypeA,
+#if LOAD_FONTS_FROM_MEM
+ GString *fontBufA,
+#else
+ char *fileNameA, GBool deleteFileA,
+#endif
+ FT_Face faceA,
+ int *codeToGIDA, int codeToGIDLenA);
+
+ SplashFTFontEngine *engine;
+ FT_Face face;
+ int *codeToGID;
+ int codeToGIDLen;
+
+ friend class SplashFTFont;
+};
+
+#endif // HAVE_FREETYPE_H
+
+#endif
diff --git a/splash/SplashFont.cc b/splash/SplashFont.cc
new file mode 100644
index 0000000..2fcd83d
--- /dev/null
+++ b/splash/SplashFont.cc
@@ -0,0 +1,195 @@
+//========================================================================
+//
+// SplashFont.cc
+//
+// Copyright 2003-2013 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <string.h>
+#include "gmem.h"
+#include "gmempp.h"
+#include "SplashMath.h"
+#include "SplashGlyphBitmap.h"
+#include "SplashFontFile.h"
+#include "SplashFont.h"
+
+//------------------------------------------------------------------------
+
+// font cache size parameters
+#define splashFontCacheAssoc 8
+#define splashFontCacheMaxSets 8
+#define splashFontCacheSize (128*1024)
+
+//------------------------------------------------------------------------
+
+struct SplashFontCacheTag {
+ int c;
+ short xFrac, yFrac; // x and y fractions
+ int mru; // valid bit (0x80000000) and MRU index
+ int x, y, w, h; // offset and size of glyph
+};
+
+//------------------------------------------------------------------------
+// SplashFont
+//------------------------------------------------------------------------
+
+SplashFont::SplashFont(SplashFontFile *fontFileA, SplashCoord *matA,
+ SplashCoord *textMatA, GBool aaA) {
+ fontFile = fontFileA;
+ fontFile->incRefCnt();
+ mat[0] = matA[0];
+ mat[1] = matA[1];
+ mat[2] = matA[2];
+ mat[3] = matA[3];
+ textMat[0] = textMatA[0];
+ textMat[1] = textMatA[1];
+ textMat[2] = textMatA[2];
+ textMat[3] = textMatA[3];
+ aa = aaA;
+
+ cache = NULL;
+ cacheTags = NULL;
+
+ xMin = yMin = xMax = yMax = 0;
+}
+
+void SplashFont::initCache() {
+ int i;
+
+ // this should be (max - min + 1), but we add some padding to
+ // deal with rounding errors
+ glyphW = xMax - xMin + 3;
+ glyphH = yMax - yMin + 3;
+ if (glyphW > 1000 || glyphH > 1000) {
+ // if the glyphs are too large, don't cache them -- setting the
+ // cache bitmap size to something tiny will cause getGlyph() to
+ // fall back to the uncached case
+ glyphW = glyphH = 0;
+ glyphSize = 0;
+ cacheSets = 0;
+ cacheAssoc = 0;
+ return;
+ }
+ if (aa) {
+ glyphSize = glyphW * glyphH;
+ } else {
+ glyphSize = ((glyphW + 7) >> 3) * glyphH;
+ }
+
+ // set up the glyph pixmap cache
+ cacheAssoc = splashFontCacheAssoc;
+ for (cacheSets = splashFontCacheMaxSets;
+ cacheSets > 1 &&
+ glyphSize > splashFontCacheSize / (cacheSets * cacheAssoc);
+ cacheSets >>= 1) ;
+ cache = (Guchar *)gmallocn(cacheSets * cacheAssoc, glyphSize);
+ cacheTags = (SplashFontCacheTag *)gmallocn(cacheSets * cacheAssoc,
+ sizeof(SplashFontCacheTag));
+ for (i = 0; i < cacheSets * cacheAssoc; ++i) {
+ cacheTags[i].mru = i & (cacheAssoc - 1);
+ }
+}
+
+SplashFont::~SplashFont() {
+ fontFile->decRefCnt();
+ if (cache) {
+ gfree(cache);
+ }
+ if (cacheTags) {
+ gfree(cacheTags);
+ }
+}
+
+GBool SplashFont::getGlyph(int c, int xFrac, int yFrac,
+ SplashGlyphBitmap *bitmap) {
+ SplashGlyphBitmap bitmap2;
+ int size;
+ Guchar *p;
+ int i, j, k;
+
+ // no fractional coordinates for large glyphs or non-anti-aliased
+ // glyphs
+ if (!aa || glyphH > 50) {
+ xFrac = yFrac = 0;
+ }
+
+ // check the cache
+ if (cache) {
+ i = (c & (cacheSets - 1)) * cacheAssoc;
+ for (j = 0; j < cacheAssoc; ++j) {
+ if ((cacheTags[i+j].mru & 0x80000000) &&
+ cacheTags[i+j].c == c &&
+ (int)cacheTags[i+j].xFrac == xFrac &&
+ (int)cacheTags[i+j].yFrac == yFrac) {
+ bitmap->x = cacheTags[i+j].x;
+ bitmap->y = cacheTags[i+j].y;
+ bitmap->w = cacheTags[i+j].w;
+ bitmap->h = cacheTags[i+j].h;
+ for (k = 0; k < cacheAssoc; ++k) {
+ if (k != j &&
+ (cacheTags[i+k].mru & 0x7fffffff) <
+ (cacheTags[i+j].mru & 0x7fffffff)) {
+ ++cacheTags[i+k].mru;
+ }
+ }
+ cacheTags[i+j].mru = 0x80000000;
+ bitmap->aa = aa;
+ bitmap->data = cache + (i+j) * glyphSize;
+ bitmap->freeData = gFalse;
+ return gTrue;
+ }
+ }
+ } else {
+ i = 0; // make gcc happy
+ }
+
+ // generate the glyph bitmap
+ if (!makeGlyph(c, xFrac, yFrac, &bitmap2)) {
+ return gFalse;
+ }
+
+ // if the glyph doesn't fit in the bounding box, return a temporary
+ // uncached bitmap
+ if (!cache || bitmap2.w > glyphW || bitmap2.h > glyphH) {
+ *bitmap = bitmap2;
+ return gTrue;
+ }
+
+ // insert glyph pixmap in cache
+ if (aa) {
+ size = bitmap2.w * bitmap2.h;
+ } else {
+ size = ((bitmap2.w + 7) >> 3) * bitmap2.h;
+ }
+ p = NULL; // make gcc happy
+ for (j = 0; j < cacheAssoc; ++j) {
+ if ((cacheTags[i+j].mru & 0x7fffffff) == cacheAssoc - 1) {
+ cacheTags[i+j].mru = 0x80000000;
+ cacheTags[i+j].c = c;
+ cacheTags[i+j].xFrac = (short)xFrac;
+ cacheTags[i+j].yFrac = (short)yFrac;
+ cacheTags[i+j].x = bitmap2.x;
+ cacheTags[i+j].y = bitmap2.y;
+ cacheTags[i+j].w = bitmap2.w;
+ cacheTags[i+j].h = bitmap2.h;
+ p = cache + (i+j) * glyphSize;
+ memcpy(p, bitmap2.data, size);
+ } else {
+ ++cacheTags[i+j].mru;
+ }
+ }
+ *bitmap = bitmap2;
+ bitmap->data = p;
+ bitmap->freeData = gFalse;
+ if (bitmap2.freeData) {
+ gfree(bitmap2.data);
+ }
+ return gTrue;
+}
diff --git a/splash/SplashFont.h b/splash/SplashFont.h
new file mode 100644
index 0000000..2bb9654
--- /dev/null
+++ b/splash/SplashFont.h
@@ -0,0 +1,111 @@
+//========================================================================
+//
+// SplashFont.h
+//
+// Copyright 2003-2013 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef SPLASHFONT_H
+#define SPLASHFONT_H
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include "gtypes.h"
+#include "SplashTypes.h"
+#include "SplashMath.h"
+
+struct SplashGlyphBitmap;
+struct SplashFontCacheTag;
+class SplashFontFile;
+class SplashPath;
+
+//------------------------------------------------------------------------
+
+// Fractional positioning uses this many bits to the right of the
+// decimal points.
+#define splashFontFractionBits 2
+#define splashFontFraction (1 << splashFontFractionBits)
+#define splashFontFractionMul \
+ ((SplashCoord)1 / (SplashCoord)splashFontFraction)
+
+//------------------------------------------------------------------------
+// SplashFont
+//------------------------------------------------------------------------
+
+class SplashFont {
+public:
+
+ SplashFont(SplashFontFile *fontFileA, SplashCoord *matA,
+ SplashCoord *textMatA, GBool aaA);
+
+ // This must be called after the constructor, so that the subclass
+ // constructor has a chance to compute the bbox.
+ void initCache();
+
+ virtual ~SplashFont();
+
+ SplashFontFile *getFontFile() { return fontFile; }
+
+ // Return true if <this> matches the specified font file and matrix.
+ GBool matches(SplashFontFile *fontFileA, SplashCoord *matA,
+ SplashCoord *textMatA) {
+ return fontFileA == fontFile &&
+ splashAbs(matA[0] - mat[0]) < 0.0001 &&
+ splashAbs(matA[1] - mat[1]) < 0.0001 &&
+ splashAbs(matA[2] - mat[2]) < 0.0001 &&
+ splashAbs(matA[3] - mat[3]) < 0.0001 &&
+ splashAbs(textMatA[0] - textMat[0]) < 0.0001 &&
+ splashAbs(textMatA[1] - textMat[1]) < 0.0001 &&
+ splashAbs(textMatA[2] - textMat[2]) < 0.0001 &&
+ splashAbs(textMatA[3] - textMat[3]) < 0.0001;
+ }
+
+ // Get a glyph - this does a cache lookup first, and if not found,
+ // creates a new bitmap and adds it to the cache. The <xFrac> and
+ // <yFrac> values are splashFontFractionBits bits each, representing
+ // the numerators of fractions in [0, 1), where the denominator is
+ // splashFontFraction = 1 << splashFontFractionBits. Subclasses
+ // should override this to zero out xFrac and/or yFrac if they don't
+ // support fractional coordinates.
+ virtual GBool getGlyph(int c, int xFrac, int yFrac,
+ SplashGlyphBitmap *bitmap);
+
+ // Rasterize a glyph. The <xFrac> and <yFrac> values are the same
+ // as described for getGlyph.
+ virtual GBool makeGlyph(int c, int xFrac, int yFrac,
+ SplashGlyphBitmap *bitmap) = 0;
+
+ // Return the path for a glyph.
+ virtual SplashPath *getGlyphPath(int c) = 0;
+
+ // Return the font transform matrix.
+ SplashCoord *getMatrix() { return mat; }
+
+ // Return the glyph bounding box.
+ void getBBox(int *xMinA, int *yMinA, int *xMaxA, int *yMaxA)
+ { *xMinA = xMin; *yMinA = yMin; *xMaxA = xMax; *yMaxA = yMax; }
+
+protected:
+
+ SplashFontFile *fontFile;
+ SplashCoord mat[4]; // font transform matrix
+ // (text space -> device space)
+ SplashCoord textMat[4]; // text transform matrix
+ // (text space -> user space)
+ GBool aa; // anti-aliasing
+ int xMin, yMin, xMax, yMax; // glyph bounding box
+ Guchar *cache; // glyph bitmap cache
+ SplashFontCacheTag * // cache tags
+ cacheTags;
+ int glyphW, glyphH; // size of glyph bitmaps
+ int glyphSize; // size of glyph bitmaps, in bytes
+ int cacheSets; // number of sets in cache
+ int cacheAssoc; // cache associativity (glyphs per set)
+};
+
+#endif
diff --git a/splash/SplashFontEngine.cc b/splash/SplashFontEngine.cc
new file mode 100644
index 0000000..81afe0c
--- /dev/null
+++ b/splash/SplashFontEngine.cc
@@ -0,0 +1,409 @@
+//========================================================================
+//
+// SplashFontEngine.cc
+//
+// Copyright 2003-2013 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#ifndef _WIN32
+# include <unistd.h>
+#endif
+#include "gmem.h"
+#include "gmempp.h"
+#include "GString.h"
+#include "GList.h"
+#include "SplashMath.h"
+#include "SplashFTFontEngine.h"
+#include "SplashFontFile.h"
+#include "SplashFontFileID.h"
+#include "SplashFont.h"
+#include "SplashFontEngine.h"
+
+#ifdef VMS
+#if (__VMS_VER < 70000000)
+extern "C" int unlink(char *filename);
+#endif
+#endif
+
+//------------------------------------------------------------------------
+// SplashFontEngine
+//------------------------------------------------------------------------
+
+SplashFontEngine::SplashFontEngine(
+#if HAVE_FREETYPE_H
+ GBool enableFreeType,
+ Guint freeTypeFlags,
+#endif
+ GBool aa) {
+ int i;
+
+ for (i = 0; i < splashFontCacheSize; ++i) {
+ fontCache[i] = NULL;
+ }
+ badFontFiles = new GList();
+
+#if HAVE_FREETYPE_H
+ if (enableFreeType) {
+ ftEngine = SplashFTFontEngine::init(aa, freeTypeFlags);
+ } else {
+ ftEngine = NULL;
+ }
+#endif
+}
+
+SplashFontEngine::~SplashFontEngine() {
+ int i;
+
+ for (i = 0; i < splashFontCacheSize; ++i) {
+ if (fontCache[i]) {
+ delete fontCache[i];
+ }
+ }
+ deleteGList(badFontFiles, SplashFontFileID);
+
+#if HAVE_FREETYPE_H
+ if (ftEngine) {
+ delete ftEngine;
+ }
+#endif
+}
+
+SplashFontFile *SplashFontEngine::getFontFile(SplashFontFileID *id) {
+ SplashFontFile *fontFile;
+ int i;
+
+ for (i = 0; i < splashFontCacheSize; ++i) {
+ if (fontCache[i]) {
+ fontFile = fontCache[i]->getFontFile();
+ if (fontFile && fontFile->getID()->matches(id)) {
+ return fontFile;
+ }
+ }
+ }
+ return NULL;
+}
+
+GBool SplashFontEngine::checkForBadFontFile(SplashFontFileID *id) {
+ for (int i = 0; i < badFontFiles->getLength(); ++i) {
+ if (((SplashFontFileID *)badFontFiles->get(i))->matches(id)) {
+ return gTrue;
+ }
+ }
+ return gFalse;
+}
+
+SplashFontFile *SplashFontEngine::loadType1Font(SplashFontFileID *idA,
+#if LOAD_FONTS_FROM_MEM
+ GString *fontBuf,
+#else
+ char *fileName,
+ GBool deleteFile,
+#endif
+ const char **enc) {
+ SplashFontFile *fontFile;
+
+ fontFile = NULL;
+#if HAVE_FREETYPE_H
+ if (!fontFile && ftEngine) {
+ fontFile = ftEngine->loadType1Font(idA,
+#if LOAD_FONTS_FROM_MEM
+ fontBuf,
+#else
+ fileName, deleteFile,
+#endif
+ enc);
+ }
+#endif
+
+#if !LOAD_FONTS_FROM_MEM && !defined(_WIN32) && !defined(__ANDROID__)
+ // delete the (temporary) font file -- with Unix hard link
+ // semantics, this will remove the last link; otherwise it will
+ // return an error, leaving the file to be deleted later (if
+ // loadXYZFont failed, the file will always be deleted)
+ if (deleteFile) {
+ unlink(fontFile ? fontFile->fileName->getCString() : fileName);
+ }
+#endif
+
+ if (!fontFile) {
+ badFontFiles->append(idA);
+ }
+
+ return fontFile;
+}
+
+SplashFontFile *SplashFontEngine::loadType1CFont(SplashFontFileID *idA,
+#if LOAD_FONTS_FROM_MEM
+ GString *fontBuf,
+#else
+ char *fileName,
+ GBool deleteFile,
+#endif
+ int *codeToGID,
+ const char **enc) {
+ SplashFontFile *fontFile;
+
+ fontFile = NULL;
+ if (!fontFile) {
+ gfree(codeToGID);
+ }
+#if HAVE_FREETYPE_H
+ if (!fontFile && ftEngine) {
+ fontFile = ftEngine->loadType1CFont(idA,
+#if LOAD_FONTS_FROM_MEM
+ fontBuf,
+#else
+ fileName, deleteFile,
+#endif
+ enc);
+ }
+#endif
+
+#if !LOAD_FONTS_FROM_MEM && !defined(_WIN32) && !defined(__ANDROID__)
+ // delete the (temporary) font file -- with Unix hard link
+ // semantics, this will remove the last link; otherwise it will
+ // return an error, leaving the file to be deleted later (if
+ // loadXYZFont failed, the file will always be deleted)
+ if (deleteFile) {
+ unlink(fontFile ? fontFile->fileName->getCString() : fileName);
+ }
+#endif
+
+ if (!fontFile) {
+ badFontFiles->append(idA);
+ }
+
+ return fontFile;
+}
+
+SplashFontFile *SplashFontEngine::loadOpenTypeT1CFont(SplashFontFileID *idA,
+#if LOAD_FONTS_FROM_MEM
+ GString *fontBuf,
+#else
+ char *fileName,
+ GBool deleteFile,
+#endif
+ int *codeToGID,
+ const char **enc) {
+ SplashFontFile *fontFile;
+
+ fontFile = NULL;
+ if (!fontFile) {
+ gfree(codeToGID);
+ }
+#if HAVE_FREETYPE_H
+ if (!fontFile && ftEngine) {
+ fontFile = ftEngine->loadOpenTypeT1CFont(idA,
+#if LOAD_FONTS_FROM_MEM
+ fontBuf,
+#else
+ fileName, deleteFile,
+#endif
+ enc);
+ }
+#endif
+
+#if !LOAD_FONTS_FROM_MEM && !defined(_WIN32) && !defined(__ANDROID__)
+ // delete the (temporary) font file -- with Unix hard link
+ // semantics, this will remove the last link; otherwise it will
+ // return an error, leaving the file to be deleted later (if
+ // loadXYZFont failed, the file will always be deleted)
+ if (deleteFile) {
+ unlink(fontFile ? fontFile->fileName->getCString() : fileName);
+ }
+#endif
+
+ if (!fontFile) {
+ badFontFiles->append(idA);
+ }
+
+ return fontFile;
+}
+
+SplashFontFile *SplashFontEngine::loadCIDFont(SplashFontFileID *idA,
+#if LOAD_FONTS_FROM_MEM
+ GString *fontBuf,
+#else
+ char *fileName,
+ GBool deleteFile,
+#endif
+ int *codeToGID,
+ int codeToGIDLen) {
+ SplashFontFile *fontFile;
+
+ fontFile = NULL;
+#if HAVE_FREETYPE_H
+ if (!fontFile && ftEngine) {
+ fontFile = ftEngine->loadCIDFont(idA,
+#if LOAD_FONTS_FROM_MEM
+ fontBuf,
+#else
+ fileName, deleteFile,
+#endif
+ codeToGID, codeToGIDLen);
+ }
+#endif
+
+ if (!fontFile) {
+ gfree(codeToGID);
+ }
+
+#if !LOAD_FONTS_FROM_MEM && !defined(_WIN32) && !defined(__ANDROID__)
+ // delete the (temporary) font file -- with Unix hard link
+ // semantics, this will remove the last link; otherwise it will
+ // return an error, leaving the file to be deleted later (if
+ // loadXYZFont failed, the file will always be deleted)
+ if (deleteFile) {
+ unlink(fontFile ? fontFile->fileName->getCString() : fileName);
+ }
+#endif
+
+ if (!fontFile) {
+ badFontFiles->append(idA);
+ }
+
+ return fontFile;
+}
+
+SplashFontFile *SplashFontEngine::loadOpenTypeCFFFont(SplashFontFileID *idA,
+#if LOAD_FONTS_FROM_MEM
+ GString *fontBuf,
+#else
+ char *fileName,
+ GBool deleteFile,
+#endif
+ int *codeToGID,
+ int codeToGIDLen) {
+ SplashFontFile *fontFile;
+
+ fontFile = NULL;
+#if HAVE_FREETYPE_H
+ if (!fontFile && ftEngine) {
+ fontFile = ftEngine->loadOpenTypeCFFFont(idA,
+#if LOAD_FONTS_FROM_MEM
+ fontBuf,
+#else
+ fileName, deleteFile,
+#endif
+ codeToGID, codeToGIDLen);
+ }
+#endif
+
+ if (!fontFile) {
+ gfree(codeToGID);
+ }
+
+#if !LOAD_FONTS_FROM_MEM && !defined(_WIN32) && !defined(__ANDROID__)
+ // delete the (temporary) font file -- with Unix hard link
+ // semantics, this will remove the last link; otherwise it will
+ // return an error, leaving the file to be deleted later (if
+ // loadXYZFont failed, the file will always be deleted)
+ if (deleteFile) {
+ unlink(fontFile ? fontFile->fileName->getCString() : fileName);
+ }
+#endif
+
+ if (!fontFile) {
+ badFontFiles->append(idA);
+ }
+
+ return fontFile;
+}
+
+SplashFontFile *SplashFontEngine::loadTrueTypeFont(SplashFontFileID *idA,
+#if LOAD_FONTS_FROM_MEM
+ GString *fontBuf,
+#else
+ char *fileName,
+ GBool deleteFile,
+#endif
+ int fontNum,
+ int *codeToGID,
+ int codeToGIDLen,
+ char *fontName) {
+ SplashFontFile *fontFile;
+
+ fontFile = NULL;
+#if HAVE_FREETYPE_H
+ if (!fontFile && ftEngine) {
+ fontFile = ftEngine->loadTrueTypeFont(idA,
+#if LOAD_FONTS_FROM_MEM
+ fontBuf,
+#else
+ fileName, deleteFile,
+#endif
+ fontNum, codeToGID, codeToGIDLen);
+ }
+#endif
+
+ if (!fontFile) {
+ gfree(codeToGID);
+ }
+
+#if !LOAD_FONTS_FROM_MEM && !defined(_WIN32) && !defined(__ANDROID__)
+ // delete the (temporary) font file -- with Unix hard link
+ // semantics, this will remove the last link; otherwise it will
+ // return an error, leaving the file to be deleted later (if
+ // loadXYZFont failed, the file will always be deleted)
+ if (deleteFile) {
+ unlink(fontFile ? fontFile->fileName->getCString() : fileName);
+ }
+#endif
+
+ if (!fontFile) {
+ badFontFiles->append(idA);
+ }
+
+ return fontFile;
+}
+
+SplashFont *SplashFontEngine::getFont(SplashFontFile *fontFile,
+ SplashCoord *textMat,
+ SplashCoord *ctm) {
+ SplashCoord mat[4];
+ SplashFont *font;
+ int i, j;
+
+ mat[0] = textMat[0] * ctm[0] + textMat[1] * ctm[2];
+ mat[1] = -(textMat[0] * ctm[1] + textMat[1] * ctm[3]);
+ mat[2] = textMat[2] * ctm[0] + textMat[3] * ctm[2];
+ mat[3] = -(textMat[2] * ctm[1] + textMat[3] * ctm[3]);
+ if (!splashCheckDet(mat[0], mat[1], mat[2], mat[3], 0.01)) {
+ // avoid a singular (or close-to-singular) matrix
+ mat[0] = 0.01; mat[1] = 0;
+ mat[2] = 0; mat[3] = 0.01;
+ }
+
+ font = fontCache[0];
+ if (font && font->matches(fontFile, mat, textMat)) {
+ return font;
+ }
+ for (i = 1; i < splashFontCacheSize; ++i) {
+ font = fontCache[i];
+ if (font && font->matches(fontFile, mat, textMat)) {
+ for (j = i; j > 0; --j) {
+ fontCache[j] = fontCache[j-1];
+ }
+ fontCache[0] = font;
+ return font;
+ }
+ }
+ font = fontFile->makeFont(mat, textMat);
+ if (fontCache[splashFontCacheSize - 1]) {
+ delete fontCache[splashFontCacheSize - 1];
+ }
+ for (j = splashFontCacheSize - 1; j > 0; --j) {
+ fontCache[j] = fontCache[j-1];
+ }
+ fontCache[0] = font;
+ return font;
+}
diff --git a/splash/SplashFontEngine.h b/splash/SplashFontEngine.h
new file mode 100644
index 0000000..59adb95
--- /dev/null
+++ b/splash/SplashFontEngine.h
@@ -0,0 +1,129 @@
+//========================================================================
+//
+// SplashFontEngine.h
+//
+// Copyright 2003-2013 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef SPLASHFONTENGINE_H
+#define SPLASHFONTENGINE_H
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include "gtypes.h"
+class GString;
+class GList;
+
+class SplashFTFontEngine;
+class SplashDTFontEngine;
+class SplashDT4FontEngine;
+class SplashFontFile;
+class SplashFontFileID;
+class SplashFont;
+
+//------------------------------------------------------------------------
+
+#define splashFontCacheSize 16
+
+#if HAVE_FREETYPE_H
+#define splashFTNoHinting (1 << 0)
+#endif
+
+//------------------------------------------------------------------------
+// SplashFontEngine
+//------------------------------------------------------------------------
+
+class SplashFontEngine {
+public:
+
+ // Create a font engine.
+ SplashFontEngine(
+#if HAVE_FREETYPE_H
+ GBool enableFreeType,
+ Guint freeTypeFlags,
+#endif
+ GBool aa);
+
+ ~SplashFontEngine();
+
+ // Get a font file from the cache. Returns NULL if there is no
+ // matching entry in the cache.
+ SplashFontFile *getFontFile(SplashFontFileID *id);
+
+ // Returns true if [id] refers to a bad font file, i.e., if one of
+ // the loadXXXFont functions has returned NULL for that ID.
+ GBool checkForBadFontFile(SplashFontFileID *id);
+
+ // Load fonts - these create new SplashFontFile objects.
+ SplashFontFile *loadType1Font(SplashFontFileID *idA,
+#if LOAD_FONTS_FROM_MEM
+ GString *fontBuf,
+#else
+ char *fileName, GBool deleteFile,
+#endif
+ const char **enc);
+ SplashFontFile *loadType1CFont(SplashFontFileID *idA,
+#if LOAD_FONTS_FROM_MEM
+ GString *fontBuf,
+#else
+ char *fileName, GBool deleteFile,
+#endif
+ int *codeToGID, const char **enc);
+ SplashFontFile *loadOpenTypeT1CFont(SplashFontFileID *idA,
+#if LOAD_FONTS_FROM_MEM
+ GString *fontBuf,
+#else
+ char *fileName, GBool deleteFile,
+#endif
+ int *codeToGID, const char **enc);
+ SplashFontFile *loadCIDFont(SplashFontFileID *idA,
+#if LOAD_FONTS_FROM_MEM
+ GString *fontBuf,
+#else
+ char *fileName, GBool deleteFile,
+#endif
+ int *codeToGID, int codeToGIDLen);
+ SplashFontFile *loadOpenTypeCFFFont(SplashFontFileID *idA,
+#if LOAD_FONTS_FROM_MEM
+ GString *fontBuf,
+#else
+ char *fileName, GBool deleteFile,
+#endif
+ int *codeToGID, int codeToGIDLen);
+ SplashFontFile *loadTrueTypeFont(SplashFontFileID *idA,
+#if LOAD_FONTS_FROM_MEM
+ GString *fontBuf,
+#else
+ char *fileName, GBool deleteFile,
+#endif
+ int fontNum,
+ int *codeToGID, int codeToGIDLen,
+ char *fontName);
+
+ // Get a font - this does a cache lookup first, and if not found,
+ // creates a new SplashFont object and adds it to the cache. The
+ // matrix, mat = textMat * ctm:
+ // [ mat[0] mat[1] ]
+ // [ mat[2] mat[3] ]
+ // specifies the font transform in PostScript style:
+ // [x' y'] = [x y] * mat
+ // Note that the Splash y axis points downward.
+ SplashFont *getFont(SplashFontFile *fontFile,
+ SplashCoord *textMat, SplashCoord *ctm);
+
+private:
+
+ SplashFont *fontCache[splashFontCacheSize];
+ GList *badFontFiles; // [SplashFontFileID]
+
+#if HAVE_FREETYPE_H
+ SplashFTFontEngine *ftEngine;
+#endif
+};
+
+#endif
diff --git a/splash/SplashFontFile.cc b/splash/SplashFontFile.cc
new file mode 100644
index 0000000..2d260e3
--- /dev/null
+++ b/splash/SplashFontFile.cc
@@ -0,0 +1,84 @@
+//========================================================================
+//
+// SplashFontFile.cc
+//
+// Copyright 2003-2013 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stdio.h>
+#ifndef _WIN32
+# include <unistd.h>
+#endif
+#include "gmempp.h"
+#include "GString.h"
+#include "SplashFontFile.h"
+#include "SplashFontFileID.h"
+
+#ifdef VMS
+#if (__VMS_VER < 70000000)
+extern "C" int unlink(char *filename);
+#endif
+#endif
+
+//------------------------------------------------------------------------
+// SplashFontFile
+//------------------------------------------------------------------------
+
+SplashFontFile::SplashFontFile(SplashFontFileID *idA,
+ SplashFontType fontTypeA,
+#if LOAD_FONTS_FROM_MEM
+ GString *fontBufA
+#else
+ char *fileNameA, GBool deleteFileA
+#endif
+ ) {
+ id = idA;
+ fontType = fontTypeA;
+#if LOAD_FONTS_FROM_MEM
+ fontBuf = fontBufA;
+#else
+ fileName = new GString(fileNameA);
+ deleteFile = deleteFileA;
+#endif
+ refCnt = 0;
+}
+
+SplashFontFile::~SplashFontFile() {
+#if LOAD_FONTS_FROM_MEM
+ delete fontBuf;
+#else
+ if (deleteFile) {
+ unlink(fileName->getCString());
+ }
+ delete fileName;
+#endif
+ delete id;
+}
+
+void SplashFontFile::incRefCnt() {
+#if MULTITHREADED
+ gAtomicIncrement(&refCnt);
+#else
+ ++refCnt;
+#endif
+}
+
+void SplashFontFile::decRefCnt() {
+ GBool done;
+
+#if MULTITHREADED
+ done = gAtomicDecrement(&refCnt) == 0;
+#else
+ done = --refCnt == 0;
+#endif
+ if (done) {
+ delete this;
+ }
+}
diff --git a/splash/SplashFontFile.h b/splash/SplashFontFile.h
new file mode 100644
index 0000000..133e6ab
--- /dev/null
+++ b/splash/SplashFontFile.h
@@ -0,0 +1,95 @@
+//========================================================================
+//
+// SplashFontFile.h
+//
+// Copyright 2003-2013 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef SPLASHFONTFILE_H
+#define SPLASHFONTFILE_H
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include "gtypes.h"
+#include "SplashTypes.h"
+
+#if MULTITHREADED
+#include "GMutex.h"
+#endif
+
+class GString;
+class SplashFontEngine;
+class SplashFont;
+class SplashFontFileID;
+
+//------------------------------------------------------------------------
+// SplashFontType
+//------------------------------------------------------------------------
+
+enum SplashFontType {
+ splashFontType1, // GfxFontType.fontType1
+ splashFontType1C, // GfxFontType.fontType1C
+ splashFontOpenTypeT1C, // GfxFontType.fontType1COT
+ splashFontCID, // GfxFontType.fontCIDType0/fontCIDType0C
+ splashFontOpenTypeCFF, // GfxFontType.fontCIDType0COT
+ splashFontTrueType // GfxFontType.fontTrueType/fontTrueTypeOT/
+ // fontCIDType2/fontCIDType2OT
+};
+
+//------------------------------------------------------------------------
+// SplashFontFile
+//------------------------------------------------------------------------
+
+class SplashFontFile {
+public:
+
+ virtual ~SplashFontFile();
+
+ // Create a new SplashFont, i.e., a scaled instance of this font
+ // file.
+ virtual SplashFont *makeFont(SplashCoord *mat, SplashCoord *textMat) = 0;
+
+ // Get the font file ID.
+ SplashFontFileID *getID() { return id; }
+
+ // Increment the reference count.
+ void incRefCnt();
+
+ // Decrement the reference count. If the new value is zero, delete
+ // the SplashFontFile object.
+ void decRefCnt();
+
+protected:
+
+ SplashFontFile(SplashFontFileID *idA,
+ SplashFontType fontTypeA,
+#if LOAD_FONTS_FROM_MEM
+ GString *fontBufA
+#else
+ char *fileNameA, GBool deleteFileA
+#endif
+ );
+
+ SplashFontFileID *id;
+ SplashFontType fontType;
+#if LOAD_FONTS_FROM_MEM
+ GString *fontBuf;
+#else
+ GString *fileName;
+ GBool deleteFile;
+#endif
+#if MULTITHREADED
+ GAtomicCounter refCnt;
+#else
+ int refCnt;
+#endif
+
+ friend class SplashFontEngine;
+};
+
+#endif
diff --git a/splash/SplashFontFileID.cc b/splash/SplashFontFileID.cc
new file mode 100644
index 0000000..27f5203
--- /dev/null
+++ b/splash/SplashFontFileID.cc
@@ -0,0 +1,26 @@
+//========================================================================
+//
+// SplashFontFileID.cc
+//
+// Copyright 2003-2013 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include "gmempp.h"
+#include "SplashFontFileID.h"
+
+//------------------------------------------------------------------------
+// SplashFontFileID
+//------------------------------------------------------------------------
+
+SplashFontFileID::SplashFontFileID() {
+}
+
+SplashFontFileID::~SplashFontFileID() {
+}
diff --git a/splash/SplashFontFileID.h b/splash/SplashFontFileID.h
new file mode 100644
index 0000000..384018a
--- /dev/null
+++ b/splash/SplashFontFileID.h
@@ -0,0 +1,32 @@
+//========================================================================
+//
+// SplashFontFileID.h
+//
+// Copyright 2003-2013 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef SPLASHFONTFILEID_H
+#define SPLASHFONTFILEID_H
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include "gtypes.h"
+
+//------------------------------------------------------------------------
+// SplashFontFileID
+//------------------------------------------------------------------------
+
+class SplashFontFileID {
+public:
+
+ SplashFontFileID();
+ virtual ~SplashFontFileID();
+ virtual GBool matches(SplashFontFileID *id) = 0;
+};
+
+#endif
diff --git a/splash/SplashGlyphBitmap.h b/splash/SplashGlyphBitmap.h
new file mode 100644
index 0000000..d375b3c
--- /dev/null
+++ b/splash/SplashGlyphBitmap.h
@@ -0,0 +1,28 @@
+//========================================================================
+//
+// SplashGlyphBitmap.h
+//
+// Copyright 2003-2013 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef SPLASHGLYPHBITMAP_H
+#define SPLASHGLYPHBITMAP_H
+
+#include <aconf.h>
+
+#include "gtypes.h"
+
+//------------------------------------------------------------------------
+// SplashGlyphBitmap
+//------------------------------------------------------------------------
+
+struct SplashGlyphBitmap {
+ int x, y, w, h; // offset and size of glyph
+ GBool aa; // anti-aliased: true means 8-bit alpha
+ // bitmap; false means 1-bit
+ Guchar *data; // bitmap data
+ GBool freeData; // true if data memory should be freed
+};
+
+#endif
diff --git a/splash/SplashMath.h b/splash/SplashMath.h
new file mode 100644
index 0000000..45f4e53
--- /dev/null
+++ b/splash/SplashMath.h
@@ -0,0 +1,378 @@
+//========================================================================
+//
+// SplashMath.h
+//
+// Copyright 2003-2013 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef SPLASHMATH_H
+#define SPLASHMATH_H
+
+#include <aconf.h>
+
+#if USE_FIXEDPONT
+# include "FixedPoint.h"
+#else
+# include <math.h>
+# if (defined(__GNUC__) && defined(__SSE2__)) || \
+ (defined(_WIN32) && (_M_IX86_FP == 2 || defined(_M_X64)))
+# include <emmintrin.h>
+# endif
+#endif
+#include "SplashTypes.h"
+
+static inline SplashCoord splashAbs(SplashCoord x) {
+#if USE_FIXEDPOINT
+ return FixedPoint::abs(x);
+#else
+ return fabs(x);
+#endif
+}
+
+// floor() and (int)() are implemented separately, which results
+// in changing the FPCW multiple times - so we optimize it with
+// some inline assembly or SSE intrinsics.
+static inline int splashFloor(SplashCoord x) {
+#if USE_FIXEDPOINT
+
+ //--- fixed point
+
+ return FixedPoint::floor(x);
+
+#elif (defined(__GNUC__) && defined(__SSE2__)) || \
+ (defined(_WIN32) && (_M_IX86_FP == 2 || defined(_M_X64)))
+
+ //--- SSE2 intrinsics
+ // NB: 64-bit x86 guarantees availability of SSE2.
+
+ __m128d m1, m2;
+ int i, s;
+
+ m1 = _mm_set_sd(x);
+ i = _mm_cvttsd_si32(m1);
+ m2 = _mm_cvtsi32_sd(m1, i);
+ s = _mm_ucomigt_sd(m2, m1);
+ return i - s;
+
+#elif defined(__GNUC__) && defined(__i386__) && !defined(__APPLE__)
+
+ //--- x87 inline assembly (gcc/clang)
+ // (this code fails on OSX for reasons I don't understand)
+
+ Gushort oldCW, newCW, t;
+ int result;
+
+ __asm__ volatile("fnstcw %0\n"
+ "movw %0, %3\n"
+ "andw $0xf3ff, %3\n"
+ "orw $0x0400, %3\n"
+ "movw %3, %1\n" // round down
+ "fldcw %1\n"
+ "fistl %2\n"
+ "fldcw %0\n"
+ : "=m" (oldCW), "=m" (newCW), "=m" (result), "=r" (t)
+ : "t" (x));
+ return result;
+
+#elif defined(_WIN32) && defined(_M_IX86)
+
+ //--- x87 inline assembly (VC)
+
+ Gushort oldCW, newCW;
+ int result;
+
+ __asm fld QWORD PTR x
+ __asm fnstcw WORD PTR oldCW
+ __asm mov ax, WORD PTR oldCW
+ __asm and ax, 0xf3ff
+ __asm or ax, 0x0400
+ __asm mov WORD PTR newCW, ax // round down
+ __asm fldcw WORD PTR newCW
+ __asm fistp DWORD PTR result
+ __asm fldcw WORD PTR oldCW
+ return result;
+
+#else
+
+ //--- all others
+
+ return (int)floor(x);
+
+#endif
+}
+
+// ceil() and (int)() are implemented separately, which results
+// in changing the FPCW multiple times - so we optimize it with
+// some inline assembly or SSE intrinsics.
+static inline int splashCeil(SplashCoord x) {
+#if USE_FIXEDPOINT
+
+ //--- fixed point
+
+ return FixedPoint::ceil(x);
+
+#elif (defined(__GNUC__) && defined(__SSE2__)) || \
+ (defined(_WIN32) && (_M_IX86_FP == 2 || defined(_M_X64)))
+
+ //--- SSE2 intrinsics
+ // NB: 64-bit x86 guarantees availability of SSE2.
+
+ __m128d m1, m2;
+ int i, s;
+
+ m1 = _mm_set_sd(x);
+ i = _mm_cvttsd_si32(m1);
+ m2 = _mm_cvtsi32_sd(m1, i);
+ s = _mm_ucomilt_sd(m2, m1);
+ return i + s;
+
+#elif defined(__GNUC__) && defined(__i386__) && !defined(__APPLE__)
+
+ //--- x87 inline assembly (gcc/clang)
+ // (this code fails on OSX for reasons I don't understand)
+
+ Gushort oldCW, newCW, t;
+ int result;
+
+ __asm__ volatile("fnstcw %0\n"
+ "movw %0, %3\n"
+ "andw $0xf3ff, %3\n"
+ "orw $0x0800, %3\n"
+ "movw %3, %1\n" // round up
+ "fldcw %1\n"
+ "fistl %2\n"
+ "fldcw %0\n"
+ : "=m" (oldCW), "=m" (newCW), "=m" (result), "=r" (t)
+ : "t" (x));
+ return result;
+
+#elif defined(_WIN32) && defined(_M_IX86)
+
+ //--- x87 inline assembly (VC)
+
+ // ceil() and (int)() are implemented separately, which results
+ // in changing the FPCW multiple times - so we optimize it with
+ // some inline assembly
+ Gushort oldCW, newCW;
+ int result;
+
+ __asm fld QWORD PTR x
+ __asm fnstcw WORD PTR oldCW
+ __asm mov ax, WORD PTR oldCW
+ __asm and ax, 0xf3ff
+ __asm or ax, 0x0800
+ __asm mov WORD PTR newCW, ax // round up
+ __asm fldcw WORD PTR newCW
+ __asm fistp DWORD PTR result
+ __asm fldcw WORD PTR oldCW
+ return result;
+
+#else
+
+ //--- all others
+
+ return (int)ceil(x);
+
+#endif
+}
+
+static inline int splashRound(SplashCoord x) {
+#if USE_FIXEDPOINT
+
+ //--- fixed point
+
+ return FixedPoint::round(x);
+
+#else
+
+ //--- all others
+
+ return splashFloor(x + 0.5);
+
+#endif
+}
+
+static inline SplashCoord splashAvg(SplashCoord x, SplashCoord y) {
+#if USE_FIXEDPOINT
+ return FixedPoint::avg(x, y);
+#else
+ return 0.5 * (x + y);
+#endif
+}
+
+static inline SplashCoord splashSqrt(SplashCoord x) {
+#if USE_FIXEDPOINT
+ return FixedPoint::sqrt(x);
+#else
+ return sqrt(x);
+#endif
+}
+
+static inline SplashCoord splashPow(SplashCoord x, SplashCoord y) {
+#if USE_FIXEDPOINT
+ return FixedPoint::pow(x, y);
+#else
+ return pow(x, y);
+#endif
+}
+
+static inline SplashCoord splashDist(SplashCoord x0, SplashCoord y0,
+ SplashCoord x1, SplashCoord y1) {
+ SplashCoord dx, dy;
+ dx = x1 - x0;
+ dy = y1 - y0;
+#if USE_FIXEDPOINT
+ // this handles the situation where dx*dx or dy*dy is too large to
+ // fit in the 16.16 fixed point format
+ SplashCoord dxa, dya, d;
+ dxa = splashAbs(dx);
+ dya = splashAbs(dy);
+ if (dxa == 0 && dya == 0) {
+ return 0;
+ } else if (dxa > dya) {
+ d = dya / dxa;
+ return dxa * FixedPoint::sqrt(d*d + 1);
+ } else {
+ d = dxa / dya;
+ return dya * FixedPoint::sqrt(d*d + 1);
+ }
+#else
+ return sqrt(dx * dx + dy * dy);
+#endif
+}
+
+static inline GBool splashCheckDet(SplashCoord m11, SplashCoord m12,
+ SplashCoord m21, SplashCoord m22,
+ SplashCoord epsilon) {
+#if USE_FIXEDPOINT
+ return FixedPoint::checkDet(m11, m12, m21, m22, epsilon);
+#else
+ return fabs(m11 * m22 - m12 * m21) >= epsilon;
+#endif
+}
+
+// Perform stroke adjustment on a SplashCoord range [xMin, xMax),
+// resulting in an int range [*xMinI, *xMaxI).
+//
+// There are several options:
+//
+// 1. Round both edge coordinates.
+// Pro: adjacent strokes/fills line up without any gaps or
+// overlaps
+// Con: lines with the same original floating point width can
+// end up with different integer widths, e.g.:
+// xMin = 10.1 xMax = 11.3 (width = 1.2)
+// --> xMinI = 10 xMaxI = 11 (width = 1)
+// but
+// xMin = 10.4 xMax = 11.6 (width = 1.2)
+// --> xMinI = 10 xMaxI = 12 (width = 2)
+//
+// 2. Round the min coordinate; add the ceiling of the width.
+// Pro: lines with the same original floating point width will
+// always end up with the same integer width
+// Con: adjacent strokes/fills can have overlaps (which is
+// problematic with transparency)
+// (This could use floor on the min coordinate, instead of
+// rounding, with similar results.)
+// (If the width is rounded instead of using ceiling, the results
+// Are similar, except that adjacent strokes/fills can have gaps
+// as well as overlaps.)
+//
+// 3. Use floor on the min coordinate and ceiling on the max
+// coordinate.
+// Pro: lines always end up at least as wide as the original
+// floating point width
+// Con: adjacent strokes/fills can have overlaps, and lines with
+// the same original floating point width can end up with
+// different integer widths; the integer width can be more
+// than one pixel wider than the original width, e.g.:
+// xMin = 10.9 xMax = 12.1 (width = 1.2)
+// --> xMinI = 10 xMaxI = 13 (width = 3)
+// but
+// xMin = 10.1 xMax = 11.3 (width = 1.2)
+// --> xMinI = 10 xMaxI = 12 (width = 2)
+//
+// 4. Use a hybrid approach, choosing between two of the above
+// options, based on width. E.g., use #2 if width <= 4, and use #1
+// if width > 4.
+//
+// If w >= 0 and strokeAdjMode is splashStrokeAdjustCAD then a special
+// mode for projecting line caps is enabled, with w being the
+// transformed line width.
+
+static inline void splashStrokeAdjust(SplashCoord xMin, SplashCoord xMax,
+ int *xMinI, int *xMaxI,
+ SplashStrokeAdjustMode strokeAdjMode,
+ SplashCoord w = -1) {
+ int x0, x1;
+
+ // make sure the coords fit in 32-bit ints
+#if USE_FIXEDPOINT
+ if (xMin < -32767) {
+ xMin = -32767;
+ } else if (xMin > 32767) {
+ xMin = 32767;
+ }
+ if (xMax < -32767) {
+ xMax = -32767;
+ } else if (xMax > 32767) {
+ xMax = 32767;
+ }
+#else
+ if (xMin < -1e9) {
+ xMin = -1e9;
+ } else if (xMin > 1e9) {
+ xMin = 1e9;
+ }
+ if (xMax < -1e9) {
+ xMax = -1e9;
+ } else if (xMax > 1e9) {
+ xMax = 1e9;
+ }
+#endif
+
+ // this will never be called with strokeAdjMode == splashStrokeAdjustOff
+ if (strokeAdjMode == splashStrokeAdjustCAD) {
+ x0 = splashRound(xMin);
+ if (w >= 0) {
+ x1 = splashRound(xMax - w) + splashRound(w);
+ } else {
+ x1 = x0 + splashRound(xMax - xMin);
+ }
+ } else {
+ // NB: enable exactly one of these.
+#if 1 // 1. Round both edge coordinates.
+ x0 = splashRound(xMin);
+ x1 = splashRound(xMax);
+#endif
+#if 0 // 2. Round the min coordinate; add the ceiling of the width.
+ x0 = splashRound(xMin);
+ x1 = x0 + splashCeil(xMax - xMin);
+#endif
+#if 0 // 3. Use floor on the min coord and ceiling on the max coord.
+ x0 = splashFloor(xMin);
+ x1 = splashCeil(xMax);
+#endif
+#if 0 // 4. Hybrid.
+ SplashCoord w = xMax - xMin;
+ x0 = splashRound(xMin);
+ if (w > 4) {
+ x1 = splashRound(xMax);
+ } else {
+ x1 = x0 + splashRound(w);
+ }
+#endif
+ }
+ if (x0 == x1) {
+ if (xMin + xMax < 2 * x0) {
+ --x0;
+ } else {
+ ++x1;
+ }
+ }
+ *xMinI = x0;
+ *xMaxI = x1;
+}
+
+#endif
diff --git a/splash/SplashPath.cc b/splash/SplashPath.cc
new file mode 100644
index 0000000..7921667
--- /dev/null
+++ b/splash/SplashPath.cc
@@ -0,0 +1,213 @@
+//========================================================================
+//
+// SplashPath.cc
+//
+// Copyright 2003-2013 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <string.h>
+#include "gmem.h"
+#include "gmempp.h"
+#include "SplashErrorCodes.h"
+#include "SplashPath.h"
+
+//------------------------------------------------------------------------
+// SplashPath
+//------------------------------------------------------------------------
+
+// A path can be in three possible states:
+//
+// 1. no current point -- zero or more finished subpaths
+// [curSubpath == length]
+//
+// 2. one point in subpath
+// [curSubpath == length - 1]
+//
+// 3. open subpath with two or more points
+// [curSubpath < length - 1]
+
+SplashPath::SplashPath() {
+ pts = NULL;
+ flags = NULL;
+ length = size = 0;
+ curSubpath = 0;
+ hints = NULL;
+ hintsLength = hintsSize = 0;
+}
+
+SplashPath::SplashPath(SplashPath *path) {
+ length = path->length;
+ size = path->size;
+ pts = (SplashPathPoint *)gmallocn(size, sizeof(SplashPathPoint));
+ flags = (Guchar *)gmallocn(size, sizeof(Guchar));
+ memcpy(pts, path->pts, length * sizeof(SplashPathPoint));
+ memcpy(flags, path->flags, length * sizeof(Guchar));
+ curSubpath = path->curSubpath;
+ if (path->hints) {
+ hintsLength = hintsSize = path->hintsLength;
+ hints = (SplashPathHint *)gmallocn(hintsSize, sizeof(SplashPathHint));
+ memcpy(hints, path->hints, hintsLength * sizeof(SplashPathHint));
+ } else {
+ hints = NULL;
+ hintsLength = hintsSize = 0;
+ }
+}
+
+SplashPath::~SplashPath() {
+ gfree(pts);
+ gfree(flags);
+ gfree(hints);
+}
+
+// Add space for <nPts> more points.
+void SplashPath::grow(int nPts) {
+ if (length + nPts > size) {
+ if (size == 0) {
+ size = 32;
+ }
+ while (size < length + nPts) {
+ size *= 2;
+ }
+ pts = (SplashPathPoint *)greallocn(pts, size, sizeof(SplashPathPoint));
+ flags = (Guchar *)greallocn(flags, size, sizeof(Guchar));
+ }
+}
+
+void SplashPath::append(SplashPath *path) {
+ int i;
+
+ curSubpath = length + path->curSubpath;
+ grow(path->length);
+ for (i = 0; i < path->length; ++i) {
+ pts[length] = path->pts[i];
+ flags[length] = path->flags[i];
+ ++length;
+ }
+}
+
+SplashError SplashPath::moveTo(SplashCoord x, SplashCoord y) {
+ if (onePointSubpath()) {
+ return splashErrBogusPath;
+ }
+ grow(1);
+ pts[length].x = x;
+ pts[length].y = y;
+ flags[length] = splashPathFirst | splashPathLast;
+ curSubpath = length++;
+ return splashOk;
+}
+
+SplashError SplashPath::lineTo(SplashCoord x, SplashCoord y) {
+ if (noCurrentPoint()) {
+ return splashErrNoCurPt;
+ }
+ flags[length-1] &= (Guchar)~splashPathLast;
+ grow(1);
+ pts[length].x = x;
+ pts[length].y = y;
+ flags[length] = splashPathLast;
+ ++length;
+ return splashOk;
+}
+
+SplashError SplashPath::curveTo(SplashCoord x1, SplashCoord y1,
+ SplashCoord x2, SplashCoord y2,
+ SplashCoord x3, SplashCoord y3) {
+ if (noCurrentPoint()) {
+ return splashErrNoCurPt;
+ }
+ flags[length-1] &= (Guchar)~splashPathLast;
+ grow(3);
+ pts[length].x = x1;
+ pts[length].y = y1;
+ flags[length] = splashPathCurve;
+ ++length;
+ pts[length].x = x2;
+ pts[length].y = y2;
+ flags[length] = splashPathCurve;
+ ++length;
+ pts[length].x = x3;
+ pts[length].y = y3;
+ flags[length] = splashPathLast;
+ ++length;
+ return splashOk;
+}
+
+SplashError SplashPath::close(GBool force) {
+ if (noCurrentPoint()) {
+ return splashErrNoCurPt;
+ }
+ if (force ||
+ curSubpath == length - 1 ||
+ pts[length - 1].x != pts[curSubpath].x ||
+ pts[length - 1].y != pts[curSubpath].y) {
+ lineTo(pts[curSubpath].x, pts[curSubpath].y);
+ }
+ flags[curSubpath] |= splashPathClosed;
+ flags[length - 1] |= splashPathClosed;
+ curSubpath = length;
+ return splashOk;
+}
+
+void SplashPath::addStrokeAdjustHint(int ctrl0, int ctrl1,
+ int firstPt, int lastPt,
+ GBool projectingCap) {
+ if (hintsLength == hintsSize) {
+ hintsSize = hintsLength ? 2 * hintsLength : 8;
+ hints = (SplashPathHint *)greallocn(hints, hintsSize,
+ sizeof(SplashPathHint));
+ }
+ hints[hintsLength].ctrl0 = ctrl0;
+ hints[hintsLength].ctrl1 = ctrl1;
+ hints[hintsLength].firstPt = firstPt;
+ hints[hintsLength].lastPt = lastPt;
+ hints[hintsLength].projectingCap = projectingCap;
+ ++hintsLength;
+}
+
+void SplashPath::offset(SplashCoord dx, SplashCoord dy) {
+ int i;
+
+ for (i = 0; i < length; ++i) {
+ pts[i].x += dx;
+ pts[i].y += dy;
+ }
+}
+
+GBool SplashPath::getCurPt(SplashCoord *x, SplashCoord *y) {
+ if (noCurrentPoint()) {
+ return gFalse;
+ }
+ *x = pts[length - 1].x;
+ *y = pts[length - 1].y;
+ return gTrue;
+}
+
+GBool SplashPath::containsZeroLengthSubpaths() {
+ GBool zeroLength;
+ int i;
+
+ zeroLength = gTrue; // make gcc happy
+ for (i = 0; i < length; ++i) {
+ if (flags[i] & splashPathFirst) {
+ zeroLength = gTrue;
+ } else {
+ if (pts[i].x != pts[i-1].x || pts[i].y != pts[i-1].y) {
+ zeroLength = gFalse;
+ }
+ if (flags[i] & splashPathLast) {
+ if (zeroLength) {
+ return gTrue;
+ }
+ }
+ }
+ }
+ return gFalse;
+}
diff --git a/splash/SplashPath.h b/splash/SplashPath.h
new file mode 100644
index 0000000..b5732b8
--- /dev/null
+++ b/splash/SplashPath.h
@@ -0,0 +1,133 @@
+//========================================================================
+//
+// SplashPath.h
+//
+// Copyright 2003-2013 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef SPLASHPATH_H
+#define SPLASHPATH_H
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include "SplashTypes.h"
+
+//------------------------------------------------------------------------
+// SplashPathPoint
+//------------------------------------------------------------------------
+
+struct SplashPathPoint {
+ SplashCoord x, y;
+};
+
+//------------------------------------------------------------------------
+// SplashPath.flags
+//------------------------------------------------------------------------
+
+// first point on each subpath sets this flag
+#define splashPathFirst 0x01
+
+// last point on each subpath sets this flag
+#define splashPathLast 0x02
+
+// if the subpath is closed, its first and last points must be
+// identical, and must set this flag
+#define splashPathClosed 0x04
+
+// curve control points set this flag
+#define splashPathCurve 0x08
+
+//------------------------------------------------------------------------
+// SplashPathHint
+//------------------------------------------------------------------------
+
+struct SplashPathHint {
+ int ctrl0, ctrl1;
+ int firstPt, lastPt;
+ GBool projectingCap;
+};
+
+//------------------------------------------------------------------------
+// SplashPath
+//------------------------------------------------------------------------
+
+class SplashPath {
+public:
+
+ // Create an empty path.
+ SplashPath();
+
+ // Copy a path.
+ SplashPath *copy() { return new SplashPath(this); }
+
+ ~SplashPath();
+
+ // Append <path> to <this>.
+ void append(SplashPath *path);
+
+ // Start a new subpath.
+ SplashError moveTo(SplashCoord x, SplashCoord y);
+
+ // Add a line segment to the last subpath.
+ SplashError lineTo(SplashCoord x, SplashCoord y);
+
+ // Add a third-order (cubic) Bezier curve segment to the last
+ // subpath.
+ SplashError curveTo(SplashCoord x1, SplashCoord y1,
+ SplashCoord x2, SplashCoord y2,
+ SplashCoord x3, SplashCoord y3);
+
+ // Close the last subpath, adding a line segment if necessary. If
+ // <force> is true, this adds a line segment even if the current
+ // point is equal to the first point in the subpath.
+ SplashError close(GBool force = gFalse);
+
+ // Add a stroke adjustment hint. The controlling segments are
+ // <ctrl0> and <ctrl1> (where segments are identified by their first
+ // point), and the points to be adjusted are <firstPt> .. <lastPt>.
+ // <projectingCap> is true if the points are part of a projecting
+ // line cap.
+ void addStrokeAdjustHint(int ctrl0, int ctrl1, int firstPt, int lastPt,
+ GBool projectingCap = gFalse);
+
+ // Add (<dx>, <dy>) to every point on this path.
+ void offset(SplashCoord dx, SplashCoord dy);
+
+ // Get the points on the path.
+ int getLength() { return length; }
+ void getPoint(int i, SplashCoord *x, SplashCoord *y, Guchar *f)
+ { *x = pts[i].x; *y = pts[i].y; *f = flags[i]; }
+
+ // Get the current point.
+ GBool getCurPt(SplashCoord *x, SplashCoord *y);
+
+ // Returns true if the path contains one or more zero length
+ // subpaths.
+ GBool containsZeroLengthSubpaths();
+
+private:
+
+ SplashPath(SplashPath *path);
+ void grow(int nPts);
+ GBool noCurrentPoint() { return curSubpath == length; }
+ GBool onePointSubpath() { return curSubpath == length - 1; }
+ GBool openSubpath() { return curSubpath < length - 1; }
+
+ SplashPathPoint *pts; // array of points
+ Guchar *flags; // array of flags
+ int length, size; // length/size of the pts and flags arrays
+ int curSubpath; // index of first point in last subpath
+
+ SplashPathHint *hints; // list of hints
+ int hintsLength, hintsSize;
+
+ friend class SplashXPath;
+ friend class Splash;
+};
+
+#endif
diff --git a/splash/SplashPattern.cc b/splash/SplashPattern.cc
new file mode 100644
index 0000000..0c5b509
--- /dev/null
+++ b/splash/SplashPattern.cc
@@ -0,0 +1,44 @@
+//========================================================================
+//
+// SplashPattern.cc
+//
+// Copyright 2003-2013 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include "gmempp.h"
+#include "SplashMath.h"
+#include "SplashScreen.h"
+#include "SplashPattern.h"
+
+//------------------------------------------------------------------------
+// SplashPattern
+//------------------------------------------------------------------------
+
+SplashPattern::SplashPattern() {
+}
+
+SplashPattern::~SplashPattern() {
+}
+
+//------------------------------------------------------------------------
+// SplashSolidColor
+//------------------------------------------------------------------------
+
+SplashSolidColor::SplashSolidColor(SplashColorPtr colorA) {
+ splashColorCopy(color, colorA);
+}
+
+SplashSolidColor::~SplashSolidColor() {
+}
+
+void SplashSolidColor::getColor(int x, int y, SplashColorPtr c) {
+ splashColorCopy(c, color);
+}
+
diff --git a/splash/SplashPattern.h b/splash/SplashPattern.h
new file mode 100644
index 0000000..fcbe21d
--- /dev/null
+++ b/splash/SplashPattern.h
@@ -0,0 +1,69 @@
+//========================================================================
+//
+// SplashPattern.h
+//
+// Copyright 2003-2013 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef SPLASHPATTERN_H
+#define SPLASHPATTERN_H
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include "SplashTypes.h"
+
+class SplashScreen;
+
+//------------------------------------------------------------------------
+// SplashPattern
+//------------------------------------------------------------------------
+
+class SplashPattern {
+public:
+
+ SplashPattern();
+
+ virtual SplashPattern *copy() = 0;
+
+ virtual ~SplashPattern();
+
+ // Return the color value for a specific pixel.
+ virtual void getColor(int x, int y, SplashColorPtr c) = 0;
+
+
+ // Returns true if this pattern object will return the same color
+ // value for all pixels.
+ virtual GBool isStatic() = 0;
+
+private:
+};
+
+//------------------------------------------------------------------------
+// SplashSolidColor
+//------------------------------------------------------------------------
+
+class SplashSolidColor: public SplashPattern {
+public:
+
+ SplashSolidColor(SplashColorPtr colorA);
+
+ virtual SplashPattern *copy() { return new SplashSolidColor(color); }
+
+ virtual ~SplashSolidColor();
+
+ virtual void getColor(int x, int y, SplashColorPtr c);
+
+ virtual GBool isStatic() { return gTrue; }
+
+private:
+
+ SplashColor color;
+};
+
+
+#endif
diff --git a/splash/SplashScreen.cc b/splash/SplashScreen.cc
new file mode 100644
index 0000000..9993edc
--- /dev/null
+++ b/splash/SplashScreen.cc
@@ -0,0 +1,383 @@
+//========================================================================
+//
+// SplashScreen.cc
+//
+// Copyright 2003-2013 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#if HAVE_STD_SORT
+#include <algorithm>
+#endif
+#include "gmem.h"
+#include "gmempp.h"
+#include "SplashMath.h"
+#include "SplashScreen.h"
+
+//------------------------------------------------------------------------
+
+static SplashScreenParams defaultParams = {
+ splashScreenDispersed, // type
+ 2, // size
+ 2, // dotRadius
+ 1.0, // gamma
+ 0.0, // blackThreshold
+ 1.0 // whiteThreshold
+};
+
+//------------------------------------------------------------------------
+
+struct SplashScreenPoint {
+ int x, y;
+ int dist;
+};
+
+#if HAVE_STD_SORT
+
+struct cmpDistancesFunctor {
+ bool operator()(const SplashScreenPoint &p0, const SplashScreenPoint &p1) {
+ return p0.dist < p1.dist;
+ }
+};
+
+#else // HAVE_STD_SORT
+
+static int cmpDistances(const void *p0, const void *p1) {
+ return ((SplashScreenPoint *)p0)->dist - ((SplashScreenPoint *)p1)->dist;
+}
+
+#endif
+
+//------------------------------------------------------------------------
+// SplashScreen
+//------------------------------------------------------------------------
+
+// If <clustered> is true, this generates a 45 degree screen using a
+// circular dot spot function. DPI = resolution / ((size / 2) *
+// sqrt(2)). If <clustered> is false, this generates an optimal
+// threshold matrix using recursive tesselation. Gamma correction
+// (gamma = 1 / 1.33) is also computed here.
+SplashScreen::SplashScreen(SplashScreenParams *params) {
+ Guchar u;
+ int black, white, i;
+
+ if (!params) {
+ params = &defaultParams;
+ }
+
+ // size must be a power of 2, and at least 2
+ for (size = 2, log2Size = 1; size < params->size; size <<= 1, ++log2Size) ;
+
+ switch (params->type) {
+
+ case splashScreenDispersed:
+ mat = (Guchar *)gmallocn(size * size, sizeof(Guchar));
+ buildDispersedMatrix(size/2, size/2, 1, size/2, 1);
+ break;
+
+ case splashScreenClustered:
+ mat = (Guchar *)gmallocn(size * size, sizeof(Guchar));
+ buildClusteredMatrix();
+ break;
+
+ case splashScreenStochasticClustered:
+ // size must be at least 2*r
+ while (size < (params->dotRadius << 1)) {
+ size <<= 1;
+ ++log2Size;
+ }
+ mat = (Guchar *)gmallocn(size * size, sizeof(Guchar));
+ buildSCDMatrix(params->dotRadius);
+ break;
+ }
+
+ sizeM1 = size - 1;
+
+ // do gamma correction and compute minVal/maxVal
+ minVal = 255;
+ maxVal = 0;
+ black = splashRound((SplashCoord)255.0 * params->blackThreshold);
+ if (black < 1) {
+ black = 1;
+ }
+ white = splashRound((SplashCoord)255.0 * params->whiteThreshold);
+ if (white > 255) {
+ white = 255;
+ }
+ for (i = 0; i < size * size; ++i) {
+ u = (Guchar)splashRound((SplashCoord)255.0 *
+ splashPow((SplashCoord)mat[i] / 255.0,
+ params->gamma));
+ if (u < black) {
+ u = (Guchar)black;
+ } else if (u >= white) {
+ u = (Guchar)white;
+ }
+ mat[i] = u;
+ if (u < minVal) {
+ minVal = u;
+ } else if (u > maxVal) {
+ maxVal = u;
+ }
+ }
+}
+
+void SplashScreen::buildDispersedMatrix(int i, int j, int val,
+ int delta, int offset) {
+ if (delta == 0) {
+ // map values in [1, size^2] --> [1, 255]
+ mat[(i << log2Size) + j] =
+ (Guchar)(1 + (254 * (val - 1)) / (size * size - 1));
+ } else {
+ buildDispersedMatrix(i, j,
+ val, delta / 2, 4*offset);
+ buildDispersedMatrix((i + delta) % size, (j + delta) % size,
+ val + offset, delta / 2, 4*offset);
+ buildDispersedMatrix((i + delta) % size, j,
+ val + 2*offset, delta / 2, 4*offset);
+ buildDispersedMatrix((i + 2*delta) % size, (j + delta) % size,
+ val + 3*offset, delta / 2, 4*offset);
+ }
+}
+
+void SplashScreen::buildClusteredMatrix() {
+ SplashCoord *dist;
+ SplashCoord u, v, d;
+ Guchar val;
+ int size2, x, y, x1, y1, i;
+
+ size2 = size >> 1;
+
+ // initialize the threshold matrix
+ for (y = 0; y < size; ++y) {
+ for (x = 0; x < size; ++x) {
+ mat[(y << log2Size) + x] = 0;
+ }
+ }
+
+ // build the distance matrix
+ dist = (SplashCoord *)gmallocn(size * size2, sizeof(SplashCoord));
+ for (y = 0; y < size2; ++y) {
+ for (x = 0; x < size2; ++x) {
+ if (x + y < size2 - 1) {
+ u = (SplashCoord)x + 0.5 - 0;
+ v = (SplashCoord)y + 0.5 - 0;
+ } else {
+ u = (SplashCoord)x + 0.5 - (SplashCoord)size2;
+ v = (SplashCoord)y + 0.5 - (SplashCoord)size2;
+ }
+ dist[y * size2 + x] = u*u + v*v;
+ }
+ }
+ for (y = 0; y < size2; ++y) {
+ for (x = 0; x < size2; ++x) {
+ if (x < y) {
+ u = (SplashCoord)x + 0.5 - 0;
+ v = (SplashCoord)y + 0.5 - (SplashCoord)size2;
+ } else {
+ u = (SplashCoord)x + 0.5 - (SplashCoord)size2;
+ v = (SplashCoord)y + 0.5 - 0;
+ }
+ dist[(size2 + y) * size2 + x] = u*u + v*v;
+ }
+ }
+
+ // build the threshold matrix
+ x1 = y1 = 0; // make gcc happy
+ for (i = 0; i < size * size2; ++i) {
+ d = -1;
+ for (y = 0; y < size; ++y) {
+ for (x = 0; x < size2; ++x) {
+ if (mat[(y << log2Size) + x] == 0 &&
+ dist[y * size2 + x] > d) {
+ x1 = x;
+ y1 = y;
+ d = dist[y1 * size2 + x1];
+ }
+ }
+ }
+ // map values in [0, 2*size*size2-1] --> [1, 255]
+ val = (Guchar)(1 + (254 * (2*i)) / (2*size*size2 - 1));
+ mat[(y1 << log2Size) + x1] = val;
+ val = (Guchar)(1 + (254 * (2*i+1)) / (2*size*size2 - 1));
+ if (y1 < size2) {
+ mat[((y1 + size2) << log2Size) + x1 + size2] = val;
+ } else {
+ mat[((y1 - size2) << log2Size) + x1 + size2] = val;
+ }
+ }
+
+ gfree(dist);
+}
+
+// Compute the distance between two points on a toroid.
+int SplashScreen::distance(int x0, int y0, int x1, int y1) {
+ int dx0, dx1, dx, dy0, dy1, dy;
+
+ dx0 = abs(x0 - x1);
+ dx1 = size - dx0;
+ dx = dx0 < dx1 ? dx0 : dx1;
+ dy0 = abs(y0 - y1);
+ dy1 = size - dy0;
+ dy = dy0 < dy1 ? dy0 : dy1;
+ return dx * dx + dy * dy;
+}
+
+// Algorithm taken from:
+// Victor Ostromoukhov and Roger D. Hersch, "Stochastic Clustered-Dot
+// Dithering" in Color Imaging: Device-Independent Color, Color
+// Hardcopy, and Graphic Arts IV, SPIE Vol. 3648, pp. 496-505, 1999.
+void SplashScreen::buildSCDMatrix(int r) {
+ SplashScreenPoint *dots, *pts;
+ int dotsLen, dotsSize;
+ char *tmpl;
+ char *grid;
+ int *region, *dist;
+ int x, y, xx, yy, x0, x1, y0, y1, i, j, d, iMin, dMin, n;
+
+ //~ this should probably happen somewhere else
+ srand(123);
+
+ // generate the random space-filling curve
+ pts = (SplashScreenPoint *)gmallocn(size * size, sizeof(SplashScreenPoint));
+ i = 0;
+ for (y = 0; y < size; ++y) {
+ for (x = 0; x < size; ++x) {
+ pts[i].x = x;
+ pts[i].y = y;
+ ++i;
+ }
+ }
+ for (i = 0; i < size * size; ++i) {
+ j = i + (int)((double)(size * size - i) *
+ (double)rand() / ((double)RAND_MAX + 1.0));
+ x = pts[i].x;
+ y = pts[i].y;
+ pts[i].x = pts[j].x;
+ pts[i].y = pts[j].y;
+ pts[j].x = x;
+ pts[j].y = y;
+ }
+
+ // construct the circle template
+ tmpl = (char *)gmallocn((r+1)*(r+1), sizeof(char));
+ for (y = 0; y <= r; ++y) {
+ for (x = 0; x <= r; ++x) {
+ tmpl[y*(r+1) + x] = (x * y <= r * r) ? 1 : 0;
+ }
+ }
+
+ // mark all grid cells as free
+ grid = (char *)gmallocn(size * size, sizeof(char));
+ for (y = 0; y < size; ++y) {
+ for (x = 0; x < size; ++x) {
+ grid[(y << log2Size) + x] = 0;
+ }
+ }
+
+ // walk the space-filling curve, adding dots
+ dotsLen = 0;
+ dotsSize = 32;
+ dots = (SplashScreenPoint *)gmallocn(dotsSize, sizeof(SplashScreenPoint));
+ for (i = 0; i < size * size; ++i) {
+ x = pts[i].x;
+ y = pts[i].y;
+ if (!grid[(y << log2Size) + x]) {
+ if (dotsLen == dotsSize) {
+ dotsSize *= 2;
+ dots = (SplashScreenPoint *)greallocn(dots, dotsSize,
+ sizeof(SplashScreenPoint));
+ }
+ dots[dotsLen++] = pts[i];
+ for (yy = 0; yy <= r; ++yy) {
+ y0 = (y + yy) % size;
+ y1 = (y - yy + size) % size;
+ for (xx = 0; xx <= r; ++xx) {
+ if (tmpl[yy*(r+1) + xx]) {
+ x0 = (x + xx) % size;
+ x1 = (x - xx + size) % size;
+ grid[(y0 << log2Size) + x0] = 1;
+ grid[(y0 << log2Size) + x1] = 1;
+ grid[(y1 << log2Size) + x0] = 1;
+ grid[(y1 << log2Size) + x1] = 1;
+ }
+ }
+ }
+ }
+ }
+
+ gfree(tmpl);
+ gfree(grid);
+
+ // assign each cell to a dot, compute distance to center of dot
+ region = (int *)gmallocn(size * size, sizeof(int));
+ dist = (int *)gmallocn(size * size, sizeof(int));
+ for (y = 0; y < size; ++y) {
+ for (x = 0; x < size; ++x) {
+ iMin = 0;
+ dMin = distance(dots[0].x, dots[0].y, x, y);
+ for (i = 1; i < dotsLen; ++i) {
+ d = distance(dots[i].x, dots[i].y, x, y);
+ if (d < dMin) {
+ iMin = i;
+ dMin = d;
+ }
+ }
+ region[(y << log2Size) + x] = iMin;
+ dist[(y << log2Size) + x] = dMin;
+ }
+ }
+
+ // compute threshold values
+ for (i = 0; i < dotsLen; ++i) {
+ n = 0;
+ for (y = 0; y < size; ++y) {
+ for (x = 0; x < size; ++x) {
+ if (region[(y << log2Size) + x] == i) {
+ pts[n].x = x;
+ pts[n].y = y;
+ pts[n].dist = distance(dots[i].x, dots[i].y, x, y);
+ ++n;
+ }
+ }
+ }
+#if HAVE_STD_SORT
+ std::sort(pts, pts + n, cmpDistancesFunctor());
+#else
+ qsort(pts, n, sizeof(SplashScreenPoint), &cmpDistances);
+#endif
+ for (j = 0; j < n; ++j) {
+ // map values in [0 .. n-1] --> [255 .. 1]
+ mat[(pts[j].y << log2Size) + pts[j].x] =
+ (Guchar)(255 - (254 * j) / (n - 1));
+ }
+ }
+
+ gfree(pts);
+ gfree(region);
+ gfree(dist);
+
+ gfree(dots);
+}
+
+SplashScreen::SplashScreen(SplashScreen *screen) {
+ size = screen->size;
+ sizeM1 = screen->sizeM1;
+ log2Size = screen->log2Size;
+ mat = (Guchar *)gmallocn(size * size, sizeof(Guchar));
+ memcpy(mat, screen->mat, size * size * sizeof(Guchar));
+ minVal = screen->minVal;
+ maxVal = screen->maxVal;
+}
+
+SplashScreen::~SplashScreen() {
+ gfree(mat);
+}
diff --git a/splash/SplashScreen.h b/splash/SplashScreen.h
new file mode 100644
index 0000000..560e275
--- /dev/null
+++ b/splash/SplashScreen.h
@@ -0,0 +1,81 @@
+//========================================================================
+//
+// SplashScreen.h
+//
+// Copyright 2003-2013 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef SPLASHSCREEN_H
+#define SPLASHSCREEN_H
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include "SplashTypes.h"
+
+//------------------------------------------------------------------------
+// SplashScreen
+//------------------------------------------------------------------------
+
+typedef Guchar *SplashScreenCursor;
+
+class SplashScreen {
+public:
+
+ SplashScreen(SplashScreenParams *params);
+ SplashScreen(SplashScreen *screen);
+ ~SplashScreen();
+
+ SplashScreen *copy() { return new SplashScreen(this); }
+
+ // Return the computed pixel value (0=black, 1=white) for the gray
+ // level <value> at (<x>, <y>).
+ int test(int x, int y, Guchar value) {
+ int xx, yy;
+ xx = x & sizeM1;
+ yy = y & sizeM1;
+ return value < mat[(yy << log2Size) + xx] ? 0 : 1;
+ }
+
+ // To do a series of tests with the same y value, call
+ // getTestCursor(y), and then call testWithCursor(cursor, x, value)
+ // for each x.
+ SplashScreenCursor getTestCursor(int y) {
+ int yy;
+ yy = y & sizeM1;
+ return &mat[yy << log2Size];
+ }
+
+ int testWithCursor(SplashScreenCursor cursor, int x, Guchar value) {
+ int xx = x & sizeM1;
+ return value >= cursor[xx];
+ }
+
+ // Returns true if value is above the white threshold or below the
+ // black threshold, i.e., if the corresponding halftone will be
+ // solid white or black.
+ GBool isStatic(Guchar value) { return value < minVal || value >= maxVal; }
+
+private:
+
+ void buildDispersedMatrix(int i, int j, int val,
+ int delta, int offset);
+ void buildClusteredMatrix();
+ int distance(int x0, int y0, int x1, int y1);
+ void buildSCDMatrix(int r);
+
+ Guchar *mat; // threshold matrix
+ int size; // size of the threshold matrix
+ int sizeM1; // size - 1
+ int log2Size; // log2(size)
+ Guchar minVal; // any pixel value below minVal generates
+ // solid black
+ Guchar maxVal; // any pixel value above maxVal generates
+ // solid white
+};
+
+#endif
diff --git a/splash/SplashState.cc b/splash/SplashState.cc
new file mode 100644
index 0000000..7fc5104
--- /dev/null
+++ b/splash/SplashState.cc
@@ -0,0 +1,349 @@
+//========================================================================
+//
+// SplashState.cc
+//
+// Copyright 2003-2013 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <string.h>
+#include "gmem.h"
+#include "gmempp.h"
+#include "SplashPattern.h"
+#include "SplashScreen.h"
+#include "SplashClip.h"
+#include "SplashBitmap.h"
+#include "SplashState.h"
+
+//------------------------------------------------------------------------
+// SplashState
+//------------------------------------------------------------------------
+
+// number of components in each color mode
+int splashColorModeNComps[] = {
+ 1, 1, 3, 3
+#if SPLASH_CMYK
+ , 4
+#endif
+};
+
+SplashState::SplashState(int width, int height, GBool vectorAntialias,
+ SplashScreenParams *screenParams) {
+ SplashColor color;
+ int i;
+
+ matrix[0] = 1; matrix[1] = 0;
+ matrix[2] = 0; matrix[3] = 1;
+ matrix[4] = 0; matrix[5] = 0;
+ memset(&color, 0, sizeof(SplashColor));
+ strokePattern = new SplashSolidColor(color);
+ fillPattern = new SplashSolidColor(color);
+ screen = new SplashScreen(screenParams);
+ blendFunc = NULL;
+ strokeAlpha = 1;
+ fillAlpha = 1;
+ lineWidth = 1;
+ lineCap = splashLineCapButt;
+ lineJoin = splashLineJoinMiter;
+ miterLimit = 10;
+ flatness = 1;
+ lineDash = NULL;
+ lineDashLength = 0;
+ lineDashPhase = 0;
+ strokeAdjust = splashStrokeAdjustOff;
+ clip = new SplashClip(0, 0, width, height);
+ clipIsShared = gFalse;
+ softMask = NULL;
+ deleteSoftMask = gFalse;
+ inNonIsolatedGroup = gFalse;
+ inKnockoutGroup = gFalse;
+#if SPLASH_CMYK
+ rgbTransferR = (Guchar *)gmalloc(8 * 256);
+ rgbTransferG = rgbTransferR + 256;
+ rgbTransferB = rgbTransferG + 256;
+ grayTransfer = rgbTransferB + 256;
+ cmykTransferC = grayTransfer + 256;
+ cmykTransferM = cmykTransferC + 256;
+ cmykTransferY = cmykTransferM + 256;
+ cmykTransferK = cmykTransferY + 256;
+#else
+ rgbTransferR = (Guchar *)gmalloc(4 * 256);
+ rgbTransferG = rgbTransferR + 256;
+ rgbTransferB = rgbTransferG + 256;
+ grayTransfer = rgbTransferB + 256;
+#endif
+ for (i = 0; i < 256; ++i) {
+ rgbTransferR[i] = (Guchar)i;
+ rgbTransferG[i] = (Guchar)i;
+ rgbTransferB[i] = (Guchar)i;
+ grayTransfer[i] = (Guchar)i;
+#if SPLASH_CMYK
+ cmykTransferC[i] = (Guchar)i;
+ cmykTransferM[i] = (Guchar)i;
+ cmykTransferY[i] = (Guchar)i;
+ cmykTransferK[i] = (Guchar)i;
+#endif
+ }
+ transferIsShared = gFalse;
+ overprintMask = 0xffffffff;
+ enablePathSimplification = gFalse;
+ next = NULL;
+}
+
+SplashState::SplashState(int width, int height, GBool vectorAntialias,
+ SplashScreen *screenA) {
+ SplashColor color;
+ int i;
+
+ matrix[0] = 1; matrix[1] = 0;
+ matrix[2] = 0; matrix[3] = 1;
+ matrix[4] = 0; matrix[5] = 0;
+ memset(&color, 0, sizeof(SplashColor));
+ strokePattern = new SplashSolidColor(color);
+ fillPattern = new SplashSolidColor(color);
+ screen = screenA->copy();
+ blendFunc = NULL;
+ strokeAlpha = 1;
+ fillAlpha = 1;
+ lineWidth = 1;
+ lineCap = splashLineCapButt;
+ lineJoin = splashLineJoinMiter;
+ miterLimit = 10;
+ flatness = 1;
+ lineDash = NULL;
+ lineDashLength = 0;
+ lineDashPhase = 0;
+ strokeAdjust = splashStrokeAdjustOff;
+ clip = new SplashClip(0, 0, width, height);
+ clipIsShared = gFalse;
+ softMask = NULL;
+ deleteSoftMask = gFalse;
+ inNonIsolatedGroup = gFalse;
+ inKnockoutGroup = gFalse;
+#if SPLASH_CMYK
+ rgbTransferR = (Guchar *)gmalloc(8 * 256);
+ rgbTransferG = rgbTransferR + 256;
+ rgbTransferB = rgbTransferG + 256;
+ grayTransfer = rgbTransferB + 256;
+ cmykTransferC = grayTransfer + 256;
+ cmykTransferM = cmykTransferC + 256;
+ cmykTransferY = cmykTransferM + 256;
+ cmykTransferK = cmykTransferY + 256;
+#else
+ rgbTransferR = (Guchar *)gmalloc(4 * 256);
+ rgbTransferG = rgbTransferR + 256;
+ rgbTransferB = rgbTransferG + 256;
+ grayTransfer = rgbTransferB + 256;
+#endif
+ for (i = 0; i < 256; ++i) {
+ rgbTransferR[i] = (Guchar)i;
+ rgbTransferG[i] = (Guchar)i;
+ rgbTransferB[i] = (Guchar)i;
+ grayTransfer[i] = (Guchar)i;
+#if SPLASH_CMYK
+ cmykTransferC[i] = (Guchar)i;
+ cmykTransferM[i] = (Guchar)i;
+ cmykTransferY[i] = (Guchar)i;
+ cmykTransferK[i] = (Guchar)i;
+#endif
+ }
+ transferIsShared = gFalse;
+ overprintMask = 0xffffffff;
+ enablePathSimplification = gFalse;
+ next = NULL;
+}
+
+SplashState::SplashState(SplashState *state) {
+ memcpy(matrix, state->matrix, 6 * sizeof(SplashCoord));
+ strokePattern = state->strokePattern->copy();
+ fillPattern = state->fillPattern->copy();
+ screen = state->screen->copy();
+ blendFunc = state->blendFunc;
+ strokeAlpha = state->strokeAlpha;
+ fillAlpha = state->fillAlpha;
+ lineWidth = state->lineWidth;
+ lineCap = state->lineCap;
+ lineJoin = state->lineJoin;
+ miterLimit = state->miterLimit;
+ flatness = state->flatness;
+ if (state->lineDash) {
+ lineDashLength = state->lineDashLength;
+ lineDash = (SplashCoord *)gmallocn(lineDashLength, sizeof(SplashCoord));
+ memcpy(lineDash, state->lineDash, lineDashLength * sizeof(SplashCoord));
+ } else {
+ lineDash = NULL;
+ lineDashLength = 0;
+ }
+ lineDashPhase = state->lineDashPhase;
+ strokeAdjust = state->strokeAdjust;
+ clip = state->clip;
+ clipIsShared = gTrue;
+ softMask = state->softMask;
+ deleteSoftMask = gFalse;
+ inNonIsolatedGroup = state->inNonIsolatedGroup;
+ inKnockoutGroup = state->inKnockoutGroup;
+ rgbTransferR = state->rgbTransferR;
+ rgbTransferG = state->rgbTransferG;
+ rgbTransferB = state->rgbTransferB;
+ grayTransfer = state->grayTransfer;
+#if SPLASH_CMYK
+ cmykTransferC = state->cmykTransferC;
+ cmykTransferM = state->cmykTransferM;
+ cmykTransferY = state->cmykTransferY;
+ cmykTransferK = state->cmykTransferK;
+#endif
+ transferIsShared = gTrue;
+ overprintMask = state->overprintMask;
+ enablePathSimplification = state->enablePathSimplification;
+ next = NULL;
+}
+
+SplashState::~SplashState() {
+ delete strokePattern;
+ delete fillPattern;
+ delete screen;
+ gfree(lineDash);
+ if (!clipIsShared) {
+ delete clip;
+ }
+ if (!transferIsShared) {
+ gfree(rgbTransferR);
+ }
+ if (deleteSoftMask && softMask) {
+ delete softMask;
+ }
+}
+
+void SplashState::setStrokePattern(SplashPattern *strokePatternA) {
+ delete strokePattern;
+ strokePattern = strokePatternA;
+}
+
+void SplashState::setFillPattern(SplashPattern *fillPatternA) {
+ delete fillPattern;
+ fillPattern = fillPatternA;
+}
+
+void SplashState::setScreen(SplashScreen *screenA) {
+ delete screen;
+ screen = screenA;
+}
+
+void SplashState::setLineDash(SplashCoord *lineDashA, int lineDashLengthA,
+ SplashCoord lineDashPhaseA) {
+ gfree(lineDash);
+ lineDashLength = lineDashLengthA;
+ if (lineDashLength > 0) {
+ lineDash = (SplashCoord *)gmallocn(lineDashLength, sizeof(SplashCoord));
+ memcpy(lineDash, lineDashA, lineDashLength * sizeof(SplashCoord));
+ } else {
+ lineDash = NULL;
+ }
+ lineDashPhase = lineDashPhaseA;
+}
+
+GBool SplashState::lineDashContainsZeroLengthDashes() {
+ int i;
+
+ if (lineDashLength == 0) {
+ return gFalse;
+ }
+
+ // if the line dash array has an odd number of elements, we need to
+ // check all of the elements; if the length is even, we only need to
+ // check even-number elements
+ if (lineDashLength & 1) {
+ for (i = 0; i < lineDashLength; ++i) {
+ if (lineDash[i] == 0) {
+ return gTrue;
+ }
+ }
+ } else {
+ for (i = 0; i < lineDashLength; i += 2) {
+ if (lineDash[i] == 0) {
+ return gTrue;
+ }
+ }
+ }
+ return gFalse;
+}
+
+void SplashState::clipResetToRect(SplashCoord x0, SplashCoord y0,
+ SplashCoord x1, SplashCoord y1) {
+ if (clipIsShared) {
+ clip = clip->copy();
+ clipIsShared = gFalse;
+ }
+ clip->resetToRect(x0, y0, x1, y1);
+}
+
+SplashError SplashState::clipToRect(SplashCoord x0, SplashCoord y0,
+ SplashCoord x1, SplashCoord y1) {
+ if (clipIsShared) {
+ clip = clip->copy();
+ clipIsShared = gFalse;
+ }
+ return clip->clipToRect(x0, y0, x1, y1);
+}
+
+SplashError SplashState::clipToPath(SplashPath *path, GBool eo) {
+ if (clipIsShared) {
+ clip = clip->copy();
+ clipIsShared = gFalse;
+ }
+ return clip->clipToPath(path, matrix, flatness, eo,
+ enablePathSimplification, strokeAdjust);
+}
+
+void SplashState::setSoftMask(SplashBitmap *softMaskA, GBool deleteBitmap) {
+ if (deleteSoftMask) {
+ delete softMask;
+ }
+ softMask = softMaskA;
+ deleteSoftMask = deleteBitmap;
+}
+
+void SplashState::setTransfer(Guchar *red, Guchar *green, Guchar *blue,
+ Guchar *gray) {
+#if SPLASH_CMYK
+ int i;
+#endif
+
+ if (transferIsShared) {
+#if SPLASH_CMYK
+ rgbTransferR = (Guchar *)gmalloc(8 * 256);
+ rgbTransferG = rgbTransferR + 256;
+ rgbTransferB = rgbTransferG + 256;
+ grayTransfer = rgbTransferB + 256;
+ cmykTransferC = grayTransfer + 256;
+ cmykTransferM = cmykTransferC + 256;
+ cmykTransferY = cmykTransferM + 256;
+ cmykTransferK = cmykTransferY + 256;
+#else
+ rgbTransferR = (Guchar *)gmalloc(4 * 256);
+ rgbTransferG = rgbTransferR + 256;
+ rgbTransferB = rgbTransferG + 256;
+ grayTransfer = rgbTransferB + 256;
+#endif
+ transferIsShared = gFalse;
+ }
+ memcpy(rgbTransferR, red, 256);
+ memcpy(rgbTransferG, green, 256);
+ memcpy(rgbTransferB, blue, 256);
+ memcpy(grayTransfer, gray, 256);
+#if SPLASH_CMYK
+ for (i = 0; i < 256; ++i) {
+ cmykTransferC[i] = (Guchar)(255 - rgbTransferR[255 - i]);
+ cmykTransferM[i] = (Guchar)(255 - rgbTransferG[255 - i]);
+ cmykTransferY[i] = (Guchar)(255 - rgbTransferB[255 - i]);
+ cmykTransferK[i] = (Guchar)(255 - grayTransfer[255 - i]);
+ }
+#endif
+}
+
diff --git a/splash/SplashState.h b/splash/SplashState.h
new file mode 100644
index 0000000..be64b47
--- /dev/null
+++ b/splash/SplashState.h
@@ -0,0 +1,136 @@
+//========================================================================
+//
+// SplashState.h
+//
+// Copyright 2003-2013 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef SPLASHSTATE_H
+#define SPLASHSTATE_H
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include "SplashTypes.h"
+
+class SplashPattern;
+class SplashScreen;
+class SplashClip;
+class SplashBitmap;
+class SplashPath;
+
+//------------------------------------------------------------------------
+// line cap values
+//------------------------------------------------------------------------
+
+#define splashLineCapButt 0
+#define splashLineCapRound 1
+#define splashLineCapProjecting 2
+
+//------------------------------------------------------------------------
+// line join values
+//------------------------------------------------------------------------
+
+#define splashLineJoinMiter 0
+#define splashLineJoinRound 1
+#define splashLineJoinBevel 2
+
+//------------------------------------------------------------------------
+// SplashState
+//------------------------------------------------------------------------
+
+class SplashState {
+public:
+
+ // Create a new state object, initialized with default settings.
+ SplashState(int width, int height, GBool vectorAntialias,
+ SplashScreenParams *screenParams);
+ SplashState(int width, int height, GBool vectorAntialias,
+ SplashScreen *screenA);
+
+ // Copy a state object.
+ SplashState *copy() { return new SplashState(this); }
+
+ ~SplashState();
+
+ // Set the stroke pattern. This does not copy <strokePatternA>.
+ void setStrokePattern(SplashPattern *strokePatternA);
+
+ // Set the fill pattern. This does not copy <fillPatternA>.
+ void setFillPattern(SplashPattern *fillPatternA);
+
+ // Set the screen. This does not copy <screenA>.
+ void setScreen(SplashScreen *screenA);
+
+ // Set the line dash pattern. This copies the <lineDashA> array.
+ void setLineDash(SplashCoord *lineDashA, int lineDashLengthA,
+ SplashCoord lineDashPhaseA);
+
+ // Returns true if the current line dash pattern contains one or
+ // more zero-length "on" sections (dashes).
+ GBool lineDashContainsZeroLengthDashes();
+
+ void clipResetToRect(SplashCoord x0, SplashCoord y0,
+ SplashCoord x1, SplashCoord y1);
+ SplashError clipToRect(SplashCoord x0, SplashCoord y0,
+ SplashCoord x1, SplashCoord y1);
+ SplashError clipToPath(SplashPath *path, GBool eo);
+
+ // Set the soft mask bitmap.
+ void setSoftMask(SplashBitmap *softMaskA, GBool deleteBitmap = gTrue);
+
+ // Set the transfer function.
+ void setTransfer(Guchar *red, Guchar *green, Guchar *blue, Guchar *gray);
+
+
+private:
+
+ SplashState(SplashState *state);
+
+ SplashCoord matrix[6];
+ SplashPattern *strokePattern;
+ SplashPattern *fillPattern;
+ SplashScreen *screen;
+ SplashBlendFunc blendFunc;
+ SplashCoord strokeAlpha;
+ SplashCoord fillAlpha;
+ SplashCoord lineWidth;
+ int lineCap;
+ int lineJoin;
+ SplashCoord miterLimit;
+ SplashCoord flatness;
+ SplashCoord *lineDash;
+ int lineDashLength;
+ SplashCoord lineDashPhase;
+ SplashStrokeAdjustMode strokeAdjust;
+ SplashClip *clip;
+ GBool clipIsShared;
+ SplashBitmap *softMask;
+ GBool deleteSoftMask;
+ GBool inNonIsolatedGroup;
+ GBool inKnockoutGroup;
+ Guchar *rgbTransferR;
+ Guchar *rgbTransferG;
+ Guchar *rgbTransferB;
+ Guchar *grayTransfer;
+#if SPLASH_CMYK
+ Guchar *cmykTransferC;
+ Guchar *cmykTransferM;
+ Guchar *cmykTransferY;
+ Guchar *cmykTransferK;
+#endif
+ GBool transferIsShared;
+ Guint overprintMask;
+ GBool enablePathSimplification;
+
+
+ SplashState *next; // used by Splash class
+
+ friend class Splash;
+};
+
+#endif
diff --git a/splash/SplashTypes.h b/splash/SplashTypes.h
new file mode 100644
index 0000000..5860884
--- /dev/null
+++ b/splash/SplashTypes.h
@@ -0,0 +1,145 @@
+//========================================================================
+//
+// SplashTypes.h
+//
+// Copyright 2003-2013 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef SPLASHTYPES_H
+#define SPLASHTYPES_H
+
+#include <aconf.h>
+#include "gtypes.h"
+
+//------------------------------------------------------------------------
+// coordinates
+//------------------------------------------------------------------------
+
+#if USE_FIXEDPOINT
+#include "FixedPoint.h"
+typedef FixedPoint SplashCoord;
+#else
+typedef double SplashCoord;
+#endif
+
+//------------------------------------------------------------------------
+// antialiasing
+//------------------------------------------------------------------------
+
+#define splashAASize 4
+
+//------------------------------------------------------------------------
+// colors
+//------------------------------------------------------------------------
+
+enum SplashColorMode {
+ splashModeMono1, // 1 bit per component, 8 pixels per byte,
+ // MSbit is on the left
+ splashModeMono8, // 1 byte per component, 1 byte per pixel
+ splashModeRGB8, // 1 byte per component, 3 bytes per pixel:
+ // RGBRGB...
+ splashModeBGR8 // 1 byte per component, 3 bytes per pixel:
+ // BGRBGR...
+
+#if SPLASH_CMYK
+ ,
+ splashModeCMYK8 // 1 byte per component, 4 bytes per pixel:
+ // CMYKCMYK...
+#endif
+};
+
+// number of components in each color mode
+// (defined in SplashState.cc)
+extern int splashColorModeNComps[];
+
+// max number of components in any SplashColor
+#define splashMaxColorComps 3
+#if SPLASH_CMYK
+# undef splashMaxColorComps
+# define splashMaxColorComps 4
+#endif
+
+typedef Guchar SplashColor[splashMaxColorComps];
+typedef Guchar *SplashColorPtr;
+
+// RGB8
+static inline Guchar splashRGB8R(SplashColorPtr rgb8) { return rgb8[0]; }
+static inline Guchar splashRGB8G(SplashColorPtr rgb8) { return rgb8[1]; }
+static inline Guchar splashRGB8B(SplashColorPtr rgb8) { return rgb8[2]; }
+
+// BGR8
+static inline Guchar splashBGR8R(SplashColorPtr bgr8) { return bgr8[2]; }
+static inline Guchar splashBGR8G(SplashColorPtr bgr8) { return bgr8[1]; }
+static inline Guchar splashBGR8B(SplashColorPtr bgr8) { return bgr8[0]; }
+
+#if SPLASH_CMYK
+// CMYK8
+static inline Guchar splashCMYK8C(SplashColorPtr cmyk8) { return cmyk8[0]; }
+static inline Guchar splashCMYK8M(SplashColorPtr cmyk8) { return cmyk8[1]; }
+static inline Guchar splashCMYK8Y(SplashColorPtr cmyk8) { return cmyk8[2]; }
+static inline Guchar splashCMYK8K(SplashColorPtr cmyk8) { return cmyk8[3]; }
+#endif
+
+static inline void splashColorCopy(SplashColorPtr dest, SplashColorPtr src) {
+ dest[0] = src[0];
+ dest[1] = src[1];
+ dest[2] = src[2];
+#if SPLASH_CMYK
+ dest[3] = src[3];
+#endif
+}
+
+static inline void splashColorXor(SplashColorPtr dest, SplashColorPtr src) {
+ dest[0] ^= src[0];
+ dest[1] ^= src[1];
+ dest[2] ^= src[2];
+#if SPLASH_CMYK
+ dest[3] ^= src[3];
+#endif
+}
+
+//------------------------------------------------------------------------
+// blend functions
+//------------------------------------------------------------------------
+
+typedef void (*SplashBlendFunc)(SplashColorPtr src, SplashColorPtr dest,
+ SplashColorPtr blend, SplashColorMode cm);
+
+//------------------------------------------------------------------------
+// stroke adjustment mode
+//------------------------------------------------------------------------
+
+enum SplashStrokeAdjustMode {
+ splashStrokeAdjustOff,
+ splashStrokeAdjustNormal,
+ splashStrokeAdjustCAD
+};
+
+//------------------------------------------------------------------------
+// screen parameters
+//------------------------------------------------------------------------
+
+enum SplashScreenType {
+ splashScreenDispersed,
+ splashScreenClustered,
+ splashScreenStochasticClustered
+};
+
+struct SplashScreenParams {
+ SplashScreenType type;
+ int size;
+ int dotRadius;
+ SplashCoord gamma;
+ SplashCoord blackThreshold;
+ SplashCoord whiteThreshold;
+};
+
+//------------------------------------------------------------------------
+// error results
+//------------------------------------------------------------------------
+
+typedef int SplashError;
+
+
+#endif
diff --git a/splash/SplashXPath.cc b/splash/SplashXPath.cc
new file mode 100644
index 0000000..4c77765
--- /dev/null
+++ b/splash/SplashXPath.cc
@@ -0,0 +1,645 @@
+//========================================================================
+//
+// SplashXPath.cc
+//
+// Copyright 2003-2013 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#if HAVE_STD_SORT
+#include <algorithm>
+#endif
+#include "gmem.h"
+#include "gmempp.h"
+#include "SplashMath.h"
+#include "SplashPath.h"
+#include "SplashXPath.h"
+
+//------------------------------------------------------------------------
+
+#define minCosSquaredJoinAngle 0.75
+#define maxPointToLineDistanceSquared 0.04
+
+//------------------------------------------------------------------------
+
+struct SplashXPathPoint {
+ SplashCoord x, y;
+};
+
+struct SplashXPathAdjust {
+ int firstPt, lastPt; // range of points
+ GBool vert; // vertical or horizontal hint
+ SplashCoord x0a, x0b, // hint boundaries
+ xma, xmb,
+ x1a, x1b;
+ SplashCoord x0, x1, xm; // adjusted coordinates
+};
+
+//------------------------------------------------------------------------
+
+// Transform a point from user space to device space.
+inline void SplashXPath::transform(SplashCoord *matrix,
+ SplashCoord xi, SplashCoord yi,
+ SplashCoord *xo, SplashCoord *yo) {
+ // [ m[0] m[1] 0 ]
+ // [xo yo 1] = [xi yi 1] * [ m[2] m[3] 0 ]
+ // [ m[4] m[5] 1 ]
+ *xo = xi * matrix[0] + yi * matrix[2] + matrix[4];
+ *yo = xi * matrix[1] + yi * matrix[3] + matrix[5];
+}
+
+//------------------------------------------------------------------------
+// SplashXPath
+//------------------------------------------------------------------------
+
+// SplashXPath segment coords are clipped to +/-maxCoord to avoid
+// problems. The xMin/yMin/xMax/yMax fields are 32-bit integers, so
+// coords need to be < 2^31 / aa{Horiz,Vert}.
+#define maxCoord 100000000.0
+
+void SplashXPath::clampCoords(SplashCoord *x, SplashCoord *y) {
+#if !USE_FIXEDPOINT
+ if (*x > maxCoord) {
+ *x = maxCoord;
+ } else if (*x < -maxCoord) {
+ *x = -maxCoord;
+ }
+ if (*y > maxCoord) {
+ *y = maxCoord;
+ } else if (*y < -maxCoord) {
+ *y = -maxCoord;
+ }
+#endif
+}
+
+SplashXPath::SplashXPath(SplashPath *path, SplashCoord *matrix,
+ SplashCoord flatness, GBool closeSubpaths,
+ GBool simplify,
+ SplashStrokeAdjustMode strokeAdjMode) {
+ SplashXPathPoint *pts;
+ SplashCoord x0, y0, x1, y1, x2, y2, x3, y3, xsp, ysp, t;
+ int curSubpath, firstSegInSubpath, i;
+ GBool adjusted;
+
+ //--- transform the points
+ pts = (SplashXPathPoint *)gmallocn(path->length, sizeof(SplashXPathPoint));
+ for (i = 0; i < path->length; ++i) {
+ transform(matrix, path->pts[i].x, path->pts[i].y, &pts[i].x, &pts[i].y);
+ clampCoords(&pts[i].x, &pts[i].y);
+ }
+
+ //--- do stroke adjustment
+ if (path->hints) {
+ adjusted = strokeAdjust(pts, path->hints, path->hintsLength,
+ strokeAdjMode);
+ } else {
+ adjusted = gFalse;
+ }
+
+ //--- construct the segments
+
+ segs = NULL;
+ length = size = 0;
+
+ x0 = y0 = xsp = ysp = 0; // make gcc happy
+ curSubpath = 0;
+ firstSegInSubpath = 0;
+ i = 0;
+ while (i < path->length) {
+
+ // first point in subpath - skip it
+ if (path->flags[i] & splashPathFirst) {
+ x0 = pts[i].x;
+ y0 = pts[i].y;
+ xsp = x0;
+ ysp = y0;
+ curSubpath = i;
+ ++i;
+
+ } else {
+
+ // curve segment
+ if (path->flags[i] & splashPathCurve) {
+ x1 = pts[i].x;
+ y1 = pts[i].y;
+ x2 = pts[i+1].x;
+ y2 = pts[i+1].y;
+ x3 = pts[i+2].x;
+ y3 = pts[i+2].y;
+ addCurve(x0, y0, x1, y1, x2, y2, x3, y3,
+ flatness,
+ (path->flags[i-1] & splashPathFirst),
+ (path->flags[i+2] & splashPathLast),
+ !closeSubpaths &&
+ (path->flags[i-1] & splashPathFirst) &&
+ !(path->flags[i-1] & splashPathClosed),
+ !closeSubpaths &&
+ (path->flags[i+2] & splashPathLast) &&
+ !(path->flags[i+2] & splashPathClosed));
+ x0 = x3;
+ y0 = y3;
+ i += 3;
+
+ // line segment
+ } else {
+ x1 = pts[i].x;
+ y1 = pts[i].y;
+ addSegment(x0, y0, x1, y1);
+ x0 = x1;
+ y0 = y1;
+ ++i;
+ }
+
+ // end a subpath
+ if (path->flags[i-1] & splashPathLast) {
+ if (closeSubpaths &&
+ (pts[i-1].x != pts[curSubpath].x ||
+ pts[i-1].y != pts[curSubpath].y)) {
+ addSegment(x0, y0, xsp, ysp);
+ }
+ if (simplify && !adjusted) {
+ mergeSegments(firstSegInSubpath);
+ }
+ firstSegInSubpath = length;
+ }
+ }
+ }
+
+ gfree(pts);
+
+ finishSegments();
+
+ //--- check for a rectangle
+ isRect = gFalse;
+ rectX0 = rectY0 = rectX1 = rectY1 = 0;
+ if (length == 4) {
+#if HAVE_STD_SORT
+ std::sort(segs, segs + length, SplashXPathSeg::cmpY);
+#else
+ qsort(segs, length, sizeof(SplashXPathSeg), &SplashXPathSeg::cmpY);
+#endif
+ if (segs[0].y0 == segs[0].y1 &&
+ segs[1].x0 == segs[1].x1 &&
+ segs[2].x0 == segs[2].x1 &&
+ segs[3].y0 == segs[3].y1) {
+ isRect = gTrue;
+ rectX0 = segs[1].x0;
+ rectX1 = segs[2].x0;
+ rectY0 = segs[0].y0;
+ rectY1 = segs[3].y0;
+ } else if (segs[0].x0 == segs[0].x1 &&
+ segs[1].y0 == segs[1].y1 &&
+ segs[2].x0 == segs[2].x1 &&
+ segs[3].y0 == segs[3].y1) {
+ isRect = gTrue;
+ rectX0 = segs[0].x0;
+ rectX1 = segs[2].x0;
+ rectY0 = segs[1].y0;
+ rectY1 = segs[3].y0;
+ } else if (segs[0].x0 == segs[0].x1 &&
+ segs[1].x0 == segs[1].x1 &&
+ segs[2].y0 == segs[2].y1 &&
+ segs[3].y0 == segs[3].y1) {
+ isRect = gTrue;
+ rectX0 = segs[0].x0;
+ rectX1 = segs[1].x0;
+ rectY0 = segs[2].y0;
+ rectY1 = segs[3].y0;
+ }
+ if (isRect) {
+ if (rectX0 > rectX1) {
+ t = rectX0; rectX0 = rectX1; rectX1 = t;
+ }
+ if (rectY0 > rectY1) {
+ t = rectY0; rectY0 = rectY1; rectY1 = t;
+ }
+ }
+ }
+}
+
+GBool SplashXPath::strokeAdjust(SplashXPathPoint *pts,
+ SplashPathHint *hints, int nHints,
+ SplashStrokeAdjustMode strokeAdjMode) {
+ SplashXPathAdjust *adjusts, *adjust;
+ SplashPathHint *hint;
+ SplashCoord x0, y0, x1, y1, x2, y2, x3, y3;
+ SplashCoord adj0, adj1, w, d;
+ int xi0, xi1;
+ int i, j;
+ GBool adjusted;
+
+ adjusted = gFalse;
+
+ // set up the stroke adjustment hints
+ adjusts = (SplashXPathAdjust *)gmallocn(nHints, sizeof(SplashXPathAdjust));
+ for (i = 0; i < nHints; ++i) {
+ hint = &hints[i];
+ x0 = pts[hint->ctrl0 ].x; y0 = pts[hint->ctrl0 ].y;
+ x1 = pts[hint->ctrl0 + 1].x; y1 = pts[hint->ctrl0 + 1].y;
+ x2 = pts[hint->ctrl1 ].x; y2 = pts[hint->ctrl1 ].y;
+ x3 = pts[hint->ctrl1 + 1].x; y3 = pts[hint->ctrl1 + 1].y;
+ w = -1;
+ if (splashAbs(x0 - x1) < 0.01 && splashAbs(x2 - x3) < 0.01) {
+ adjusts[i].vert = gTrue;
+ adj0 = x0;
+ adj1 = x2;
+ if (hint->projectingCap) {
+ w = splashAbs(y1 - y0);
+ }
+ } else if (splashAbs(y0 - y1) < 0.01 && splashAbs(y2 - y3) < 0.01) {
+ adjusts[i].vert = gFalse;
+ adj0 = y0;
+ adj1 = y2;
+ if (hint->projectingCap) {
+ w = splashAbs(x1 - x0);
+ }
+ } else {
+ goto done;
+ }
+ if (adj0 > adj1) {
+ x0 = adj0;
+ adj0 = adj1;
+ adj1 = x0;
+ }
+ d = adj1 - adj0;
+ if (d > 0.04) {
+ d = 0.01;
+ } else {
+ d *= 0.25;
+ }
+ adjusts[i].x0a = adj0 - d;
+ adjusts[i].x0b = adj0 + d;
+ adjusts[i].xma = (SplashCoord)0.5 * (adj0 + adj1) - d;
+ adjusts[i].xmb = (SplashCoord)0.5 * (adj0 + adj1) + d;
+ adjusts[i].x1a = adj1 - d;
+ adjusts[i].x1b = adj1 + d;
+ splashStrokeAdjust(adj0, adj1, &xi0, &xi1, strokeAdjMode, w);
+ adjusts[i].x0 = (SplashCoord)xi0;
+ // the "minus epsilon" thing here is needed when vector
+ // antialiasing is turned off -- otherwise stroke adjusted lines
+ // will touch an extra pixel on one edge
+ adjusts[i].x1 = (SplashCoord)xi1 - 0.001;
+ adjusts[i].xm = (SplashCoord)0.5 * (adjusts[i].x0 + adjusts[i].x1);
+ adjusts[i].firstPt = hint->firstPt;
+ adjusts[i].lastPt = hint->lastPt;
+ }
+
+ // perform stroke adjustment
+ for (i = 0, adjust = adjusts; i < nHints; ++i, ++adjust) {
+ for (j = adjust->firstPt; j <= adjust->lastPt; ++j) {
+ if (adjust->vert) {
+ x0 = pts[j].x;
+ if (x0 > adjust->x0a && x0 < adjust->x0b) {
+ pts[j].x = adjust->x0;
+ } else if (x0 > adjust->xma && x0 < adjust->xmb) {
+ pts[j].x = adjust->xm;
+ } else if (x0 > adjust->x1a && x0 < adjust->x1b) {
+ pts[j].x = adjust->x1;
+ }
+ } else {
+ y0 = pts[j].y;
+ if (y0 > adjust->x0a && y0 < adjust->x0b) {
+ pts[j].y = adjust->x0;
+ } else if (y0 > adjust->xma && y0 < adjust->xmb) {
+ pts[j].y = adjust->xm;
+ } else if (y0 > adjust->x1a && y0 < adjust->x1b) {
+ pts[j].y = adjust->x1;
+ }
+ }
+ }
+ }
+ adjusted = gTrue;
+
+ done:
+ gfree(adjusts);
+ return adjusted;
+}
+
+SplashXPath::SplashXPath(SplashXPath *xPath) {
+ length = xPath->length;
+ size = xPath->size;
+ segs = (SplashXPathSeg *)gmallocn(size, sizeof(SplashXPathSeg));
+ memcpy(segs, xPath->segs, length * sizeof(SplashXPathSeg));
+ xMin = xPath->xMin;
+ yMin = xPath->yMin;
+ xMax = xPath->xMax;
+ yMax = xPath->yMax;
+}
+
+SplashXPath::~SplashXPath() {
+ gfree(segs);
+}
+
+// Add space for <nSegs> more segments
+void SplashXPath::grow(int nSegs) {
+ if (length + nSegs > size) {
+ if (size == 0) {
+ size = 32;
+ }
+ while (size < length + nSegs) {
+ size *= 2;
+ }
+ segs = (SplashXPathSeg *)greallocn(segs, size, sizeof(SplashXPathSeg));
+ }
+}
+
+void SplashXPath::addCurve(SplashCoord x0, SplashCoord y0,
+ SplashCoord x1, SplashCoord y1,
+ SplashCoord x2, SplashCoord y2,
+ SplashCoord x3, SplashCoord y3,
+ SplashCoord flatness,
+ GBool first, GBool last, GBool end0, GBool end1) {
+ SplashCoord cx[splashMaxCurveSplits + 1][3];
+ SplashCoord cy[splashMaxCurveSplits + 1][3];
+ int cNext[splashMaxCurveSplits + 1];
+ SplashCoord xl0, xl1, xl2, xr0, xr1, xr2, xr3, xx1, xx2, xh;
+ SplashCoord yl0, yl1, yl2, yr0, yr1, yr2, yr3, yy1, yy2, yh;
+ SplashCoord dx, dy, mx, my, d1, d2, flatness2;
+ int p1, p2, p3;
+
+#if USE_FIXEDPOINT
+ flatness2 = flatness;
+#else
+ flatness2 = flatness * flatness;
+#endif
+
+ // initial segment
+ p1 = 0;
+ p2 = splashMaxCurveSplits;
+ cx[p1][0] = x0; cy[p1][0] = y0;
+ cx[p1][1] = x1; cy[p1][1] = y1;
+ cx[p1][2] = x2; cy[p1][2] = y2;
+ cx[p2][0] = x3; cy[p2][0] = y3;
+ cNext[p1] = p2;
+
+ while (p1 < splashMaxCurveSplits) {
+
+ // get the next segment
+ xl0 = cx[p1][0]; yl0 = cy[p1][0];
+ xx1 = cx[p1][1]; yy1 = cy[p1][1];
+ xx2 = cx[p1][2]; yy2 = cy[p1][2];
+ p2 = cNext[p1];
+ xr3 = cx[p2][0]; yr3 = cy[p2][0];
+
+ // compute the distances from the control points to the
+ // midpoint of the straight line (this is a bit of a hack, but
+ // it's much faster than computing the actual distances to the
+ // line)
+ mx = (xl0 + xr3) * 0.5;
+ my = (yl0 + yr3) * 0.5;
+#if USE_FIXEDPOINT
+ d1 = splashDist(xx1, yy1, mx, my);
+ d2 = splashDist(xx2, yy2, mx, my);
+#else
+ dx = xx1 - mx;
+ dy = yy1 - my;
+ d1 = dx*dx + dy*dy;
+ dx = xx2 - mx;
+ dy = yy2 - my;
+ d2 = dx*dx + dy*dy;
+#endif
+
+ // if the curve is flat enough, or no more subdivisions are
+ // allowed, add the straight line segment
+ if (p2 - p1 == 1 || (d1 <= flatness2 && d2 <= flatness2)) {
+ addSegment(xl0, yl0, xr3, yr3);
+ p1 = p2;
+
+ // otherwise, subdivide the curve
+ } else {
+ xl1 = (xl0 + xx1) * 0.5;
+ yl1 = (yl0 + yy1) * 0.5;
+ xh = (xx1 + xx2) * 0.5;
+ yh = (yy1 + yy2) * 0.5;
+ xl2 = (xl1 + xh) * 0.5;
+ yl2 = (yl1 + yh) * 0.5;
+ xr2 = (xx2 + xr3) * 0.5;
+ yr2 = (yy2 + yr3) * 0.5;
+ xr1 = (xh + xr2) * 0.5;
+ yr1 = (yh + yr2) * 0.5;
+ xr0 = (xl2 + xr1) * 0.5;
+ yr0 = (yl2 + yr1) * 0.5;
+ // add the new subdivision points
+ p3 = (p1 + p2) / 2;
+ cx[p1][1] = xl1; cy[p1][1] = yl1;
+ cx[p1][2] = xl2; cy[p1][2] = yl2;
+ cNext[p1] = p3;
+ cx[p3][0] = xr0; cy[p3][0] = yr0;
+ cx[p3][1] = xr1; cy[p3][1] = yr1;
+ cx[p3][2] = xr2; cy[p3][2] = yr2;
+ cNext[p3] = p2;
+ }
+ }
+}
+
+void SplashXPath::addSegment(SplashCoord x0, SplashCoord y0,
+ SplashCoord x1, SplashCoord y1) {
+ grow(1);
+ segs[length].x0 = x0;
+ segs[length].y0 = y0;
+ segs[length].x1 = x1;
+ segs[length].y1 = y1;
+ ++length;
+}
+
+// Returns true if the angle between (x0,y0)-(x1,y1) and
+// (x1,y1)-(x2,y2) is close to 180 degrees.
+static GBool joinAngleIsFlat(SplashCoord x0, SplashCoord y0,
+ SplashCoord x1, SplashCoord y1,
+ SplashCoord x2, SplashCoord y2) {
+ SplashCoord dx1, dy1, dx2, dy2, d, len1, len2;
+
+ dx1 = x1 - x0;
+ dy1 = y1 - y0;
+ dx2 = x2 - x1;
+ dy2 = y2 - y1;
+ d = dx1 * dx2 + dy1 * dy2;
+ len1 = dx1 * dx1 + dy1 * dy1;
+ len2 = dx2 * dx2 + dy2 * dy2;
+ return d > 0 && d * d > len1 * len2 * minCosSquaredJoinAngle;
+}
+
+// Returns true if (x1,y1) is sufficiently close to the segment
+// (x0,y0)-(x2,y2), looking at the perpendicular point-to-line
+// distance.
+static GBool pointCloseToSegment(SplashCoord x0, SplashCoord y0,
+ SplashCoord x1, SplashCoord y1,
+ SplashCoord x2, SplashCoord y2) {
+ SplashCoord t1, t2, dx, dy;
+
+ // compute the perpendicular distance from the point to the segment,
+ // i.e., the projection of (x0,y0)-(x1,y1) onto a unit normal to the
+ // segment (this actually computes the square of the distance)
+ dx = x2 - x0;
+ dy = y2 - y0;
+ t1 = dx*dx + dy*dy;
+ if (t1 < 0.0001) {
+ // degenerate case: (x0,y0) and (x2,y2) are (nearly) identical --
+ // just compute the distance to (x1,y1)
+ dx = x0 - x1;
+ dy = y0 - y1;
+ t2 = dx*dx + dy*dy;
+ return t2 < maxPointToLineDistanceSquared;
+ }
+ t2 = x1 * dy - dx * y1 - x0 * y2 + x2 * y0;
+ // actual distance = t2 / sqrt(t1)
+ return t2 * t2 < t1 * maxPointToLineDistanceSquared;
+}
+
+// Attempt to simplify the path by merging sequences of consecutive
+// segments in [first] .. [length]-1.
+void SplashXPath::mergeSegments(int first) {
+ GBool horiz, vert;
+ int in, out, prev, i, j;
+
+ in = out = first;
+ while (in < length) {
+
+ // skip zero-length segments
+ if (segs[in].x0 == segs[in].x1 && segs[in].y0 == segs[in].y1) {
+ ++in;
+ continue;
+ }
+
+ horiz = segs[in].y0 == segs[in].y1;
+ vert = segs[in].x0 == segs[in].x1;
+
+ // check for a sequence of mergeable segments: in .. i
+ prev = in;
+ for (i = in + 1; i < length; ++i) {
+
+ // skip zero-length segments
+ if (segs[i].x0 == segs[i].x1 && segs[i].y0 == segs[i].y1) {
+ continue;
+ }
+
+ // check for a horizontal or vertical segment
+ if ((horiz && segs[in].y0 != segs[in].y1) ||
+ (vert && segs[in].x0 != segs[in].x1)) {
+ break;
+ }
+
+ // check the angle between segs i-1 and i
+ // (actually, we compare seg i to the previous non-zero-length
+ // segment, which may not be i-1)
+ if (!joinAngleIsFlat(segs[prev].x0, segs[prev].y0,
+ segs[i].x0, segs[i].y0,
+ segs[i].x1, segs[i].y1)) {
+ break;
+ }
+
+ // check the distances from the ends of segs in .. i-1 to the
+ // proposed new segment
+ for (j = in; j < i; ++j) {
+ if (!pointCloseToSegment(segs[in].x0, segs[in].y0,
+ segs[j].x1, segs[j].y1,
+ segs[i].x1, segs[i].y1)) {
+ break;
+ }
+ }
+ if (j < i) {
+ break;
+ }
+
+ prev = i;
+ }
+
+ // we can merge segs: in .. i-1
+ // (this may be the single segment: in)
+ segs[out].x0 = segs[in].x0;
+ segs[out].y0 = segs[in].y0;
+ segs[out].x1 = segs[i-1].x1;
+ segs[out].y1 = segs[i-1].y1;
+ in = i;
+ ++out;
+ }
+
+ length = out;
+}
+
+void SplashXPath::finishSegments() {
+ SplashXPathSeg *seg;
+ SplashCoord xMinFP, xMaxFP, yMinFP, yMaxFP, t;
+ int i;
+
+ xMinFP = yMinFP = xMaxFP = yMaxFP = 0;
+
+ for (i = 0; i < length; ++i) {
+ seg = &segs[i];
+
+ //--- compute the slopes
+ if (seg->y0 <= seg->y1) {
+ seg->count = 1;
+ } else {
+ t = seg->x0; seg->x0 = seg->x1; seg->x1 = t;
+ t = seg->y0; seg->y0 = seg->y1; seg->y1 = t;
+ seg->count = -1;
+ }
+#if USE_FIXEDPOINT
+ if (seg->y0 == seg->y1 || seg->x0 == seg->x1 ||
+ !FixedPoint::divCheck(seg->x1 - seg->x0, seg->y1 - seg->y0,
+ &seg->dxdy) ||
+ !FixedPoint::divCheck(seg->y1 - seg->y0, seg->x1 - seg->x0,
+ &seg->dydx)) {
+ seg->dxdy = 0;
+ seg->dydx = 0;
+ }
+#else
+ if (splashAbs(seg->y1 - seg->y0) < 1e-200 ||
+ splashAbs(seg->x1 - seg->x0) < 1e-200) {
+ seg->dxdy = 0;
+ seg->dydx = 0;
+ } else {
+ seg->dxdy = (seg->x1 - seg->x0) / (seg->y1 - seg->y0);
+ if (seg->dxdy == 0) {
+ seg->dydx = 0;
+ } else {
+ seg->dydx = 1 / seg->dxdy;
+ }
+ }
+#endif
+
+ //--- update bbox
+ if (i == 0) {
+ if (seg->x0 <= seg->x1) {
+ xMinFP = seg->x0;
+ xMaxFP = seg->x1;
+ } else {
+ xMinFP = seg->x1;
+ xMaxFP = seg->x0;
+ }
+ yMinFP = seg->y0;
+ yMaxFP = seg->y1;
+ } else {
+ if (seg->x0 < xMinFP) {
+ xMinFP = seg->x0;
+ } else if (seg->x0 > xMaxFP) {
+ xMaxFP = seg->x0;
+ }
+ if (seg->x1 < xMinFP) {
+ xMinFP = seg->x1;
+ } else if (seg->x1 > xMaxFP) {
+ xMaxFP = seg->x1;
+ }
+ if (seg->y0 < yMinFP) {
+ yMinFP = seg->y0;
+ }
+ if (seg->y1 > yMaxFP) {
+ yMaxFP = seg->y1;
+ }
+ }
+ }
+
+ xMin = splashFloor(xMinFP);
+ yMin = splashFloor(yMinFP);
+ xMax = splashFloor(xMaxFP);
+ yMax = splashFloor(yMaxFP);
+}
diff --git a/splash/SplashXPath.h b/splash/SplashXPath.h
new file mode 100644
index 0000000..82d7889
--- /dev/null
+++ b/splash/SplashXPath.h
@@ -0,0 +1,143 @@
+//========================================================================
+//
+// SplashXPath.h
+//
+// Copyright 2003-2013 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef SPLASHXPATH_H
+#define SPLASHXPATH_H
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include "SplashTypes.h"
+
+class SplashPath;
+struct SplashXPathPoint;
+struct SplashPathHint;
+
+//------------------------------------------------------------------------
+
+#define splashMaxCurveSplits (1 << 10)
+
+//------------------------------------------------------------------------
+// SplashXPathSeg
+//------------------------------------------------------------------------
+
+struct SplashXPathSeg {
+ SplashCoord x0, y0; // first endpoint (y0 <= y1)
+ SplashCoord x1, y1; // second endpoint
+ SplashCoord dxdy; // slope: delta-x / delta-y
+ SplashCoord dydx; // slope: delta-y / delta-x
+ int count; // EO/NZWN counter increment
+
+ //----- used by SplashXPathScanner
+ int iy;
+ SplashCoord sx0, sx1, mx;
+ SplashXPathSeg *prev, *next;
+
+#if HAVE_STD_SORT
+
+ static bool cmpMX(const SplashXPathSeg &s0,
+ const SplashXPathSeg &s1) {
+ if (s0.iy != s1.iy) {
+ return s0.iy < s1.iy;
+ }
+ return s0.mx < s1.mx;
+ }
+
+ static bool cmpY(const SplashXPathSeg &seg0,
+ const SplashXPathSeg &seg1) {
+ return seg0.y0 < seg1.y0;
+ }
+
+#else
+
+ static int cmpMX(const void *p0, const void *p1) {
+ SplashXPathSeg *s0 = (SplashXPathSeg *)p0;
+ SplashXPathSeg *s1 = (SplashXPathSeg *)p1;
+ SplashCoord cmp;
+
+ if (s0->iy != s1->iy) {
+ return s0->iy - s1->iy;
+ }
+ cmp = s0->mx - s1->mx;
+ return (cmp < 0) ? -1 : (cmp > 0) ? 1 : 0;
+ }
+
+ static int cmpY(const void *seg0, const void *seg1) {
+ SplashCoord cmp;
+
+ cmp = ((SplashXPathSeg *)seg0)->y0
+ - ((SplashXPathSeg *)seg1)->y0;
+ return (cmp > 0) ? 1 : (cmp < 0) ? -1 : 0;
+ }
+
+#endif
+};
+
+//------------------------------------------------------------------------
+// SplashXPath
+//------------------------------------------------------------------------
+
+class SplashXPath {
+public:
+
+ // Expands (converts to segments) and flattens (converts curves to
+ // lines) <path>. Transforms all points from user space to device
+ // space, via <matrix>. If <closeSubpaths> is true, closes all open
+ // subpaths.
+ SplashXPath(SplashPath *path, SplashCoord *matrix,
+ SplashCoord flatness, GBool closeSubpaths,
+ GBool simplify, SplashStrokeAdjustMode strokeAdjMode);
+
+ // Copy an expanded path.
+ SplashXPath *copy() { return new SplashXPath(this); }
+
+ ~SplashXPath();
+
+ int getXMin() { return xMin; }
+ int getXMax() { return xMax; }
+ int getYMin() { return yMin; }
+ int getYMax() { return yMax; }
+
+private:
+
+ static void clampCoords(SplashCoord *x, SplashCoord *y);
+ SplashXPath(SplashXPath *xPath);
+ void transform(SplashCoord *matrix, SplashCoord xi, SplashCoord yi,
+ SplashCoord *xo, SplashCoord *yo);
+ GBool strokeAdjust(SplashXPathPoint *pts,
+ SplashPathHint *hints, int nHints,
+ SplashStrokeAdjustMode strokeAdjMode);
+ void grow(int nSegs);
+ void addCurve(SplashCoord x0, SplashCoord y0,
+ SplashCoord x1, SplashCoord y1,
+ SplashCoord x2, SplashCoord y2,
+ SplashCoord x3, SplashCoord y3,
+ SplashCoord flatness,
+ GBool first, GBool last, GBool end0, GBool end1);
+ void mergeSegments(int first);
+ void addSegment(SplashCoord x0, SplashCoord y0,
+ SplashCoord x1, SplashCoord y1);
+ void finishSegments();
+
+ SplashXPathSeg *segs;
+ int length, size; // length and size of segs array
+ int xMin, xMax;
+ int yMin, yMax;
+
+ GBool isRect;
+ SplashCoord rectX0, rectY0, rectX1, rectY1;
+
+ friend class SplashXPathScanner;
+ friend class SplashClip;
+ friend class Splash;
+};
+
+#endif
diff --git a/splash/SplashXPathScanner.cc b/splash/SplashXPathScanner.cc
new file mode 100644
index 0000000..3f167b8
--- /dev/null
+++ b/splash/SplashXPathScanner.cc
@@ -0,0 +1,620 @@
+//========================================================================
+//
+// SplashXPathScanner.cc
+//
+// Copyright 2003-2013 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#if HAVE_STD_SORT
+#include <algorithm>
+#endif
+#include "gmem.h"
+#include "gmempp.h"
+#include "GList.h"
+#include "SplashMath.h"
+#include "SplashXPath.h"
+#include "SplashXPathScanner.h"
+
+//------------------------------------------------------------------------
+
+#if ANTIALIAS_256
+
+#define aaVert 15
+#define aaHoriz 17
+
+#else
+
+#define aaVert 4
+#define aaHoriz 4
+
+static Guchar map16to255[17] = {
+ 0,
+ 16,
+ 32,
+ 48,
+ 64,
+ 80,
+ 96,
+ 112,
+ 128,
+ 143,
+ 159,
+ 175,
+ 191,
+ 207,
+ 223,
+ 239,
+ 255
+};
+
+#endif
+
+//------------------------------------------------------------------------
+
+SplashXPathScanner::SplashXPathScanner(SplashXPath *xPathA, GBool eo,
+ int yMinA, int yMaxA) {
+ xPath = xPathA;
+ eoMask = eo ? 1 : 0xffffffff;
+ yMin = yMinA;
+ yMax = yMaxA;
+ if (xPath->isRect) {
+ rectX0I = splashFloor(xPath->rectX0);
+ rectY0I = splashFloor(xPath->rectY0);
+ rectX1I = splashFloor(xPath->rectX1);
+ rectY1I = splashFloor(xPath->rectY1);
+ }
+
+ pre = &preSeg;
+ post = &postSeg;
+ pre->mx = xPath->xMin - 1;
+ post->mx = xPath->xMax + 1;
+
+ resetDone = gFalse;
+ resetAA = gFalse;
+}
+
+SplashXPathScanner::~SplashXPathScanner() {
+}
+
+void SplashXPathScanner::insertSegmentBefore(SplashXPathSeg *s,
+ SplashXPathSeg *sNext) {
+ SplashXPathSeg *sPrev;
+
+ sPrev = sNext->prev;
+ sPrev->next = s;
+ s->prev = sPrev;
+ s->next = sNext;
+ sNext->prev = s;
+}
+
+void SplashXPathScanner::removeSegment(SplashXPathSeg *s) {
+ SplashXPathSeg *sPrev, *sNext;
+
+ sPrev = s->prev;
+ sNext = s->next;
+ sPrev->next = sNext;
+ sNext->prev = sPrev;
+ s->prev = s->next = NULL;
+}
+
+void SplashXPathScanner::moveSegmentAfter(SplashXPathSeg *s,
+ SplashXPathSeg *sPrev) {
+ SplashXPathSeg *sNext;
+
+ s->prev->next = s->next;
+ s->next->prev = s->prev;
+
+ sNext = sPrev->next;
+ sPrev->next = s;
+ s->prev = sPrev;
+ s->next = sNext;
+ sNext->prev = s;
+}
+
+void SplashXPathScanner::reset(GBool aa, GBool aaChanged) {
+ SplashXPathSeg *seg;
+ SplashCoord y;
+ int i;
+
+ //--- initialize segment parameters
+ for (i = 0; i < xPath->length; ++i) {
+ seg = &xPath->segs[i];
+ if (aa) {
+ if (aaChanged) {
+ seg->iy = splashFloor(seg->y0 * aaVert);
+ }
+ y = (SplashCoord)(seg->iy + 1) / (SplashCoord)aaVert;
+ } else {
+ if (aaChanged) {
+ seg->iy = splashFloor(seg->y0);
+ }
+ y = (SplashCoord)(seg->iy + 1);
+ }
+ seg->sx0 = seg->x0;
+ if (seg->y1 <= y) {
+ seg->sx1 = seg->x1;
+ } else {
+ seg->sx1 = seg->x0 + (y - seg->y0) * seg->dxdy;
+ }
+ seg->mx = (seg->sx0 <= seg->sx1) ? seg->sx0 : seg->sx1;
+ seg->prev = seg->next = NULL;
+ }
+
+ //--- sort the inactive segments by iy, mx
+ if (aaChanged) {
+#if HAVE_STD_SORT
+ std::sort(xPath->segs, xPath->segs + xPath->length, &SplashXPathSeg::cmpMX);
+#else
+ qsort(xPath->segs, xPath->length, sizeof(SplashXPathSeg),
+ &SplashXPathSeg::cmpMX);
+#endif
+ }
+
+ //--- initialize the active list
+ pre->prev = NULL;
+ pre->next = post;
+ post->prev = pre;
+ post->next = NULL;
+
+ //--- initialize the scan state
+ nextSeg = 0;
+ if (xPath->length) {
+ yBottomI = xPath->segs[0].iy;
+ if (aa) {
+ yBottomI -= yBottomI % aaVert;
+ }
+ } else {
+ yBottomI = 0;
+ }
+ yTopI = yBottomI - 1;
+ if (aa) {
+ yTop = (SplashCoord)yTopI / (SplashCoord)aaVert;
+ yBottom = (SplashCoord)yBottomI / (SplashCoord)aaVert;
+ } else {
+ yTop = (SplashCoord)yTopI;
+ yBottom = (SplashCoord)yBottomI;
+ }
+
+ resetDone = gTrue;
+ resetAA = aa;
+}
+
+void SplashXPathScanner::skip(int newYBottomI, GBool aa) {
+ SplashXPathSeg *s0, *s1,*s2;
+ int iy;
+
+ yTopI = newYBottomI - 1;
+ yBottomI = newYBottomI;
+ if (aa) {
+ yTop = (SplashCoord)yTopI / (SplashCoord)aaVert;
+ yBottom = (SplashCoord)yBottomI / (SplashCoord)aaVert;
+ } else {
+ yTop = (SplashCoord)yTopI;
+ yBottom = (SplashCoord)yBottomI;
+ }
+
+ //--- remove finished segments; update sx0, sx1, mx for active segments
+ s0 = pre->next;
+ while (s0 != post) {
+ s1 = s0->next;
+
+ // check for a finished segment
+ if (s0->y1 < yTop) {
+ removeSegment(s0);
+
+ // compute sx0, sx1, mx
+ } else {
+ if (s0->y0 >= yTop) {
+ s0->sx0 = s0->x0;
+ } else {
+ s0->sx0 = s0->x0 + (yTop - s0->y0) * s0->dxdy;
+ }
+ if (s0->y1 <= yBottom) {
+ s0->sx1 = s0->x1;
+ } else {
+ s0->sx1 = s0->x0 + (yBottom - s0->y0) * s0->dxdy;
+ }
+ s0->mx = (s0->sx0 <= s0->sx1) ? s0->sx0 : s0->sx1;
+ }
+
+ s0 = s1;
+ }
+
+ //--- check for intersections
+ s0 = pre->next;
+ if (s0 != post) {
+ s1 = s0->next;
+ while (s1 != post) {
+ if (s1->mx < s0->mx) {
+ for (s2 = s0->prev; s1->mx < s2->mx; s2 = s2->prev) ;
+ moveSegmentAfter(s1, s2);
+ } else {
+ s0 = s1;
+ }
+ s1 = s0->next;
+ }
+ }
+
+ //--- insert new segments with a merge sort
+ // - this has to be done one (sub)scanline at a time, because the
+ // inactive list is bin-sorted by (sub)scanline
+ while (nextSeg < xPath->length && xPath->segs[nextSeg].iy <= yTopI) {
+ // the first inactive segment determines the next scanline to process
+ iy = xPath->segs[nextSeg].iy;
+ s0 = pre->next;
+ do {
+ s1 = &xPath->segs[nextSeg];
+ ++nextSeg;
+ if (s1->y1 < yTop) {
+ continue;
+ }
+ if (s1->y0 >= yTop) {
+ s1->sx0 = s1->x0;
+ } else {
+ s1->sx0 = s1->x0 + (yTop - s1->y0) * s1->dxdy;
+ }
+ if (s1->y1 <= yBottom) {
+ s1->sx1 = s1->x1;
+ } else {
+ s1->sx1 = s1->x0 + (yBottom - s1->y0) * s1->dxdy;
+ }
+ s1->mx = (s1->sx0 <= s1->sx1) ? s1->sx0 : s1->sx1;
+ insertSegmentBefore(s1, s0);
+ } while (nextSeg < xPath->length && xPath->segs[nextSeg].iy <= iy);
+ }
+}
+
+void SplashXPathScanner::advance(GBool aa) {
+ SplashXPathSeg *s, *sNext, *s1;
+
+ yTopI = yBottomI;
+ yTop = yBottom;
+ yBottomI = yTopI + 1;
+ if (aa) {
+ yBottom = (SplashCoord)yBottomI / (SplashCoord)aaVert;
+ } else {
+ yBottom = (SplashCoord)yBottomI;
+ }
+
+ s = pre->next;
+ while (s != post) {
+ sNext = s->next;
+
+ // check for a finished segment
+ if (s->y1 < yTop) {
+ removeSegment(s);
+
+ } else {
+
+ // compute sx0, sx1, mx
+ s->sx0 = s->sx1;
+ if (s->y1 <= yBottom) {
+ s->sx1 = s->x1;
+ } else {
+ s->sx1 = s->x0 + (yBottom - s->y0) * s->dxdy;
+ }
+ s->mx = (s->sx0 <= s->sx1) ? s->sx0 : s->sx1;
+
+ // check for intersection
+ if (s->mx < s->prev->mx) {
+ for (s1 = s->prev->prev; s->mx < s1->mx; s1 = s1->prev) ;
+ moveSegmentAfter(s, s1);
+ }
+ }
+
+ s = sNext;
+ }
+
+ // insert new segments
+ s = pre->next;
+ while (nextSeg < xPath->length && xPath->segs[nextSeg].iy <= yTopI) {
+ s1 = &xPath->segs[nextSeg];
+ ++nextSeg;
+ while (s1->mx > s->mx) {
+ s = s->next;
+ }
+ insertSegmentBefore(s1, s);
+ }
+}
+
+void SplashXPathScanner::generatePixels(int x0, int x1, Guchar *line,
+ int *xMin, int *xMax) {
+ SplashXPathSeg *s;
+ int fillCount, x, xEnd, ix0, ix1, t;
+
+ fillCount = 0;
+ x = x0 * aaHoriz;
+ xEnd = (x1 + 1) * aaHoriz;
+ for (s = pre->next; s != post && x < xEnd; s = s->next) {
+ ix0 = splashFloor(s->sx0 * aaHoriz);
+ ix1 = splashFloor(s->sx1 * aaHoriz);
+ if (ix0 > ix1) {
+ t = ix0; ix0 = ix1; ix1 = t;
+ }
+ if (!(fillCount & eoMask)) {
+ if (ix0 > x) {
+ x = ix0;
+ }
+ }
+ if (ix1 >= xEnd) {
+ ix1 = xEnd - 1;
+ }
+ if (x / aaHoriz < *xMin) {
+ *xMin = x / aaHoriz;
+ }
+ if (ix1 / aaHoriz > *xMax) {
+ *xMax = ix1 / aaHoriz;
+ }
+ for (; x <= ix1; ++x) {
+ ++line[x / aaHoriz];
+ }
+ if (s->y0 <= yTop && s->y1 > yTop) {
+ fillCount += s->count;
+ }
+ }
+}
+
+void SplashXPathScanner::generatePixelsBinary(int x0, int x1, Guchar *line,
+ int *xMin, int *xMax) {
+ SplashXPathSeg *s;
+ int fillCount, x, xEnd, ix0, ix1, t;
+
+ fillCount = 0;
+ x = x0;
+ xEnd = x1 + 1;
+ for (s = pre->next; s != post && x < xEnd; s = s->next) {
+ ix0 = splashFloor(s->sx0);
+ ix1 = splashFloor(s->sx1);
+ if (ix0 > ix1) {
+ t = ix0; ix0 = ix1; ix1 = t;
+ }
+ if (!(fillCount & eoMask)) {
+ if (ix0 > x) {
+ x = ix0;
+ }
+ }
+ if (ix1 >= xEnd) {
+ ix1 = xEnd - 1;
+ }
+ if (x < *xMin) {
+ *xMin = x;
+ }
+ if (ix1 > *xMax) {
+ *xMax = ix1;
+ }
+ for (; x <= ix1; ++x) {
+ line[x] = 255;
+ }
+ if (s->y0 <= yTop && s->y1 > yTop) {
+ fillCount += s->count;
+ }
+ }
+}
+
+void SplashXPathScanner::drawRectangleSpan(Guchar *line, int y,
+ int x0, int x1,
+ int *xMin, int *xMax) {
+ SplashCoord edge;
+ Guchar pix;
+ int xe, x;
+
+ if (rectX0I > x1 || rectX1I < x0) {
+ return;
+ }
+
+ *xMin = x0 <= rectX0I ? rectX0I : x0;
+ *xMax = rectX1I <= x1 ? rectX1I : x1;
+
+ //--- upper edge
+ if (y == rectY0I) {
+
+ // handle a rectangle less than one pixel high
+ if (rectY0I == rectY1I) {
+ edge = xPath->rectY1 - xPath->rectY0;
+ } else {
+ edge = (SplashCoord)1 - (xPath->rectY0 - rectY0I);
+ }
+
+ // upper left corner
+ if (x0 <= rectX0I) {
+ pix = (Guchar)splashCeil(edge
+ * ((SplashCoord)1 - (xPath->rectX0 - rectX0I))
+ * 255);
+ if (pix < 16) {
+ pix = 16;
+ }
+ line[rectX0I] = pix;
+ x = rectX0I + 1;
+ } else {
+ x = x0;
+ }
+
+ // upper right corner
+ if (rectX1I <= x1) {
+ pix = (Guchar)splashCeil(edge * (xPath->rectX1 - rectX1I) * 255);
+ if (pix < 16) {
+ pix = 16;
+ }
+ line[rectX1I] = pix;
+ xe = rectX1I - 1;
+ } else {
+ xe = x1;
+ }
+
+ // upper edge
+ pix = (Guchar)splashCeil(edge * 255);
+ if (pix < 16) {
+ pix = 16;
+ }
+ for (; x <= xe; ++x) {
+ line[x] = pix;
+ }
+
+ //--- lower edge
+ } else if (y == rectY1I) {
+ edge = xPath->rectY1 - rectY1I;
+
+ // lower left corner
+ if (x0 <= rectX0I) {
+ pix = (Guchar)splashCeil(edge
+ * ((SplashCoord)1 - (xPath->rectX0 - rectX0I))
+ * 255);
+ if (pix < 16) {
+ pix = 16;
+ }
+ line[rectX0I] = pix;
+ x = rectX0I + 1;
+ } else {
+ x = x0;
+ }
+
+ // lower right corner
+ if (rectX1I <= x1) {
+ pix = (Guchar)splashCeil(edge * (xPath->rectX1 - rectX1I) * 255);
+ if (pix < 16) {
+ pix = 16;
+ }
+ line[rectX1I] = pix;
+ xe = rectX1I - 1;
+ } else {
+ xe = x1;
+ }
+
+ // lower edge
+ pix = (Guchar)splashCeil(edge * 255);
+ if (pix < 16) {
+ pix = 16;
+ }
+ for (; x <= xe; ++x) {
+ line[x] = pix;
+ }
+
+ //--- between the upper and lower edges
+ } else if (y > rectY0I && y < rectY1I) {
+
+ // left edge
+ if (x0 <= rectX0I) {
+ pix = (Guchar)splashCeil(((SplashCoord)1 - (xPath->rectX0 - rectX0I))
+ * 255);
+ if (pix < 16) {
+ pix = 16;
+ }
+ line[rectX0I] = pix;
+ x = rectX0I + 1;
+ } else {
+ x = x0;
+ }
+
+ // right edge
+ if (rectX1I <= x1) {
+ pix = (Guchar)splashCeil((xPath->rectX1 - rectX1I) * 255);
+ if (pix < 16) {
+ pix = 16;
+ }
+ line[rectX1I] = pix;
+ xe = rectX1I - 1;
+ } else {
+ xe = x1;
+ }
+
+ // middle
+ for (; x <= xe; ++x) {
+ line[x] = 255;
+ }
+ }
+}
+
+void SplashXPathScanner::drawRectangleSpanBinary(Guchar *line, int y,
+ int x0, int x1,
+ int *xMin, int *xMax) {
+ int xe, x;
+
+ if (y >= rectY0I && y <= rectY1I) {
+ if (x0 <= rectX0I) {
+ x = rectX0I;
+ } else {
+ x = x0;
+ }
+ *xMin = x;
+ if (rectX1I <= x1) {
+ xe = rectX1I;
+ } else {
+ xe = x1;
+ }
+ *xMax = xe;
+ for (; x <= xe; ++x) {
+ line[x] = 255;
+ }
+ }
+}
+
+void SplashXPathScanner::getSpan(Guchar *line, int y, int x0, int x1,
+ int *xMin, int *xMax) {
+ int iy, x, k;
+
+ iy = y * aaVert;
+ if (!resetDone || !resetAA) {
+ reset(gTrue, gTrue);
+ } else if (yBottomI > iy) {
+ reset(gTrue, gFalse);
+ }
+ memset(line + x0, 0, x1 - x0 + 1);
+
+ *xMin = x1 + 1;
+ *xMax = x0 - 1;
+
+ if (xPath->isRect) {
+ drawRectangleSpan(line, y, x0, x1, xMin, xMax);
+ return;
+ }
+
+ if (yBottomI < iy) {
+ skip(iy, gTrue);
+ }
+ for (k = 0; k < aaVert; ++k, ++iy) {
+ advance(gTrue);
+ generatePixels(x0, x1, line, xMin, xMax);
+ }
+
+#if !ANTIALIAS_256
+ for (x = *xMin; x <= *xMax; ++x) {
+ line[x] = map16to255[line[x]];
+ }
+#endif
+}
+
+void SplashXPathScanner::getSpanBinary(Guchar *line, int y, int x0, int x1,
+ int *xMin, int *xMax) {
+ int iy;
+
+ iy = y;
+ if (!resetDone || resetAA) {
+ reset(gFalse, gTrue);
+ } else if (yBottomI > iy) {
+ reset(gFalse, gFalse);
+ }
+ memset(line + x0, 0, x1 - x0 + 1);
+
+ *xMin = x1 + 1;
+ *xMax = x0 - 1;
+
+ if (xPath->isRect) {
+ drawRectangleSpanBinary(line, y, x0, x1, xMin, xMax);
+ return;
+ }
+
+ if (yBottomI < iy) {
+ skip(iy, gFalse);
+ }
+ advance(gFalse);
+ generatePixelsBinary(x0, x1, line, xMin, xMax);
+}
diff --git a/splash/SplashXPathScanner.h b/splash/SplashXPathScanner.h
new file mode 100644
index 0000000..39cc0eb
--- /dev/null
+++ b/splash/SplashXPathScanner.h
@@ -0,0 +1,84 @@
+//========================================================================
+//
+// SplashXPathScanner.h
+//
+// Copyright 2003-2013 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef SPLASHXPATHSCANNER_H
+#define SPLASHXPATHSCANNER_H
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include "SplashTypes.h"
+#include "SplashXPath.h"
+
+class GList;
+
+//------------------------------------------------------------------------
+
+// Set this to 0 for antialiasing with 16 levels of gray.
+// Set it to 1 for (much slower) antialiasing with 256 levels of gray.
+#define ANTIALIAS_256 0
+
+//------------------------------------------------------------------------
+// SplashXPathScanner
+//------------------------------------------------------------------------
+
+class SplashXPathScanner {
+public:
+
+ // Create a new SplashXPathScanner object. <xPathA> must be sorted.
+ SplashXPathScanner(SplashXPath *xPathA, GBool eo,
+ int yMinA, int yMaxA);
+
+ ~SplashXPathScanner();
+
+ // Compute shape values for a scan line. Fills in line[] with shape
+ // values for one scan line: ([x0, x1], y). The values are in [0,
+ // 255]. Also returns the min/max x positions with non-zero shape
+ // values.
+ void getSpan(Guchar *line, int y, int x0, int x1, int *xMin, int *xMax);
+
+ // Like getSpan(), but uses the values 0 and 255 only. Writes 255
+ // for all pixels which include non-zero area inside the path.
+ void getSpanBinary(Guchar *line, int y, int x0, int x1,
+ int *xMin, int *xMax);
+
+private:
+
+ void insertSegmentBefore(SplashXPathSeg *s, SplashXPathSeg *sNext);
+ void removeSegment(SplashXPathSeg *s);
+ void moveSegmentAfter(SplashXPathSeg *s, SplashXPathSeg *sPrev);
+ void reset(GBool aa, GBool aaChanged);
+ void skip(int newYBottomI, GBool aa);
+ void advance(GBool aa);
+ void generatePixels(int x0, int x1, Guchar *line, int *xMin, int *xMax);
+ void generatePixelsBinary(int x0, int x1, Guchar *line,
+ int *xMin, int *xMax);
+ void drawRectangleSpan(Guchar *line, int y, int x0, int x1,
+ int *xMin, int *xMax);
+ void drawRectangleSpanBinary(Guchar *line, int y, int x0, int x1,
+ int *xMin, int *xMax);
+
+ SplashXPath *xPath;
+ int eoMask;
+ int yMin, yMax;
+ int rectX0I, rectY0I, rectX1I, rectY1I;
+
+ SplashXPathSeg preSeg, postSeg;
+ SplashXPathSeg *pre, *post;
+
+ GBool resetDone;
+ GBool resetAA;
+ int nextSeg;
+ int yTopI, yBottomI;
+ SplashCoord yTop, yBottom;
+};
+
+#endif
diff --git a/splash/cmake_install.cmake b/splash/cmake_install.cmake
new file mode 100644
index 0000000..b77fd18
--- /dev/null
+++ b/splash/cmake_install.cmake
@@ -0,0 +1,44 @@
+# Install script for directory: /home/calvin/src/xpdf-4.04/splash
+
+# 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()
+
diff --git a/splash/libsplash.a b/splash/libsplash.a
new file mode 100644
index 0000000..3be214e
--- /dev/null
+++ b/splash/libsplash.a
Binary files differ
diff --git a/xpdf-qt/CMakeCache.txt b/xpdf-qt/CMakeCache.txt
new file mode 100644
index 0000000..47f1b82
--- /dev/null
+++ b/xpdf-qt/CMakeCache.txt
@@ -0,0 +1,376 @@
+# This is the CMakeCache file.
+# For build in directory: /home/calvin/src/xpdf-4.04/xpdf-qt
+# It was generated by CMake: /usr/bin/cmake
+# You can edit this file to change values found and used by cmake.
+# If you do not want to change any of the values, simply exit the editor.
+# If you do want to change a value, simply edit, save, and exit the editor.
+# The syntax for the file is as follows:
+# KEY:TYPE=VALUE
+# KEY is the name of a variable in the cache.
+# TYPE is a hint to GUIs for the type of VALUE, DO NOT EDIT TYPE!.
+# VALUE is the current value for the KEY.
+
+########################
+# EXTERNAL cache entries
+########################
+
+//Path to a program.
+CMAKE_ADDR2LINE:FILEPATH=/usr/bin/addr2line
+
+//Path to a program.
+CMAKE_AR:FILEPATH=/usr/bin/ar
+
+//For backwards compatibility, what version of CMake commands and
+// syntax should this version of CMake try to support.
+CMAKE_BACKWARDS_COMPATIBILITY:STRING=2.4
+
+//Choose the type of build, options are: None Debug Release RelWithDebInfo
+// MinSizeRel ...
+CMAKE_BUILD_TYPE:STRING=
+
+//Enable/Disable color output during build.
+CMAKE_COLOR_MAKEFILE:BOOL=ON
+
+//CXX compiler
+CMAKE_CXX_COMPILER:FILEPATH=/usr/bin/c++
+
+//A wrapper around 'ar' adding the appropriate '--plugin' option
+// for the GCC compiler
+CMAKE_CXX_COMPILER_AR:FILEPATH=/usr/bin/gcc-ar-10
+
+//A wrapper around 'ranlib' adding the appropriate '--plugin' option
+// for the GCC compiler
+CMAKE_CXX_COMPILER_RANLIB:FILEPATH=/usr/bin/gcc-ranlib-10
+
+//Flags used by the CXX compiler during all build types.
+CMAKE_CXX_FLAGS:STRING=
+
+//Flags used by the CXX compiler during DEBUG builds.
+CMAKE_CXX_FLAGS_DEBUG:STRING=-g
+
+//Flags used by the CXX compiler during MINSIZEREL builds.
+CMAKE_CXX_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG
+
+//Flags used by the CXX compiler during RELEASE builds.
+CMAKE_CXX_FLAGS_RELEASE:STRING=-O3 -DNDEBUG
+
+//Flags used by the CXX compiler during RELWITHDEBINFO builds.
+CMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG
+
+//C compiler
+CMAKE_C_COMPILER:FILEPATH=/usr/bin/cc
+
+//A wrapper around 'ar' adding the appropriate '--plugin' option
+// for the GCC compiler
+CMAKE_C_COMPILER_AR:FILEPATH=/usr/bin/gcc-ar-10
+
+//A wrapper around 'ranlib' adding the appropriate '--plugin' option
+// for the GCC compiler
+CMAKE_C_COMPILER_RANLIB:FILEPATH=/usr/bin/gcc-ranlib-10
+
+//Flags used by the C compiler during all build types.
+CMAKE_C_FLAGS:STRING=
+
+//Flags used by the C compiler during DEBUG builds.
+CMAKE_C_FLAGS_DEBUG:STRING=-g
+
+//Flags used by the C compiler during MINSIZEREL builds.
+CMAKE_C_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG
+
+//Flags used by the C compiler during RELEASE builds.
+CMAKE_C_FLAGS_RELEASE:STRING=-O3 -DNDEBUG
+
+//Flags used by the C compiler during RELWITHDEBINFO builds.
+CMAKE_C_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG
+
+//Path to a program.
+CMAKE_DLLTOOL:FILEPATH=CMAKE_DLLTOOL-NOTFOUND
+
+//Flags used by the linker during all build types.
+CMAKE_EXE_LINKER_FLAGS:STRING=
+
+//Flags used by the linker during DEBUG builds.
+CMAKE_EXE_LINKER_FLAGS_DEBUG:STRING=
+
+//Flags used by the linker during MINSIZEREL builds.
+CMAKE_EXE_LINKER_FLAGS_MINSIZEREL:STRING=
+
+//Flags used by the linker during RELEASE builds.
+CMAKE_EXE_LINKER_FLAGS_RELEASE:STRING=
+
+//Flags used by the linker during RELWITHDEBINFO builds.
+CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO:STRING=
+
+//Enable/Disable output of compile commands during generation.
+CMAKE_EXPORT_COMPILE_COMMANDS:BOOL=
+
+//Install path prefix, prepended onto install directories.
+CMAKE_INSTALL_PREFIX:PATH=/usr/local
+
+//Path to a program.
+CMAKE_LINKER:FILEPATH=/usr/bin/ld
+
+//Path to a program.
+CMAKE_MAKE_PROGRAM:FILEPATH=/usr/bin/gmake
+
+//Flags used by the linker during the creation of modules during
+// all build types.
+CMAKE_MODULE_LINKER_FLAGS:STRING=
+
+//Flags used by the linker during the creation of modules during
+// DEBUG builds.
+CMAKE_MODULE_LINKER_FLAGS_DEBUG:STRING=
+
+//Flags used by the linker during the creation of modules during
+// MINSIZEREL builds.
+CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL:STRING=
+
+//Flags used by the linker during the creation of modules during
+// RELEASE builds.
+CMAKE_MODULE_LINKER_FLAGS_RELEASE:STRING=
+
+//Flags used by the linker during the creation of modules during
+// RELWITHDEBINFO builds.
+CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO:STRING=
+
+//Path to a program.
+CMAKE_NM:FILEPATH=/usr/bin/nm
+
+//Path to a program.
+CMAKE_OBJCOPY:FILEPATH=/usr/bin/objcopy
+
+//Path to a program.
+CMAKE_OBJDUMP:FILEPATH=/usr/bin/objdump
+
+//Value Computed by CMake
+CMAKE_PROJECT_DESCRIPTION:STATIC=
+
+//Value Computed by CMake
+CMAKE_PROJECT_HOMEPAGE_URL:STATIC=
+
+//Value Computed by CMake
+CMAKE_PROJECT_NAME:STATIC=Project
+
+//Path to a program.
+CMAKE_RANLIB:FILEPATH=/usr/bin/ranlib
+
+//Path to a program.
+CMAKE_READELF:FILEPATH=/usr/bin/readelf
+
+//Flags used by the linker during the creation of shared libraries
+// during all build types.
+CMAKE_SHARED_LINKER_FLAGS:STRING=
+
+//Flags used by the linker during the creation of shared libraries
+// during DEBUG builds.
+CMAKE_SHARED_LINKER_FLAGS_DEBUG:STRING=
+
+//Flags used by the linker during the creation of shared libraries
+// during MINSIZEREL builds.
+CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL:STRING=
+
+//Flags used by the linker during the creation of shared libraries
+// during RELEASE builds.
+CMAKE_SHARED_LINKER_FLAGS_RELEASE:STRING=
+
+//Flags used by the linker during the creation of shared libraries
+// during RELWITHDEBINFO builds.
+CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO:STRING=
+
+//If set, runtime paths are not added when installing shared libraries,
+// but are added when building.
+CMAKE_SKIP_INSTALL_RPATH:BOOL=NO
+
+//If set, runtime paths are not added when using shared libraries.
+CMAKE_SKIP_RPATH:BOOL=NO
+
+//Flags used by the linker during the creation of static libraries
+// during all build types.
+CMAKE_STATIC_LINKER_FLAGS:STRING=
+
+//Flags used by the linker during the creation of static libraries
+// during DEBUG builds.
+CMAKE_STATIC_LINKER_FLAGS_DEBUG:STRING=
+
+//Flags used by the linker during the creation of static libraries
+// during MINSIZEREL builds.
+CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL:STRING=
+
+//Flags used by the linker during the creation of static libraries
+// during RELEASE builds.
+CMAKE_STATIC_LINKER_FLAGS_RELEASE:STRING=
+
+//Flags used by the linker during the creation of static libraries
+// during RELWITHDEBINFO builds.
+CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO:STRING=
+
+//Path to a program.
+CMAKE_STRIP:FILEPATH=/usr/bin/strip
+
+//If this value is on, makefiles will be generated without the
+// .SILENT directive, and all commands will be echoed to the console
+// during the make. This is useful for debugging only. With Visual
+// Studio IDE projects all commands are done without /nologo.
+CMAKE_VERBOSE_MAKEFILE:BOOL=FALSE
+
+//Single output directory for building all executables.
+EXECUTABLE_OUTPUT_PATH:PATH=
+
+//Single output directory for building all libraries.
+LIBRARY_OUTPUT_PATH:PATH=
+
+//Value Computed by CMake
+Project_BINARY_DIR:STATIC=/home/calvin/src/xpdf-4.04/xpdf-qt
+
+//Value Computed by CMake
+Project_SOURCE_DIR:STATIC=/home/calvin/src/xpdf-4.04/xpdf-qt
+
+
+########################
+# INTERNAL cache entries
+########################
+
+//ADVANCED property for variable: CMAKE_ADDR2LINE
+CMAKE_ADDR2LINE-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_AR
+CMAKE_AR-ADVANCED:INTERNAL=1
+//This is the directory where this CMakeCache.txt was created
+CMAKE_CACHEFILE_DIR:INTERNAL=/home/calvin/src/xpdf-4.04/xpdf-qt
+//Major version of cmake used to create the current loaded cache
+CMAKE_CACHE_MAJOR_VERSION:INTERNAL=3
+//Minor version of cmake used to create the current loaded cache
+CMAKE_CACHE_MINOR_VERSION:INTERNAL=18
+//Patch version of cmake used to create the current loaded cache
+CMAKE_CACHE_PATCH_VERSION:INTERNAL=4
+//ADVANCED property for variable: CMAKE_COLOR_MAKEFILE
+CMAKE_COLOR_MAKEFILE-ADVANCED:INTERNAL=1
+//Path to CMake executable.
+CMAKE_COMMAND:INTERNAL=/usr/bin/cmake
+//Path to cpack program executable.
+CMAKE_CPACK_COMMAND:INTERNAL=/usr/bin/cpack
+//Path to ctest program executable.
+CMAKE_CTEST_COMMAND:INTERNAL=/usr/bin/ctest
+//ADVANCED property for variable: CMAKE_CXX_COMPILER
+CMAKE_CXX_COMPILER-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_CXX_COMPILER_AR
+CMAKE_CXX_COMPILER_AR-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_CXX_COMPILER_RANLIB
+CMAKE_CXX_COMPILER_RANLIB-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_CXX_FLAGS
+CMAKE_CXX_FLAGS-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_CXX_FLAGS_DEBUG
+CMAKE_CXX_FLAGS_DEBUG-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_CXX_FLAGS_MINSIZEREL
+CMAKE_CXX_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELEASE
+CMAKE_CXX_FLAGS_RELEASE-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELWITHDEBINFO
+CMAKE_CXX_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_C_COMPILER
+CMAKE_C_COMPILER-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_C_COMPILER_AR
+CMAKE_C_COMPILER_AR-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_C_COMPILER_RANLIB
+CMAKE_C_COMPILER_RANLIB-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_C_FLAGS
+CMAKE_C_FLAGS-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_C_FLAGS_DEBUG
+CMAKE_C_FLAGS_DEBUG-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_C_FLAGS_MINSIZEREL
+CMAKE_C_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_C_FLAGS_RELEASE
+CMAKE_C_FLAGS_RELEASE-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_C_FLAGS_RELWITHDEBINFO
+CMAKE_C_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_DLLTOOL
+CMAKE_DLLTOOL-ADVANCED:INTERNAL=1
+//Executable file format
+CMAKE_EXECUTABLE_FORMAT:INTERNAL=ELF
+//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS
+CMAKE_EXE_LINKER_FLAGS-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_DEBUG
+CMAKE_EXE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_MINSIZEREL
+CMAKE_EXE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELEASE
+CMAKE_EXE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO
+CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_EXPORT_COMPILE_COMMANDS
+CMAKE_EXPORT_COMPILE_COMMANDS-ADVANCED:INTERNAL=1
+//Name of external makefile project generator.
+CMAKE_EXTRA_GENERATOR:INTERNAL=
+//Name of generator.
+CMAKE_GENERATOR:INTERNAL=Unix Makefiles
+//Generator instance identifier.
+CMAKE_GENERATOR_INSTANCE:INTERNAL=
+//Name of generator platform.
+CMAKE_GENERATOR_PLATFORM:INTERNAL=
+//Name of generator toolset.
+CMAKE_GENERATOR_TOOLSET:INTERNAL=
+//Source directory with the top level CMakeLists.txt file for this
+// project
+CMAKE_HOME_DIRECTORY:INTERNAL=/home/calvin/src/xpdf-4.04/xpdf-qt
+//Install .so files without execute permission.
+CMAKE_INSTALL_SO_NO_EXE:INTERNAL=1
+//ADVANCED property for variable: CMAKE_LINKER
+CMAKE_LINKER-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_MAKE_PROGRAM
+CMAKE_MAKE_PROGRAM-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS
+CMAKE_MODULE_LINKER_FLAGS-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_DEBUG
+CMAKE_MODULE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL
+CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELEASE
+CMAKE_MODULE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO
+CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_NM
+CMAKE_NM-ADVANCED:INTERNAL=1
+//number of local generators
+CMAKE_NUMBER_OF_MAKEFILES:INTERNAL=1
+//ADVANCED property for variable: CMAKE_OBJCOPY
+CMAKE_OBJCOPY-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_OBJDUMP
+CMAKE_OBJDUMP-ADVANCED:INTERNAL=1
+//Platform information initialized
+CMAKE_PLATFORM_INFO_INITIALIZED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_RANLIB
+CMAKE_RANLIB-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_READELF
+CMAKE_READELF-ADVANCED:INTERNAL=1
+//Path to CMake installation.
+CMAKE_ROOT:INTERNAL=/usr/share/cmake-3.18
+//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS
+CMAKE_SHARED_LINKER_FLAGS-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_DEBUG
+CMAKE_SHARED_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL
+CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELEASE
+CMAKE_SHARED_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO
+CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_SKIP_INSTALL_RPATH
+CMAKE_SKIP_INSTALL_RPATH-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_SKIP_RPATH
+CMAKE_SKIP_RPATH-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS
+CMAKE_STATIC_LINKER_FLAGS-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_DEBUG
+CMAKE_STATIC_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL
+CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELEASE
+CMAKE_STATIC_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO
+CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_STRIP
+CMAKE_STRIP-ADVANCED:INTERNAL=1
+//uname command
+CMAKE_UNAME:INTERNAL=/usr/bin/uname
+//ADVANCED property for variable: CMAKE_VERBOSE_MAKEFILE
+CMAKE_VERBOSE_MAKEFILE-ADVANCED:INTERNAL=1
+
diff --git a/xpdf-qt/CMakeFiles/3.18.4/CMakeCCompiler.cmake b/xpdf-qt/CMakeFiles/3.18.4/CMakeCCompiler.cmake
new file mode 100644
index 0000000..e033eb1
--- /dev/null
+++ b/xpdf-qt/CMakeFiles/3.18.4/CMakeCCompiler.cmake
@@ -0,0 +1,77 @@
+set(CMAKE_C_COMPILER "/usr/bin/cc")
+set(CMAKE_C_COMPILER_ARG1 "")
+set(CMAKE_C_COMPILER_ID "GNU")
+set(CMAKE_C_COMPILER_VERSION "10.2.1")
+set(CMAKE_C_COMPILER_VERSION_INTERNAL "")
+set(CMAKE_C_COMPILER_WRAPPER "")
+set(CMAKE_C_STANDARD_COMPUTED_DEFAULT "11")
+set(CMAKE_C_COMPILE_FEATURES "c_std_90;c_function_prototypes;c_std_99;c_restrict;c_variadic_macros;c_std_11;c_static_assert")
+set(CMAKE_C90_COMPILE_FEATURES "c_std_90;c_function_prototypes")
+set(CMAKE_C99_COMPILE_FEATURES "c_std_99;c_restrict;c_variadic_macros")
+set(CMAKE_C11_COMPILE_FEATURES "c_std_11;c_static_assert")
+
+set(CMAKE_C_PLATFORM_ID "Linux")
+set(CMAKE_C_SIMULATE_ID "")
+set(CMAKE_C_COMPILER_FRONTEND_VARIANT "")
+set(CMAKE_C_SIMULATE_VERSION "")
+
+
+
+
+set(CMAKE_AR "/usr/bin/ar")
+set(CMAKE_C_COMPILER_AR "/usr/bin/gcc-ar-10")
+set(CMAKE_RANLIB "/usr/bin/ranlib")
+set(CMAKE_C_COMPILER_RANLIB "/usr/bin/gcc-ranlib-10")
+set(CMAKE_LINKER "/usr/bin/ld")
+set(CMAKE_MT "")
+set(CMAKE_COMPILER_IS_GNUCC 1)
+set(CMAKE_C_COMPILER_LOADED 1)
+set(CMAKE_C_COMPILER_WORKS TRUE)
+set(CMAKE_C_ABI_COMPILED TRUE)
+set(CMAKE_COMPILER_IS_MINGW )
+set(CMAKE_COMPILER_IS_CYGWIN )
+if(CMAKE_COMPILER_IS_CYGWIN)
+ set(CYGWIN 1)
+ set(UNIX 1)
+endif()
+
+set(CMAKE_C_COMPILER_ENV_VAR "CC")
+
+if(CMAKE_COMPILER_IS_MINGW)
+ set(MINGW 1)
+endif()
+set(CMAKE_C_COMPILER_ID_RUN 1)
+set(CMAKE_C_SOURCE_FILE_EXTENSIONS c;m)
+set(CMAKE_C_IGNORE_EXTENSIONS h;H;o;O;obj;OBJ;def;DEF;rc;RC)
+set(CMAKE_C_LINKER_PREFERENCE 10)
+
+# Save compiler ABI information.
+set(CMAKE_C_SIZEOF_DATA_PTR "8")
+set(CMAKE_C_COMPILER_ABI "ELF")
+set(CMAKE_C_LIBRARY_ARCHITECTURE "x86_64-linux-gnu")
+
+if(CMAKE_C_SIZEOF_DATA_PTR)
+ set(CMAKE_SIZEOF_VOID_P "${CMAKE_C_SIZEOF_DATA_PTR}")
+endif()
+
+if(CMAKE_C_COMPILER_ABI)
+ set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_C_COMPILER_ABI}")
+endif()
+
+if(CMAKE_C_LIBRARY_ARCHITECTURE)
+ set(CMAKE_LIBRARY_ARCHITECTURE "x86_64-linux-gnu")
+endif()
+
+set(CMAKE_C_CL_SHOWINCLUDES_PREFIX "")
+if(CMAKE_C_CL_SHOWINCLUDES_PREFIX)
+ set(CMAKE_CL_SHOWINCLUDES_PREFIX "${CMAKE_C_CL_SHOWINCLUDES_PREFIX}")
+endif()
+
+
+
+
+
+set(CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES "/usr/lib/gcc/x86_64-linux-gnu/10/include;/usr/local/include;/usr/include/x86_64-linux-gnu;/usr/include")
+set(CMAKE_C_IMPLICIT_LINK_LIBRARIES "gcc;gcc_s;c;gcc;gcc_s")
+set(CMAKE_C_IMPLICIT_LINK_DIRECTORIES "/usr/lib/gcc/x86_64-linux-gnu/10;/usr/lib/x86_64-linux-gnu;/usr/lib;/lib/x86_64-linux-gnu;/lib")
+set(CMAKE_C_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "")
diff --git a/xpdf-qt/CMakeFiles/3.18.4/CMakeCXXCompiler.cmake b/xpdf-qt/CMakeFiles/3.18.4/CMakeCXXCompiler.cmake
new file mode 100644
index 0000000..7d1c1cf
--- /dev/null
+++ b/xpdf-qt/CMakeFiles/3.18.4/CMakeCXXCompiler.cmake
@@ -0,0 +1,89 @@
+set(CMAKE_CXX_COMPILER "/usr/bin/c++")
+set(CMAKE_CXX_COMPILER_ARG1 "")
+set(CMAKE_CXX_COMPILER_ID "GNU")
+set(CMAKE_CXX_COMPILER_VERSION "10.2.1")
+set(CMAKE_CXX_COMPILER_VERSION_INTERNAL "")
+set(CMAKE_CXX_COMPILER_WRAPPER "")
+set(CMAKE_CXX_STANDARD_COMPUTED_DEFAULT "14")
+set(CMAKE_CXX_COMPILE_FEATURES "cxx_std_98;cxx_template_template_parameters;cxx_std_11;cxx_alias_templates;cxx_alignas;cxx_alignof;cxx_attributes;cxx_auto_type;cxx_constexpr;cxx_decltype;cxx_decltype_incomplete_return_types;cxx_default_function_template_args;cxx_defaulted_functions;cxx_defaulted_move_initializers;cxx_delegating_constructors;cxx_deleted_functions;cxx_enum_forward_declarations;cxx_explicit_conversions;cxx_extended_friend_declarations;cxx_extern_templates;cxx_final;cxx_func_identifier;cxx_generalized_initializers;cxx_inheriting_constructors;cxx_inline_namespaces;cxx_lambdas;cxx_local_type_template_args;cxx_long_long_type;cxx_noexcept;cxx_nonstatic_member_init;cxx_nullptr;cxx_override;cxx_range_for;cxx_raw_string_literals;cxx_reference_qualified_functions;cxx_right_angle_brackets;cxx_rvalue_references;cxx_sizeof_member;cxx_static_assert;cxx_strong_enums;cxx_thread_local;cxx_trailing_return_types;cxx_unicode_literals;cxx_uniform_initialization;cxx_unrestricted_unions;cxx_user_literals;cxx_variadic_macros;cxx_variadic_templates;cxx_std_14;cxx_aggregate_default_initializers;cxx_attribute_deprecated;cxx_binary_literals;cxx_contextual_conversions;cxx_decltype_auto;cxx_digit_separators;cxx_generic_lambdas;cxx_lambda_init_captures;cxx_relaxed_constexpr;cxx_return_type_deduction;cxx_variable_templates;cxx_std_17;cxx_std_20")
+set(CMAKE_CXX98_COMPILE_FEATURES "cxx_std_98;cxx_template_template_parameters")
+set(CMAKE_CXX11_COMPILE_FEATURES "cxx_std_11;cxx_alias_templates;cxx_alignas;cxx_alignof;cxx_attributes;cxx_auto_type;cxx_constexpr;cxx_decltype;cxx_decltype_incomplete_return_types;cxx_default_function_template_args;cxx_defaulted_functions;cxx_defaulted_move_initializers;cxx_delegating_constructors;cxx_deleted_functions;cxx_enum_forward_declarations;cxx_explicit_conversions;cxx_extended_friend_declarations;cxx_extern_templates;cxx_final;cxx_func_identifier;cxx_generalized_initializers;cxx_inheriting_constructors;cxx_inline_namespaces;cxx_lambdas;cxx_local_type_template_args;cxx_long_long_type;cxx_noexcept;cxx_nonstatic_member_init;cxx_nullptr;cxx_override;cxx_range_for;cxx_raw_string_literals;cxx_reference_qualified_functions;cxx_right_angle_brackets;cxx_rvalue_references;cxx_sizeof_member;cxx_static_assert;cxx_strong_enums;cxx_thread_local;cxx_trailing_return_types;cxx_unicode_literals;cxx_uniform_initialization;cxx_unrestricted_unions;cxx_user_literals;cxx_variadic_macros;cxx_variadic_templates")
+set(CMAKE_CXX14_COMPILE_FEATURES "cxx_std_14;cxx_aggregate_default_initializers;cxx_attribute_deprecated;cxx_binary_literals;cxx_contextual_conversions;cxx_decltype_auto;cxx_digit_separators;cxx_generic_lambdas;cxx_lambda_init_captures;cxx_relaxed_constexpr;cxx_return_type_deduction;cxx_variable_templates")
+set(CMAKE_CXX17_COMPILE_FEATURES "cxx_std_17")
+set(CMAKE_CXX20_COMPILE_FEATURES "cxx_std_20")
+
+set(CMAKE_CXX_PLATFORM_ID "Linux")
+set(CMAKE_CXX_SIMULATE_ID "")
+set(CMAKE_CXX_COMPILER_FRONTEND_VARIANT "")
+set(CMAKE_CXX_SIMULATE_VERSION "")
+
+
+
+
+set(CMAKE_AR "/usr/bin/ar")
+set(CMAKE_CXX_COMPILER_AR "/usr/bin/gcc-ar-10")
+set(CMAKE_RANLIB "/usr/bin/ranlib")
+set(CMAKE_CXX_COMPILER_RANLIB "/usr/bin/gcc-ranlib-10")
+set(CMAKE_LINKER "/usr/bin/ld")
+set(CMAKE_MT "")
+set(CMAKE_COMPILER_IS_GNUCXX 1)
+set(CMAKE_CXX_COMPILER_LOADED 1)
+set(CMAKE_CXX_COMPILER_WORKS TRUE)
+set(CMAKE_CXX_ABI_COMPILED TRUE)
+set(CMAKE_COMPILER_IS_MINGW )
+set(CMAKE_COMPILER_IS_CYGWIN )
+if(CMAKE_COMPILER_IS_CYGWIN)
+ set(CYGWIN 1)
+ set(UNIX 1)
+endif()
+
+set(CMAKE_CXX_COMPILER_ENV_VAR "CXX")
+
+if(CMAKE_COMPILER_IS_MINGW)
+ set(MINGW 1)
+endif()
+set(CMAKE_CXX_COMPILER_ID_RUN 1)
+set(CMAKE_CXX_SOURCE_FILE_EXTENSIONS C;M;c++;cc;cpp;cxx;m;mm;CPP)
+set(CMAKE_CXX_IGNORE_EXTENSIONS inl;h;hpp;HPP;H;o;O;obj;OBJ;def;DEF;rc;RC)
+
+foreach (lang C OBJC OBJCXX)
+ if (CMAKE_${lang}_COMPILER_ID_RUN)
+ foreach(extension IN LISTS CMAKE_${lang}_SOURCE_FILE_EXTENSIONS)
+ list(REMOVE_ITEM CMAKE_CXX_SOURCE_FILE_EXTENSIONS ${extension})
+ endforeach()
+ endif()
+endforeach()
+
+set(CMAKE_CXX_LINKER_PREFERENCE 30)
+set(CMAKE_CXX_LINKER_PREFERENCE_PROPAGATES 1)
+
+# Save compiler ABI information.
+set(CMAKE_CXX_SIZEOF_DATA_PTR "8")
+set(CMAKE_CXX_COMPILER_ABI "ELF")
+set(CMAKE_CXX_LIBRARY_ARCHITECTURE "x86_64-linux-gnu")
+
+if(CMAKE_CXX_SIZEOF_DATA_PTR)
+ set(CMAKE_SIZEOF_VOID_P "${CMAKE_CXX_SIZEOF_DATA_PTR}")
+endif()
+
+if(CMAKE_CXX_COMPILER_ABI)
+ set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_CXX_COMPILER_ABI}")
+endif()
+
+if(CMAKE_CXX_LIBRARY_ARCHITECTURE)
+ set(CMAKE_LIBRARY_ARCHITECTURE "x86_64-linux-gnu")
+endif()
+
+set(CMAKE_CXX_CL_SHOWINCLUDES_PREFIX "")
+if(CMAKE_CXX_CL_SHOWINCLUDES_PREFIX)
+ set(CMAKE_CL_SHOWINCLUDES_PREFIX "${CMAKE_CXX_CL_SHOWINCLUDES_PREFIX}")
+endif()
+
+
+
+
+
+set(CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES "/usr/include/c++/10;/usr/include/x86_64-linux-gnu/c++/10;/usr/include/c++/10/backward;/usr/lib/gcc/x86_64-linux-gnu/10/include;/usr/local/include;/usr/include/x86_64-linux-gnu;/usr/include")
+set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "stdc++;m;gcc_s;gcc;c;gcc_s;gcc")
+set(CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "/usr/lib/gcc/x86_64-linux-gnu/10;/usr/lib/x86_64-linux-gnu;/usr/lib;/lib/x86_64-linux-gnu;/lib")
+set(CMAKE_CXX_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "")
diff --git a/xpdf-qt/CMakeFiles/3.18.4/CMakeDetermineCompilerABI_C.bin b/xpdf-qt/CMakeFiles/3.18.4/CMakeDetermineCompilerABI_C.bin
new file mode 100755
index 0000000..9386501
--- /dev/null
+++ b/xpdf-qt/CMakeFiles/3.18.4/CMakeDetermineCompilerABI_C.bin
Binary files differ
diff --git a/xpdf-qt/CMakeFiles/3.18.4/CMakeDetermineCompilerABI_CXX.bin b/xpdf-qt/CMakeFiles/3.18.4/CMakeDetermineCompilerABI_CXX.bin
new file mode 100755
index 0000000..1160b1d
--- /dev/null
+++ b/xpdf-qt/CMakeFiles/3.18.4/CMakeDetermineCompilerABI_CXX.bin
Binary files differ
diff --git a/xpdf-qt/CMakeFiles/3.18.4/CMakeSystem.cmake b/xpdf-qt/CMakeFiles/3.18.4/CMakeSystem.cmake
new file mode 100644
index 0000000..319373a
--- /dev/null
+++ b/xpdf-qt/CMakeFiles/3.18.4/CMakeSystem.cmake
@@ -0,0 +1,15 @@
+set(CMAKE_HOST_SYSTEM "Linux-5.10.0-12-amd64")
+set(CMAKE_HOST_SYSTEM_NAME "Linux")
+set(CMAKE_HOST_SYSTEM_VERSION "5.10.0-12-amd64")
+set(CMAKE_HOST_SYSTEM_PROCESSOR "x86_64")
+
+
+
+set(CMAKE_SYSTEM "Linux-5.10.0-12-amd64")
+set(CMAKE_SYSTEM_NAME "Linux")
+set(CMAKE_SYSTEM_VERSION "5.10.0-12-amd64")
+set(CMAKE_SYSTEM_PROCESSOR "x86_64")
+
+set(CMAKE_CROSSCOMPILING "FALSE")
+
+set(CMAKE_SYSTEM_LOADED 1)
diff --git a/xpdf-qt/CMakeFiles/3.18.4/CompilerIdC/CMakeCCompilerId.c b/xpdf-qt/CMakeFiles/3.18.4/CompilerIdC/CMakeCCompilerId.c
new file mode 100644
index 0000000..6c0aa93
--- /dev/null
+++ b/xpdf-qt/CMakeFiles/3.18.4/CompilerIdC/CMakeCCompilerId.c
@@ -0,0 +1,674 @@
+#ifdef __cplusplus
+# error "A C++ compiler has been selected for C."
+#endif
+
+#if defined(__18CXX)
+# define ID_VOID_MAIN
+#endif
+#if defined(__CLASSIC_C__)
+/* cv-qualifiers did not exist in K&R C */
+# define const
+# define volatile
+#endif
+
+
+/* Version number components: V=Version, R=Revision, P=Patch
+ Version date components: YYYY=Year, MM=Month, DD=Day */
+
+#if defined(__INTEL_COMPILER) || defined(__ICC)
+# define COMPILER_ID "Intel"
+# if defined(_MSC_VER)
+# define SIMULATE_ID "MSVC"
+# endif
+# if defined(__GNUC__)
+# define SIMULATE_ID "GNU"
+# endif
+ /* __INTEL_COMPILER = VRP */
+# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER/100)
+# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER/10 % 10)
+# if defined(__INTEL_COMPILER_UPDATE)
+# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER_UPDATE)
+# else
+# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER % 10)
+# endif
+# if defined(__INTEL_COMPILER_BUILD_DATE)
+ /* __INTEL_COMPILER_BUILD_DATE = YYYYMMDD */
+# define COMPILER_VERSION_TWEAK DEC(__INTEL_COMPILER_BUILD_DATE)
+# endif
+# if defined(_MSC_VER)
+ /* _MSC_VER = VVRR */
+# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100)
+# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100)
+# endif
+# if defined(__GNUC__)
+# define SIMULATE_VERSION_MAJOR DEC(__GNUC__)
+# elif defined(__GNUG__)
+# define SIMULATE_VERSION_MAJOR DEC(__GNUG__)
+# endif
+# if defined(__GNUC_MINOR__)
+# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__)
+# endif
+# if defined(__GNUC_PATCHLEVEL__)
+# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__)
+# endif
+
+#elif defined(__PATHCC__)
+# define COMPILER_ID "PathScale"
+# define COMPILER_VERSION_MAJOR DEC(__PATHCC__)
+# define COMPILER_VERSION_MINOR DEC(__PATHCC_MINOR__)
+# if defined(__PATHCC_PATCHLEVEL__)
+# define COMPILER_VERSION_PATCH DEC(__PATHCC_PATCHLEVEL__)
+# endif
+
+#elif defined(__BORLANDC__) && defined(__CODEGEARC_VERSION__)
+# define COMPILER_ID "Embarcadero"
+# define COMPILER_VERSION_MAJOR HEX(__CODEGEARC_VERSION__>>24 & 0x00FF)
+# define COMPILER_VERSION_MINOR HEX(__CODEGEARC_VERSION__>>16 & 0x00FF)
+# define COMPILER_VERSION_PATCH DEC(__CODEGEARC_VERSION__ & 0xFFFF)
+
+#elif defined(__BORLANDC__)
+# define COMPILER_ID "Borland"
+ /* __BORLANDC__ = 0xVRR */
+# define COMPILER_VERSION_MAJOR HEX(__BORLANDC__>>8)
+# define COMPILER_VERSION_MINOR HEX(__BORLANDC__ & 0xFF)
+
+#elif defined(__WATCOMC__) && __WATCOMC__ < 1200
+# define COMPILER_ID "Watcom"
+ /* __WATCOMC__ = VVRR */
+# define COMPILER_VERSION_MAJOR DEC(__WATCOMC__ / 100)
+# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10)
+# if (__WATCOMC__ % 10) > 0
+# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10)
+# endif
+
+#elif defined(__WATCOMC__)
+# define COMPILER_ID "OpenWatcom"
+ /* __WATCOMC__ = VVRP + 1100 */
+# define COMPILER_VERSION_MAJOR DEC((__WATCOMC__ - 1100) / 100)
+# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10)
+# if (__WATCOMC__ % 10) > 0
+# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10)
+# endif
+
+#elif defined(__SUNPRO_C)
+# define COMPILER_ID "SunPro"
+# if __SUNPRO_C >= 0x5100
+ /* __SUNPRO_C = 0xVRRP */
+# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>12)
+# define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xFF)
+# define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF)
+# else
+ /* __SUNPRO_CC = 0xVRP */
+# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>8)
+# define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xF)
+# define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF)
+# endif
+
+#elif defined(__HP_cc)
+# define COMPILER_ID "HP"
+ /* __HP_cc = VVRRPP */
+# define COMPILER_VERSION_MAJOR DEC(__HP_cc/10000)
+# define COMPILER_VERSION_MINOR DEC(__HP_cc/100 % 100)
+# define COMPILER_VERSION_PATCH DEC(__HP_cc % 100)
+
+#elif defined(__DECC)
+# define COMPILER_ID "Compaq"
+ /* __DECC_VER = VVRRTPPPP */
+# define COMPILER_VERSION_MAJOR DEC(__DECC_VER/10000000)
+# define COMPILER_VERSION_MINOR DEC(__DECC_VER/100000 % 100)
+# define COMPILER_VERSION_PATCH DEC(__DECC_VER % 10000)
+
+#elif defined(__IBMC__) && defined(__COMPILER_VER__)
+# define COMPILER_ID "zOS"
+ /* __IBMC__ = VRP */
+# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100)
+# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10)
+# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10)
+
+#elif defined(__ibmxl__) && defined(__clang__)
+# define COMPILER_ID "XLClang"
+# define COMPILER_VERSION_MAJOR DEC(__ibmxl_version__)
+# define COMPILER_VERSION_MINOR DEC(__ibmxl_release__)
+# define COMPILER_VERSION_PATCH DEC(__ibmxl_modification__)
+# define COMPILER_VERSION_TWEAK DEC(__ibmxl_ptf_fix_level__)
+
+
+#elif defined(__IBMC__) && !defined(__COMPILER_VER__) && __IBMC__ >= 800
+# define COMPILER_ID "XL"
+ /* __IBMC__ = VRP */
+# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100)
+# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10)
+# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10)
+
+#elif defined(__IBMC__) && !defined(__COMPILER_VER__) && __IBMC__ < 800
+# define COMPILER_ID "VisualAge"
+ /* __IBMC__ = VRP */
+# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100)
+# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10)
+# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10)
+
+#elif defined(__PGI)
+# define COMPILER_ID "PGI"
+# define COMPILER_VERSION_MAJOR DEC(__PGIC__)
+# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__)
+# if defined(__PGIC_PATCHLEVEL__)
+# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__)
+# endif
+
+#elif defined(_CRAYC)
+# define COMPILER_ID "Cray"
+# define COMPILER_VERSION_MAJOR DEC(_RELEASE_MAJOR)
+# define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR)
+
+#elif defined(__TI_COMPILER_VERSION__)
+# define COMPILER_ID "TI"
+ /* __TI_COMPILER_VERSION__ = VVVRRRPPP */
+# define COMPILER_VERSION_MAJOR DEC(__TI_COMPILER_VERSION__/1000000)
+# define COMPILER_VERSION_MINOR DEC(__TI_COMPILER_VERSION__/1000 % 1000)
+# define COMPILER_VERSION_PATCH DEC(__TI_COMPILER_VERSION__ % 1000)
+
+#elif defined(__FUJITSU) || defined(__FCC_VERSION) || defined(__fcc_version)
+# define COMPILER_ID "Fujitsu"
+
+#elif defined(__ghs__)
+# define COMPILER_ID "GHS"
+/* __GHS_VERSION_NUMBER = VVVVRP */
+# ifdef __GHS_VERSION_NUMBER
+# define COMPILER_VERSION_MAJOR DEC(__GHS_VERSION_NUMBER / 100)
+# define COMPILER_VERSION_MINOR DEC(__GHS_VERSION_NUMBER / 10 % 10)
+# define COMPILER_VERSION_PATCH DEC(__GHS_VERSION_NUMBER % 10)
+# endif
+
+#elif defined(__TINYC__)
+# define COMPILER_ID "TinyCC"
+
+#elif defined(__BCC__)
+# define COMPILER_ID "Bruce"
+
+#elif defined(__SCO_VERSION__)
+# define COMPILER_ID "SCO"
+
+#elif defined(__ARMCC_VERSION) && !defined(__clang__)
+# define COMPILER_ID "ARMCC"
+#if __ARMCC_VERSION >= 1000000
+ /* __ARMCC_VERSION = VRRPPPP */
+ # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/1000000)
+ # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 100)
+ # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000)
+#else
+ /* __ARMCC_VERSION = VRPPPP */
+ # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/100000)
+ # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 10)
+ # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000)
+#endif
+
+
+#elif defined(__clang__) && defined(__apple_build_version__)
+# define COMPILER_ID "AppleClang"
+# if defined(_MSC_VER)
+# define SIMULATE_ID "MSVC"
+# endif
+# define COMPILER_VERSION_MAJOR DEC(__clang_major__)
+# define COMPILER_VERSION_MINOR DEC(__clang_minor__)
+# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__)
+# if defined(_MSC_VER)
+ /* _MSC_VER = VVRR */
+# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100)
+# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100)
+# endif
+# define COMPILER_VERSION_TWEAK DEC(__apple_build_version__)
+
+#elif defined(__clang__) && defined(__ARMCOMPILER_VERSION)
+# define COMPILER_ID "ARMClang"
+ # define COMPILER_VERSION_MAJOR DEC(__ARMCOMPILER_VERSION/1000000)
+ # define COMPILER_VERSION_MINOR DEC(__ARMCOMPILER_VERSION/10000 % 100)
+ # define COMPILER_VERSION_PATCH DEC(__ARMCOMPILER_VERSION % 10000)
+# define COMPILER_VERSION_INTERNAL DEC(__ARMCOMPILER_VERSION)
+
+#elif defined(__clang__)
+# define COMPILER_ID "Clang"
+# if defined(_MSC_VER)
+# define SIMULATE_ID "MSVC"
+# endif
+# define COMPILER_VERSION_MAJOR DEC(__clang_major__)
+# define COMPILER_VERSION_MINOR DEC(__clang_minor__)
+# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__)
+# if defined(_MSC_VER)
+ /* _MSC_VER = VVRR */
+# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100)
+# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100)
+# endif
+
+#elif defined(__GNUC__)
+# define COMPILER_ID "GNU"
+# define COMPILER_VERSION_MAJOR DEC(__GNUC__)
+# if defined(__GNUC_MINOR__)
+# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__)
+# endif
+# if defined(__GNUC_PATCHLEVEL__)
+# define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__)
+# endif
+
+#elif defined(_MSC_VER)
+# define COMPILER_ID "MSVC"
+ /* _MSC_VER = VVRR */
+# define COMPILER_VERSION_MAJOR DEC(_MSC_VER / 100)
+# define COMPILER_VERSION_MINOR DEC(_MSC_VER % 100)
+# if defined(_MSC_FULL_VER)
+# if _MSC_VER >= 1400
+ /* _MSC_FULL_VER = VVRRPPPPP */
+# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 100000)
+# else
+ /* _MSC_FULL_VER = VVRRPPPP */
+# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 10000)
+# endif
+# endif
+# if defined(_MSC_BUILD)
+# define COMPILER_VERSION_TWEAK DEC(_MSC_BUILD)
+# endif
+
+#elif defined(__VISUALDSPVERSION__) || defined(__ADSPBLACKFIN__) || defined(__ADSPTS__) || defined(__ADSP21000__)
+# define COMPILER_ID "ADSP"
+#if defined(__VISUALDSPVERSION__)
+ /* __VISUALDSPVERSION__ = 0xVVRRPP00 */
+# define COMPILER_VERSION_MAJOR HEX(__VISUALDSPVERSION__>>24)
+# define COMPILER_VERSION_MINOR HEX(__VISUALDSPVERSION__>>16 & 0xFF)
+# define COMPILER_VERSION_PATCH HEX(__VISUALDSPVERSION__>>8 & 0xFF)
+#endif
+
+#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC)
+# define COMPILER_ID "IAR"
+# if defined(__VER__) && defined(__ICCARM__)
+# define COMPILER_VERSION_MAJOR DEC((__VER__) / 1000000)
+# define COMPILER_VERSION_MINOR DEC(((__VER__) / 1000) % 1000)
+# define COMPILER_VERSION_PATCH DEC((__VER__) % 1000)
+# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__)
+# elif defined(__VER__) && (defined(__ICCAVR__) || defined(__ICCRX__) || defined(__ICCRH850__) || defined(__ICCRL78__) || defined(__ICC430__) || defined(__ICCRISCV__) || defined(__ICCV850__) || defined(__ICC8051__))
+# define COMPILER_VERSION_MAJOR DEC((__VER__) / 100)
+# define COMPILER_VERSION_MINOR DEC((__VER__) - (((__VER__) / 100)*100))
+# define COMPILER_VERSION_PATCH DEC(__SUBVERSION__)
+# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__)
+# endif
+
+#elif defined(__SDCC_VERSION_MAJOR) || defined(SDCC)
+# define COMPILER_ID "SDCC"
+# if defined(__SDCC_VERSION_MAJOR)
+# define COMPILER_VERSION_MAJOR DEC(__SDCC_VERSION_MAJOR)
+# define COMPILER_VERSION_MINOR DEC(__SDCC_VERSION_MINOR)
+# define COMPILER_VERSION_PATCH DEC(__SDCC_VERSION_PATCH)
+# else
+ /* SDCC = VRP */
+# define COMPILER_VERSION_MAJOR DEC(SDCC/100)
+# define COMPILER_VERSION_MINOR DEC(SDCC/10 % 10)
+# define COMPILER_VERSION_PATCH DEC(SDCC % 10)
+# endif
+
+
+/* These compilers are either not known or too old to define an
+ identification macro. Try to identify the platform and guess that
+ it is the native compiler. */
+#elif defined(__hpux) || defined(__hpua)
+# define COMPILER_ID "HP"
+
+#else /* unknown compiler */
+# define COMPILER_ID ""
+#endif
+
+/* Construct the string literal in pieces to prevent the source from
+ getting matched. Store it in a pointer rather than an array
+ because some compilers will just produce instructions to fill the
+ array rather than assigning a pointer to a static array. */
+char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]";
+#ifdef SIMULATE_ID
+char const* info_simulate = "INFO" ":" "simulate[" SIMULATE_ID "]";
+#endif
+
+#ifdef __QNXNTO__
+char const* qnxnto = "INFO" ":" "qnxnto[]";
+#endif
+
+#if defined(__CRAYXE) || defined(__CRAYXC)
+char const *info_cray = "INFO" ":" "compiler_wrapper[CrayPrgEnv]";
+#endif
+
+#define STRINGIFY_HELPER(X) #X
+#define STRINGIFY(X) STRINGIFY_HELPER(X)
+
+/* Identify known platforms by name. */
+#if defined(__linux) || defined(__linux__) || defined(linux)
+# define PLATFORM_ID "Linux"
+
+#elif defined(__CYGWIN__)
+# define PLATFORM_ID "Cygwin"
+
+#elif defined(__MINGW32__)
+# define PLATFORM_ID "MinGW"
+
+#elif defined(__APPLE__)
+# define PLATFORM_ID "Darwin"
+
+#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
+# define PLATFORM_ID "Windows"
+
+#elif defined(__FreeBSD__) || defined(__FreeBSD)
+# define PLATFORM_ID "FreeBSD"
+
+#elif defined(__NetBSD__) || defined(__NetBSD)
+# define PLATFORM_ID "NetBSD"
+
+#elif defined(__OpenBSD__) || defined(__OPENBSD)
+# define PLATFORM_ID "OpenBSD"
+
+#elif defined(__sun) || defined(sun)
+# define PLATFORM_ID "SunOS"
+
+#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__)
+# define PLATFORM_ID "AIX"
+
+#elif defined(__hpux) || defined(__hpux__)
+# define PLATFORM_ID "HP-UX"
+
+#elif defined(__HAIKU__)
+# define PLATFORM_ID "Haiku"
+
+#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS)
+# define PLATFORM_ID "BeOS"
+
+#elif defined(__QNX__) || defined(__QNXNTO__)
+# define PLATFORM_ID "QNX"
+
+#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__)
+# define PLATFORM_ID "Tru64"
+
+#elif defined(__riscos) || defined(__riscos__)
+# define PLATFORM_ID "RISCos"
+
+#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__)
+# define PLATFORM_ID "SINIX"
+
+#elif defined(__UNIX_SV__)
+# define PLATFORM_ID "UNIX_SV"
+
+#elif defined(__bsdos__)
+# define PLATFORM_ID "BSDOS"
+
+#elif defined(_MPRAS) || defined(MPRAS)
+# define PLATFORM_ID "MP-RAS"
+
+#elif defined(__osf) || defined(__osf__)
+# define PLATFORM_ID "OSF1"
+
+#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv)
+# define PLATFORM_ID "SCO_SV"
+
+#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX)
+# define PLATFORM_ID "ULTRIX"
+
+#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX)
+# define PLATFORM_ID "Xenix"
+
+#elif defined(__WATCOMC__)
+# if defined(__LINUX__)
+# define PLATFORM_ID "Linux"
+
+# elif defined(__DOS__)
+# define PLATFORM_ID "DOS"
+
+# elif defined(__OS2__)
+# define PLATFORM_ID "OS2"
+
+# elif defined(__WINDOWS__)
+# define PLATFORM_ID "Windows3x"
+
+# elif defined(__VXWORKS__)
+# define PLATFORM_ID "VxWorks"
+
+# else /* unknown platform */
+# define PLATFORM_ID
+# endif
+
+#elif defined(__INTEGRITY)
+# if defined(INT_178B)
+# define PLATFORM_ID "Integrity178"
+
+# else /* regular Integrity */
+# define PLATFORM_ID "Integrity"
+# endif
+
+#else /* unknown platform */
+# define PLATFORM_ID
+
+#endif
+
+/* For windows compilers MSVC and Intel we can determine
+ the architecture of the compiler being used. This is because
+ the compilers do not have flags that can change the architecture,
+ but rather depend on which compiler is being used
+*/
+#if defined(_WIN32) && defined(_MSC_VER)
+# if defined(_M_IA64)
+# define ARCHITECTURE_ID "IA64"
+
+# elif defined(_M_X64) || defined(_M_AMD64)
+# define ARCHITECTURE_ID "x64"
+
+# elif defined(_M_IX86)
+# define ARCHITECTURE_ID "X86"
+
+# elif defined(_M_ARM64)
+# define ARCHITECTURE_ID "ARM64"
+
+# elif defined(_M_ARM)
+# if _M_ARM == 4
+# define ARCHITECTURE_ID "ARMV4I"
+# elif _M_ARM == 5
+# define ARCHITECTURE_ID "ARMV5I"
+# else
+# define ARCHITECTURE_ID "ARMV" STRINGIFY(_M_ARM)
+# endif
+
+# elif defined(_M_MIPS)
+# define ARCHITECTURE_ID "MIPS"
+
+# elif defined(_M_SH)
+# define ARCHITECTURE_ID "SHx"
+
+# else /* unknown architecture */
+# define ARCHITECTURE_ID ""
+# endif
+
+#elif defined(__WATCOMC__)
+# if defined(_M_I86)
+# define ARCHITECTURE_ID "I86"
+
+# elif defined(_M_IX86)
+# define ARCHITECTURE_ID "X86"
+
+# else /* unknown architecture */
+# define ARCHITECTURE_ID ""
+# endif
+
+#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC)
+# if defined(__ICCARM__)
+# define ARCHITECTURE_ID "ARM"
+
+# elif defined(__ICCRX__)
+# define ARCHITECTURE_ID "RX"
+
+# elif defined(__ICCRH850__)
+# define ARCHITECTURE_ID "RH850"
+
+# elif defined(__ICCRL78__)
+# define ARCHITECTURE_ID "RL78"
+
+# elif defined(__ICCRISCV__)
+# define ARCHITECTURE_ID "RISCV"
+
+# elif defined(__ICCAVR__)
+# define ARCHITECTURE_ID "AVR"
+
+# elif defined(__ICC430__)
+# define ARCHITECTURE_ID "MSP430"
+
+# elif defined(__ICCV850__)
+# define ARCHITECTURE_ID "V850"
+
+# elif defined(__ICC8051__)
+# define ARCHITECTURE_ID "8051"
+
+# else /* unknown architecture */
+# define ARCHITECTURE_ID ""
+# endif
+
+#elif defined(__ghs__)
+# if defined(__PPC64__)
+# define ARCHITECTURE_ID "PPC64"
+
+# elif defined(__ppc__)
+# define ARCHITECTURE_ID "PPC"
+
+# elif defined(__ARM__)
+# define ARCHITECTURE_ID "ARM"
+
+# elif defined(__x86_64__)
+# define ARCHITECTURE_ID "x64"
+
+# elif defined(__i386__)
+# define ARCHITECTURE_ID "X86"
+
+# else /* unknown architecture */
+# define ARCHITECTURE_ID ""
+# endif
+#else
+# define ARCHITECTURE_ID
+#endif
+
+/* Convert integer to decimal digit literals. */
+#define DEC(n) \
+ ('0' + (((n) / 10000000)%10)), \
+ ('0' + (((n) / 1000000)%10)), \
+ ('0' + (((n) / 100000)%10)), \
+ ('0' + (((n) / 10000)%10)), \
+ ('0' + (((n) / 1000)%10)), \
+ ('0' + (((n) / 100)%10)), \
+ ('0' + (((n) / 10)%10)), \
+ ('0' + ((n) % 10))
+
+/* Convert integer to hex digit literals. */
+#define HEX(n) \
+ ('0' + ((n)>>28 & 0xF)), \
+ ('0' + ((n)>>24 & 0xF)), \
+ ('0' + ((n)>>20 & 0xF)), \
+ ('0' + ((n)>>16 & 0xF)), \
+ ('0' + ((n)>>12 & 0xF)), \
+ ('0' + ((n)>>8 & 0xF)), \
+ ('0' + ((n)>>4 & 0xF)), \
+ ('0' + ((n) & 0xF))
+
+/* Construct a string literal encoding the version number components. */
+#ifdef COMPILER_VERSION_MAJOR
+char const info_version[] = {
+ 'I', 'N', 'F', 'O', ':',
+ 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[',
+ COMPILER_VERSION_MAJOR,
+# ifdef COMPILER_VERSION_MINOR
+ '.', COMPILER_VERSION_MINOR,
+# ifdef COMPILER_VERSION_PATCH
+ '.', COMPILER_VERSION_PATCH,
+# ifdef COMPILER_VERSION_TWEAK
+ '.', COMPILER_VERSION_TWEAK,
+# endif
+# endif
+# endif
+ ']','\0'};
+#endif
+
+/* Construct a string literal encoding the internal version number. */
+#ifdef COMPILER_VERSION_INTERNAL
+char const info_version_internal[] = {
+ 'I', 'N', 'F', 'O', ':',
+ 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','_',
+ 'i','n','t','e','r','n','a','l','[',
+ COMPILER_VERSION_INTERNAL,']','\0'};
+#endif
+
+/* Construct a string literal encoding the version number components. */
+#ifdef SIMULATE_VERSION_MAJOR
+char const info_simulate_version[] = {
+ 'I', 'N', 'F', 'O', ':',
+ 's','i','m','u','l','a','t','e','_','v','e','r','s','i','o','n','[',
+ SIMULATE_VERSION_MAJOR,
+# ifdef SIMULATE_VERSION_MINOR
+ '.', SIMULATE_VERSION_MINOR,
+# ifdef SIMULATE_VERSION_PATCH
+ '.', SIMULATE_VERSION_PATCH,
+# ifdef SIMULATE_VERSION_TWEAK
+ '.', SIMULATE_VERSION_TWEAK,
+# endif
+# endif
+# endif
+ ']','\0'};
+#endif
+
+/* Construct the string literal in pieces to prevent the source from
+ getting matched. Store it in a pointer rather than an array
+ because some compilers will just produce instructions to fill the
+ array rather than assigning a pointer to a static array. */
+char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]";
+char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]";
+
+
+
+
+#if !defined(__STDC__)
+# if (defined(_MSC_VER) && !defined(__clang__)) \
+ || (defined(__ibmxl__) || defined(__IBMC__))
+# define C_DIALECT "90"
+# else
+# define C_DIALECT
+# endif
+#elif __STDC_VERSION__ >= 201000L
+# define C_DIALECT "11"
+#elif __STDC_VERSION__ >= 199901L
+# define C_DIALECT "99"
+#else
+# define C_DIALECT "90"
+#endif
+const char* info_language_dialect_default =
+ "INFO" ":" "dialect_default[" C_DIALECT "]";
+
+/*--------------------------------------------------------------------------*/
+
+#ifdef ID_VOID_MAIN
+void main() {}
+#else
+# if defined(__CLASSIC_C__)
+int main(argc, argv) int argc; char *argv[];
+# else
+int main(int argc, char* argv[])
+# endif
+{
+ int require = 0;
+ require += info_compiler[argc];
+ require += info_platform[argc];
+ require += info_arch[argc];
+#ifdef COMPILER_VERSION_MAJOR
+ require += info_version[argc];
+#endif
+#ifdef COMPILER_VERSION_INTERNAL
+ require += info_version_internal[argc];
+#endif
+#ifdef SIMULATE_ID
+ require += info_simulate[argc];
+#endif
+#ifdef SIMULATE_VERSION_MAJOR
+ require += info_simulate_version[argc];
+#endif
+#if defined(__CRAYXE) || defined(__CRAYXC)
+ require += info_cray[argc];
+#endif
+ require += info_language_dialect_default[argc];
+ (void)argv;
+ return require;
+}
+#endif
diff --git a/xpdf-qt/CMakeFiles/3.18.4/CompilerIdC/a.out b/xpdf-qt/CMakeFiles/3.18.4/CompilerIdC/a.out
new file mode 100755
index 0000000..dec38b4
--- /dev/null
+++ b/xpdf-qt/CMakeFiles/3.18.4/CompilerIdC/a.out
Binary files differ
diff --git a/xpdf-qt/CMakeFiles/3.18.4/CompilerIdCXX/CMakeCXXCompilerId.cpp b/xpdf-qt/CMakeFiles/3.18.4/CompilerIdCXX/CMakeCXXCompilerId.cpp
new file mode 100644
index 0000000..37c21ca
--- /dev/null
+++ b/xpdf-qt/CMakeFiles/3.18.4/CompilerIdCXX/CMakeCXXCompilerId.cpp
@@ -0,0 +1,663 @@
+/* This source file must have a .cpp extension so that all C++ compilers
+ recognize the extension without flags. Borland does not know .cxx for
+ example. */
+#ifndef __cplusplus
+# error "A C compiler has been selected for C++."
+#endif
+
+
+/* Version number components: V=Version, R=Revision, P=Patch
+ Version date components: YYYY=Year, MM=Month, DD=Day */
+
+#if defined(__COMO__)
+# define COMPILER_ID "Comeau"
+ /* __COMO_VERSION__ = VRR */
+# define COMPILER_VERSION_MAJOR DEC(__COMO_VERSION__ / 100)
+# define COMPILER_VERSION_MINOR DEC(__COMO_VERSION__ % 100)
+
+#elif defined(__INTEL_COMPILER) || defined(__ICC)
+# define COMPILER_ID "Intel"
+# if defined(_MSC_VER)
+# define SIMULATE_ID "MSVC"
+# endif
+# if defined(__GNUC__)
+# define SIMULATE_ID "GNU"
+# endif
+ /* __INTEL_COMPILER = VRP */
+# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER/100)
+# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER/10 % 10)
+# if defined(__INTEL_COMPILER_UPDATE)
+# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER_UPDATE)
+# else
+# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER % 10)
+# endif
+# if defined(__INTEL_COMPILER_BUILD_DATE)
+ /* __INTEL_COMPILER_BUILD_DATE = YYYYMMDD */
+# define COMPILER_VERSION_TWEAK DEC(__INTEL_COMPILER_BUILD_DATE)
+# endif
+# if defined(_MSC_VER)
+ /* _MSC_VER = VVRR */
+# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100)
+# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100)
+# endif
+# if defined(__GNUC__)
+# define SIMULATE_VERSION_MAJOR DEC(__GNUC__)
+# elif defined(__GNUG__)
+# define SIMULATE_VERSION_MAJOR DEC(__GNUG__)
+# endif
+# if defined(__GNUC_MINOR__)
+# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__)
+# endif
+# if defined(__GNUC_PATCHLEVEL__)
+# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__)
+# endif
+
+#elif defined(__PATHCC__)
+# define COMPILER_ID "PathScale"
+# define COMPILER_VERSION_MAJOR DEC(__PATHCC__)
+# define COMPILER_VERSION_MINOR DEC(__PATHCC_MINOR__)
+# if defined(__PATHCC_PATCHLEVEL__)
+# define COMPILER_VERSION_PATCH DEC(__PATHCC_PATCHLEVEL__)
+# endif
+
+#elif defined(__BORLANDC__) && defined(__CODEGEARC_VERSION__)
+# define COMPILER_ID "Embarcadero"
+# define COMPILER_VERSION_MAJOR HEX(__CODEGEARC_VERSION__>>24 & 0x00FF)
+# define COMPILER_VERSION_MINOR HEX(__CODEGEARC_VERSION__>>16 & 0x00FF)
+# define COMPILER_VERSION_PATCH DEC(__CODEGEARC_VERSION__ & 0xFFFF)
+
+#elif defined(__BORLANDC__)
+# define COMPILER_ID "Borland"
+ /* __BORLANDC__ = 0xVRR */
+# define COMPILER_VERSION_MAJOR HEX(__BORLANDC__>>8)
+# define COMPILER_VERSION_MINOR HEX(__BORLANDC__ & 0xFF)
+
+#elif defined(__WATCOMC__) && __WATCOMC__ < 1200
+# define COMPILER_ID "Watcom"
+ /* __WATCOMC__ = VVRR */
+# define COMPILER_VERSION_MAJOR DEC(__WATCOMC__ / 100)
+# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10)
+# if (__WATCOMC__ % 10) > 0
+# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10)
+# endif
+
+#elif defined(__WATCOMC__)
+# define COMPILER_ID "OpenWatcom"
+ /* __WATCOMC__ = VVRP + 1100 */
+# define COMPILER_VERSION_MAJOR DEC((__WATCOMC__ - 1100) / 100)
+# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10)
+# if (__WATCOMC__ % 10) > 0
+# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10)
+# endif
+
+#elif defined(__SUNPRO_CC)
+# define COMPILER_ID "SunPro"
+# if __SUNPRO_CC >= 0x5100
+ /* __SUNPRO_CC = 0xVRRP */
+# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_CC>>12)
+# define COMPILER_VERSION_MINOR HEX(__SUNPRO_CC>>4 & 0xFF)
+# define COMPILER_VERSION_PATCH HEX(__SUNPRO_CC & 0xF)
+# else
+ /* __SUNPRO_CC = 0xVRP */
+# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_CC>>8)
+# define COMPILER_VERSION_MINOR HEX(__SUNPRO_CC>>4 & 0xF)
+# define COMPILER_VERSION_PATCH HEX(__SUNPRO_CC & 0xF)
+# endif
+
+#elif defined(__HP_aCC)
+# define COMPILER_ID "HP"
+ /* __HP_aCC = VVRRPP */
+# define COMPILER_VERSION_MAJOR DEC(__HP_aCC/10000)
+# define COMPILER_VERSION_MINOR DEC(__HP_aCC/100 % 100)
+# define COMPILER_VERSION_PATCH DEC(__HP_aCC % 100)
+
+#elif defined(__DECCXX)
+# define COMPILER_ID "Compaq"
+ /* __DECCXX_VER = VVRRTPPPP */
+# define COMPILER_VERSION_MAJOR DEC(__DECCXX_VER/10000000)
+# define COMPILER_VERSION_MINOR DEC(__DECCXX_VER/100000 % 100)
+# define COMPILER_VERSION_PATCH DEC(__DECCXX_VER % 10000)
+
+#elif defined(__IBMCPP__) && defined(__COMPILER_VER__)
+# define COMPILER_ID "zOS"
+ /* __IBMCPP__ = VRP */
+# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100)
+# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10)
+# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10)
+
+#elif defined(__ibmxl__) && defined(__clang__)
+# define COMPILER_ID "XLClang"
+# define COMPILER_VERSION_MAJOR DEC(__ibmxl_version__)
+# define COMPILER_VERSION_MINOR DEC(__ibmxl_release__)
+# define COMPILER_VERSION_PATCH DEC(__ibmxl_modification__)
+# define COMPILER_VERSION_TWEAK DEC(__ibmxl_ptf_fix_level__)
+
+
+#elif defined(__IBMCPP__) && !defined(__COMPILER_VER__) && __IBMCPP__ >= 800
+# define COMPILER_ID "XL"
+ /* __IBMCPP__ = VRP */
+# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100)
+# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10)
+# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10)
+
+#elif defined(__IBMCPP__) && !defined(__COMPILER_VER__) && __IBMCPP__ < 800
+# define COMPILER_ID "VisualAge"
+ /* __IBMCPP__ = VRP */
+# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100)
+# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10)
+# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10)
+
+#elif defined(__PGI)
+# define COMPILER_ID "PGI"
+# define COMPILER_VERSION_MAJOR DEC(__PGIC__)
+# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__)
+# if defined(__PGIC_PATCHLEVEL__)
+# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__)
+# endif
+
+#elif defined(_CRAYC)
+# define COMPILER_ID "Cray"
+# define COMPILER_VERSION_MAJOR DEC(_RELEASE_MAJOR)
+# define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR)
+
+#elif defined(__TI_COMPILER_VERSION__)
+# define COMPILER_ID "TI"
+ /* __TI_COMPILER_VERSION__ = VVVRRRPPP */
+# define COMPILER_VERSION_MAJOR DEC(__TI_COMPILER_VERSION__/1000000)
+# define COMPILER_VERSION_MINOR DEC(__TI_COMPILER_VERSION__/1000 % 1000)
+# define COMPILER_VERSION_PATCH DEC(__TI_COMPILER_VERSION__ % 1000)
+
+#elif defined(__FUJITSU) || defined(__FCC_VERSION) || defined(__fcc_version)
+# define COMPILER_ID "Fujitsu"
+
+#elif defined(__ghs__)
+# define COMPILER_ID "GHS"
+/* __GHS_VERSION_NUMBER = VVVVRP */
+# ifdef __GHS_VERSION_NUMBER
+# define COMPILER_VERSION_MAJOR DEC(__GHS_VERSION_NUMBER / 100)
+# define COMPILER_VERSION_MINOR DEC(__GHS_VERSION_NUMBER / 10 % 10)
+# define COMPILER_VERSION_PATCH DEC(__GHS_VERSION_NUMBER % 10)
+# endif
+
+#elif defined(__SCO_VERSION__)
+# define COMPILER_ID "SCO"
+
+#elif defined(__ARMCC_VERSION) && !defined(__clang__)
+# define COMPILER_ID "ARMCC"
+#if __ARMCC_VERSION >= 1000000
+ /* __ARMCC_VERSION = VRRPPPP */
+ # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/1000000)
+ # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 100)
+ # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000)
+#else
+ /* __ARMCC_VERSION = VRPPPP */
+ # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/100000)
+ # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 10)
+ # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000)
+#endif
+
+
+#elif defined(__clang__) && defined(__apple_build_version__)
+# define COMPILER_ID "AppleClang"
+# if defined(_MSC_VER)
+# define SIMULATE_ID "MSVC"
+# endif
+# define COMPILER_VERSION_MAJOR DEC(__clang_major__)
+# define COMPILER_VERSION_MINOR DEC(__clang_minor__)
+# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__)
+# if defined(_MSC_VER)
+ /* _MSC_VER = VVRR */
+# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100)
+# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100)
+# endif
+# define COMPILER_VERSION_TWEAK DEC(__apple_build_version__)
+
+#elif defined(__clang__) && defined(__ARMCOMPILER_VERSION)
+# define COMPILER_ID "ARMClang"
+ # define COMPILER_VERSION_MAJOR DEC(__ARMCOMPILER_VERSION/1000000)
+ # define COMPILER_VERSION_MINOR DEC(__ARMCOMPILER_VERSION/10000 % 100)
+ # define COMPILER_VERSION_PATCH DEC(__ARMCOMPILER_VERSION % 10000)
+# define COMPILER_VERSION_INTERNAL DEC(__ARMCOMPILER_VERSION)
+
+#elif defined(__clang__)
+# define COMPILER_ID "Clang"
+# if defined(_MSC_VER)
+# define SIMULATE_ID "MSVC"
+# endif
+# define COMPILER_VERSION_MAJOR DEC(__clang_major__)
+# define COMPILER_VERSION_MINOR DEC(__clang_minor__)
+# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__)
+# if defined(_MSC_VER)
+ /* _MSC_VER = VVRR */
+# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100)
+# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100)
+# endif
+
+#elif defined(__GNUC__) || defined(__GNUG__)
+# define COMPILER_ID "GNU"
+# if defined(__GNUC__)
+# define COMPILER_VERSION_MAJOR DEC(__GNUC__)
+# else
+# define COMPILER_VERSION_MAJOR DEC(__GNUG__)
+# endif
+# if defined(__GNUC_MINOR__)
+# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__)
+# endif
+# if defined(__GNUC_PATCHLEVEL__)
+# define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__)
+# endif
+
+#elif defined(_MSC_VER)
+# define COMPILER_ID "MSVC"
+ /* _MSC_VER = VVRR */
+# define COMPILER_VERSION_MAJOR DEC(_MSC_VER / 100)
+# define COMPILER_VERSION_MINOR DEC(_MSC_VER % 100)
+# if defined(_MSC_FULL_VER)
+# if _MSC_VER >= 1400
+ /* _MSC_FULL_VER = VVRRPPPPP */
+# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 100000)
+# else
+ /* _MSC_FULL_VER = VVRRPPPP */
+# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 10000)
+# endif
+# endif
+# if defined(_MSC_BUILD)
+# define COMPILER_VERSION_TWEAK DEC(_MSC_BUILD)
+# endif
+
+#elif defined(__VISUALDSPVERSION__) || defined(__ADSPBLACKFIN__) || defined(__ADSPTS__) || defined(__ADSP21000__)
+# define COMPILER_ID "ADSP"
+#if defined(__VISUALDSPVERSION__)
+ /* __VISUALDSPVERSION__ = 0xVVRRPP00 */
+# define COMPILER_VERSION_MAJOR HEX(__VISUALDSPVERSION__>>24)
+# define COMPILER_VERSION_MINOR HEX(__VISUALDSPVERSION__>>16 & 0xFF)
+# define COMPILER_VERSION_PATCH HEX(__VISUALDSPVERSION__>>8 & 0xFF)
+#endif
+
+#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC)
+# define COMPILER_ID "IAR"
+# if defined(__VER__) && defined(__ICCARM__)
+# define COMPILER_VERSION_MAJOR DEC((__VER__) / 1000000)
+# define COMPILER_VERSION_MINOR DEC(((__VER__) / 1000) % 1000)
+# define COMPILER_VERSION_PATCH DEC((__VER__) % 1000)
+# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__)
+# elif defined(__VER__) && (defined(__ICCAVR__) || defined(__ICCRX__) || defined(__ICCRH850__) || defined(__ICCRL78__) || defined(__ICC430__) || defined(__ICCRISCV__) || defined(__ICCV850__) || defined(__ICC8051__))
+# define COMPILER_VERSION_MAJOR DEC((__VER__) / 100)
+# define COMPILER_VERSION_MINOR DEC((__VER__) - (((__VER__) / 100)*100))
+# define COMPILER_VERSION_PATCH DEC(__SUBVERSION__)
+# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__)
+# endif
+
+
+/* These compilers are either not known or too old to define an
+ identification macro. Try to identify the platform and guess that
+ it is the native compiler. */
+#elif defined(__hpux) || defined(__hpua)
+# define COMPILER_ID "HP"
+
+#else /* unknown compiler */
+# define COMPILER_ID ""
+#endif
+
+/* Construct the string literal in pieces to prevent the source from
+ getting matched. Store it in a pointer rather than an array
+ because some compilers will just produce instructions to fill the
+ array rather than assigning a pointer to a static array. */
+char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]";
+#ifdef SIMULATE_ID
+char const* info_simulate = "INFO" ":" "simulate[" SIMULATE_ID "]";
+#endif
+
+#ifdef __QNXNTO__
+char const* qnxnto = "INFO" ":" "qnxnto[]";
+#endif
+
+#if defined(__CRAYXE) || defined(__CRAYXC)
+char const *info_cray = "INFO" ":" "compiler_wrapper[CrayPrgEnv]";
+#endif
+
+#define STRINGIFY_HELPER(X) #X
+#define STRINGIFY(X) STRINGIFY_HELPER(X)
+
+/* Identify known platforms by name. */
+#if defined(__linux) || defined(__linux__) || defined(linux)
+# define PLATFORM_ID "Linux"
+
+#elif defined(__CYGWIN__)
+# define PLATFORM_ID "Cygwin"
+
+#elif defined(__MINGW32__)
+# define PLATFORM_ID "MinGW"
+
+#elif defined(__APPLE__)
+# define PLATFORM_ID "Darwin"
+
+#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
+# define PLATFORM_ID "Windows"
+
+#elif defined(__FreeBSD__) || defined(__FreeBSD)
+# define PLATFORM_ID "FreeBSD"
+
+#elif defined(__NetBSD__) || defined(__NetBSD)
+# define PLATFORM_ID "NetBSD"
+
+#elif defined(__OpenBSD__) || defined(__OPENBSD)
+# define PLATFORM_ID "OpenBSD"
+
+#elif defined(__sun) || defined(sun)
+# define PLATFORM_ID "SunOS"
+
+#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__)
+# define PLATFORM_ID "AIX"
+
+#elif defined(__hpux) || defined(__hpux__)
+# define PLATFORM_ID "HP-UX"
+
+#elif defined(__HAIKU__)
+# define PLATFORM_ID "Haiku"
+
+#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS)
+# define PLATFORM_ID "BeOS"
+
+#elif defined(__QNX__) || defined(__QNXNTO__)
+# define PLATFORM_ID "QNX"
+
+#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__)
+# define PLATFORM_ID "Tru64"
+
+#elif defined(__riscos) || defined(__riscos__)
+# define PLATFORM_ID "RISCos"
+
+#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__)
+# define PLATFORM_ID "SINIX"
+
+#elif defined(__UNIX_SV__)
+# define PLATFORM_ID "UNIX_SV"
+
+#elif defined(__bsdos__)
+# define PLATFORM_ID "BSDOS"
+
+#elif defined(_MPRAS) || defined(MPRAS)
+# define PLATFORM_ID "MP-RAS"
+
+#elif defined(__osf) || defined(__osf__)
+# define PLATFORM_ID "OSF1"
+
+#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv)
+# define PLATFORM_ID "SCO_SV"
+
+#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX)
+# define PLATFORM_ID "ULTRIX"
+
+#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX)
+# define PLATFORM_ID "Xenix"
+
+#elif defined(__WATCOMC__)
+# if defined(__LINUX__)
+# define PLATFORM_ID "Linux"
+
+# elif defined(__DOS__)
+# define PLATFORM_ID "DOS"
+
+# elif defined(__OS2__)
+# define PLATFORM_ID "OS2"
+
+# elif defined(__WINDOWS__)
+# define PLATFORM_ID "Windows3x"
+
+# elif defined(__VXWORKS__)
+# define PLATFORM_ID "VxWorks"
+
+# else /* unknown platform */
+# define PLATFORM_ID
+# endif
+
+#elif defined(__INTEGRITY)
+# if defined(INT_178B)
+# define PLATFORM_ID "Integrity178"
+
+# else /* regular Integrity */
+# define PLATFORM_ID "Integrity"
+# endif
+
+#else /* unknown platform */
+# define PLATFORM_ID
+
+#endif
+
+/* For windows compilers MSVC and Intel we can determine
+ the architecture of the compiler being used. This is because
+ the compilers do not have flags that can change the architecture,
+ but rather depend on which compiler is being used
+*/
+#if defined(_WIN32) && defined(_MSC_VER)
+# if defined(_M_IA64)
+# define ARCHITECTURE_ID "IA64"
+
+# elif defined(_M_X64) || defined(_M_AMD64)
+# define ARCHITECTURE_ID "x64"
+
+# elif defined(_M_IX86)
+# define ARCHITECTURE_ID "X86"
+
+# elif defined(_M_ARM64)
+# define ARCHITECTURE_ID "ARM64"
+
+# elif defined(_M_ARM)
+# if _M_ARM == 4
+# define ARCHITECTURE_ID "ARMV4I"
+# elif _M_ARM == 5
+# define ARCHITECTURE_ID "ARMV5I"
+# else
+# define ARCHITECTURE_ID "ARMV" STRINGIFY(_M_ARM)
+# endif
+
+# elif defined(_M_MIPS)
+# define ARCHITECTURE_ID "MIPS"
+
+# elif defined(_M_SH)
+# define ARCHITECTURE_ID "SHx"
+
+# else /* unknown architecture */
+# define ARCHITECTURE_ID ""
+# endif
+
+#elif defined(__WATCOMC__)
+# if defined(_M_I86)
+# define ARCHITECTURE_ID "I86"
+
+# elif defined(_M_IX86)
+# define ARCHITECTURE_ID "X86"
+
+# else /* unknown architecture */
+# define ARCHITECTURE_ID ""
+# endif
+
+#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC)
+# if defined(__ICCARM__)
+# define ARCHITECTURE_ID "ARM"
+
+# elif defined(__ICCRX__)
+# define ARCHITECTURE_ID "RX"
+
+# elif defined(__ICCRH850__)
+# define ARCHITECTURE_ID "RH850"
+
+# elif defined(__ICCRL78__)
+# define ARCHITECTURE_ID "RL78"
+
+# elif defined(__ICCRISCV__)
+# define ARCHITECTURE_ID "RISCV"
+
+# elif defined(__ICCAVR__)
+# define ARCHITECTURE_ID "AVR"
+
+# elif defined(__ICC430__)
+# define ARCHITECTURE_ID "MSP430"
+
+# elif defined(__ICCV850__)
+# define ARCHITECTURE_ID "V850"
+
+# elif defined(__ICC8051__)
+# define ARCHITECTURE_ID "8051"
+
+# else /* unknown architecture */
+# define ARCHITECTURE_ID ""
+# endif
+
+#elif defined(__ghs__)
+# if defined(__PPC64__)
+# define ARCHITECTURE_ID "PPC64"
+
+# elif defined(__ppc__)
+# define ARCHITECTURE_ID "PPC"
+
+# elif defined(__ARM__)
+# define ARCHITECTURE_ID "ARM"
+
+# elif defined(__x86_64__)
+# define ARCHITECTURE_ID "x64"
+
+# elif defined(__i386__)
+# define ARCHITECTURE_ID "X86"
+
+# else /* unknown architecture */
+# define ARCHITECTURE_ID ""
+# endif
+#else
+# define ARCHITECTURE_ID
+#endif
+
+/* Convert integer to decimal digit literals. */
+#define DEC(n) \
+ ('0' + (((n) / 10000000)%10)), \
+ ('0' + (((n) / 1000000)%10)), \
+ ('0' + (((n) / 100000)%10)), \
+ ('0' + (((n) / 10000)%10)), \
+ ('0' + (((n) / 1000)%10)), \
+ ('0' + (((n) / 100)%10)), \
+ ('0' + (((n) / 10)%10)), \
+ ('0' + ((n) % 10))
+
+/* Convert integer to hex digit literals. */
+#define HEX(n) \
+ ('0' + ((n)>>28 & 0xF)), \
+ ('0' + ((n)>>24 & 0xF)), \
+ ('0' + ((n)>>20 & 0xF)), \
+ ('0' + ((n)>>16 & 0xF)), \
+ ('0' + ((n)>>12 & 0xF)), \
+ ('0' + ((n)>>8 & 0xF)), \
+ ('0' + ((n)>>4 & 0xF)), \
+ ('0' + ((n) & 0xF))
+
+/* Construct a string literal encoding the version number components. */
+#ifdef COMPILER_VERSION_MAJOR
+char const info_version[] = {
+ 'I', 'N', 'F', 'O', ':',
+ 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[',
+ COMPILER_VERSION_MAJOR,
+# ifdef COMPILER_VERSION_MINOR
+ '.', COMPILER_VERSION_MINOR,
+# ifdef COMPILER_VERSION_PATCH
+ '.', COMPILER_VERSION_PATCH,
+# ifdef COMPILER_VERSION_TWEAK
+ '.', COMPILER_VERSION_TWEAK,
+# endif
+# endif
+# endif
+ ']','\0'};
+#endif
+
+/* Construct a string literal encoding the internal version number. */
+#ifdef COMPILER_VERSION_INTERNAL
+char const info_version_internal[] = {
+ 'I', 'N', 'F', 'O', ':',
+ 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','_',
+ 'i','n','t','e','r','n','a','l','[',
+ COMPILER_VERSION_INTERNAL,']','\0'};
+#endif
+
+/* Construct a string literal encoding the version number components. */
+#ifdef SIMULATE_VERSION_MAJOR
+char const info_simulate_version[] = {
+ 'I', 'N', 'F', 'O', ':',
+ 's','i','m','u','l','a','t','e','_','v','e','r','s','i','o','n','[',
+ SIMULATE_VERSION_MAJOR,
+# ifdef SIMULATE_VERSION_MINOR
+ '.', SIMULATE_VERSION_MINOR,
+# ifdef SIMULATE_VERSION_PATCH
+ '.', SIMULATE_VERSION_PATCH,
+# ifdef SIMULATE_VERSION_TWEAK
+ '.', SIMULATE_VERSION_TWEAK,
+# endif
+# endif
+# endif
+ ']','\0'};
+#endif
+
+/* Construct the string literal in pieces to prevent the source from
+ getting matched. Store it in a pointer rather than an array
+ because some compilers will just produce instructions to fill the
+ array rather than assigning a pointer to a static array. */
+char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]";
+char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]";
+
+
+
+
+#if defined(__INTEL_COMPILER) && defined(_MSVC_LANG) && _MSVC_LANG < 201403L
+# if defined(__INTEL_CXX11_MODE__)
+# if defined(__cpp_aggregate_nsdmi)
+# define CXX_STD 201402L
+# else
+# define CXX_STD 201103L
+# endif
+# else
+# define CXX_STD 199711L
+# endif
+#elif defined(_MSC_VER) && defined(_MSVC_LANG)
+# define CXX_STD _MSVC_LANG
+#else
+# define CXX_STD __cplusplus
+#endif
+
+const char* info_language_dialect_default = "INFO" ":" "dialect_default["
+#if CXX_STD > 201703L
+ "20"
+#elif CXX_STD >= 201703L
+ "17"
+#elif CXX_STD >= 201402L
+ "14"
+#elif CXX_STD >= 201103L
+ "11"
+#else
+ "98"
+#endif
+"]";
+
+/*--------------------------------------------------------------------------*/
+
+int main(int argc, char* argv[])
+{
+ int require = 0;
+ require += info_compiler[argc];
+ require += info_platform[argc];
+#ifdef COMPILER_VERSION_MAJOR
+ require += info_version[argc];
+#endif
+#ifdef COMPILER_VERSION_INTERNAL
+ require += info_version_internal[argc];
+#endif
+#ifdef SIMULATE_ID
+ require += info_simulate[argc];
+#endif
+#ifdef SIMULATE_VERSION_MAJOR
+ require += info_simulate_version[argc];
+#endif
+#if defined(__CRAYXE) || defined(__CRAYXC)
+ require += info_cray[argc];
+#endif
+ require += info_language_dialect_default[argc];
+ (void)argv;
+ return require;
+}
diff --git a/xpdf-qt/CMakeFiles/3.18.4/CompilerIdCXX/a.out b/xpdf-qt/CMakeFiles/3.18.4/CompilerIdCXX/a.out
new file mode 100755
index 0000000..5bf5fac
--- /dev/null
+++ b/xpdf-qt/CMakeFiles/3.18.4/CompilerIdCXX/a.out
Binary files differ
diff --git a/xpdf-qt/CMakeFiles/CMakeDirectoryInformation.cmake b/xpdf-qt/CMakeFiles/CMakeDirectoryInformation.cmake
new file mode 100644
index 0000000..aef4d6c
--- /dev/null
+++ b/xpdf-qt/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-qt/CMakeFiles/CMakeOutput.log b/xpdf-qt/CMakeFiles/CMakeOutput.log
new file mode 100644
index 0000000..de9cb8d
--- /dev/null
+++ b/xpdf-qt/CMakeFiles/CMakeOutput.log
@@ -0,0 +1,439 @@
+The system is: Linux - 5.10.0-12-amd64 - x86_64
+Compiling the C compiler identification source file "CMakeCCompilerId.c" succeeded.
+Compiler: /usr/bin/cc
+Build flags:
+Id flags:
+
+The output was:
+0
+
+
+Compilation of the C compiler identification source "CMakeCCompilerId.c" produced "a.out"
+
+The C compiler identification is GNU, found in "/home/calvin/src/xpdf-4.04/xpdf-qt/CMakeFiles/3.18.4/CompilerIdC/a.out"
+
+Compiling the CXX compiler identification source file "CMakeCXXCompilerId.cpp" succeeded.
+Compiler: /usr/bin/c++
+Build flags:
+Id flags:
+
+The output was:
+0
+
+
+Compilation of the CXX compiler identification source "CMakeCXXCompilerId.cpp" produced "a.out"
+
+The CXX compiler identification is GNU, found in "/home/calvin/src/xpdf-4.04/xpdf-qt/CMakeFiles/3.18.4/CompilerIdCXX/a.out"
+
+Detecting C compiler ABI info compiled with the following output:
+Change Dir: /home/calvin/src/xpdf-4.04/xpdf-qt/CMakeFiles/CMakeTmp
+
+Run Build Command(s):/usr/bin/gmake cmTC_63b3f/fast && /usr/bin/gmake -f CMakeFiles/cmTC_63b3f.dir/build.make CMakeFiles/cmTC_63b3f.dir/build
+gmake[1]: Entering directory '/home/calvin/src/xpdf-4.04/xpdf-qt/CMakeFiles/CMakeTmp'
+Building C object CMakeFiles/cmTC_63b3f.dir/CMakeCCompilerABI.c.o
+/usr/bin/cc -v -o CMakeFiles/cmTC_63b3f.dir/CMakeCCompilerABI.c.o -c /usr/share/cmake-3.18/Modules/CMakeCCompilerABI.c
+Using built-in specs.
+COLLECT_GCC=/usr/bin/cc
+OFFLOAD_TARGET_NAMES=nvptx-none:amdgcn-amdhsa:hsa
+OFFLOAD_TARGET_DEFAULT=1
+Target: x86_64-linux-gnu
+Configured with: ../src/configure -v --with-pkgversion='Debian 10.2.1-6' --with-bugurl=file:///usr/share/doc/gcc-10/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++,m2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-10 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --enable-libphobos-checking=release --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-10-Km9U7s/gcc-10-10.2.1/debian/tmp-nvptx/usr,amdgcn-amdhsa=/build/gcc-10-Km9U7s/gcc-10-10.2.1/debian/tmp-gcn/usr,hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu --with-build-config=bootstrap-lto-lean --enable-link-mutex
+Thread model: posix
+Supported LTO compression algorithms: zlib zstd
+gcc version 10.2.1 20210110 (Debian 10.2.1-6)
+COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_63b3f.dir/CMakeCCompilerABI.c.o' '-c' '-mtune=generic' '-march=x86-64'
+ /usr/lib/gcc/x86_64-linux-gnu/10/cc1 -quiet -v -imultiarch x86_64-linux-gnu /usr/share/cmake-3.18/Modules/CMakeCCompilerABI.c -quiet -dumpbase CMakeCCompilerABI.c -mtune=generic -march=x86-64 -auxbase-strip CMakeFiles/cmTC_63b3f.dir/CMakeCCompilerABI.c.o -version -fasynchronous-unwind-tables -o /tmp/ccjR73dl.s
+GNU C17 (Debian 10.2.1-6) version 10.2.1 20210110 (x86_64-linux-gnu)
+ compiled by GNU C version 10.2.1 20210110, GMP version 6.2.1, MPFR version 4.1.0, MPC version 1.2.0, isl version isl-0.23-GMP
+
+GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
+ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu"
+ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/10/include-fixed"
+ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/10/../../../../x86_64-linux-gnu/include"
+#include "..." search starts here:
+#include <...> search starts here:
+ /usr/lib/gcc/x86_64-linux-gnu/10/include
+ /usr/local/include
+ /usr/include/x86_64-linux-gnu
+ /usr/include
+End of search list.
+GNU C17 (Debian 10.2.1-6) version 10.2.1 20210110 (x86_64-linux-gnu)
+ compiled by GNU C version 10.2.1 20210110, GMP version 6.2.1, MPFR version 4.1.0, MPC version 1.2.0, isl version isl-0.23-GMP
+
+GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
+Compiler executable checksum: 1f803793fa2e3418c492b25e7d3eac2f
+COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_63b3f.dir/CMakeCCompilerABI.c.o' '-c' '-mtune=generic' '-march=x86-64'
+ as -v --64 -o CMakeFiles/cmTC_63b3f.dir/CMakeCCompilerABI.c.o /tmp/ccjR73dl.s
+GNU assembler version 2.35.2 (x86_64-linux-gnu) using BFD version (GNU Binutils for Debian) 2.35.2
+COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/
+LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../:/lib/:/usr/lib/
+COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_63b3f.dir/CMakeCCompilerABI.c.o' '-c' '-mtune=generic' '-march=x86-64'
+Linking C executable cmTC_63b3f
+/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTC_63b3f.dir/link.txt --verbose=1
+/usr/bin/cc -v -rdynamic CMakeFiles/cmTC_63b3f.dir/CMakeCCompilerABI.c.o -o cmTC_63b3f
+Using built-in specs.
+COLLECT_GCC=/usr/bin/cc
+COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/10/lto-wrapper
+OFFLOAD_TARGET_NAMES=nvptx-none:amdgcn-amdhsa:hsa
+OFFLOAD_TARGET_DEFAULT=1
+Target: x86_64-linux-gnu
+Configured with: ../src/configure -v --with-pkgversion='Debian 10.2.1-6' --with-bugurl=file:///usr/share/doc/gcc-10/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++,m2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-10 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --enable-libphobos-checking=release --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-10-Km9U7s/gcc-10-10.2.1/debian/tmp-nvptx/usr,amdgcn-amdhsa=/build/gcc-10-Km9U7s/gcc-10-10.2.1/debian/tmp-gcn/usr,hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu --with-build-config=bootstrap-lto-lean --enable-link-mutex
+Thread model: posix
+Supported LTO compression algorithms: zlib zstd
+gcc version 10.2.1 20210110 (Debian 10.2.1-6)
+COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/
+LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../:/lib/:/usr/lib/
+COLLECT_GCC_OPTIONS='-v' '-rdynamic' '-o' 'cmTC_63b3f' '-mtune=generic' '-march=x86-64'
+ /usr/lib/gcc/x86_64-linux-gnu/10/collect2 -plugin /usr/lib/gcc/x86_64-linux-gnu/10/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/10/lto-wrapper -plugin-opt=-fresolution=/tmp/cckryhrJ.res -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed -export-dynamic -dynamic-linker /lib64/ld-linux-x86-64.so.2 -pie -o cmTC_63b3f /usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/Scrt1.o /usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/10/crtbeginS.o -L/usr/lib/gcc/x86_64-linux-gnu/10 -L/usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/10/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/10/../../.. CMakeFiles/cmTC_63b3f.dir/CMakeCCompilerABI.c.o -lgcc --push-state --as-needed -lgcc_s --pop-state -lc -lgcc --push-state --as-needed -lgcc_s --pop-state /usr/lib/gcc/x86_64-linux-gnu/10/crtendS.o /usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/crtn.o
+COLLECT_GCC_OPTIONS='-v' '-rdynamic' '-o' 'cmTC_63b3f' '-mtune=generic' '-march=x86-64'
+gmake[1]: Leaving directory '/home/calvin/src/xpdf-4.04/xpdf-qt/CMakeFiles/CMakeTmp'
+
+
+
+Parsed C implicit include dir info from above output: rv=done
+ found start of include info
+ found start of implicit include info
+ add: [/usr/lib/gcc/x86_64-linux-gnu/10/include]
+ add: [/usr/local/include]
+ add: [/usr/include/x86_64-linux-gnu]
+ add: [/usr/include]
+ end of search list found
+ collapse include dir [/usr/lib/gcc/x86_64-linux-gnu/10/include] ==> [/usr/lib/gcc/x86_64-linux-gnu/10/include]
+ collapse include dir [/usr/local/include] ==> [/usr/local/include]
+ collapse include dir [/usr/include/x86_64-linux-gnu] ==> [/usr/include/x86_64-linux-gnu]
+ collapse include dir [/usr/include] ==> [/usr/include]
+ implicit include dirs: [/usr/lib/gcc/x86_64-linux-gnu/10/include;/usr/local/include;/usr/include/x86_64-linux-gnu;/usr/include]
+
+
+Parsed C implicit link information from above output:
+ link line regex: [^( *|.*[/\])(ld|CMAKE_LINK_STARTFILE-NOTFOUND|([^/\]+-)?ld|collect2)[^/\]*( |$)]
+ ignore line: [Change Dir: /home/calvin/src/xpdf-4.04/xpdf-qt/CMakeFiles/CMakeTmp]
+ ignore line: []
+ ignore line: [Run Build Command(s):/usr/bin/gmake cmTC_63b3f/fast && /usr/bin/gmake -f CMakeFiles/cmTC_63b3f.dir/build.make CMakeFiles/cmTC_63b3f.dir/build]
+ ignore line: [gmake[1]: Entering directory '/home/calvin/src/xpdf-4.04/xpdf-qt/CMakeFiles/CMakeTmp']
+ ignore line: [Building C object CMakeFiles/cmTC_63b3f.dir/CMakeCCompilerABI.c.o]
+ ignore line: [/usr/bin/cc -v -o CMakeFiles/cmTC_63b3f.dir/CMakeCCompilerABI.c.o -c /usr/share/cmake-3.18/Modules/CMakeCCompilerABI.c]
+ ignore line: [Using built-in specs.]
+ ignore line: [COLLECT_GCC=/usr/bin/cc]
+ ignore line: [OFFLOAD_TARGET_NAMES=nvptx-none:amdgcn-amdhsa:hsa]
+ ignore line: [OFFLOAD_TARGET_DEFAULT=1]
+ ignore line: [Target: x86_64-linux-gnu]
+ ignore line: [Configured with: ../src/configure -v --with-pkgversion='Debian 10.2.1-6' --with-bugurl=file:///usr/share/doc/gcc-10/README.Bugs --enable-languages=c ada c++ go brig d fortran objc obj-c++ m2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-10 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --enable-libphobos-checking=release --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32 m64 mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-10-Km9U7s/gcc-10-10.2.1/debian/tmp-nvptx/usr amdgcn-amdhsa=/build/gcc-10-Km9U7s/gcc-10-10.2.1/debian/tmp-gcn/usr hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu --with-build-config=bootstrap-lto-lean --enable-link-mutex]
+ ignore line: [Thread model: posix]
+ ignore line: [Supported LTO compression algorithms: zlib zstd]
+ ignore line: [gcc version 10.2.1 20210110 (Debian 10.2.1-6) ]
+ ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_63b3f.dir/CMakeCCompilerABI.c.o' '-c' '-mtune=generic' '-march=x86-64']
+ ignore line: [ /usr/lib/gcc/x86_64-linux-gnu/10/cc1 -quiet -v -imultiarch x86_64-linux-gnu /usr/share/cmake-3.18/Modules/CMakeCCompilerABI.c -quiet -dumpbase CMakeCCompilerABI.c -mtune=generic -march=x86-64 -auxbase-strip CMakeFiles/cmTC_63b3f.dir/CMakeCCompilerABI.c.o -version -fasynchronous-unwind-tables -o /tmp/ccjR73dl.s]
+ ignore line: [GNU C17 (Debian 10.2.1-6) version 10.2.1 20210110 (x86_64-linux-gnu)]
+ ignore line: [ compiled by GNU C version 10.2.1 20210110 GMP version 6.2.1 MPFR version 4.1.0 MPC version 1.2.0 isl version isl-0.23-GMP]
+ ignore line: []
+ ignore line: [GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072]
+ ignore line: [ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu"]
+ ignore line: [ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/10/include-fixed"]
+ ignore line: [ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/10/../../../../x86_64-linux-gnu/include"]
+ ignore line: [#include "..." search starts here:]
+ ignore line: [#include <...> search starts here:]
+ ignore line: [ /usr/lib/gcc/x86_64-linux-gnu/10/include]
+ ignore line: [ /usr/local/include]
+ ignore line: [ /usr/include/x86_64-linux-gnu]
+ ignore line: [ /usr/include]
+ ignore line: [End of search list.]
+ ignore line: [GNU C17 (Debian 10.2.1-6) version 10.2.1 20210110 (x86_64-linux-gnu)]
+ ignore line: [ compiled by GNU C version 10.2.1 20210110 GMP version 6.2.1 MPFR version 4.1.0 MPC version 1.2.0 isl version isl-0.23-GMP]
+ ignore line: []
+ ignore line: [GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072]
+ ignore line: [Compiler executable checksum: 1f803793fa2e3418c492b25e7d3eac2f]
+ ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_63b3f.dir/CMakeCCompilerABI.c.o' '-c' '-mtune=generic' '-march=x86-64']
+ ignore line: [ as -v --64 -o CMakeFiles/cmTC_63b3f.dir/CMakeCCompilerABI.c.o /tmp/ccjR73dl.s]
+ ignore line: [GNU assembler version 2.35.2 (x86_64-linux-gnu) using BFD version (GNU Binutils for Debian) 2.35.2]
+ ignore line: [COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/]
+ ignore line: [LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../:/lib/:/usr/lib/]
+ ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_63b3f.dir/CMakeCCompilerABI.c.o' '-c' '-mtune=generic' '-march=x86-64']
+ ignore line: [Linking C executable cmTC_63b3f]
+ ignore line: [/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTC_63b3f.dir/link.txt --verbose=1]
+ ignore line: [/usr/bin/cc -v -rdynamic CMakeFiles/cmTC_63b3f.dir/CMakeCCompilerABI.c.o -o cmTC_63b3f ]
+ ignore line: [Using built-in specs.]
+ ignore line: [COLLECT_GCC=/usr/bin/cc]
+ ignore line: [COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/10/lto-wrapper]
+ ignore line: [OFFLOAD_TARGET_NAMES=nvptx-none:amdgcn-amdhsa:hsa]
+ ignore line: [OFFLOAD_TARGET_DEFAULT=1]
+ ignore line: [Target: x86_64-linux-gnu]
+ ignore line: [Configured with: ../src/configure -v --with-pkgversion='Debian 10.2.1-6' --with-bugurl=file:///usr/share/doc/gcc-10/README.Bugs --enable-languages=c ada c++ go brig d fortran objc obj-c++ m2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-10 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --enable-libphobos-checking=release --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32 m64 mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-10-Km9U7s/gcc-10-10.2.1/debian/tmp-nvptx/usr amdgcn-amdhsa=/build/gcc-10-Km9U7s/gcc-10-10.2.1/debian/tmp-gcn/usr hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu --with-build-config=bootstrap-lto-lean --enable-link-mutex]
+ ignore line: [Thread model: posix]
+ ignore line: [Supported LTO compression algorithms: zlib zstd]
+ ignore line: [gcc version 10.2.1 20210110 (Debian 10.2.1-6) ]
+ ignore line: [COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/]
+ ignore line: [LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../:/lib/:/usr/lib/]
+ ignore line: [COLLECT_GCC_OPTIONS='-v' '-rdynamic' '-o' 'cmTC_63b3f' '-mtune=generic' '-march=x86-64']
+ link line: [ /usr/lib/gcc/x86_64-linux-gnu/10/collect2 -plugin /usr/lib/gcc/x86_64-linux-gnu/10/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/10/lto-wrapper -plugin-opt=-fresolution=/tmp/cckryhrJ.res -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed -export-dynamic -dynamic-linker /lib64/ld-linux-x86-64.so.2 -pie -o cmTC_63b3f /usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/Scrt1.o /usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/10/crtbeginS.o -L/usr/lib/gcc/x86_64-linux-gnu/10 -L/usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/10/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/10/../../.. CMakeFiles/cmTC_63b3f.dir/CMakeCCompilerABI.c.o -lgcc --push-state --as-needed -lgcc_s --pop-state -lc -lgcc --push-state --as-needed -lgcc_s --pop-state /usr/lib/gcc/x86_64-linux-gnu/10/crtendS.o /usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/crtn.o]
+ arg [/usr/lib/gcc/x86_64-linux-gnu/10/collect2] ==> ignore
+ arg [-plugin] ==> ignore
+ arg [/usr/lib/gcc/x86_64-linux-gnu/10/liblto_plugin.so] ==> ignore
+ arg [-plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/10/lto-wrapper] ==> ignore
+ arg [-plugin-opt=-fresolution=/tmp/cckryhrJ.res] ==> ignore
+ arg [-plugin-opt=-pass-through=-lgcc] ==> ignore
+ arg [-plugin-opt=-pass-through=-lgcc_s] ==> ignore
+ arg [-plugin-opt=-pass-through=-lc] ==> ignore
+ arg [-plugin-opt=-pass-through=-lgcc] ==> ignore
+ arg [-plugin-opt=-pass-through=-lgcc_s] ==> ignore
+ arg [--build-id] ==> ignore
+ arg [--eh-frame-hdr] ==> ignore
+ arg [-m] ==> ignore
+ arg [elf_x86_64] ==> ignore
+ arg [--hash-style=gnu] ==> ignore
+ arg [--as-needed] ==> ignore
+ arg [-export-dynamic] ==> ignore
+ arg [-dynamic-linker] ==> ignore
+ arg [/lib64/ld-linux-x86-64.so.2] ==> ignore
+ arg [-pie] ==> ignore
+ arg [-o] ==> ignore
+ arg [cmTC_63b3f] ==> ignore
+ arg [/usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/Scrt1.o] ==> ignore
+ arg [/usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/crti.o] ==> ignore
+ arg [/usr/lib/gcc/x86_64-linux-gnu/10/crtbeginS.o] ==> ignore
+ arg [-L/usr/lib/gcc/x86_64-linux-gnu/10] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/10]
+ arg [-L/usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu]
+ arg [-L/usr/lib/gcc/x86_64-linux-gnu/10/../../../../lib] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/10/../../../../lib]
+ arg [-L/lib/x86_64-linux-gnu] ==> dir [/lib/x86_64-linux-gnu]
+ arg [-L/lib/../lib] ==> dir [/lib/../lib]
+ arg [-L/usr/lib/x86_64-linux-gnu] ==> dir [/usr/lib/x86_64-linux-gnu]
+ arg [-L/usr/lib/../lib] ==> dir [/usr/lib/../lib]
+ arg [-L/usr/lib/gcc/x86_64-linux-gnu/10/../../..] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/10/../../..]
+ arg [CMakeFiles/cmTC_63b3f.dir/CMakeCCompilerABI.c.o] ==> ignore
+ arg [-lgcc] ==> lib [gcc]
+ arg [--push-state] ==> ignore
+ arg [--as-needed] ==> ignore
+ arg [-lgcc_s] ==> lib [gcc_s]
+ arg [--pop-state] ==> ignore
+ arg [-lc] ==> lib [c]
+ arg [-lgcc] ==> lib [gcc]
+ arg [--push-state] ==> ignore
+ arg [--as-needed] ==> ignore
+ arg [-lgcc_s] ==> lib [gcc_s]
+ arg [--pop-state] ==> ignore
+ arg [/usr/lib/gcc/x86_64-linux-gnu/10/crtendS.o] ==> ignore
+ arg [/usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/crtn.o] ==> ignore
+ collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/10] ==> [/usr/lib/gcc/x86_64-linux-gnu/10]
+ collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu] ==> [/usr/lib/x86_64-linux-gnu]
+ collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/10/../../../../lib] ==> [/usr/lib]
+ collapse library dir [/lib/x86_64-linux-gnu] ==> [/lib/x86_64-linux-gnu]
+ collapse library dir [/lib/../lib] ==> [/lib]
+ collapse library dir [/usr/lib/x86_64-linux-gnu] ==> [/usr/lib/x86_64-linux-gnu]
+ collapse library dir [/usr/lib/../lib] ==> [/usr/lib]
+ collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/10/../../..] ==> [/usr/lib]
+ implicit libs: [gcc;gcc_s;c;gcc;gcc_s]
+ implicit dirs: [/usr/lib/gcc/x86_64-linux-gnu/10;/usr/lib/x86_64-linux-gnu;/usr/lib;/lib/x86_64-linux-gnu;/lib]
+ implicit fwks: []
+
+
+Detecting CXX compiler ABI info compiled with the following output:
+Change Dir: /home/calvin/src/xpdf-4.04/xpdf-qt/CMakeFiles/CMakeTmp
+
+Run Build Command(s):/usr/bin/gmake cmTC_9b41c/fast && /usr/bin/gmake -f CMakeFiles/cmTC_9b41c.dir/build.make CMakeFiles/cmTC_9b41c.dir/build
+gmake[1]: Entering directory '/home/calvin/src/xpdf-4.04/xpdf-qt/CMakeFiles/CMakeTmp'
+Building CXX object CMakeFiles/cmTC_9b41c.dir/CMakeCXXCompilerABI.cpp.o
+/usr/bin/c++ -v -o CMakeFiles/cmTC_9b41c.dir/CMakeCXXCompilerABI.cpp.o -c /usr/share/cmake-3.18/Modules/CMakeCXXCompilerABI.cpp
+Using built-in specs.
+COLLECT_GCC=/usr/bin/c++
+OFFLOAD_TARGET_NAMES=nvptx-none:amdgcn-amdhsa:hsa
+OFFLOAD_TARGET_DEFAULT=1
+Target: x86_64-linux-gnu
+Configured with: ../src/configure -v --with-pkgversion='Debian 10.2.1-6' --with-bugurl=file:///usr/share/doc/gcc-10/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++,m2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-10 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --enable-libphobos-checking=release --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-10-Km9U7s/gcc-10-10.2.1/debian/tmp-nvptx/usr,amdgcn-amdhsa=/build/gcc-10-Km9U7s/gcc-10-10.2.1/debian/tmp-gcn/usr,hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu --with-build-config=bootstrap-lto-lean --enable-link-mutex
+Thread model: posix
+Supported LTO compression algorithms: zlib zstd
+gcc version 10.2.1 20210110 (Debian 10.2.1-6)
+COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_9b41c.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64'
+ /usr/lib/gcc/x86_64-linux-gnu/10/cc1plus -quiet -v -imultiarch x86_64-linux-gnu -D_GNU_SOURCE /usr/share/cmake-3.18/Modules/CMakeCXXCompilerABI.cpp -quiet -dumpbase CMakeCXXCompilerABI.cpp -mtune=generic -march=x86-64 -auxbase-strip CMakeFiles/cmTC_9b41c.dir/CMakeCXXCompilerABI.cpp.o -version -fasynchronous-unwind-tables -o /tmp/cczUkCmh.s
+GNU C++14 (Debian 10.2.1-6) version 10.2.1 20210110 (x86_64-linux-gnu)
+ compiled by GNU C version 10.2.1 20210110, GMP version 6.2.1, MPFR version 4.1.0, MPC version 1.2.0, isl version isl-0.23-GMP
+
+GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
+ignoring duplicate directory "/usr/include/x86_64-linux-gnu/c++/10"
+ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu"
+ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/10/include-fixed"
+ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/10/../../../../x86_64-linux-gnu/include"
+#include "..." search starts here:
+#include <...> search starts here:
+ /usr/include/c++/10
+ /usr/include/x86_64-linux-gnu/c++/10
+ /usr/include/c++/10/backward
+ /usr/lib/gcc/x86_64-linux-gnu/10/include
+ /usr/local/include
+ /usr/include/x86_64-linux-gnu
+ /usr/include
+End of search list.
+GNU C++14 (Debian 10.2.1-6) version 10.2.1 20210110 (x86_64-linux-gnu)
+ compiled by GNU C version 10.2.1 20210110, GMP version 6.2.1, MPFR version 4.1.0, MPC version 1.2.0, isl version isl-0.23-GMP
+
+GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
+Compiler executable checksum: 048fcaee3460a99eb0d68522358720e1
+COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_9b41c.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64'
+ as -v --64 -o CMakeFiles/cmTC_9b41c.dir/CMakeCXXCompilerABI.cpp.o /tmp/cczUkCmh.s
+GNU assembler version 2.35.2 (x86_64-linux-gnu) using BFD version (GNU Binutils for Debian) 2.35.2
+COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/
+LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../:/lib/:/usr/lib/
+COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_9b41c.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64'
+Linking CXX executable cmTC_9b41c
+/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTC_9b41c.dir/link.txt --verbose=1
+/usr/bin/c++ -v -rdynamic CMakeFiles/cmTC_9b41c.dir/CMakeCXXCompilerABI.cpp.o -o cmTC_9b41c
+Using built-in specs.
+COLLECT_GCC=/usr/bin/c++
+COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/10/lto-wrapper
+OFFLOAD_TARGET_NAMES=nvptx-none:amdgcn-amdhsa:hsa
+OFFLOAD_TARGET_DEFAULT=1
+Target: x86_64-linux-gnu
+Configured with: ../src/configure -v --with-pkgversion='Debian 10.2.1-6' --with-bugurl=file:///usr/share/doc/gcc-10/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++,m2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-10 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --enable-libphobos-checking=release --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-10-Km9U7s/gcc-10-10.2.1/debian/tmp-nvptx/usr,amdgcn-amdhsa=/build/gcc-10-Km9U7s/gcc-10-10.2.1/debian/tmp-gcn/usr,hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu --with-build-config=bootstrap-lto-lean --enable-link-mutex
+Thread model: posix
+Supported LTO compression algorithms: zlib zstd
+gcc version 10.2.1 20210110 (Debian 10.2.1-6)
+COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/
+LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../:/lib/:/usr/lib/
+COLLECT_GCC_OPTIONS='-v' '-rdynamic' '-o' 'cmTC_9b41c' '-shared-libgcc' '-mtune=generic' '-march=x86-64'
+ /usr/lib/gcc/x86_64-linux-gnu/10/collect2 -plugin /usr/lib/gcc/x86_64-linux-gnu/10/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/10/lto-wrapper -plugin-opt=-fresolution=/tmp/ccoQSRtJ.res -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed -export-dynamic -dynamic-linker /lib64/ld-linux-x86-64.so.2 -pie -o cmTC_9b41c /usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/Scrt1.o /usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/10/crtbeginS.o -L/usr/lib/gcc/x86_64-linux-gnu/10 -L/usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/10/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/10/../../.. CMakeFiles/cmTC_9b41c.dir/CMakeCXXCompilerABI.cpp.o -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /usr/lib/gcc/x86_64-linux-gnu/10/crtendS.o /usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/crtn.o
+COLLECT_GCC_OPTIONS='-v' '-rdynamic' '-o' 'cmTC_9b41c' '-shared-libgcc' '-mtune=generic' '-march=x86-64'
+gmake[1]: Leaving directory '/home/calvin/src/xpdf-4.04/xpdf-qt/CMakeFiles/CMakeTmp'
+
+
+
+Parsed CXX implicit include dir info from above output: rv=done
+ found start of include info
+ found start of implicit include info
+ add: [/usr/include/c++/10]
+ add: [/usr/include/x86_64-linux-gnu/c++/10]
+ add: [/usr/include/c++/10/backward]
+ add: [/usr/lib/gcc/x86_64-linux-gnu/10/include]
+ add: [/usr/local/include]
+ add: [/usr/include/x86_64-linux-gnu]
+ add: [/usr/include]
+ end of search list found
+ collapse include dir [/usr/include/c++/10] ==> [/usr/include/c++/10]
+ collapse include dir [/usr/include/x86_64-linux-gnu/c++/10] ==> [/usr/include/x86_64-linux-gnu/c++/10]
+ collapse include dir [/usr/include/c++/10/backward] ==> [/usr/include/c++/10/backward]
+ collapse include dir [/usr/lib/gcc/x86_64-linux-gnu/10/include] ==> [/usr/lib/gcc/x86_64-linux-gnu/10/include]
+ collapse include dir [/usr/local/include] ==> [/usr/local/include]
+ collapse include dir [/usr/include/x86_64-linux-gnu] ==> [/usr/include/x86_64-linux-gnu]
+ collapse include dir [/usr/include] ==> [/usr/include]
+ implicit include dirs: [/usr/include/c++/10;/usr/include/x86_64-linux-gnu/c++/10;/usr/include/c++/10/backward;/usr/lib/gcc/x86_64-linux-gnu/10/include;/usr/local/include;/usr/include/x86_64-linux-gnu;/usr/include]
+
+
+Parsed CXX implicit link information from above output:
+ link line regex: [^( *|.*[/\])(ld|CMAKE_LINK_STARTFILE-NOTFOUND|([^/\]+-)?ld|collect2)[^/\]*( |$)]
+ ignore line: [Change Dir: /home/calvin/src/xpdf-4.04/xpdf-qt/CMakeFiles/CMakeTmp]
+ ignore line: []
+ ignore line: [Run Build Command(s):/usr/bin/gmake cmTC_9b41c/fast && /usr/bin/gmake -f CMakeFiles/cmTC_9b41c.dir/build.make CMakeFiles/cmTC_9b41c.dir/build]
+ ignore line: [gmake[1]: Entering directory '/home/calvin/src/xpdf-4.04/xpdf-qt/CMakeFiles/CMakeTmp']
+ ignore line: [Building CXX object CMakeFiles/cmTC_9b41c.dir/CMakeCXXCompilerABI.cpp.o]
+ ignore line: [/usr/bin/c++ -v -o CMakeFiles/cmTC_9b41c.dir/CMakeCXXCompilerABI.cpp.o -c /usr/share/cmake-3.18/Modules/CMakeCXXCompilerABI.cpp]
+ ignore line: [Using built-in specs.]
+ ignore line: [COLLECT_GCC=/usr/bin/c++]
+ ignore line: [OFFLOAD_TARGET_NAMES=nvptx-none:amdgcn-amdhsa:hsa]
+ ignore line: [OFFLOAD_TARGET_DEFAULT=1]
+ ignore line: [Target: x86_64-linux-gnu]
+ ignore line: [Configured with: ../src/configure -v --with-pkgversion='Debian 10.2.1-6' --with-bugurl=file:///usr/share/doc/gcc-10/README.Bugs --enable-languages=c ada c++ go brig d fortran objc obj-c++ m2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-10 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --enable-libphobos-checking=release --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32 m64 mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-10-Km9U7s/gcc-10-10.2.1/debian/tmp-nvptx/usr amdgcn-amdhsa=/build/gcc-10-Km9U7s/gcc-10-10.2.1/debian/tmp-gcn/usr hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu --with-build-config=bootstrap-lto-lean --enable-link-mutex]
+ ignore line: [Thread model: posix]
+ ignore line: [Supported LTO compression algorithms: zlib zstd]
+ ignore line: [gcc version 10.2.1 20210110 (Debian 10.2.1-6) ]
+ ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_9b41c.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64']
+ ignore line: [ /usr/lib/gcc/x86_64-linux-gnu/10/cc1plus -quiet -v -imultiarch x86_64-linux-gnu -D_GNU_SOURCE /usr/share/cmake-3.18/Modules/CMakeCXXCompilerABI.cpp -quiet -dumpbase CMakeCXXCompilerABI.cpp -mtune=generic -march=x86-64 -auxbase-strip CMakeFiles/cmTC_9b41c.dir/CMakeCXXCompilerABI.cpp.o -version -fasynchronous-unwind-tables -o /tmp/cczUkCmh.s]
+ ignore line: [GNU C++14 (Debian 10.2.1-6) version 10.2.1 20210110 (x86_64-linux-gnu)]
+ ignore line: [ compiled by GNU C version 10.2.1 20210110 GMP version 6.2.1 MPFR version 4.1.0 MPC version 1.2.0 isl version isl-0.23-GMP]
+ ignore line: []
+ ignore line: [GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072]
+ ignore line: [ignoring duplicate directory "/usr/include/x86_64-linux-gnu/c++/10"]
+ ignore line: [ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu"]
+ ignore line: [ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/10/include-fixed"]
+ ignore line: [ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/10/../../../../x86_64-linux-gnu/include"]
+ ignore line: [#include "..." search starts here:]
+ ignore line: [#include <...> search starts here:]
+ ignore line: [ /usr/include/c++/10]
+ ignore line: [ /usr/include/x86_64-linux-gnu/c++/10]
+ ignore line: [ /usr/include/c++/10/backward]
+ ignore line: [ /usr/lib/gcc/x86_64-linux-gnu/10/include]
+ ignore line: [ /usr/local/include]
+ ignore line: [ /usr/include/x86_64-linux-gnu]
+ ignore line: [ /usr/include]
+ ignore line: [End of search list.]
+ ignore line: [GNU C++14 (Debian 10.2.1-6) version 10.2.1 20210110 (x86_64-linux-gnu)]
+ ignore line: [ compiled by GNU C version 10.2.1 20210110 GMP version 6.2.1 MPFR version 4.1.0 MPC version 1.2.0 isl version isl-0.23-GMP]
+ ignore line: []
+ ignore line: [GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072]
+ ignore line: [Compiler executable checksum: 048fcaee3460a99eb0d68522358720e1]
+ ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_9b41c.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64']
+ ignore line: [ as -v --64 -o CMakeFiles/cmTC_9b41c.dir/CMakeCXXCompilerABI.cpp.o /tmp/cczUkCmh.s]
+ ignore line: [GNU assembler version 2.35.2 (x86_64-linux-gnu) using BFD version (GNU Binutils for Debian) 2.35.2]
+ ignore line: [COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/]
+ ignore line: [LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../:/lib/:/usr/lib/]
+ ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_9b41c.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64']
+ ignore line: [Linking CXX executable cmTC_9b41c]
+ ignore line: [/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTC_9b41c.dir/link.txt --verbose=1]
+ ignore line: [/usr/bin/c++ -v -rdynamic CMakeFiles/cmTC_9b41c.dir/CMakeCXXCompilerABI.cpp.o -o cmTC_9b41c ]
+ ignore line: [Using built-in specs.]
+ ignore line: [COLLECT_GCC=/usr/bin/c++]
+ ignore line: [COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/10/lto-wrapper]
+ ignore line: [OFFLOAD_TARGET_NAMES=nvptx-none:amdgcn-amdhsa:hsa]
+ ignore line: [OFFLOAD_TARGET_DEFAULT=1]
+ ignore line: [Target: x86_64-linux-gnu]
+ ignore line: [Configured with: ../src/configure -v --with-pkgversion='Debian 10.2.1-6' --with-bugurl=file:///usr/share/doc/gcc-10/README.Bugs --enable-languages=c ada c++ go brig d fortran objc obj-c++ m2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-10 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --enable-libphobos-checking=release --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32 m64 mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-10-Km9U7s/gcc-10-10.2.1/debian/tmp-nvptx/usr amdgcn-amdhsa=/build/gcc-10-Km9U7s/gcc-10-10.2.1/debian/tmp-gcn/usr hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu --with-build-config=bootstrap-lto-lean --enable-link-mutex]
+ ignore line: [Thread model: posix]
+ ignore line: [Supported LTO compression algorithms: zlib zstd]
+ ignore line: [gcc version 10.2.1 20210110 (Debian 10.2.1-6) ]
+ ignore line: [COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/]
+ ignore line: [LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../:/lib/:/usr/lib/]
+ ignore line: [COLLECT_GCC_OPTIONS='-v' '-rdynamic' '-o' 'cmTC_9b41c' '-shared-libgcc' '-mtune=generic' '-march=x86-64']
+ link line: [ /usr/lib/gcc/x86_64-linux-gnu/10/collect2 -plugin /usr/lib/gcc/x86_64-linux-gnu/10/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/10/lto-wrapper -plugin-opt=-fresolution=/tmp/ccoQSRtJ.res -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed -export-dynamic -dynamic-linker /lib64/ld-linux-x86-64.so.2 -pie -o cmTC_9b41c /usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/Scrt1.o /usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/10/crtbeginS.o -L/usr/lib/gcc/x86_64-linux-gnu/10 -L/usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/10/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/10/../../.. CMakeFiles/cmTC_9b41c.dir/CMakeCXXCompilerABI.cpp.o -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /usr/lib/gcc/x86_64-linux-gnu/10/crtendS.o /usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/crtn.o]
+ arg [/usr/lib/gcc/x86_64-linux-gnu/10/collect2] ==> ignore
+ arg [-plugin] ==> ignore
+ arg [/usr/lib/gcc/x86_64-linux-gnu/10/liblto_plugin.so] ==> ignore
+ arg [-plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/10/lto-wrapper] ==> ignore
+ arg [-plugin-opt=-fresolution=/tmp/ccoQSRtJ.res] ==> ignore
+ arg [-plugin-opt=-pass-through=-lgcc_s] ==> ignore
+ arg [-plugin-opt=-pass-through=-lgcc] ==> ignore
+ arg [-plugin-opt=-pass-through=-lc] ==> ignore
+ arg [-plugin-opt=-pass-through=-lgcc_s] ==> ignore
+ arg [-plugin-opt=-pass-through=-lgcc] ==> ignore
+ arg [--build-id] ==> ignore
+ arg [--eh-frame-hdr] ==> ignore
+ arg [-m] ==> ignore
+ arg [elf_x86_64] ==> ignore
+ arg [--hash-style=gnu] ==> ignore
+ arg [--as-needed] ==> ignore
+ arg [-export-dynamic] ==> ignore
+ arg [-dynamic-linker] ==> ignore
+ arg [/lib64/ld-linux-x86-64.so.2] ==> ignore
+ arg [-pie] ==> ignore
+ arg [-o] ==> ignore
+ arg [cmTC_9b41c] ==> ignore
+ arg [/usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/Scrt1.o] ==> ignore
+ arg [/usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/crti.o] ==> ignore
+ arg [/usr/lib/gcc/x86_64-linux-gnu/10/crtbeginS.o] ==> ignore
+ arg [-L/usr/lib/gcc/x86_64-linux-gnu/10] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/10]
+ arg [-L/usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu]
+ arg [-L/usr/lib/gcc/x86_64-linux-gnu/10/../../../../lib] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/10/../../../../lib]
+ arg [-L/lib/x86_64-linux-gnu] ==> dir [/lib/x86_64-linux-gnu]
+ arg [-L/lib/../lib] ==> dir [/lib/../lib]
+ arg [-L/usr/lib/x86_64-linux-gnu] ==> dir [/usr/lib/x86_64-linux-gnu]
+ arg [-L/usr/lib/../lib] ==> dir [/usr/lib/../lib]
+ arg [-L/usr/lib/gcc/x86_64-linux-gnu/10/../../..] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/10/../../..]
+ arg [CMakeFiles/cmTC_9b41c.dir/CMakeCXXCompilerABI.cpp.o] ==> ignore
+ arg [-lstdc++] ==> lib [stdc++]
+ arg [-lm] ==> lib [m]
+ arg [-lgcc_s] ==> lib [gcc_s]
+ arg [-lgcc] ==> lib [gcc]
+ arg [-lc] ==> lib [c]
+ arg [-lgcc_s] ==> lib [gcc_s]
+ arg [-lgcc] ==> lib [gcc]
+ arg [/usr/lib/gcc/x86_64-linux-gnu/10/crtendS.o] ==> ignore
+ arg [/usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/crtn.o] ==> ignore
+ collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/10] ==> [/usr/lib/gcc/x86_64-linux-gnu/10]
+ collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu] ==> [/usr/lib/x86_64-linux-gnu]
+ collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/10/../../../../lib] ==> [/usr/lib]
+ collapse library dir [/lib/x86_64-linux-gnu] ==> [/lib/x86_64-linux-gnu]
+ collapse library dir [/lib/../lib] ==> [/lib]
+ collapse library dir [/usr/lib/x86_64-linux-gnu] ==> [/usr/lib/x86_64-linux-gnu]
+ collapse library dir [/usr/lib/../lib] ==> [/usr/lib]
+ collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/10/../../..] ==> [/usr/lib]
+ implicit libs: [stdc++;m;gcc_s;gcc;c;gcc_s;gcc]
+ implicit dirs: [/usr/lib/gcc/x86_64-linux-gnu/10;/usr/lib/x86_64-linux-gnu;/usr/lib;/lib/x86_64-linux-gnu;/lib]
+ implicit fwks: []
+
+
diff --git a/xpdf-qt/CMakeFiles/Makefile.cmake b/xpdf-qt/CMakeFiles/Makefile.cmake
new file mode 100644
index 0000000..5185ff3
--- /dev/null
+++ b/xpdf-qt/CMakeFiles/Makefile.cmake
@@ -0,0 +1,119 @@
+# CMAKE generated file: DO NOT EDIT!
+# Generated by "Unix Makefiles" Generator, CMake Version 3.18
+
+# The generator used is:
+set(CMAKE_DEPENDS_GENERATOR "Unix Makefiles")
+
+# The top level Makefile was generated from the following files:
+set(CMAKE_MAKEFILE_DEPENDS
+ "CMakeCache.txt"
+ "CMakeFiles/3.18.4/CMakeCCompiler.cmake"
+ "CMakeFiles/3.18.4/CMakeCXXCompiler.cmake"
+ "CMakeFiles/3.18.4/CMakeSystem.cmake"
+ "CMakeLists.txt"
+ "/usr/share/cmake-3.18/Modules/CMakeCCompiler.cmake.in"
+ "/usr/share/cmake-3.18/Modules/CMakeCCompilerABI.c"
+ "/usr/share/cmake-3.18/Modules/CMakeCInformation.cmake"
+ "/usr/share/cmake-3.18/Modules/CMakeCXXCompiler.cmake.in"
+ "/usr/share/cmake-3.18/Modules/CMakeCXXCompilerABI.cpp"
+ "/usr/share/cmake-3.18/Modules/CMakeCXXInformation.cmake"
+ "/usr/share/cmake-3.18/Modules/CMakeCheckCompilerFlagCommonPatterns.cmake"
+ "/usr/share/cmake-3.18/Modules/CMakeCommonLanguageInclude.cmake"
+ "/usr/share/cmake-3.18/Modules/CMakeCompilerIdDetection.cmake"
+ "/usr/share/cmake-3.18/Modules/CMakeDetermineCCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/CMakeDetermineCXXCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/CMakeDetermineCompileFeatures.cmake"
+ "/usr/share/cmake-3.18/Modules/CMakeDetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/CMakeDetermineCompilerABI.cmake"
+ "/usr/share/cmake-3.18/Modules/CMakeDetermineCompilerId.cmake"
+ "/usr/share/cmake-3.18/Modules/CMakeDetermineSystem.cmake"
+ "/usr/share/cmake-3.18/Modules/CMakeFindBinUtils.cmake"
+ "/usr/share/cmake-3.18/Modules/CMakeGenericSystem.cmake"
+ "/usr/share/cmake-3.18/Modules/CMakeInitializeConfigs.cmake"
+ "/usr/share/cmake-3.18/Modules/CMakeLanguageInformation.cmake"
+ "/usr/share/cmake-3.18/Modules/CMakeParseImplicitIncludeInfo.cmake"
+ "/usr/share/cmake-3.18/Modules/CMakeParseImplicitLinkInfo.cmake"
+ "/usr/share/cmake-3.18/Modules/CMakeSystem.cmake.in"
+ "/usr/share/cmake-3.18/Modules/CMakeSystemSpecificInformation.cmake"
+ "/usr/share/cmake-3.18/Modules/CMakeSystemSpecificInitialize.cmake"
+ "/usr/share/cmake-3.18/Modules/CMakeTestCCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/CMakeTestCXXCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/CMakeTestCompilerCommon.cmake"
+ "/usr/share/cmake-3.18/Modules/CMakeUnixFindMake.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/ADSP-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/ARMCC-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/ARMClang-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/AppleClang-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/Borland-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/Bruce-C-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/CMakeCommonCompilerMacros.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/Clang-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/Clang-DetermineCompilerInternal.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/Comeau-CXX-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/Compaq-C-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/Compaq-CXX-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/Cray-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/Embarcadero-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/Fujitsu-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/GHS-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/GNU-C-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/GNU-C.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/GNU-CXX-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/GNU-CXX.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/GNU-FindBinUtils.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/GNU.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/HP-C-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/HP-CXX-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/IAR-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/IBMCPP-CXX-DetermineVersionInternal.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/Intel-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/MSVC-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/NVIDIA-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/OpenWatcom-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/PGI-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/PathScale-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/SCO-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/SDCC-C-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/SunPro-C-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/SunPro-CXX-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/TI-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/TinyCC-C-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/VisualAge-C-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/VisualAge-CXX-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/Watcom-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/XL-C-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/XL-CXX-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/XLClang-C-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/XLClang-CXX-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/zOS-C-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Compiler/zOS-CXX-DetermineCompiler.cmake"
+ "/usr/share/cmake-3.18/Modules/Internal/CMakeCheckCompilerFlag.cmake"
+ "/usr/share/cmake-3.18/Modules/Internal/FeatureTesting.cmake"
+ "/usr/share/cmake-3.18/Modules/Platform/Linux-Determine-CXX.cmake"
+ "/usr/share/cmake-3.18/Modules/Platform/Linux-GNU-C.cmake"
+ "/usr/share/cmake-3.18/Modules/Platform/Linux-GNU-CXX.cmake"
+ "/usr/share/cmake-3.18/Modules/Platform/Linux-GNU.cmake"
+ "/usr/share/cmake-3.18/Modules/Platform/Linux.cmake"
+ "/usr/share/cmake-3.18/Modules/Platform/UnixPaths.cmake"
+ )
+
+# The corresponding makefile is:
+set(CMAKE_MAKEFILE_OUTPUTS
+ "Makefile"
+ "CMakeFiles/cmake.check_cache"
+ )
+
+# Byproducts of CMake generate step:
+set(CMAKE_MAKEFILE_PRODUCTS
+ "CMakeFiles/3.18.4/CMakeSystem.cmake"
+ "CMakeFiles/3.18.4/CMakeCCompiler.cmake"
+ "CMakeFiles/3.18.4/CMakeCXXCompiler.cmake"
+ "CMakeFiles/3.18.4/CMakeCCompiler.cmake"
+ "CMakeFiles/3.18.4/CMakeCXXCompiler.cmake"
+ "CMakeFiles/CMakeDirectoryInformation.cmake"
+ )
+
+# Dependency information for all targets:
+set(CMAKE_DEPEND_INFO_FILES
+ )
diff --git a/xpdf-qt/CMakeFiles/Makefile2 b/xpdf-qt/CMakeFiles/Makefile2
new file mode 100644
index 0000000..91e032d
--- /dev/null
+++ b/xpdf-qt/CMakeFiles/Makefile2
@@ -0,0 +1,98 @@
+# 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
+
+#=============================================================================
+# 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/xpdf-qt
+
+# The top-level build directory on which CMake was run.
+CMAKE_BINARY_DIR = /home/calvin/src/xpdf-4.04/xpdf-qt
+
+#=============================================================================
+# Directory level rules for the build root directory
+
+# The main recursive "all" target.
+all:
+
+.PHONY : all
+
+# The main recursive "preinstall" target.
+preinstall:
+
+.PHONY : preinstall
+
+# The main recursive "clean" target.
+clean:
+
+.PHONY : clean
+
+#=============================================================================
+# 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:
+ $(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-qt/CMakeFiles/TargetDirectories.txt b/xpdf-qt/CMakeFiles/TargetDirectories.txt
new file mode 100644
index 0000000..163761c
--- /dev/null
+++ b/xpdf-qt/CMakeFiles/TargetDirectories.txt
@@ -0,0 +1,2 @@
+/home/calvin/src/xpdf-4.04/xpdf-qt/CMakeFiles/rebuild_cache.dir
+/home/calvin/src/xpdf-4.04/xpdf-qt/CMakeFiles/edit_cache.dir
diff --git a/xpdf-qt/CMakeFiles/cmake.check_cache b/xpdf-qt/CMakeFiles/cmake.check_cache
new file mode 100644
index 0000000..3dccd73
--- /dev/null
+++ b/xpdf-qt/CMakeFiles/cmake.check_cache
@@ -0,0 +1 @@
+# This file is generated by cmake for dependency checking of the CMakeCache.txt file
diff --git a/xpdf-qt/CMakeFiles/progress.marks b/xpdf-qt/CMakeFiles/progress.marks
new file mode 100644
index 0000000..78eb67c
--- /dev/null
+++ b/xpdf-qt/CMakeFiles/progress.marks
@@ -0,0 +1 @@
+75
diff --git a/xpdf-qt/CMakeFiles/xpdf.dir/CXX.includecache b/xpdf-qt/CMakeFiles/xpdf.dir/CXX.includecache
new file mode 100644
index 0000000..90cafb0
--- /dev/null
+++ b/xpdf-qt/CMakeFiles/xpdf.dir/CXX.includecache
@@ -0,0 +1,1784 @@
+#IncludeRegexLine: ^[ ]*[#%][ ]*(include|import)[ ]*[<"]([^">]+)([">])
+
+#IncludeRegexScan: ^.*$
+
+#IncludeRegexComplain: ^$
+
+#IncludeRegexTransform:
+
+/home/calvin/src/xpdf-4.04/xpdf-qt/QtPDFCore.cc
+aconf.h
+-
+math.h
+-
+string.h
+-
+QApplication
+-
+QClipboard
+-
+QDesktopServices
+-
+QFileInfo
+-
+QImage
+-
+QInputDialog
+-
+QMessageBox
+-
+QPainter
+-
+QProcess
+-
+QScrollBar
+-
+QStyle
+-
+QUrl
+-
+QWidget
+-
+gmem.h
+/home/calvin/src/xpdf-4.04/xpdf-qt/gmem.h
+gmempp.h
+/home/calvin/src/xpdf-4.04/xpdf-qt/gmempp.h
+gfile.h
+/home/calvin/src/xpdf-4.04/xpdf-qt/gfile.h
+GString.h
+/home/calvin/src/xpdf-4.04/xpdf-qt/GString.h
+GList.h
+/home/calvin/src/xpdf-4.04/xpdf-qt/GList.h
+Error.h
+/home/calvin/src/xpdf-4.04/xpdf-qt/Error.h
+GlobalParams.h
+/home/calvin/src/xpdf-4.04/xpdf-qt/GlobalParams.h
+PDFDoc.h
+/home/calvin/src/xpdf-4.04/xpdf-qt/PDFDoc.h
+Link.h
+/home/calvin/src/xpdf-4.04/xpdf-qt/Link.h
+ErrorCodes.h
+/home/calvin/src/xpdf-4.04/xpdf-qt/ErrorCodes.h
+GfxState.h
+/home/calvin/src/xpdf-4.04/xpdf-qt/GfxState.h
+PSOutputDev.h
+/home/calvin/src/xpdf-4.04/xpdf-qt/PSOutputDev.h
+TextOutputDev.h
+/home/calvin/src/xpdf-4.04/xpdf-qt/TextOutputDev.h
+SplashBitmap.h
+/home/calvin/src/xpdf-4.04/xpdf-qt/SplashBitmap.h
+DisplayState.h
+/home/calvin/src/xpdf-4.04/xpdf-qt/DisplayState.h
+TileMap.h
+/home/calvin/src/xpdf-4.04/xpdf-qt/TileMap.h
+QtPDFCore.h
+/home/calvin/src/xpdf-4.04/xpdf-qt/QtPDFCore.h
+
+/home/calvin/src/xpdf-4.04/xpdf-qt/QtPDFCore.h
+aconf.h
+-
+QDateTime
+-
+gtypes.h
+/home/calvin/src/xpdf-4.04/xpdf-qt/gtypes.h
+SplashTypes.h
+/home/calvin/src/xpdf-4.04/xpdf-qt/SplashTypes.h
+PDFCore.h
+/home/calvin/src/xpdf-4.04/xpdf-qt/PDFCore.h
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/QDateTime
+qdatetime.h
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qdatetime.h
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/QFileInfo
+qfileinfo.h
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qfileinfo.h
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/QProcess
+qprocess.h
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qprocess.h
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/QUrl
+qurl.h
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qurl.h
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qalgorithms.h
+QtCore/qglobal.h
+-
+intrin.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qarraydata.h
+QtCore/qrefcount.h
+-
+string.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qatomic.h
+QtCore/qglobal.h
+-
+QtCore/qbasicatomic.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qatomic_bootstrap.h
+QtCore/qgenericatomic.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qatomic_cxx11.h
+QtCore/qgenericatomic.h
+-
+atomic
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qatomic_msvc.h
+QtCore/qgenericatomic.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qbasicatomic.h
+QtCore/qglobal.h
+-
+QtCore/qatomic_bootstrap.h
+-
+QtCore/qatomic_cxx11.h
+-
+QtCore/qatomic_msvc.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qbytearray.h
+QtCore/qrefcount.h
+-
+QtCore/qnamespace.h
+-
+QtCore/qarraydata.h
+-
+stdlib.h
+-
+string.h
+-
+stdarg.h
+-
+string
+-
+iterator
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qbytearraylist.h
+QtCore/qlist.h
+-
+QtCore/qbytearray.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qchar.h
+QtCore/qglobal.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qcompilerdetection.h
+QtCore/qglobal.h
+-
+utility
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qconfig-bootstrapped.h
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qconfig.h
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qcontainerfwd.h
+QtCore/qglobal.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qcontainertools_impl.h
+QtCore/qglobal.h
+-
+iterator
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qcontiguouscache.h
+QtCore/qatomic.h
+-
+limits.h
+-
+new
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qcoreapplication.h
+QtCore/qglobal.h
+-
+QtCore/qstring.h
+-
+QtCore/qobject.h
+-
+QtCore/qcoreevent.h
+-
+QtCore/qeventloop.h
+-
+QtCore/qscopedpointer.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qcoreevent.h
+QtCore/qnamespace.h
+-
+QtCore/qbytearray.h
+-
+QtCore/qobjectdefs.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qdatastream.h
+QtCore/qscopedpointer.h
+-
+QtCore/qiodevice.h
+-
+QtCore/qpair.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qdatetime.h
+QtCore/qstring.h
+-
+QtCore/qnamespace.h
+-
+QtCore/qshareddata.h
+-
+limits
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qdebug.h
+QtCore/qalgorithms.h
+-
+QtCore/qhash.h
+-
+QtCore/qlist.h
+-
+QtCore/qmap.h
+-
+QtCore/qpair.h
+-
+QtCore/qtextstream.h
+-
+QtCore/qstring.h
+-
+QtCore/qvector.h
+-
+QtCore/qset.h
+-
+QtCore/qcontiguouscache.h
+-
+QtCore/qsharedpointer.h
+-
+vector
+-
+list
+-
+map
+-
+utility
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qeventloop.h
+QtCore/qobject.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qfile.h
+QtCore/qfiledevice.h
+-
+QtCore/qstring.h
+-
+stdio.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qfiledevice.h
+QtCore/qiodevice.h
+-
+QtCore/qstring.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qfileinfo.h
+QtCore/qfile.h
+-
+QtCore/qlist.h
+-
+QtCore/qshareddata.h
+-
+QtCore/qmetatype.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qflags.h
+QtCore/qglobal.h
+-
+initializer_list
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qgenericatomic.h
+QtCore/qglobal.h
+-
+QtCore/qtypeinfo.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qglobal.h
+type_traits
+-
+cstddef
+-
+utility
+-
+assert.h
+-
+stddef.h
+-
+QtCore/qconfig-bootstrapped.h
+-
+QtCore/qconfig.h
+-
+QtCore/qtcore-config.h
+-
+QtCore/qsystemdetection.h
+-
+QtCore/qprocessordetection.h
+-
+QtCore/qcompilerdetection.h
+-
+algorithm
+-
+QtCore/qtypeinfo.h
+-
+QtCore/qsysinfo.h
+-
+QtCore/qlogging.h
+-
+QtCore/qflags.h
+-
+QtCore/qatomic.h
+-
+QtCore/qglobalstatic.h
+-
+QtCore/qnumeric.h
+-
+QtCore/qversiontagging.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qglobalstatic.h
+QtCore/qglobal.h
+-
+QtCore/qatomic.h
+-
+QtCore/qmutex.h
+-
+mutex
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qhash.h
+QtCore/qchar.h
+-
+QtCore/qiterator.h
+-
+QtCore/qlist.h
+-
+QtCore/qrefcount.h
+-
+QtCore/qhashfunctions.h
+-
+QtCore/qcontainertools_impl.h
+-
+algorithm
+-
+initializer_list
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qhashfunctions.h
+QtCore/qstring.h
+-
+QtCore/qpair.h
+-
+numeric
+-
+functional
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qiodevice.h
+QtCore/qglobal.h
+-
+QtCore/qobject.h
+-
+QtCore/qobjectdefs.h
+-
+QtCore/qscopedpointer.h
+-
+QtCore/qstring.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qiterator.h
+QtCore/qglobal.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qline.h
+QtCore/qpoint.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qlist.h
+QtCore/qalgorithms.h
+-
+QtCore/qiterator.h
+-
+QtCore/qrefcount.h
+-
+QtCore/qarraydata.h
+-
+QtCore/qhashfunctions.h
+-
+QtCore/qvector.h
+-
+QtCore/qcontainertools_impl.h
+-
+algorithm
+-
+initializer_list
+-
+iterator
+-
+list
+-
+stdlib.h
+-
+new
+-
+limits.h
+-
+string.h
+-
+QtCore/qbytearraylist.h
+-
+QtCore/qstringlist.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qlocale.h
+QtCore/qvariant.h
+-
+QtCore/qstring.h
+-
+QtCore/qobjectdefs.h
+-
+QtCore/qshareddata.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qlogging.h
+QtCore/qglobal.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qmap.h
+QtCore/qiterator.h
+-
+QtCore/qlist.h
+-
+QtCore/qrefcount.h
+-
+QtCore/qpair.h
+-
+QtCore/qdebug.h
+-
+functional
+-
+initializer_list
+-
+map
+-
+new
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qmargins.h
+QtCore/qnamespace.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qmetatype.h
+QtCore/qglobal.h
+-
+QtCore/qatomic.h
+-
+QtCore/qbytearray.h
+-
+QtCore/qvarlengtharray.h
+-
+QtCore/qobjectdefs.h
+-
+new
+-
+vector
+-
+list
+-
+map
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qmutex.h
+QtCore/qglobal.h
+-
+QtCore/qatomic.h
+-
+new
+-
+chrono
+-
+limits
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qnamespace.h
+QtCore/qglobal.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qnumeric.h
+QtCore/qglobal.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qobject.h
+QtCore/qobjectdefs.h
+-
+QtCore/qstring.h
+-
+QtCore/qbytearray.h
+-
+QtCore/qlist.h
+-
+QtCore/qcoreevent.h
+-
+QtCore/qscopedpointer.h
+-
+QtCore/qmetatype.h
+-
+QtCore/qobject_impl.h
+-
+chrono
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qobject_impl.h
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qobjectdefs.h
+QtCore/qnamespace.h
+-
+QtCore/qobjectdefs_impl.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qobjectdefs_impl.h
+QtCore/qnamespace.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qpair.h
+QtCore/qglobal.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qpoint.h
+QtCore/qnamespace.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qprocess.h
+QtCore/qiodevice.h
+-
+QtCore/qstringlist.h
+-
+QtCore/qshareddata.h
+-
+functional
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qprocessordetection.h
+QtCore/qglobal.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qrect.h
+QtCore/qmargins.h
+-
+QtCore/qsize.h
+-
+QtCore/qpoint.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qrefcount.h
+QtCore/qatomic.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qregexp.h
+QtCore/qglobal.h
+-
+QtCore/qstring.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qscopedpointer.h
+QtCore/qglobal.h
+-
+stdlib.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qset.h
+QtCore/qhash.h
+-
+QtCore/qcontainertools_impl.h
+-
+initializer_list
+-
+iterator
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qshareddata.h
+QtCore/qglobal.h
+-
+QtCore/qatomic.h
+-
+QtCore/qhash.h
+-
+QtCore/qhashfunctions.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qsharedpointer.h
+QtCore/qglobal.h
+-
+QtCore/qatomic.h
+-
+QtCore/qshareddata.h
+-
+QtCore/qsharedpointer_impl.h
+-
+memory
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qsharedpointer_impl.h
+new
+-
+QtCore/qatomic.h
+-
+QtCore/qobject.h
+-
+QtCore/qhash.h
+-
+QtCore/qhashfunctions.h
+-
+memory
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qsize.h
+QtCore/qnamespace.h
+-
+QtCore/qmargins.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qstandardpaths.h
+QtCore/qstringlist.h
+-
+QtCore/qobjectdefs.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qstring.h
+QtCore/qchar.h
+-
+QtCore/qbytearray.h
+-
+QtCore/qrefcount.h
+-
+QtCore/qnamespace.h
+-
+QtCore/qstringliteral.h
+-
+QtCore/qstringalgorithms.h
+-
+QtCore/qstringview.h
+-
+string
+-
+iterator
+-
+stdarg.h
+-
+QtCore/qstringbuilder.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qstringalgorithms.h
+QtCore/qnamespace.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qstringbuilder.h
+QtCore/qstring.h
+-
+QtCore/qbytearray.h
+-
+string.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qstringlist.h
+QtCore/qlist.h
+-
+QtCore/qalgorithms.h
+-
+QtCore/qcontainertools_impl.h
+-
+QtCore/qregexp.h
+-
+QtCore/qstring.h
+-
+QtCore/qstringmatcher.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qstringliteral.h
+QtCore/qarraydata.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qstringmatcher.h
+QtCore/qstring.h
+-
+QtCore/qstringview.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qstringview.h
+QtCore/qchar.h
+-
+QtCore/qbytearray.h
+-
+QtCore/qstringliteral.h
+-
+QtCore/qstringalgorithms.h
+-
+string
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qsysinfo.h
+QtCore/qglobal.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qsystemdetection.h
+QtCore/qglobal.h
+-
+TargetConditionals.h
+-
+Availability.h
+-
+AvailabilityMacros.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qtcore-config.h
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qtextstream.h
+QtCore/qiodevice.h
+-
+QtCore/qstring.h
+-
+QtCore/qchar.h
+-
+QtCore/qlocale.h
+-
+QtCore/qscopedpointer.h
+-
+stdio.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qtypeinfo.h
+QtCore/qglobal.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qurl.h
+QtCore/qbytearray.h
+-
+QtCore/qobjectdefs.h
+-
+QtCore/qstring.h
+-
+QtCore/qlist.h
+-
+QtCore/qpair.h
+-
+QtCore/qglobal.h
+-
+QtCore/qurlquery.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qurlquery.h
+QtCore/qpair.h
+-
+QtCore/qshareddata.h
+-
+QtCore/qurl.h
+-
+QtCore/qstringlist.h
+-
+initializer_list
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qvariant.h
+QtCore/qatomic.h
+-
+QtCore/qbytearray.h
+-
+QtCore/qlist.h
+-
+QtCore/qmetatype.h
+-
+QtCore/qmap.h
+-
+QtCore/qhash.h
+-
+QtCore/qstring.h
+-
+QtCore/qstringlist.h
+-
+QtCore/qobject.h
+-
+QtCore/qbytearraylist.h
+-
+variant
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qvarlengtharray.h
+QtCore/qcontainerfwd.h
+-
+QtCore/qglobal.h
+-
+QtCore/qalgorithms.h
+-
+QtCore/qcontainertools_impl.h
+-
+QtCore/qhashfunctions.h
+-
+algorithm
+-
+initializer_list
+-
+iterator
+-
+new
+-
+string.h
+-
+stdlib.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qvector.h
+QtCore/qalgorithms.h
+-
+QtCore/qiterator.h
+-
+QtCore/qrefcount.h
+-
+QtCore/qarraydata.h
+-
+QtCore/qhashfunctions.h
+-
+QtCore/qcontainertools_impl.h
+-
+iterator
+-
+initializer_list
+-
+vector
+-
+stdlib.h
+-
+string.h
+-
+algorithm
+-
+QtCore/qpoint.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtCore/qversiontagging.h
+QtCore/qglobal.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtGui/QClipboard
+qclipboard.h
+/usr/include/x86_64-linux-gnu/qt5/QtGui/qclipboard.h
+
+/usr/include/x86_64-linux-gnu/qt5/QtGui/QDesktopServices
+qdesktopservices.h
+/usr/include/x86_64-linux-gnu/qt5/QtGui/qdesktopservices.h
+
+/usr/include/x86_64-linux-gnu/qt5/QtGui/QImage
+qimage.h
+/usr/include/x86_64-linux-gnu/qt5/QtGui/qimage.h
+
+/usr/include/x86_64-linux-gnu/qt5/QtGui/QPainter
+qpainter.h
+/usr/include/x86_64-linux-gnu/qt5/QtGui/qpainter.h
+
+/usr/include/x86_64-linux-gnu/qt5/QtGui/qbrush.h
+QtGui/qtguiglobal.h
+-
+QtCore/qpair.h
+-
+QtCore/qpoint.h
+-
+QtCore/qvector.h
+-
+QtCore/qscopedpointer.h
+-
+QtGui/qcolor.h
+-
+QtGui/qmatrix.h
+-
+QtGui/qtransform.h
+-
+QtGui/qimage.h
+-
+QtGui/qpixmap.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtGui/qclipboard.h
+QtGui/qtguiglobal.h
+-
+QtCore/qobject.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtGui/qcolor.h
+QtGui/qtguiglobal.h
+-
+QtGui/qrgb.h
+-
+QtCore/qnamespace.h
+-
+QtCore/qstringlist.h
+-
+QtGui/qrgba64.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtGui/qcursor.h
+QtGui/qtguiglobal.h
+-
+QtCore/qpoint.h
+-
+QtGui/qwindowdefs.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtGui/qdesktopservices.h
+QtGui/qtguiglobal.h
+-
+QtCore/qstring.h
+-
+QtCore/qstandardpaths.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtGui/qevent.h
+QtGui/qtguiglobal.h
+-
+QtGui/qwindowdefs.h
+-
+QtGui/qregion.h
+-
+QtCore/qnamespace.h
+-
+QtCore/qstring.h
+-
+QtGui/qkeysequence.h
+-
+QtCore/qcoreevent.h
+-
+QtCore/qvariant.h
+-
+QtCore/qmap.h
+-
+QtCore/qvector.h
+-
+QtCore/qset.h
+-
+QtCore/qurl.h
+-
+QtCore/qfile.h
+-
+QtGui/qvector2d.h
+-
+QtGui/qtouchdevice.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtGui/qfont.h
+QtGui/qtguiglobal.h
+-
+QtGui/qwindowdefs.h
+-
+QtCore/qstring.h
+-
+QtCore/qsharedpointer.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtGui/qfontinfo.h
+QtGui/qtguiglobal.h
+-
+QtGui/qfont.h
+-
+QtCore/qsharedpointer.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtGui/qfontmetrics.h
+QtGui/qtguiglobal.h
+-
+QtGui/qfont.h
+-
+QtCore/qsharedpointer.h
+-
+QtCore/qrect.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtGui/qguiapplication.h
+QtGui/qtguiglobal.h
+-
+QtCore/qcoreapplication.h
+-
+QtGui/qwindowdefs.h
+-
+QtGui/qinputmethod.h
+-
+QtCore/qlocale.h
+-
+QtCore/qpoint.h
+-
+QtCore/qsize.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtGui/qicon.h
+QtGui/qtguiglobal.h
+-
+QtCore/qsize.h
+-
+QtCore/qlist.h
+-
+QtGui/qpixmap.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtGui/qimage.h
+QtGui/qtguiglobal.h
+-
+QtGui/qcolor.h
+-
+QtGui/qrgb.h
+-
+QtGui/qpaintdevice.h
+-
+QtGui/qpixelformat.h
+-
+QtGui/qtransform.h
+-
+QtCore/qbytearray.h
+-
+QtCore/qrect.h
+-
+QtCore/qstring.h
+-
+QtCore/qstringlist.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtGui/qinputmethod.h
+QtGui/qtguiglobal.h
+-
+QtCore/qobject.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtGui/qkeysequence.h
+QtGui/qtguiglobal.h
+-
+QtCore/qstring.h
+-
+QtCore/qobjectdefs.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtGui/qmatrix.h
+QtGui/qtguiglobal.h
+-
+QtGui/qpolygon.h
+-
+QtGui/qregion.h
+-
+QtGui/qwindowdefs.h
+-
+QtCore/qline.h
+-
+QtCore/qpoint.h
+-
+QtCore/qrect.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtGui/qpaintdevice.h
+QtGui/qtguiglobal.h
+-
+QtGui/qwindowdefs.h
+-
+QtCore/qrect.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtGui/qpainter.h
+QtGui/qtguiglobal.h
+-
+QtCore/qnamespace.h
+-
+QtCore/qrect.h
+-
+QtCore/qpoint.h
+-
+QtCore/qscopedpointer.h
+-
+QtGui/qpixmap.h
+-
+QtGui/qimage.h
+-
+QtGui/qtextoption.h
+-
+QtGui/qpolygon.h
+-
+QtGui/qpen.h
+-
+QtGui/qbrush.h
+-
+QtGui/qmatrix.h
+-
+QtGui/qtransform.h
+-
+QtGui/qfontinfo.h
+-
+QtGui/qfontmetrics.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtGui/qpalette.h
+QtGui/qtguiglobal.h
+-
+QtGui/qwindowdefs.h
+-
+QtGui/qcolor.h
+-
+QtGui/qbrush.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtGui/qpen.h
+QtGui/qtguiglobal.h
+-
+QtGui/qcolor.h
+-
+QtGui/qbrush.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtGui/qpixelformat.h
+QtGui/qtguiglobal.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtGui/qpixmap.h
+QtGui/qtguiglobal.h
+-
+QtGui/qpaintdevice.h
+-
+QtGui/qcolor.h
+-
+QtCore/qnamespace.h
+-
+QtCore/qstring.h
+-
+QtCore/qsharedpointer.h
+-
+QtGui/qimage.h
+-
+QtGui/qtransform.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtGui/qpolygon.h
+QtGui/qtguiglobal.h
+-
+QtCore/qvector.h
+-
+QtCore/qpoint.h
+-
+QtCore/qrect.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtGui/qregion.h
+QtGui/qtguiglobal.h
+-
+QtCore/qatomic.h
+-
+QtCore/qrect.h
+-
+QtGui/qwindowdefs.h
+-
+QtCore/qdatastream.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtGui/qrgb.h
+QtGui/qtguiglobal.h
+-
+QtCore/qprocessordetection.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtGui/qrgba64.h
+QtGui/qtguiglobal.h
+-
+QtCore/qprocessordetection.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtGui/qtextcursor.h
+QtGui/qtguiglobal.h
+-
+QtCore/qstring.h
+-
+QtCore/qshareddata.h
+-
+QtGui/qtextformat.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtGui/qtextformat.h
+QtGui/qtguiglobal.h
+-
+QtGui/qcolor.h
+-
+QtGui/qfont.h
+-
+QtCore/qshareddata.h
+-
+QtCore/qvector.h
+-
+QtCore/qvariant.h
+-
+QtGui/qpen.h
+-
+QtGui/qbrush.h
+-
+QtGui/qtextoption.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtGui/qtextoption.h
+QtGui/qtguiglobal.h
+-
+QtCore/qnamespace.h
+-
+QtCore/qchar.h
+-
+QtCore/qmetatype.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtGui/qtgui-config.h
+
+/usr/include/x86_64-linux-gnu/qt5/QtGui/qtguiglobal.h
+QtCore/qglobal.h
+-
+QtGui/qtgui-config.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtGui/qtouchdevice.h
+QtGui/qtguiglobal.h
+-
+QtCore/qobject.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtGui/qtransform.h
+QtGui/qtguiglobal.h
+-
+QtGui/qmatrix.h
+-
+QtGui/qpolygon.h
+-
+QtGui/qregion.h
+-
+QtGui/qwindowdefs.h
+-
+QtCore/qline.h
+-
+QtCore/qpoint.h
+-
+QtCore/qrect.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtGui/qvector2d.h
+QtGui/qtguiglobal.h
+-
+QtCore/qpoint.h
+-
+QtCore/qmetatype.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtGui/qwindowdefs.h
+QtGui/qtguiglobal.h
+-
+QtCore/qobjectdefs.h
+-
+QtCore/qnamespace.h
+-
+QtGui/qwindowdefs_win.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtGui/qwindowdefs_win.h
+QtGui/qtguiglobal.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtWidgets/QApplication
+qapplication.h
+/usr/include/x86_64-linux-gnu/qt5/QtWidgets/qapplication.h
+
+/usr/include/x86_64-linux-gnu/qt5/QtWidgets/QInputDialog
+qinputdialog.h
+/usr/include/x86_64-linux-gnu/qt5/QtWidgets/qinputdialog.h
+
+/usr/include/x86_64-linux-gnu/qt5/QtWidgets/QMessageBox
+qmessagebox.h
+/usr/include/x86_64-linux-gnu/qt5/QtWidgets/qmessagebox.h
+
+/usr/include/x86_64-linux-gnu/qt5/QtWidgets/QScrollBar
+qscrollbar.h
+/usr/include/x86_64-linux-gnu/qt5/QtWidgets/qscrollbar.h
+
+/usr/include/x86_64-linux-gnu/qt5/QtWidgets/QStyle
+qstyle.h
+/usr/include/x86_64-linux-gnu/qt5/QtWidgets/qstyle.h
+
+/usr/include/x86_64-linux-gnu/qt5/QtWidgets/QWidget
+qwidget.h
+/usr/include/x86_64-linux-gnu/qt5/QtWidgets/qwidget.h
+
+/usr/include/x86_64-linux-gnu/qt5/QtWidgets/qabstractslider.h
+QtWidgets/qtwidgetsglobal.h
+-
+QtWidgets/qwidget.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtWidgets/qapplication.h
+QtWidgets/qtwidgetsglobal.h
+-
+QtCore/qcoreapplication.h
+-
+QtGui/qwindowdefs.h
+-
+QtCore/qpoint.h
+-
+QtCore/qsize.h
+-
+QtGui/qcursor.h
+-
+QtWidgets/qdesktopwidget.h
+-
+QtGui/qguiapplication.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtWidgets/qdesktopwidget.h
+QtWidgets/qtwidgetsglobal.h
+-
+QtWidgets/qwidget.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtWidgets/qdialog.h
+QtWidgets/qtwidgetsglobal.h
+-
+QtWidgets/qwidget.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtWidgets/qframe.h
+QtWidgets/qtwidgetsglobal.h
+-
+QtWidgets/qwidget.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtWidgets/qinputdialog.h
+QtWidgets/qtwidgetsglobal.h
+-
+QtCore/qstring.h
+-
+QtWidgets/qlineedit.h
+-
+QtWidgets/qdialog.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtWidgets/qlineedit.h
+QtWidgets/qtwidgetsglobal.h
+-
+QtWidgets/qframe.h
+-
+QtGui/qtextcursor.h
+-
+QtCore/qstring.h
+-
+QtCore/qmargins.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtWidgets/qmessagebox.h
+QtWidgets/qtwidgetsglobal.h
+-
+QtWidgets/qdialog.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtWidgets/qscrollbar.h
+QtWidgets/qtwidgetsglobal.h
+-
+QtWidgets/qwidget.h
+-
+QtWidgets/qabstractslider.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtWidgets/qsizepolicy.h
+QtWidgets/qtwidgetsglobal.h
+-
+QtCore/qobject.h
+-
+QtCore/qalgorithms.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtWidgets/qstyle.h
+QtWidgets/qtwidgetsglobal.h
+-
+QtCore/qobject.h
+-
+QtCore/qrect.h
+-
+QtCore/qsize.h
+-
+QtGui/qicon.h
+-
+QtGui/qpixmap.h
+-
+QtGui/qpalette.h
+-
+QtWidgets/qsizepolicy.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtWidgets/qtwidgets-config.h
+
+/usr/include/x86_64-linux-gnu/qt5/QtWidgets/qtwidgetsglobal.h
+QtGui/qtguiglobal.h
+-
+QtWidgets/qtwidgets-config.h
+-
+
+/usr/include/x86_64-linux-gnu/qt5/QtWidgets/qwidget.h
+QtWidgets/qtwidgetsglobal.h
+-
+QtGui/qwindowdefs.h
+-
+QtCore/qobject.h
+-
+QtCore/qmargins.h
+-
+QtGui/qpaintdevice.h
+-
+QtGui/qpalette.h
+-
+QtGui/qfont.h
+-
+QtGui/qfontmetrics.h
+-
+QtGui/qfontinfo.h
+-
+QtWidgets/qsizepolicy.h
+-
+QtGui/qregion.h
+-
+QtGui/qbrush.h
+-
+QtGui/qcursor.h
+-
+QtGui/qkeysequence.h
+-
+QtGui/qevent.h
+-
+
+aconf.h
+aconf2.h
+-
+
+aconf2.h
+AvailabilityMacros.h
+-
+
+goo/FixedPoint.h
+aconf.h
+-
+stdio.h
+-
+stdlib.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/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/SplashBitmap.h
+aconf.h
+-
+stdio.h
+-
+limits.h
+-
+stdint.h
+-
+SplashTypes.h
+splash/SplashTypes.h
+
+splash/SplashTypes.h
+aconf.h
+-
+gtypes.h
+splash/gtypes.h
+FixedPoint.h
+splash/FixedPoint.h
+
+xpdf/Array.h
+aconf.h
+-
+GMutex.h
+xpdf/GMutex.h
+Object.h
+xpdf/Object.h
+
+xpdf/Catalog.h
+aconf.h
+-
+GMutex.h
+xpdf/GMutex.h
+CharTypes.h
+xpdf/CharTypes.h
+
+xpdf/CharTypes.h
+
+xpdf/Dict.h
+aconf.h
+-
+GMutex.h
+xpdf/GMutex.h
+Object.h
+xpdf/Object.h
+
+xpdf/DisplayState.h
+aconf.h
+-
+gtypes.h
+xpdf/gtypes.h
+SplashTypes.h
+xpdf/SplashTypes.h
+
+xpdf/Error.h
+aconf.h
+-
+stdio.h
+-
+config.h
+xpdf/config.h
+gfile.h
+xpdf/gfile.h
+
+xpdf/ErrorCodes.h
+
+xpdf/Function.h
+aconf.h
+-
+gtypes.h
+xpdf/gtypes.h
+Object.h
+xpdf/Object.h
+
+xpdf/GfxFont.h
+aconf.h
+-
+gtypes.h
+xpdf/gtypes.h
+GString.h
+xpdf/GString.h
+Object.h
+xpdf/Object.h
+CharTypes.h
+xpdf/CharTypes.h
+
+xpdf/GfxState.h
+aconf.h
+-
+gtypes.h
+xpdf/gtypes.h
+Object.h
+xpdf/Object.h
+Function.h
+xpdf/Function.h
+
+xpdf/GlobalParams.h
+aconf.h
+-
+stdio.h
+-
+windows.h
+-
+gtypes.h
+xpdf/gtypes.h
+CharTypes.h
+xpdf/CharTypes.h
+GMutex.h
+xpdf/GMutex.h
+
+xpdf/Link.h
+aconf.h
+-
+Object.h
+xpdf/Object.h
+
+xpdf/Object.h
+aconf.h
+-
+stdio.h
+-
+string.h
+-
+gtypes.h
+xpdf/gtypes.h
+gmem.h
+xpdf/gmem.h
+gfile.h
+xpdf/gfile.h
+GString.h
+xpdf/GString.h
+GMutex.h
+xpdf/GMutex.h
+Array.h
+xpdf/Array.h
+Dict.h
+xpdf/Dict.h
+Stream.h
+xpdf/Stream.h
+
+xpdf/OutputDev.h
+aconf.h
+-
+gtypes.h
+xpdf/gtypes.h
+CharTypes.h
+xpdf/CharTypes.h
+
+xpdf/PDFCore.h
+aconf.h
+-
+stdlib.h
+-
+SplashTypes.h
+xpdf/SplashTypes.h
+CharTypes.h
+xpdf/CharTypes.h
+DisplayState.h
+xpdf/DisplayState.h
+TextOutputDev.h
+xpdf/TextOutputDev.h
+
+xpdf/PDFDoc.h
+aconf.h
+-
+stdio.h
+-
+XRef.h
+xpdf/XRef.h
+Catalog.h
+xpdf/Catalog.h
+Page.h
+xpdf/Page.h
+
+xpdf/PSOutputDev.h
+aconf.h
+-
+stddef.h
+-
+config.h
+xpdf/config.h
+Object.h
+xpdf/Object.h
+GlobalParams.h
+xpdf/GlobalParams.h
+OutputDev.h
+xpdf/OutputDev.h
+
+xpdf/Page.h
+aconf.h
+-
+Object.h
+xpdf/Object.h
+
+xpdf/Stream.h
+aconf.h
+-
+stdio.h
+-
+jpeglib.h
+-
+setjmp.h
+-
+gtypes.h
+xpdf/gtypes.h
+gfile.h
+xpdf/gfile.h
+Object.h
+xpdf/Object.h
+
+xpdf/TextOutputDev.h
+aconf.h
+-
+stdio.h
+-
+gtypes.h
+xpdf/gtypes.h
+GfxFont.h
+xpdf/GfxFont.h
+OutputDev.h
+xpdf/OutputDev.h
+
+xpdf/TileMap.h
+aconf.h
+-
+gtypes.h
+xpdf/gtypes.h
+
+xpdf/XRef.h
+aconf.h
+-
+gtypes.h
+xpdf/gtypes.h
+gfile.h
+xpdf/gfile.h
+Object.h
+xpdf/Object.h
+GMutex.h
+xpdf/GMutex.h
+
+xpdf/config.h
+
diff --git a/xpdf-qt/CMakeFiles/xpdf.dir/DependInfo.cmake b/xpdf-qt/CMakeFiles/xpdf.dir/DependInfo.cmake
new file mode 100644
index 0000000..53943b3
--- /dev/null
+++ b/xpdf-qt/CMakeFiles/xpdf.dir/DependInfo.cmake
@@ -0,0 +1,53 @@
+# 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-qt/QtPDFCore.cc" "/home/calvin/src/xpdf-4.04/xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o"
+ "/home/calvin/src/xpdf-4.04/xpdf-qt/XpdfApp.cc" "/home/calvin/src/xpdf-4.04/xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o"
+ "/home/calvin/src/xpdf-4.04/xpdf-qt/XpdfViewer.cc" "/home/calvin/src/xpdf-4.04/xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o"
+ "/home/calvin/src/xpdf-4.04/xpdf-qt/XpdfWidget.cc" "/home/calvin/src/xpdf-4.04/xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o"
+ "/home/calvin/src/xpdf-4.04/xpdf-qt/XpdfWidgetPrint.cc" "/home/calvin/src/xpdf-4.04/xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o"
+ "/home/calvin/src/xpdf-4.04/xpdf-qt/moc_XpdfApp.cpp" "/home/calvin/src/xpdf-4.04/xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o"
+ "/home/calvin/src/xpdf-4.04/xpdf-qt/moc_XpdfViewer.cpp" "/home/calvin/src/xpdf-4.04/xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o"
+ "/home/calvin/src/xpdf-4.04/xpdf-qt/moc_XpdfWidget.cpp" "/home/calvin/src/xpdf-4.04/xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o"
+ "/home/calvin/src/xpdf-4.04/xpdf-qt/qrc_icons.cpp" "/home/calvin/src/xpdf-4.04/xpdf-qt/CMakeFiles/xpdf.dir/qrc_icons.cpp.o"
+ "/home/calvin/src/xpdf-4.04/xpdf-qt/xpdf.cc" "/home/calvin/src/xpdf-4.04/xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o"
+ )
+set(CMAKE_CXX_COMPILER_ID "GNU")
+
+# Preprocessor definitions for this target.
+set(CMAKE_TARGET_DEFINITIONS_CXX
+ "QT_CORE_LIB"
+ "QT_GUI_LIB"
+ "QT_NETWORK_LIB"
+ "QT_NO_DEBUG"
+ "QT_PRINTSUPPORT_LIB"
+ "QT_WIDGETS_LIB"
+ "XPDFWIDGET_PRINTING=1"
+ )
+
+# The include file search paths:
+set(CMAKE_CXX_TARGET_INCLUDE_PATH
+ "."
+ "goo"
+ "fofi"
+ "splash"
+ "xpdf"
+ "/usr/include/x86_64-linux-gnu/qt5"
+ "/usr/include/x86_64-linux-gnu/qt5/QtWidgets"
+ "/usr/include/x86_64-linux-gnu/qt5/QtGui"
+ "/usr/include/x86_64-linux-gnu/qt5/QtCore"
+ "/usr/lib/x86_64-linux-gnu/qt5/mkspecs/linux-g++ /usr/include/x86_64-linux-gnu/qt5"
+ "/usr/include/x86_64-linux-gnu/qt5/QtNetwork"
+ "/usr/include/x86_64-linux-gnu/qt5/QtPrintSupport"
+ "/usr/lib/x86_64-linux-gnu/qt5/mkspecs/linux-g++"
+ )
+
+# 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-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o b/xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o
new file mode 100644
index 0000000..9a4b536
--- /dev/null
+++ b/xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o
Binary files differ
diff --git a/xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o b/xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o
new file mode 100644
index 0000000..3e3c607
--- /dev/null
+++ b/xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o
Binary files differ
diff --git a/xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o b/xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o
new file mode 100644
index 0000000..ab1667c
--- /dev/null
+++ b/xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o
Binary files differ
diff --git a/xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o b/xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o
new file mode 100644
index 0000000..41b4e53
--- /dev/null
+++ b/xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o
Binary files differ
diff --git a/xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o b/xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o
new file mode 100644
index 0000000..de6529d
--- /dev/null
+++ b/xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o
Binary files differ
diff --git a/xpdf-qt/CMakeFiles/xpdf.dir/build.make b/xpdf-qt/CMakeFiles/xpdf.dir/build.make
new file mode 100644
index 0000000..386e1f5
--- /dev/null
+++ b/xpdf-qt/CMakeFiles/xpdf.dir/build.make
@@ -0,0 +1,479 @@
+# 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-qt/CMakeFiles/xpdf.dir/depend.make
+
+# Include the progress variables for this target.
+include xpdf-qt/CMakeFiles/xpdf.dir/progress.make
+
+# Include the compile flags for this target's objects.
+include xpdf-qt/CMakeFiles/xpdf.dir/flags.make
+
+xpdf-qt/moc_XpdfApp.cpp: xpdf-qt/XpdfApp.h
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --blue --bold --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_1) "Generating moc_XpdfApp.cpp"
+ cd /home/calvin/src/xpdf-4.04/xpdf-qt && /usr/lib/qt5/bin/moc @/home/calvin/src/xpdf-4.04/xpdf-qt/moc_XpdfApp.cpp_parameters
+
+xpdf-qt/moc_XpdfViewer.cpp: xpdf-qt/XpdfViewer.h
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --blue --bold --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_2) "Generating moc_XpdfViewer.cpp"
+ cd /home/calvin/src/xpdf-4.04/xpdf-qt && /usr/lib/qt5/bin/moc @/home/calvin/src/xpdf-4.04/xpdf-qt/moc_XpdfViewer.cpp_parameters
+
+xpdf-qt/moc_XpdfWidget.cpp: xpdf-qt/XpdfWidget.h
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --blue --bold --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_3) "Generating moc_XpdfWidget.cpp"
+ cd /home/calvin/src/xpdf-4.04/xpdf-qt && /usr/lib/qt5/bin/moc @/home/calvin/src/xpdf-4.04/xpdf-qt/moc_XpdfWidget.cpp_parameters
+
+xpdf-qt/qrc_icons.cpp: xpdf-qt/back.svg
+xpdf-qt/qrc_icons.cpp: xpdf-qt/forward.svg
+xpdf-qt/qrc_icons.cpp: xpdf-qt/findNext.svg
+xpdf-qt/qrc_icons.cpp: xpdf-qt/findPrevious.svg
+xpdf-qt/qrc_icons.cpp: xpdf-qt/findSettings.svg
+xpdf-qt/qrc_icons.cpp: xpdf-qt/fitPage.svg
+xpdf-qt/qrc_icons.cpp: xpdf-qt/fitPageOn.svg
+xpdf-qt/qrc_icons.cpp: xpdf-qt/fitWidth.svg
+xpdf-qt/qrc_icons.cpp: xpdf-qt/fitWidthOn.svg
+xpdf-qt/qrc_icons.cpp: xpdf-qt/toggleSidebar.svg
+xpdf-qt/qrc_icons.cpp: xpdf-qt/zoomIn.svg
+xpdf-qt/qrc_icons.cpp: xpdf-qt/zoomOut.svg
+xpdf-qt/qrc_icons.cpp: xpdf-qt/indicator-icon0.svg
+xpdf-qt/qrc_icons.cpp: xpdf-qt/indicator-icon1.svg
+xpdf-qt/qrc_icons.cpp: xpdf-qt/indicator-icon2.svg
+xpdf-qt/qrc_icons.cpp: xpdf-qt/indicator-icon3.svg
+xpdf-qt/qrc_icons.cpp: xpdf-qt/indicator-icon4.svg
+xpdf-qt/qrc_icons.cpp: xpdf-qt/indicator-icon5.svg
+xpdf-qt/qrc_icons.cpp: xpdf-qt/indicator-icon6.svg
+xpdf-qt/qrc_icons.cpp: xpdf-qt/indicator-icon7.svg
+xpdf-qt/qrc_icons.cpp: xpdf-qt/indicator-icon-err0.svg
+xpdf-qt/qrc_icons.cpp: xpdf-qt/indicator-icon-err1.svg
+xpdf-qt/qrc_icons.cpp: xpdf-qt/indicator-icon-err2.svg
+xpdf-qt/qrc_icons.cpp: xpdf-qt/indicator-icon-err3.svg
+xpdf-qt/qrc_icons.cpp: xpdf-qt/indicator-icon-err4.svg
+xpdf-qt/qrc_icons.cpp: xpdf-qt/indicator-icon-err5.svg
+xpdf-qt/qrc_icons.cpp: xpdf-qt/indicator-icon-err6.svg
+xpdf-qt/qrc_icons.cpp: xpdf-qt/indicator-icon-err7.svg
+xpdf-qt/qrc_icons.cpp: xpdf-qt/selectModeLinear.svg
+xpdf-qt/qrc_icons.cpp: xpdf-qt/selectModeBlock.svg
+xpdf-qt/qrc_icons.cpp: xpdf-qt/xpdf-icon.svg
+xpdf-qt/qrc_icons.cpp: xpdf-qt/icons.qrc.depends
+xpdf-qt/qrc_icons.cpp: xpdf-qt/icons.qrc
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --blue --bold --progress-dir=/home/calvin/src/xpdf-4.04/CMakeFiles --progress-num=$(CMAKE_PROGRESS_4) "Generating qrc_icons.cpp"
+ cd /home/calvin/src/xpdf-4.04/xpdf-qt && /usr/lib/qt5/bin/rcc --name icons --output /home/calvin/src/xpdf-4.04/xpdf-qt/qrc_icons.cpp /home/calvin/src/xpdf-4.04/xpdf-qt/icons.qrc
+
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: xpdf-qt/CMakeFiles/xpdf.dir/flags.make
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: xpdf-qt/XpdfWidgetPrint.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-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o"
+ cd /home/calvin/src/xpdf-4.04/xpdf-qt && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o -c /home/calvin/src/xpdf-4.04/xpdf-qt/XpdfWidgetPrint.cc
+
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.i: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.i"
+ cd /home/calvin/src/xpdf-4.04/xpdf-qt && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf-qt/XpdfWidgetPrint.cc > CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.i
+
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.s: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.s"
+ cd /home/calvin/src/xpdf-4.04/xpdf-qt && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf-qt/XpdfWidgetPrint.cc -o CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.s
+
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: xpdf-qt/CMakeFiles/xpdf.dir/flags.make
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: xpdf-qt/QtPDFCore.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-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o"
+ cd /home/calvin/src/xpdf-4.04/xpdf-qt && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/xpdf.dir/QtPDFCore.cc.o -c /home/calvin/src/xpdf-4.04/xpdf-qt/QtPDFCore.cc
+
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.i: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/xpdf.dir/QtPDFCore.cc.i"
+ cd /home/calvin/src/xpdf-4.04/xpdf-qt && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf-qt/QtPDFCore.cc > CMakeFiles/xpdf.dir/QtPDFCore.cc.i
+
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.s: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/xpdf.dir/QtPDFCore.cc.s"
+ cd /home/calvin/src/xpdf-4.04/xpdf-qt && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf-qt/QtPDFCore.cc -o CMakeFiles/xpdf.dir/QtPDFCore.cc.s
+
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: xpdf-qt/CMakeFiles/xpdf.dir/flags.make
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: xpdf-qt/XpdfApp.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-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o"
+ cd /home/calvin/src/xpdf-4.04/xpdf-qt && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/xpdf.dir/XpdfApp.cc.o -c /home/calvin/src/xpdf-4.04/xpdf-qt/XpdfApp.cc
+
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.i: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/xpdf.dir/XpdfApp.cc.i"
+ cd /home/calvin/src/xpdf-4.04/xpdf-qt && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf-qt/XpdfApp.cc > CMakeFiles/xpdf.dir/XpdfApp.cc.i
+
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.s: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/xpdf.dir/XpdfApp.cc.s"
+ cd /home/calvin/src/xpdf-4.04/xpdf-qt && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf-qt/XpdfApp.cc -o CMakeFiles/xpdf.dir/XpdfApp.cc.s
+
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: xpdf-qt/CMakeFiles/xpdf.dir/flags.make
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: xpdf-qt/XpdfViewer.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-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o"
+ cd /home/calvin/src/xpdf-4.04/xpdf-qt && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/xpdf.dir/XpdfViewer.cc.o -c /home/calvin/src/xpdf-4.04/xpdf-qt/XpdfViewer.cc
+
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.i: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/xpdf.dir/XpdfViewer.cc.i"
+ cd /home/calvin/src/xpdf-4.04/xpdf-qt && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf-qt/XpdfViewer.cc > CMakeFiles/xpdf.dir/XpdfViewer.cc.i
+
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.s: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/xpdf.dir/XpdfViewer.cc.s"
+ cd /home/calvin/src/xpdf-4.04/xpdf-qt && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf-qt/XpdfViewer.cc -o CMakeFiles/xpdf.dir/XpdfViewer.cc.s
+
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: xpdf-qt/CMakeFiles/xpdf.dir/flags.make
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: xpdf-qt/XpdfWidget.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-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o"
+ cd /home/calvin/src/xpdf-4.04/xpdf-qt && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/xpdf.dir/XpdfWidget.cc.o -c /home/calvin/src/xpdf-4.04/xpdf-qt/XpdfWidget.cc
+
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.i: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/xpdf.dir/XpdfWidget.cc.i"
+ cd /home/calvin/src/xpdf-4.04/xpdf-qt && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf-qt/XpdfWidget.cc > CMakeFiles/xpdf.dir/XpdfWidget.cc.i
+
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.s: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/xpdf.dir/XpdfWidget.cc.s"
+ cd /home/calvin/src/xpdf-4.04/xpdf-qt && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf-qt/XpdfWidget.cc -o CMakeFiles/xpdf.dir/XpdfWidget.cc.s
+
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: xpdf-qt/CMakeFiles/xpdf.dir/flags.make
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: xpdf-qt/xpdf.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-qt/CMakeFiles/xpdf.dir/xpdf.cc.o"
+ cd /home/calvin/src/xpdf-4.04/xpdf-qt && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/xpdf.dir/xpdf.cc.o -c /home/calvin/src/xpdf-4.04/xpdf-qt/xpdf.cc
+
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.i: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/xpdf.dir/xpdf.cc.i"
+ cd /home/calvin/src/xpdf-4.04/xpdf-qt && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf-qt/xpdf.cc > CMakeFiles/xpdf.dir/xpdf.cc.i
+
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.s: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/xpdf.dir/xpdf.cc.s"
+ cd /home/calvin/src/xpdf-4.04/xpdf-qt && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf-qt/xpdf.cc -o CMakeFiles/xpdf.dir/xpdf.cc.s
+
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: xpdf-qt/CMakeFiles/xpdf.dir/flags.make
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: xpdf-qt/moc_XpdfApp.cpp
+ @$(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-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o"
+ cd /home/calvin/src/xpdf-4.04/xpdf-qt && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o -c /home/calvin/src/xpdf-4.04/xpdf-qt/moc_XpdfApp.cpp
+
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.i: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.i"
+ cd /home/calvin/src/xpdf-4.04/xpdf-qt && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf-qt/moc_XpdfApp.cpp > CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.i
+
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.s: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.s"
+ cd /home/calvin/src/xpdf-4.04/xpdf-qt && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf-qt/moc_XpdfApp.cpp -o CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.s
+
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: xpdf-qt/CMakeFiles/xpdf.dir/flags.make
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: xpdf-qt/moc_XpdfViewer.cpp
+ @$(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-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o"
+ cd /home/calvin/src/xpdf-4.04/xpdf-qt && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o -c /home/calvin/src/xpdf-4.04/xpdf-qt/moc_XpdfViewer.cpp
+
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.i: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.i"
+ cd /home/calvin/src/xpdf-4.04/xpdf-qt && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf-qt/moc_XpdfViewer.cpp > CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.i
+
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.s: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.s"
+ cd /home/calvin/src/xpdf-4.04/xpdf-qt && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf-qt/moc_XpdfViewer.cpp -o CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.s
+
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: xpdf-qt/CMakeFiles/xpdf.dir/flags.make
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: xpdf-qt/moc_XpdfWidget.cpp
+ @$(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-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o"
+ cd /home/calvin/src/xpdf-4.04/xpdf-qt && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o -c /home/calvin/src/xpdf-4.04/xpdf-qt/moc_XpdfWidget.cpp
+
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.i: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.i"
+ cd /home/calvin/src/xpdf-4.04/xpdf-qt && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf-qt/moc_XpdfWidget.cpp > CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.i
+
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.s: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.s"
+ cd /home/calvin/src/xpdf-4.04/xpdf-qt && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf-qt/moc_XpdfWidget.cpp -o CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.s
+
+xpdf-qt/CMakeFiles/xpdf.dir/qrc_icons.cpp.o: xpdf-qt/CMakeFiles/xpdf.dir/flags.make
+xpdf-qt/CMakeFiles/xpdf.dir/qrc_icons.cpp.o: xpdf-qt/qrc_icons.cpp
+ @$(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-qt/CMakeFiles/xpdf.dir/qrc_icons.cpp.o"
+ cd /home/calvin/src/xpdf-4.04/xpdf-qt && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/xpdf.dir/qrc_icons.cpp.o -c /home/calvin/src/xpdf-4.04/xpdf-qt/qrc_icons.cpp
+
+xpdf-qt/CMakeFiles/xpdf.dir/qrc_icons.cpp.i: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/xpdf.dir/qrc_icons.cpp.i"
+ cd /home/calvin/src/xpdf-4.04/xpdf-qt && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/calvin/src/xpdf-4.04/xpdf-qt/qrc_icons.cpp > CMakeFiles/xpdf.dir/qrc_icons.cpp.i
+
+xpdf-qt/CMakeFiles/xpdf.dir/qrc_icons.cpp.s: cmake_force
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/xpdf.dir/qrc_icons.cpp.s"
+ cd /home/calvin/src/xpdf-4.04/xpdf-qt && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/calvin/src/xpdf-4.04/xpdf-qt/qrc_icons.cpp -o CMakeFiles/xpdf.dir/qrc_icons.cpp.s
+
+# Object files for target xpdf
+xpdf_OBJECTS = \
+"CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o" \
+"CMakeFiles/xpdf.dir/QtPDFCore.cc.o" \
+"CMakeFiles/xpdf.dir/XpdfApp.cc.o" \
+"CMakeFiles/xpdf.dir/XpdfViewer.cc.o" \
+"CMakeFiles/xpdf.dir/XpdfWidget.cc.o" \
+"CMakeFiles/xpdf.dir/xpdf.cc.o" \
+"CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o" \
+"CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o" \
+"CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o" \
+"CMakeFiles/xpdf.dir/qrc_icons.cpp.o"
+
+# External object files for target xpdf
+xpdf_EXTERNAL_OBJECTS = \
+"/home/calvin/src/xpdf-4.04/goo/CMakeFiles/goo_objs.dir/FixedPoint.cc.o" \
+"/home/calvin/src/xpdf-4.04/goo/CMakeFiles/goo_objs.dir/GHash.cc.o" \
+"/home/calvin/src/xpdf-4.04/goo/CMakeFiles/goo_objs.dir/GList.cc.o" \
+"/home/calvin/src/xpdf-4.04/goo/CMakeFiles/goo_objs.dir/GString.cc.o" \
+"/home/calvin/src/xpdf-4.04/goo/CMakeFiles/goo_objs.dir/gfile.cc.o" \
+"/home/calvin/src/xpdf-4.04/goo/CMakeFiles/goo_objs.dir/gmem.cc.o" \
+"/home/calvin/src/xpdf-4.04/goo/CMakeFiles/goo_objs.dir/gmempp.cc.o" \
+"/home/calvin/src/xpdf-4.04/goo/CMakeFiles/goo_objs.dir/parseargs.c.o" \
+"/home/calvin/src/xpdf-4.04/goo/CMakeFiles/goo_objs.dir/Trace.cc.o" \
+"/home/calvin/src/xpdf-4.04/fofi/CMakeFiles/fofi_objs.dir/FoFiBase.cc.o" \
+"/home/calvin/src/xpdf-4.04/fofi/CMakeFiles/fofi_objs.dir/FoFiEncodings.cc.o" \
+"/home/calvin/src/xpdf-4.04/fofi/CMakeFiles/fofi_objs.dir/FoFiIdentifier.cc.o" \
+"/home/calvin/src/xpdf-4.04/fofi/CMakeFiles/fofi_objs.dir/FoFiTrueType.cc.o" \
+"/home/calvin/src/xpdf-4.04/fofi/CMakeFiles/fofi_objs.dir/FoFiType1.cc.o" \
+"/home/calvin/src/xpdf-4.04/fofi/CMakeFiles/fofi_objs.dir/FoFiType1C.cc.o" \
+"/home/calvin/src/xpdf-4.04/splash/CMakeFiles/splash_objs.dir/Splash.cc.o" \
+"/home/calvin/src/xpdf-4.04/splash/CMakeFiles/splash_objs.dir/SplashBitmap.cc.o" \
+"/home/calvin/src/xpdf-4.04/splash/CMakeFiles/splash_objs.dir/SplashClip.cc.o" \
+"/home/calvin/src/xpdf-4.04/splash/CMakeFiles/splash_objs.dir/SplashFTFont.cc.o" \
+"/home/calvin/src/xpdf-4.04/splash/CMakeFiles/splash_objs.dir/SplashFTFontEngine.cc.o" \
+"/home/calvin/src/xpdf-4.04/splash/CMakeFiles/splash_objs.dir/SplashFTFontFile.cc.o" \
+"/home/calvin/src/xpdf-4.04/splash/CMakeFiles/splash_objs.dir/SplashFont.cc.o" \
+"/home/calvin/src/xpdf-4.04/splash/CMakeFiles/splash_objs.dir/SplashFontEngine.cc.o" \
+"/home/calvin/src/xpdf-4.04/splash/CMakeFiles/splash_objs.dir/SplashFontFile.cc.o" \
+"/home/calvin/src/xpdf-4.04/splash/CMakeFiles/splash_objs.dir/SplashFontFileID.cc.o" \
+"/home/calvin/src/xpdf-4.04/splash/CMakeFiles/splash_objs.dir/SplashPath.cc.o" \
+"/home/calvin/src/xpdf-4.04/splash/CMakeFiles/splash_objs.dir/SplashPattern.cc.o" \
+"/home/calvin/src/xpdf-4.04/splash/CMakeFiles/splash_objs.dir/SplashScreen.cc.o" \
+"/home/calvin/src/xpdf-4.04/splash/CMakeFiles/splash_objs.dir/SplashState.cc.o" \
+"/home/calvin/src/xpdf-4.04/splash/CMakeFiles/splash_objs.dir/SplashXPath.cc.o" \
+"/home/calvin/src/xpdf-4.04/splash/CMakeFiles/splash_objs.dir/SplashXPathScanner.cc.o" \
+"/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" \
+"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_widget_objs.dir/DisplayState.cc.o" \
+"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_widget_objs.dir/PDFCore.cc.o" \
+"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_widget_objs.dir/PreScanOutputDev.cc.o" \
+"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_widget_objs.dir/PSOutputDev.cc.o" \
+"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_widget_objs.dir/ShadingImage.cc.o" \
+"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_widget_objs.dir/SplashOutputDev.cc.o" \
+"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_widget_objs.dir/TextOutputDev.cc.o" \
+"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCache.cc.o" \
+"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCompositor.cc.o" \
+"/home/calvin/src/xpdf-4.04/xpdf/CMakeFiles/xpdf_widget_objs.dir/TileMap.cc.o"
+
+xpdf-qt/xpdf: xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o
+xpdf-qt/xpdf: xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o
+xpdf-qt/xpdf: xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o
+xpdf-qt/xpdf: xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o
+xpdf-qt/xpdf: xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o
+xpdf-qt/xpdf: xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o
+xpdf-qt/xpdf: xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o
+xpdf-qt/xpdf: xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o
+xpdf-qt/xpdf: xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o
+xpdf-qt/xpdf: xpdf-qt/CMakeFiles/xpdf.dir/qrc_icons.cpp.o
+xpdf-qt/xpdf: goo/CMakeFiles/goo_objs.dir/FixedPoint.cc.o
+xpdf-qt/xpdf: goo/CMakeFiles/goo_objs.dir/GHash.cc.o
+xpdf-qt/xpdf: goo/CMakeFiles/goo_objs.dir/GList.cc.o
+xpdf-qt/xpdf: goo/CMakeFiles/goo_objs.dir/GString.cc.o
+xpdf-qt/xpdf: goo/CMakeFiles/goo_objs.dir/gfile.cc.o
+xpdf-qt/xpdf: goo/CMakeFiles/goo_objs.dir/gmem.cc.o
+xpdf-qt/xpdf: goo/CMakeFiles/goo_objs.dir/gmempp.cc.o
+xpdf-qt/xpdf: goo/CMakeFiles/goo_objs.dir/parseargs.c.o
+xpdf-qt/xpdf: goo/CMakeFiles/goo_objs.dir/Trace.cc.o
+xpdf-qt/xpdf: fofi/CMakeFiles/fofi_objs.dir/FoFiBase.cc.o
+xpdf-qt/xpdf: fofi/CMakeFiles/fofi_objs.dir/FoFiEncodings.cc.o
+xpdf-qt/xpdf: fofi/CMakeFiles/fofi_objs.dir/FoFiIdentifier.cc.o
+xpdf-qt/xpdf: fofi/CMakeFiles/fofi_objs.dir/FoFiTrueType.cc.o
+xpdf-qt/xpdf: fofi/CMakeFiles/fofi_objs.dir/FoFiType1.cc.o
+xpdf-qt/xpdf: fofi/CMakeFiles/fofi_objs.dir/FoFiType1C.cc.o
+xpdf-qt/xpdf: splash/CMakeFiles/splash_objs.dir/Splash.cc.o
+xpdf-qt/xpdf: splash/CMakeFiles/splash_objs.dir/SplashBitmap.cc.o
+xpdf-qt/xpdf: splash/CMakeFiles/splash_objs.dir/SplashClip.cc.o
+xpdf-qt/xpdf: splash/CMakeFiles/splash_objs.dir/SplashFTFont.cc.o
+xpdf-qt/xpdf: splash/CMakeFiles/splash_objs.dir/SplashFTFontEngine.cc.o
+xpdf-qt/xpdf: splash/CMakeFiles/splash_objs.dir/SplashFTFontFile.cc.o
+xpdf-qt/xpdf: splash/CMakeFiles/splash_objs.dir/SplashFont.cc.o
+xpdf-qt/xpdf: splash/CMakeFiles/splash_objs.dir/SplashFontEngine.cc.o
+xpdf-qt/xpdf: splash/CMakeFiles/splash_objs.dir/SplashFontFile.cc.o
+xpdf-qt/xpdf: splash/CMakeFiles/splash_objs.dir/SplashFontFileID.cc.o
+xpdf-qt/xpdf: splash/CMakeFiles/splash_objs.dir/SplashPath.cc.o
+xpdf-qt/xpdf: splash/CMakeFiles/splash_objs.dir/SplashPattern.cc.o
+xpdf-qt/xpdf: splash/CMakeFiles/splash_objs.dir/SplashScreen.cc.o
+xpdf-qt/xpdf: splash/CMakeFiles/splash_objs.dir/SplashState.cc.o
+xpdf-qt/xpdf: splash/CMakeFiles/splash_objs.dir/SplashXPath.cc.o
+xpdf-qt/xpdf: splash/CMakeFiles/splash_objs.dir/SplashXPathScanner.cc.o
+xpdf-qt/xpdf: xpdf/CMakeFiles/xpdf_objs.dir/AcroForm.cc.o
+xpdf-qt/xpdf: xpdf/CMakeFiles/xpdf_objs.dir/Annot.cc.o
+xpdf-qt/xpdf: xpdf/CMakeFiles/xpdf_objs.dir/Array.cc.o
+xpdf-qt/xpdf: xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFont.cc.o
+xpdf-qt/xpdf: xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFontTables.cc.o
+xpdf-qt/xpdf: xpdf/CMakeFiles/xpdf_objs.dir/Catalog.cc.o
+xpdf-qt/xpdf: xpdf/CMakeFiles/xpdf_objs.dir/CharCodeToUnicode.cc.o
+xpdf-qt/xpdf: xpdf/CMakeFiles/xpdf_objs.dir/CMap.cc.o
+xpdf-qt/xpdf: xpdf/CMakeFiles/xpdf_objs.dir/Decrypt.cc.o
+xpdf-qt/xpdf: xpdf/CMakeFiles/xpdf_objs.dir/Dict.cc.o
+xpdf-qt/xpdf: xpdf/CMakeFiles/xpdf_objs.dir/Error.cc.o
+xpdf-qt/xpdf: xpdf/CMakeFiles/xpdf_objs.dir/FontEncodingTables.cc.o
+xpdf-qt/xpdf: xpdf/CMakeFiles/xpdf_objs.dir/Function.cc.o
+xpdf-qt/xpdf: xpdf/CMakeFiles/xpdf_objs.dir/Gfx.cc.o
+xpdf-qt/xpdf: xpdf/CMakeFiles/xpdf_objs.dir/GfxFont.cc.o
+xpdf-qt/xpdf: xpdf/CMakeFiles/xpdf_objs.dir/GfxState.cc.o
+xpdf-qt/xpdf: xpdf/CMakeFiles/xpdf_objs.dir/GlobalParams.cc.o
+xpdf-qt/xpdf: xpdf/CMakeFiles/xpdf_objs.dir/JArithmeticDecoder.cc.o
+xpdf-qt/xpdf: xpdf/CMakeFiles/xpdf_objs.dir/JBIG2Stream.cc.o
+xpdf-qt/xpdf: xpdf/CMakeFiles/xpdf_objs.dir/JPXStream.cc.o
+xpdf-qt/xpdf: xpdf/CMakeFiles/xpdf_objs.dir/Lexer.cc.o
+xpdf-qt/xpdf: xpdf/CMakeFiles/xpdf_objs.dir/Link.cc.o
+xpdf-qt/xpdf: xpdf/CMakeFiles/xpdf_objs.dir/NameToCharCode.cc.o
+xpdf-qt/xpdf: xpdf/CMakeFiles/xpdf_objs.dir/Object.cc.o
+xpdf-qt/xpdf: xpdf/CMakeFiles/xpdf_objs.dir/OptionalContent.cc.o
+xpdf-qt/xpdf: xpdf/CMakeFiles/xpdf_objs.dir/Outline.cc.o
+xpdf-qt/xpdf: xpdf/CMakeFiles/xpdf_objs.dir/OutputDev.cc.o
+xpdf-qt/xpdf: xpdf/CMakeFiles/xpdf_objs.dir/Page.cc.o
+xpdf-qt/xpdf: xpdf/CMakeFiles/xpdf_objs.dir/Parser.cc.o
+xpdf-qt/xpdf: xpdf/CMakeFiles/xpdf_objs.dir/PDF417Barcode.cc.o
+xpdf-qt/xpdf: xpdf/CMakeFiles/xpdf_objs.dir/PDFDoc.cc.o
+xpdf-qt/xpdf: xpdf/CMakeFiles/xpdf_objs.dir/PDFDocEncoding.cc.o
+xpdf-qt/xpdf: xpdf/CMakeFiles/xpdf_objs.dir/PSTokenizer.cc.o
+xpdf-qt/xpdf: xpdf/CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.o
+xpdf-qt/xpdf: xpdf/CMakeFiles/xpdf_objs.dir/Stream.cc.o
+xpdf-qt/xpdf: xpdf/CMakeFiles/xpdf_objs.dir/TextString.cc.o
+xpdf-qt/xpdf: xpdf/CMakeFiles/xpdf_objs.dir/UnicodeMap.cc.o
+xpdf-qt/xpdf: xpdf/CMakeFiles/xpdf_objs.dir/UnicodeRemapping.cc.o
+xpdf-qt/xpdf: xpdf/CMakeFiles/xpdf_objs.dir/UnicodeTypeTable.cc.o
+xpdf-qt/xpdf: xpdf/CMakeFiles/xpdf_objs.dir/UTF8.cc.o
+xpdf-qt/xpdf: xpdf/CMakeFiles/xpdf_objs.dir/XFAScanner.cc.o
+xpdf-qt/xpdf: xpdf/CMakeFiles/xpdf_objs.dir/XRef.cc.o
+xpdf-qt/xpdf: xpdf/CMakeFiles/xpdf_objs.dir/Zoox.cc.o
+xpdf-qt/xpdf: xpdf/CMakeFiles/xpdf_widget_objs.dir/DisplayState.cc.o
+xpdf-qt/xpdf: xpdf/CMakeFiles/xpdf_widget_objs.dir/PDFCore.cc.o
+xpdf-qt/xpdf: xpdf/CMakeFiles/xpdf_widget_objs.dir/PreScanOutputDev.cc.o
+xpdf-qt/xpdf: xpdf/CMakeFiles/xpdf_widget_objs.dir/PSOutputDev.cc.o
+xpdf-qt/xpdf: xpdf/CMakeFiles/xpdf_widget_objs.dir/ShadingImage.cc.o
+xpdf-qt/xpdf: xpdf/CMakeFiles/xpdf_widget_objs.dir/SplashOutputDev.cc.o
+xpdf-qt/xpdf: xpdf/CMakeFiles/xpdf_widget_objs.dir/TextOutputDev.cc.o
+xpdf-qt/xpdf: xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCache.cc.o
+xpdf-qt/xpdf: xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCompositor.cc.o
+xpdf-qt/xpdf: xpdf/CMakeFiles/xpdf_widget_objs.dir/TileMap.cc.o
+xpdf-qt/xpdf: xpdf-qt/CMakeFiles/xpdf.dir/build.make
+xpdf-qt/xpdf: /usr/lib/x86_64-linux-gnu/libQt5Network.so.5.15.2
+xpdf-qt/xpdf: /usr/lib/x86_64-linux-gnu/libQt5PrintSupport.so.5.15.2
+xpdf-qt/xpdf: /usr/lib/x86_64-linux-gnu/libcups.so
+xpdf-qt/xpdf: /usr/lib/x86_64-linux-gnu/libfreetype.so
+xpdf-qt/xpdf: /usr/lib/x86_64-linux-gnu/libfontconfig.so
+xpdf-qt/xpdf: /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5.15.2
+xpdf-qt/xpdf: /usr/lib/x86_64-linux-gnu/libQt5Gui.so.5.15.2
+xpdf-qt/xpdf: /usr/lib/x86_64-linux-gnu/libQt5Core.so.5.15.2
+xpdf-qt/xpdf: xpdf-qt/CMakeFiles/xpdf.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_15) "Linking CXX executable xpdf"
+ cd /home/calvin/src/xpdf-4.04/xpdf-qt && $(CMAKE_COMMAND) -E cmake_link_script CMakeFiles/xpdf.dir/link.txt --verbose=$(VERBOSE)
+
+# Rule to build all files generated by this target.
+xpdf-qt/CMakeFiles/xpdf.dir/build: xpdf-qt/xpdf
+
+.PHONY : xpdf-qt/CMakeFiles/xpdf.dir/build
+
+xpdf-qt/CMakeFiles/xpdf.dir/clean:
+ cd /home/calvin/src/xpdf-4.04/xpdf-qt && $(CMAKE_COMMAND) -P CMakeFiles/xpdf.dir/cmake_clean.cmake
+.PHONY : xpdf-qt/CMakeFiles/xpdf.dir/clean
+
+xpdf-qt/CMakeFiles/xpdf.dir/depend: xpdf-qt/moc_XpdfApp.cpp
+xpdf-qt/CMakeFiles/xpdf.dir/depend: xpdf-qt/moc_XpdfViewer.cpp
+xpdf-qt/CMakeFiles/xpdf.dir/depend: xpdf-qt/moc_XpdfWidget.cpp
+xpdf-qt/CMakeFiles/xpdf.dir/depend: xpdf-qt/qrc_icons.cpp
+ 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-qt /home/calvin/src/xpdf-4.04 /home/calvin/src/xpdf-4.04/xpdf-qt /home/calvin/src/xpdf-4.04/xpdf-qt/CMakeFiles/xpdf.dir/DependInfo.cmake --color=$(COLOR)
+.PHONY : xpdf-qt/CMakeFiles/xpdf.dir/depend
+
diff --git a/xpdf-qt/CMakeFiles/xpdf.dir/cmake_clean.cmake b/xpdf-qt/CMakeFiles/xpdf.dir/cmake_clean.cmake
new file mode 100644
index 0000000..0263ddf
--- /dev/null
+++ b/xpdf-qt/CMakeFiles/xpdf.dir/cmake_clean.cmake
@@ -0,0 +1,23 @@
+file(REMOVE_RECURSE
+ "CMakeFiles/xpdf.dir/QtPDFCore.cc.o"
+ "CMakeFiles/xpdf.dir/XpdfApp.cc.o"
+ "CMakeFiles/xpdf.dir/XpdfViewer.cc.o"
+ "CMakeFiles/xpdf.dir/XpdfWidget.cc.o"
+ "CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o"
+ "CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o"
+ "CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o"
+ "CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o"
+ "CMakeFiles/xpdf.dir/qrc_icons.cpp.o"
+ "CMakeFiles/xpdf.dir/xpdf.cc.o"
+ "moc_XpdfApp.cpp"
+ "moc_XpdfViewer.cpp"
+ "moc_XpdfWidget.cpp"
+ "qrc_icons.cpp"
+ "xpdf"
+ "xpdf.pdb"
+)
+
+# Per-language clean rules from dependency scanning.
+foreach(lang C CXX)
+ include(CMakeFiles/xpdf.dir/cmake_clean_${lang}.cmake OPTIONAL)
+endforeach()
diff --git a/xpdf-qt/CMakeFiles/xpdf.dir/depend.internal b/xpdf-qt/CMakeFiles/xpdf.dir/depend.internal
new file mode 100644
index 0000000..c0ef3d7
--- /dev/null
+++ b/xpdf-qt/CMakeFiles/xpdf.dir/depend.internal
@@ -0,0 +1,1412 @@
+# CMAKE generated file: DO NOT EDIT!
+# Generated by "Unix Makefiles" Generator, CMake Version 3.18
+
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o
+ /home/calvin/src/xpdf-4.04/xpdf-qt/QtPDFCore.cc
+ /home/calvin/src/xpdf-4.04/xpdf-qt/QtPDFCore.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/QDateTime
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/QFileInfo
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/QProcess
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/QUrl
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qalgorithms.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qarraydata.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qatomic.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qatomic_bootstrap.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qatomic_cxx11.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qatomic_msvc.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qbasicatomic.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qbytearray.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qbytearraylist.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qchar.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qcompilerdetection.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qconfig-bootstrapped.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qconfig.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qcontainerfwd.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qcontainertools_impl.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qcontiguouscache.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qcoreapplication.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qcoreevent.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qdatastream.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qdatetime.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qdebug.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qeventloop.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qfile.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qfiledevice.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qfileinfo.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qflags.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qgenericatomic.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qglobal.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qglobalstatic.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qhash.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qhashfunctions.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qiodevice.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qiterator.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qline.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qlist.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qlocale.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qlogging.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qmap.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qmargins.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qmetatype.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qmutex.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qnamespace.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qnumeric.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qobject.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qobject_impl.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qobjectdefs.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qobjectdefs_impl.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qpair.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qpoint.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qprocess.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qprocessordetection.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qrect.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qrefcount.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qregexp.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qscopedpointer.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qset.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qshareddata.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qsharedpointer.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qsharedpointer_impl.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qsize.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qstandardpaths.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qstring.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringalgorithms.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringbuilder.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringlist.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringliteral.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringmatcher.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringview.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qsysinfo.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qsystemdetection.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qtcore-config.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qtextstream.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qtypeinfo.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qurl.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qurlquery.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qvariant.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qvarlengtharray.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qvector.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qversiontagging.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/QClipboard
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/QDesktopServices
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/QImage
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/QPainter
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qbrush.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qclipboard.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qcolor.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qcursor.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qdesktopservices.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qevent.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qfont.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qfontinfo.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qfontmetrics.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qguiapplication.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qicon.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qimage.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qinputmethod.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qkeysequence.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qmatrix.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qpaintdevice.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qpainter.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qpalette.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qpen.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qpixelformat.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qpixmap.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qpolygon.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qregion.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qrgb.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qrgba64.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qtextcursor.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qtextformat.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qtextoption.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qtgui-config.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qtguiglobal.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qtouchdevice.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qtransform.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qvector2d.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qwindowdefs.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qwindowdefs_win.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QApplication
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QInputDialog
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QMessageBox
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QScrollBar
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QStyle
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QWidget
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qabstractslider.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qapplication.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qdesktopwidget.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qdialog.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qframe.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qinputdialog.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qlineedit.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qmessagebox.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qscrollbar.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qsizepolicy.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qstyle.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qtwidgets-config.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qtwidgetsglobal.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qwidget.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/Array.h
+ xpdf/Catalog.h
+ xpdf/CharTypes.h
+ xpdf/Dict.h
+ xpdf/DisplayState.h
+ xpdf/Error.h
+ xpdf/ErrorCodes.h
+ xpdf/Function.h
+ xpdf/GfxFont.h
+ xpdf/GfxState.h
+ xpdf/GlobalParams.h
+ xpdf/Link.h
+ xpdf/Object.h
+ xpdf/OutputDev.h
+ xpdf/PDFCore.h
+ xpdf/PDFDoc.h
+ xpdf/PSOutputDev.h
+ xpdf/Page.h
+ xpdf/Stream.h
+ xpdf/TextOutputDev.h
+ xpdf/TileMap.h
+ xpdf/XRef.h
+ xpdf/config.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o
+ /home/calvin/src/xpdf-4.04/xpdf-qt/XpdfApp.cc
+ /home/calvin/src/xpdf-4.04/xpdf-qt/XpdfApp.h
+ /home/calvin/src/xpdf-4.04/xpdf-qt/XpdfViewer.h
+ /home/calvin/src/xpdf-4.04/xpdf-qt/XpdfWidget.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/QDateTime
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/QFileInfo
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qalgorithms.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qarraydata.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qatomic.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qatomic_bootstrap.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qatomic_cxx11.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qatomic_msvc.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qbasicatomic.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qbytearray.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qbytearraylist.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qchar.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qcompilerdetection.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qconfig-bootstrapped.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qconfig.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qcontainerfwd.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qcontainertools_impl.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qcontiguouscache.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qcoreapplication.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qcoreevent.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qdatastream.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qdatetime.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qdebug.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qeventloop.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qfile.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qfiledevice.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qfileinfo.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qflags.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qgenericatomic.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qglobal.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qglobalstatic.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qhash.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qhashfunctions.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qiodevice.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qiterator.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qline.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qlist.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qlocale.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qlogging.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qmap.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qmargins.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qmetatype.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qmutex.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qnamespace.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qnumeric.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qobject.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qobject_impl.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qobjectdefs.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qobjectdefs_impl.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qpair.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qpoint.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qprocessordetection.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qrect.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qrefcount.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qregexp.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qscopedpointer.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qset.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qshareddata.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qsharedpointer.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qsharedpointer_impl.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qsize.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qstring.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringalgorithms.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringbuilder.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringlist.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringliteral.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringmatcher.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringview.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qsysinfo.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qsystemdetection.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qtcore-config.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qtextstream.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qtypeinfo.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qurl.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qurlquery.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qvariant.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qvarlengtharray.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qvector.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qversiontagging.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/QColor
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/QIcon
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qbrush.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qcolor.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qcursor.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qevent.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qfont.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qfontinfo.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qfontmetrics.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qguiapplication.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qicon.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qimage.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qinputmethod.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qkeysequence.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qmatrix.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qpaintdevice.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qpalette.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qpixelformat.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qpixmap.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qpolygon.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qregion.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qrgb.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qrgba64.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qtgui-config.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qtguiglobal.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qtouchdevice.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qtransform.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qvector2d.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qwindowdefs.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qwindowdefs_win.h
+ /usr/include/x86_64-linux-gnu/qt5/QtNetwork/QLocalServer
+ /usr/include/x86_64-linux-gnu/qt5/QtNetwork/QLocalSocket
+ /usr/include/x86_64-linux-gnu/qt5/QtNetwork/qabstractsocket.h
+ /usr/include/x86_64-linux-gnu/qt5/QtNetwork/qlocalserver.h
+ /usr/include/x86_64-linux-gnu/qt5/QtNetwork/qlocalsocket.h
+ /usr/include/x86_64-linux-gnu/qt5/QtNetwork/qtnetwork-config.h
+ /usr/include/x86_64-linux-gnu/qt5/QtNetwork/qtnetworkglobal.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QAbstractScrollArea
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QApplication
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QDialog
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QMainWindow
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QToolButton
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qabstractbutton.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qabstractscrollarea.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qapplication.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qdesktopwidget.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qdialog.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qframe.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qmainwindow.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qsizepolicy.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qtabwidget.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qtoolbutton.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qtwidgets-config.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qtwidgetsglobal.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qwidget.h
+ aconf.h
+ aconf2.h
+ goo/GList.h
+ goo/GMutex.h
+ goo/GString.h
+ goo/gfile.h
+ goo/gmempp.h
+ goo/gtypes.h
+ goo/parseargs.h
+ xpdf/CharTypes.h
+ xpdf/Error.h
+ xpdf/GlobalParams.h
+ xpdf/config.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o
+ /home/calvin/src/xpdf-4.04/xpdf-qt/QtPDFCore.h
+ /home/calvin/src/xpdf-4.04/xpdf-qt/XpdfApp.h
+ /home/calvin/src/xpdf-4.04/xpdf-qt/XpdfViewer.cc
+ /home/calvin/src/xpdf-4.04/xpdf-qt/XpdfViewer.h
+ /home/calvin/src/xpdf-4.04/xpdf-qt/XpdfWidget.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/QAbstractItemModel
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/QDateTime
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/QList
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/QMimeData
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/QObject
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/QProcess
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/QPropertyAnimation
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/QRect
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/QSignalMapper
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/QSize
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/QSizeF
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/QTimer
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qabstractanimation.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qabstractitemmodel.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qalgorithms.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qarraydata.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qatomic.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qatomic_bootstrap.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qatomic_cxx11.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qatomic_msvc.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qbasicatomic.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qbasictimer.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qbytearray.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qbytearraylist.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qchar.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qcompilerdetection.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qconfig-bootstrapped.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qconfig.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qcontainerfwd.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qcontainertools_impl.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qcontiguouscache.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qcoreapplication.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qcoreevent.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qdatastream.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qdatetime.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qdebug.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qdir.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qeasingcurve.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qeventloop.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qfile.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qfiledevice.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qfileinfo.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qflags.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qgenericatomic.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qglobal.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qglobalstatic.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qhash.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qhashfunctions.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qiodevice.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qitemselectionmodel.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qiterator.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qline.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qlist.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qlocale.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qlogging.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qmap.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qmargins.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qmetatype.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qmimedata.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qmutex.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qnamespace.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qnumeric.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qobject.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qobject_impl.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qobjectdefs.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qobjectdefs_impl.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qpair.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qpoint.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qprocess.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qprocessordetection.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qpropertyanimation.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qrect.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qrefcount.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qregexp.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qregularexpression.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qscopedpointer.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qset.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qshareddata.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qsharedpointer.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qsharedpointer_impl.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qsignalmapper.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qsize.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qstandardpaths.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qstring.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringalgorithms.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringbuilder.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringlist.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringliteral.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringmatcher.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringview.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qsysinfo.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qsystemdetection.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qtcore-config.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qtextstream.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qtimer.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qtypeinfo.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qurl.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qurlquery.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qvariant.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qvariantanimation.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qvarlengtharray.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qvector.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qversiontagging.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/QClipboard
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/QColor
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/QDesktopServices
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/QIcon
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/QKeyEvent
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/QMouseEvent
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/QScreen
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/QTransform
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qbrush.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qclipboard.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qcolor.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qcursor.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qdesktopservices.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qevent.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qfont.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qfontinfo.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qfontmetrics.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qguiapplication.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qicon.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qimage.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qinputmethod.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qkeysequence.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qmatrix.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qpaintdevice.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qpalette.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qpen.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qpixelformat.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qpixmap.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qpolygon.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qregion.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qrgb.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qrgba64.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qscreen.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qtextcursor.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qtextdocument.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qtextformat.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qtextoption.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qtgui-config.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qtguiglobal.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qtouchdevice.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qtransform.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qvalidator.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qvector2d.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qwindowdefs.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qwindowdefs_win.h
+ /usr/include/x86_64-linux-gnu/qt5/QtNetwork/QLocalServer
+ /usr/include/x86_64-linux-gnu/qt5/QtNetwork/QLocalSocket
+ /usr/include/x86_64-linux-gnu/qt5/QtNetwork/qabstractsocket.h
+ /usr/include/x86_64-linux-gnu/qt5/QtNetwork/qlocalserver.h
+ /usr/include/x86_64-linux-gnu/qt5/QtNetwork/qlocalsocket.h
+ /usr/include/x86_64-linux-gnu/qt5/QtNetwork/qtnetwork-config.h
+ /usr/include/x86_64-linux-gnu/qt5/QtNetwork/qtnetworkglobal.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QAbstractScrollArea
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QAction
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QActionGroup
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QApplication
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QButtonGroup
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QComboBox
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QDialog
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QFileDialog
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QFrame
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QGridLayout
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QHBoxLayout
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QHeaderView
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QLabel
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QLineEdit
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QListWidget
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QMainWindow
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QMenu
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QMenuBar
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QMessageBox
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QProgressDialog
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QPushButton
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QRadioButton
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QScrollBar
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QSplitter
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QStackedLayout
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QStackedWidget
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QTabWidget
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QTableWidget
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QTextBrowser
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QToolBar
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QToolButton
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QTreeView
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QVBoxLayout
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qabstractbutton.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qabstractitemdelegate.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qabstractitemview.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qabstractscrollarea.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qabstractslider.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qabstractspinbox.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qaction.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qactiongroup.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qapplication.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qboxlayout.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qbuttongroup.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qcombobox.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qdesktopwidget.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qdialog.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qfiledialog.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qframe.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qgridlayout.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qheaderview.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qlabel.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qlayout.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qlayoutitem.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qlineedit.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qlistview.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qlistwidget.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qmainwindow.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qmenu.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qmenubar.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qmessagebox.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qprogressdialog.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qpushbutton.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qradiobutton.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qrubberband.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qscrollbar.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qsizepolicy.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qslider.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qsplitter.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qstackedlayout.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qstackedwidget.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qstyle.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qstyleoption.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qtabbar.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qtableview.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qtablewidget.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qtabwidget.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qtextbrowser.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qtextedit.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qtoolbar.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qtoolbutton.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qtreeview.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qtwidgets-config.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qtwidgetsglobal.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qwidget.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
+ xpdf/AcroForm.h
+ xpdf/Annot.h
+ xpdf/Array.h
+ xpdf/Catalog.h
+ xpdf/CharTypes.h
+ xpdf/Dict.h
+ xpdf/DisplayState.h
+ xpdf/Error.h
+ xpdf/GfxFont.h
+ xpdf/GlobalParams.h
+ xpdf/Object.h
+ xpdf/OutputDev.h
+ xpdf/PDFCore.h
+ xpdf/PDFDoc.h
+ xpdf/Page.h
+ xpdf/Stream.h
+ xpdf/TextOutputDev.h
+ xpdf/TextString.h
+ xpdf/XRef.h
+ xpdf/Zoox.h
+ xpdf/config.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o
+ /home/calvin/src/xpdf-4.04/xpdf-qt/QtPDFCore.h
+ /home/calvin/src/xpdf-4.04/xpdf-qt/XpdfWidget.cc
+ /home/calvin/src/xpdf-4.04/xpdf-qt/XpdfWidget.h
+ /home/calvin/src/xpdf-4.04/xpdf-qt/XpdfWidgetPrint.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/QDateTime
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/QMutex
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/QTimer
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qalgorithms.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qarraydata.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qatomic.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qatomic_bootstrap.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qatomic_cxx11.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qatomic_msvc.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qbasicatomic.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qbasictimer.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qbytearray.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qbytearraylist.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qchar.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qcompilerdetection.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qconfig-bootstrapped.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qconfig.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qcontainerfwd.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qcontainertools_impl.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qcontiguouscache.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qcoreapplication.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qcoreevent.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qdatastream.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qdatetime.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qdebug.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qeventloop.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qfile.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qfiledevice.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qflags.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qgenericatomic.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qglobal.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qglobalstatic.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qhash.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qhashfunctions.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qiodevice.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qiterator.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qline.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qlist.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qlocale.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qlogging.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qmap.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qmargins.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qmetatype.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qmutex.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qnamespace.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qnumeric.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qobject.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qobject_impl.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qobjectdefs.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qobjectdefs_impl.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qpair.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qpoint.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qprocessordetection.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qrect.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qrefcount.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qregexp.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qscopedpointer.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qset.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qshareddata.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qsharedpointer.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qsharedpointer_impl.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qsize.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qstring.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringalgorithms.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringbuilder.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringlist.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringliteral.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringmatcher.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringview.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qsysinfo.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qsystemdetection.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qtcore-config.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qtextstream.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qtimer.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qtypeinfo.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qurl.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qurlquery.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qvariant.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qvarlengtharray.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qvector.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qversiontagging.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/QKeyEvent
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/QPaintEvent
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qbrush.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qcolor.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qcursor.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qevent.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qfont.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qfontinfo.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qfontmetrics.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qguiapplication.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qimage.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qinputmethod.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qkeysequence.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qmatrix.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qpagedpaintdevice.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qpagelayout.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qpagesize.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qpaintdevice.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qpalette.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qpixelformat.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qpixmap.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qpolygon.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qregion.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qrgb.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qrgba64.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qtgui-config.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qtguiglobal.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qtouchdevice.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qtransform.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qvector2d.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qwindowdefs.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qwindowdefs_win.h
+ /usr/include/x86_64-linux-gnu/qt5/QtPrintSupport/QPrintDialog
+ /usr/include/x86_64-linux-gnu/qt5/QtPrintSupport/QPrinter
+ /usr/include/x86_64-linux-gnu/qt5/QtPrintSupport/qabstractprintdialog.h
+ /usr/include/x86_64-linux-gnu/qt5/QtPrintSupport/qprintdialog.h
+ /usr/include/x86_64-linux-gnu/qt5/QtPrintSupport/qprinter.h
+ /usr/include/x86_64-linux-gnu/qt5/QtPrintSupport/qtprintsupport-config.h
+ /usr/include/x86_64-linux-gnu/qt5/QtPrintSupport/qtprintsupportglobal.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QAbstractScrollArea
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QApplication
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QGesture
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QGestureEvent
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qabstractscrollarea.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qapplication.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qdesktopwidget.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qdialog.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qframe.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qgesture.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qsizepolicy.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qtwidgets-config.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qtwidgetsglobal.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qwidget.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/AcroForm.h
+ xpdf/Annot.h
+ xpdf/Array.h
+ xpdf/Catalog.h
+ xpdf/CharTypes.h
+ xpdf/Dict.h
+ xpdf/DisplayState.h
+ xpdf/Function.h
+ xpdf/GfxFont.h
+ xpdf/GfxState.h
+ xpdf/GlobalParams.h
+ xpdf/Link.h
+ xpdf/Object.h
+ xpdf/OptionalContent.h
+ xpdf/Outline.h
+ xpdf/OutputDev.h
+ xpdf/PDFCore.h
+ xpdf/PDFDoc.h
+ xpdf/Page.h
+ xpdf/SplashOutputDev.h
+ xpdf/Stream.h
+ xpdf/TextOutputDev.h
+ xpdf/TextString.h
+ xpdf/XRef.h
+ xpdf/config.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o
+ /home/calvin/src/xpdf-4.04/xpdf-qt/XpdfWidget.h
+ /home/calvin/src/xpdf-4.04/xpdf-qt/XpdfWidgetPrint.cc
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qalgorithms.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qarraydata.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qatomic.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qatomic_bootstrap.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qatomic_cxx11.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qatomic_msvc.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qbasicatomic.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qbytearray.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qbytearraylist.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qchar.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qcompilerdetection.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qconfig-bootstrapped.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qconfig.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qcontainerfwd.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qcontainertools_impl.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qcontiguouscache.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qcoreevent.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qdatastream.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qdebug.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qfile.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qfiledevice.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qflags.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qgenericatomic.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qglobal.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qglobalstatic.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qhash.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qhashfunctions.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qiodevice.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qiterator.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qline.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qlist.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qlocale.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qlogging.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qmap.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qmargins.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qmetatype.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qmutex.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qnamespace.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qnumeric.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qobject.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qobject_impl.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qobjectdefs.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qobjectdefs_impl.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qpair.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qpoint.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qprocessordetection.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qrect.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qrefcount.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qregexp.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qscopedpointer.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qset.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qshareddata.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qsharedpointer.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qsharedpointer_impl.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qsize.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qstring.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringalgorithms.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringbuilder.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringlist.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringliteral.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringmatcher.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringview.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qsysinfo.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qsystemdetection.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qtcore-config.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qtextstream.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qtypeinfo.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qurl.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qurlquery.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qvariant.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qvarlengtharray.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qvector.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qversiontagging.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qbrush.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qcolor.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qcursor.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qevent.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qfont.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qfontinfo.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qfontmetrics.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qimage.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qkeysequence.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qmatrix.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qpagedpaintdevice.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qpagelayout.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qpagesize.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qpaintdevice.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qpalette.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qpixelformat.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qpixmap.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qpolygon.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qregion.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qrgb.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qrgba64.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qtgui-config.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qtguiglobal.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qtouchdevice.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qtransform.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qvector2d.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qwindowdefs.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qwindowdefs_win.h
+ /usr/include/x86_64-linux-gnu/qt5/QtPrintSupport/QPrinter
+ /usr/include/x86_64-linux-gnu/qt5/QtPrintSupport/qprinter.h
+ /usr/include/x86_64-linux-gnu/qt5/QtPrintSupport/qtprintsupport-config.h
+ /usr/include/x86_64-linux-gnu/qt5/QtPrintSupport/qtprintsupportglobal.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QAbstractScrollArea
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qabstractscrollarea.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qframe.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qsizepolicy.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qtwidgets-config.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qtwidgetsglobal.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qwidget.h
+ aconf.h
+ aconf2.h
+ goo/GMutex.h
+ goo/GString.h
+ goo/gfile.h
+ goo/gmem.h
+ goo/gmempp.h
+ goo/gtypes.h
+ xpdf/Array.h
+ xpdf/Catalog.h
+ xpdf/CharTypes.h
+ xpdf/Dict.h
+ xpdf/ErrorCodes.h
+ xpdf/GlobalParams.h
+ xpdf/Object.h
+ xpdf/OutputDev.h
+ xpdf/PDFDoc.h
+ xpdf/PSOutputDev.h
+ xpdf/Page.h
+ xpdf/Stream.h
+ xpdf/XRef.h
+ xpdf/config.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o
+ /home/calvin/src/xpdf-4.04/xpdf-qt/XpdfApp.h
+ /home/calvin/src/xpdf-4.04/xpdf-qt/moc_XpdfApp.cpp
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/QDateTime
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qalgorithms.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qarraydata.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qatomic.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qatomic_bootstrap.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qatomic_cxx11.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qatomic_msvc.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qbasicatomic.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qbytearray.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qbytearraylist.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qchar.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qcompilerdetection.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qconfig-bootstrapped.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qconfig.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qcontainerfwd.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qcontainertools_impl.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qcontiguouscache.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qcoreapplication.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qcoreevent.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qdatastream.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qdatetime.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qdebug.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qeventloop.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qfile.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qfiledevice.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qflags.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qgenericatomic.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qglobal.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qglobalstatic.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qhash.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qhashfunctions.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qiodevice.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qiterator.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qline.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qlist.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qlocale.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qlogging.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qmap.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qmargins.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qmetatype.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qmutex.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qnamespace.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qnumeric.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qobject.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qobject_impl.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qobjectdefs.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qobjectdefs_impl.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qpair.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qpoint.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qprocessordetection.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qrect.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qrefcount.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qregexp.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qscopedpointer.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qset.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qshareddata.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qsharedpointer.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qsharedpointer_impl.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qsize.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qstring.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringalgorithms.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringbuilder.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringlist.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringliteral.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringmatcher.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringview.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qsysinfo.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qsystemdetection.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qtcore-config.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qtextstream.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qtypeinfo.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qurl.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qurlquery.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qvariant.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qvarlengtharray.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qvector.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qversiontagging.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/QColor
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qbrush.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qcolor.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qcursor.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qevent.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qfont.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qfontinfo.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qfontmetrics.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qguiapplication.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qimage.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qinputmethod.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qkeysequence.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qmatrix.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qpaintdevice.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qpalette.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qpixelformat.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qpixmap.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qpolygon.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qregion.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qrgb.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qrgba64.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qtgui-config.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qtguiglobal.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qtouchdevice.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qtransform.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qvector2d.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qwindowdefs.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qwindowdefs_win.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QApplication
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qapplication.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qdesktopwidget.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qsizepolicy.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qtwidgets-config.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qtwidgetsglobal.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qwidget.h
+ aconf.h
+ aconf2.h
+ goo/gtypes.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o
+ /home/calvin/src/xpdf-4.04/xpdf-qt/XpdfViewer.h
+ /home/calvin/src/xpdf-4.04/xpdf-qt/XpdfWidget.h
+ /home/calvin/src/xpdf-4.04/xpdf-qt/moc_XpdfViewer.cpp
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qalgorithms.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qarraydata.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qatomic.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qatomic_bootstrap.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qatomic_cxx11.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qatomic_msvc.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qbasicatomic.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qbytearray.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qbytearraylist.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qchar.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qcompilerdetection.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qconfig-bootstrapped.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qconfig.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qcontainerfwd.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qcontainertools_impl.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qcontiguouscache.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qcoreevent.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qdatastream.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qdebug.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qfile.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qfiledevice.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qflags.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qgenericatomic.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qglobal.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qglobalstatic.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qhash.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qhashfunctions.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qiodevice.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qiterator.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qline.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qlist.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qlocale.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qlogging.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qmap.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qmargins.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qmetatype.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qmutex.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qnamespace.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qnumeric.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qobject.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qobject_impl.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qobjectdefs.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qobjectdefs_impl.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qpair.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qpoint.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qprocessordetection.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qrect.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qrefcount.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qregexp.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qscopedpointer.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qset.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qshareddata.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qsharedpointer.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qsharedpointer_impl.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qsize.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qstring.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringalgorithms.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringbuilder.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringlist.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringliteral.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringmatcher.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringview.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qsysinfo.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qsystemdetection.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qtcore-config.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qtextstream.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qtypeinfo.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qurl.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qurlquery.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qvariant.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qvarlengtharray.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qvector.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qversiontagging.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/QIcon
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qbrush.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qcolor.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qcursor.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qevent.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qfont.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qfontinfo.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qfontmetrics.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qicon.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qimage.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qkeysequence.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qmatrix.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qpaintdevice.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qpalette.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qpixelformat.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qpixmap.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qpolygon.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qregion.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qrgb.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qrgba64.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qtgui-config.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qtguiglobal.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qtouchdevice.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qtransform.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qvector2d.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qwindowdefs.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qwindowdefs_win.h
+ /usr/include/x86_64-linux-gnu/qt5/QtNetwork/QLocalServer
+ /usr/include/x86_64-linux-gnu/qt5/QtNetwork/qabstractsocket.h
+ /usr/include/x86_64-linux-gnu/qt5/QtNetwork/qlocalserver.h
+ /usr/include/x86_64-linux-gnu/qt5/QtNetwork/qtnetwork-config.h
+ /usr/include/x86_64-linux-gnu/qt5/QtNetwork/qtnetworkglobal.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QAbstractScrollArea
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QDialog
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QMainWindow
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QToolButton
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qabstractbutton.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qabstractscrollarea.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qdialog.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qframe.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qmainwindow.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qsizepolicy.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qtabwidget.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qtoolbutton.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qtwidgets-config.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qtwidgetsglobal.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qwidget.h
+ aconf.h
+ aconf2.h
+ goo/gfile.h
+ goo/gtypes.h
+ xpdf/Error.h
+ xpdf/config.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o
+ /home/calvin/src/xpdf-4.04/xpdf-qt/XpdfWidget.h
+ /home/calvin/src/xpdf-4.04/xpdf-qt/moc_XpdfWidget.cpp
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qalgorithms.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qarraydata.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qatomic.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qatomic_bootstrap.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qatomic_cxx11.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qatomic_msvc.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qbasicatomic.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qbytearray.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qbytearraylist.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qchar.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qcompilerdetection.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qconfig-bootstrapped.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qconfig.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qcontainerfwd.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qcontainertools_impl.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qcontiguouscache.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qcoreevent.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qdatastream.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qdebug.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qfile.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qfiledevice.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qflags.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qgenericatomic.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qglobal.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qglobalstatic.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qhash.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qhashfunctions.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qiodevice.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qiterator.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qline.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qlist.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qlocale.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qlogging.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qmap.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qmargins.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qmetatype.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qmutex.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qnamespace.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qnumeric.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qobject.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qobject_impl.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qobjectdefs.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qobjectdefs_impl.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qpair.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qpoint.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qprocessordetection.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qrect.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qrefcount.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qregexp.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qscopedpointer.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qset.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qshareddata.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qsharedpointer.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qsharedpointer_impl.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qsize.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qstring.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringalgorithms.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringbuilder.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringlist.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringliteral.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringmatcher.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringview.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qsysinfo.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qsystemdetection.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qtcore-config.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qtextstream.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qtypeinfo.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qurl.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qurlquery.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qvariant.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qvarlengtharray.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qvector.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qversiontagging.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qbrush.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qcolor.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qcursor.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qevent.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qfont.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qfontinfo.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qfontmetrics.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qimage.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qkeysequence.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qmatrix.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qpaintdevice.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qpalette.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qpixelformat.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qpixmap.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qpolygon.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qregion.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qrgb.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qrgba64.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qtgui-config.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qtguiglobal.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qtouchdevice.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qtransform.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qvector2d.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qwindowdefs.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qwindowdefs_win.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QAbstractScrollArea
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qabstractscrollarea.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qframe.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qsizepolicy.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qtwidgets-config.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qtwidgetsglobal.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qwidget.h
+ aconf.h
+ aconf2.h
+xpdf-qt/CMakeFiles/xpdf.dir/qrc_icons.cpp.o
+ /home/calvin/src/xpdf-4.04/xpdf-qt/qrc_icons.cpp
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o
+ /home/calvin/src/xpdf-4.04/xpdf-qt/XpdfApp.h
+ /home/calvin/src/xpdf-4.04/xpdf-qt/xpdf.cc
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/QDateTime
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qalgorithms.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qarraydata.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qatomic.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qatomic_bootstrap.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qatomic_cxx11.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qatomic_msvc.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qbasicatomic.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qbytearray.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qbytearraylist.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qchar.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qcompilerdetection.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qconfig-bootstrapped.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qconfig.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qcontainerfwd.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qcontainertools_impl.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qcontiguouscache.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qcoreapplication.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qcoreevent.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qdatastream.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qdatetime.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qdebug.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qeventloop.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qfile.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qfiledevice.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qflags.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qgenericatomic.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qglobal.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qglobalstatic.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qhash.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qhashfunctions.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qiodevice.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qiterator.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qline.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qlist.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qlocale.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qlogging.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qmap.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qmargins.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qmetatype.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qmutex.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qnamespace.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qnumeric.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qobject.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qobject_impl.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qobjectdefs.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qobjectdefs_impl.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qpair.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qpoint.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qprocessordetection.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qrect.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qrefcount.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qregexp.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qscopedpointer.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qset.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qshareddata.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qsharedpointer.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qsharedpointer_impl.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qsize.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qstring.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringalgorithms.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringbuilder.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringlist.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringliteral.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringmatcher.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringview.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qsysinfo.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qsystemdetection.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qtcore-config.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qtextstream.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qtypeinfo.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qurl.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qurlquery.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qvariant.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qvarlengtharray.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qvector.h
+ /usr/include/x86_64-linux-gnu/qt5/QtCore/qversiontagging.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/QColor
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qbrush.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qcolor.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qcursor.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qevent.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qfont.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qfontinfo.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qfontmetrics.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qguiapplication.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qimage.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qinputmethod.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qkeysequence.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qmatrix.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qpaintdevice.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qpalette.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qpixelformat.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qpixmap.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qpolygon.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qregion.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qrgb.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qrgba64.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qtgui-config.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qtguiglobal.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qtouchdevice.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qtransform.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qvector2d.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qwindowdefs.h
+ /usr/include/x86_64-linux-gnu/qt5/QtGui/qwindowdefs_win.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QApplication
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qapplication.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qdesktopwidget.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qsizepolicy.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qtwidgets-config.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qtwidgetsglobal.h
+ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qwidget.h
+ aconf.h
+ aconf2.h
+ goo/GMutex.h
+ goo/GString.h
+ goo/gfile.h
+ goo/gmem.h
+ goo/gtypes.h
+ xpdf/Array.h
+ xpdf/Dict.h
+ xpdf/Object.h
+ xpdf/Stream.h
diff --git a/xpdf-qt/CMakeFiles/xpdf.dir/depend.make b/xpdf-qt/CMakeFiles/xpdf.dir/depend.make
new file mode 100644
index 0000000..f289c11
--- /dev/null
+++ b/xpdf-qt/CMakeFiles/xpdf.dir/depend.make
@@ -0,0 +1,1412 @@
+# CMAKE generated file: DO NOT EDIT!
+# Generated by "Unix Makefiles" Generator, CMake Version 3.18
+
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: xpdf-qt/QtPDFCore.cc
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: xpdf-qt/QtPDFCore.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/QDateTime
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/QFileInfo
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/QProcess
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/QUrl
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qalgorithms.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qarraydata.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qatomic.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qatomic_bootstrap.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qatomic_cxx11.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qatomic_msvc.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qbasicatomic.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qbytearray.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qbytearraylist.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qchar.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qcompilerdetection.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qconfig-bootstrapped.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qconfig.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qcontainerfwd.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qcontainertools_impl.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qcontiguouscache.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qcoreapplication.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qcoreevent.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qdatastream.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qdatetime.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qdebug.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qeventloop.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qfile.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qfiledevice.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qfileinfo.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qflags.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qgenericatomic.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qglobal.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qglobalstatic.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qhash.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qhashfunctions.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qiodevice.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qiterator.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qline.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qlist.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qlocale.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qlogging.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qmap.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qmargins.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qmetatype.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qmutex.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qnamespace.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qnumeric.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qobject.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qobject_impl.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qobjectdefs.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qobjectdefs_impl.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qpair.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qpoint.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qprocess.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qprocessordetection.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qrect.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qrefcount.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qregexp.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qscopedpointer.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qset.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qshareddata.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qsharedpointer.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qsharedpointer_impl.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qsize.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qstandardpaths.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qstring.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringalgorithms.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringbuilder.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringlist.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringliteral.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringmatcher.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringview.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qsysinfo.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qsystemdetection.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qtcore-config.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qtextstream.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qtypeinfo.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qurl.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qurlquery.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qvariant.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qvarlengtharray.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qvector.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qversiontagging.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/QClipboard
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/QDesktopServices
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/QImage
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/QPainter
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qbrush.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qclipboard.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qcolor.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qcursor.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qdesktopservices.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qevent.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qfont.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qfontinfo.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qfontmetrics.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qguiapplication.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qicon.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qimage.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qinputmethod.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qkeysequence.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qmatrix.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qpaintdevice.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qpainter.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qpalette.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qpen.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qpixelformat.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qpixmap.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qpolygon.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qregion.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qrgb.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qrgba64.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qtextcursor.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qtextformat.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qtextoption.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qtgui-config.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qtguiglobal.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qtouchdevice.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qtransform.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qvector2d.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qwindowdefs.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qwindowdefs_win.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QApplication
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QInputDialog
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QMessageBox
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QScrollBar
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QStyle
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QWidget
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qabstractslider.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qapplication.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qdesktopwidget.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qdialog.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qframe.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qinputdialog.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qlineedit.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qmessagebox.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qscrollbar.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qsizepolicy.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qstyle.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qtwidgets-config.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qtwidgetsglobal.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qwidget.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: aconf.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: aconf2.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: goo/FixedPoint.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: goo/GList.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: goo/GMutex.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: goo/GString.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: goo/gfile.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: goo/gmem.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: goo/gmempp.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: goo/gtypes.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: splash/SplashBitmap.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: splash/SplashTypes.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: xpdf/Array.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: xpdf/Catalog.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: xpdf/CharTypes.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: xpdf/Dict.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: xpdf/DisplayState.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: xpdf/Error.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: xpdf/ErrorCodes.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: xpdf/Function.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: xpdf/GfxFont.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: xpdf/GfxState.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: xpdf/GlobalParams.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: xpdf/Link.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: xpdf/Object.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: xpdf/OutputDev.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: xpdf/PDFCore.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: xpdf/PDFDoc.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: xpdf/PSOutputDev.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: xpdf/Page.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: xpdf/Stream.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: xpdf/TextOutputDev.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: xpdf/TileMap.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: xpdf/XRef.h
+xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o: xpdf/config.h
+
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: xpdf-qt/XpdfApp.cc
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: xpdf-qt/XpdfApp.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: xpdf-qt/XpdfViewer.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: xpdf-qt/XpdfWidget.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/QDateTime
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/QFileInfo
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qalgorithms.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qarraydata.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qatomic.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qatomic_bootstrap.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qatomic_cxx11.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qatomic_msvc.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qbasicatomic.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qbytearray.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qbytearraylist.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qchar.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qcompilerdetection.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qconfig-bootstrapped.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qconfig.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qcontainerfwd.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qcontainertools_impl.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qcontiguouscache.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qcoreapplication.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qcoreevent.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qdatastream.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qdatetime.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qdebug.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qeventloop.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qfile.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qfiledevice.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qfileinfo.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qflags.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qgenericatomic.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qglobal.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qglobalstatic.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qhash.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qhashfunctions.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qiodevice.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qiterator.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qline.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qlist.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qlocale.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qlogging.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qmap.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qmargins.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qmetatype.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qmutex.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qnamespace.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qnumeric.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qobject.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qobject_impl.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qobjectdefs.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qobjectdefs_impl.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qpair.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qpoint.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qprocessordetection.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qrect.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qrefcount.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qregexp.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qscopedpointer.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qset.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qshareddata.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qsharedpointer.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qsharedpointer_impl.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qsize.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qstring.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringalgorithms.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringbuilder.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringlist.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringliteral.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringmatcher.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringview.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qsysinfo.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qsystemdetection.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qtcore-config.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qtextstream.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qtypeinfo.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qurl.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qurlquery.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qvariant.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qvarlengtharray.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qvector.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qversiontagging.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/QColor
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/QIcon
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qbrush.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qcolor.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qcursor.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qevent.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qfont.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qfontinfo.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qfontmetrics.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qguiapplication.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qicon.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qimage.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qinputmethod.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qkeysequence.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qmatrix.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qpaintdevice.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qpalette.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qpixelformat.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qpixmap.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qpolygon.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qregion.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qrgb.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qrgba64.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qtgui-config.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qtguiglobal.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qtouchdevice.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qtransform.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qvector2d.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qwindowdefs.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qwindowdefs_win.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtNetwork/QLocalServer
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtNetwork/QLocalSocket
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtNetwork/qabstractsocket.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtNetwork/qlocalserver.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtNetwork/qlocalsocket.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtNetwork/qtnetwork-config.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtNetwork/qtnetworkglobal.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QAbstractScrollArea
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QApplication
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QDialog
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QMainWindow
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QToolButton
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qabstractbutton.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qabstractscrollarea.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qapplication.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qdesktopwidget.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qdialog.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qframe.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qmainwindow.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qsizepolicy.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qtabwidget.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qtoolbutton.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qtwidgets-config.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qtwidgetsglobal.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qwidget.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: aconf.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: aconf2.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: goo/GList.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: goo/GMutex.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: goo/GString.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: goo/gfile.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: goo/gmempp.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: goo/gtypes.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: goo/parseargs.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: xpdf/CharTypes.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: xpdf/Error.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: xpdf/GlobalParams.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o: xpdf/config.h
+
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: xpdf-qt/QtPDFCore.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: xpdf-qt/XpdfApp.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: xpdf-qt/XpdfViewer.cc
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: xpdf-qt/XpdfViewer.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: xpdf-qt/XpdfWidget.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/QAbstractItemModel
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/QDateTime
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/QList
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/QMimeData
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/QObject
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/QProcess
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/QPropertyAnimation
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/QRect
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/QSignalMapper
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/QSize
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/QSizeF
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/QTimer
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qabstractanimation.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qabstractitemmodel.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qalgorithms.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qarraydata.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qatomic.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qatomic_bootstrap.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qatomic_cxx11.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qatomic_msvc.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qbasicatomic.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qbasictimer.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qbytearray.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qbytearraylist.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qchar.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qcompilerdetection.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qconfig-bootstrapped.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qconfig.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qcontainerfwd.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qcontainertools_impl.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qcontiguouscache.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qcoreapplication.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qcoreevent.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qdatastream.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qdatetime.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qdebug.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qdir.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qeasingcurve.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qeventloop.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qfile.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qfiledevice.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qfileinfo.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qflags.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qgenericatomic.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qglobal.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qglobalstatic.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qhash.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qhashfunctions.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qiodevice.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qitemselectionmodel.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qiterator.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qline.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qlist.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qlocale.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qlogging.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qmap.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qmargins.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qmetatype.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qmimedata.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qmutex.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qnamespace.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qnumeric.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qobject.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qobject_impl.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qobjectdefs.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qobjectdefs_impl.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qpair.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qpoint.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qprocess.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qprocessordetection.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qpropertyanimation.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qrect.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qrefcount.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qregexp.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qregularexpression.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qscopedpointer.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qset.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qshareddata.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qsharedpointer.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qsharedpointer_impl.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qsignalmapper.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qsize.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qstandardpaths.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qstring.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringalgorithms.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringbuilder.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringlist.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringliteral.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringmatcher.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringview.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qsysinfo.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qsystemdetection.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qtcore-config.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qtextstream.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qtimer.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qtypeinfo.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qurl.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qurlquery.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qvariant.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qvariantanimation.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qvarlengtharray.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qvector.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qversiontagging.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/QClipboard
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/QColor
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/QDesktopServices
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/QIcon
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/QKeyEvent
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/QMouseEvent
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/QScreen
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/QTransform
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qbrush.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qclipboard.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qcolor.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qcursor.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qdesktopservices.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qevent.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qfont.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qfontinfo.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qfontmetrics.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qguiapplication.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qicon.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qimage.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qinputmethod.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qkeysequence.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qmatrix.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qpaintdevice.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qpalette.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qpen.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qpixelformat.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qpixmap.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qpolygon.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qregion.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qrgb.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qrgba64.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qscreen.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qtextcursor.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qtextdocument.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qtextformat.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qtextoption.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qtgui-config.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qtguiglobal.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qtouchdevice.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qtransform.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qvalidator.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qvector2d.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qwindowdefs.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qwindowdefs_win.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtNetwork/QLocalServer
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtNetwork/QLocalSocket
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtNetwork/qabstractsocket.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtNetwork/qlocalserver.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtNetwork/qlocalsocket.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtNetwork/qtnetwork-config.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtNetwork/qtnetworkglobal.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QAbstractScrollArea
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QAction
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QActionGroup
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QApplication
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QButtonGroup
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QComboBox
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QDialog
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QFileDialog
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QFrame
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QGridLayout
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QHBoxLayout
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QHeaderView
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QLabel
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QLineEdit
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QListWidget
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QMainWindow
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QMenu
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QMenuBar
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QMessageBox
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QProgressDialog
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QPushButton
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QRadioButton
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QScrollBar
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QSplitter
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QStackedLayout
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QStackedWidget
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QTabWidget
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QTableWidget
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QTextBrowser
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QToolBar
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QToolButton
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QTreeView
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QVBoxLayout
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qabstractbutton.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qabstractitemdelegate.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qabstractitemview.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qabstractscrollarea.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qabstractslider.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qabstractspinbox.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qaction.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qactiongroup.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qapplication.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qboxlayout.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qbuttongroup.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qcombobox.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qdesktopwidget.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qdialog.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qfiledialog.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qframe.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qgridlayout.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qheaderview.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qlabel.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qlayout.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qlayoutitem.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qlineedit.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qlistview.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qlistwidget.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qmainwindow.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qmenu.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qmenubar.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qmessagebox.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qprogressdialog.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qpushbutton.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qradiobutton.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qrubberband.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qscrollbar.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qsizepolicy.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qslider.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qsplitter.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qstackedlayout.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qstackedwidget.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qstyle.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qstyleoption.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qtabbar.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qtableview.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qtablewidget.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qtabwidget.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qtextbrowser.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qtextedit.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qtoolbar.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qtoolbutton.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qtreeview.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qtwidgets-config.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qtwidgetsglobal.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qwidget.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: aconf.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: aconf2.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: goo/FixedPoint.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: goo/GList.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: goo/GMutex.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: goo/GString.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: goo/gfile.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: goo/gmem.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: goo/gmempp.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: goo/gtypes.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: splash/SplashTypes.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: xpdf/AcroForm.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: xpdf/Annot.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: xpdf/Array.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: xpdf/Catalog.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: xpdf/CharTypes.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: xpdf/Dict.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: xpdf/DisplayState.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: xpdf/Error.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: xpdf/GfxFont.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: xpdf/GlobalParams.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: xpdf/Object.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: xpdf/OutputDev.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: xpdf/PDFCore.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: xpdf/PDFDoc.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: xpdf/Page.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: xpdf/Stream.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: xpdf/TextOutputDev.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: xpdf/TextString.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: xpdf/XRef.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: xpdf/Zoox.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o: xpdf/config.h
+
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: xpdf-qt/QtPDFCore.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: xpdf-qt/XpdfWidget.cc
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: xpdf-qt/XpdfWidget.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: xpdf-qt/XpdfWidgetPrint.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/QDateTime
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/QMutex
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/QTimer
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qalgorithms.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qarraydata.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qatomic.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qatomic_bootstrap.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qatomic_cxx11.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qatomic_msvc.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qbasicatomic.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qbasictimer.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qbytearray.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qbytearraylist.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qchar.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qcompilerdetection.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qconfig-bootstrapped.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qconfig.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qcontainerfwd.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qcontainertools_impl.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qcontiguouscache.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qcoreapplication.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qcoreevent.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qdatastream.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qdatetime.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qdebug.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qeventloop.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qfile.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qfiledevice.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qflags.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qgenericatomic.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qglobal.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qglobalstatic.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qhash.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qhashfunctions.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qiodevice.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qiterator.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qline.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qlist.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qlocale.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qlogging.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qmap.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qmargins.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qmetatype.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qmutex.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qnamespace.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qnumeric.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qobject.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qobject_impl.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qobjectdefs.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qobjectdefs_impl.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qpair.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qpoint.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qprocessordetection.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qrect.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qrefcount.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qregexp.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qscopedpointer.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qset.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qshareddata.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qsharedpointer.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qsharedpointer_impl.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qsize.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qstring.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringalgorithms.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringbuilder.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringlist.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringliteral.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringmatcher.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringview.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qsysinfo.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qsystemdetection.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qtcore-config.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qtextstream.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qtimer.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qtypeinfo.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qurl.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qurlquery.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qvariant.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qvarlengtharray.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qvector.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qversiontagging.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/QKeyEvent
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/QPaintEvent
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qbrush.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qcolor.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qcursor.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qevent.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qfont.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qfontinfo.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qfontmetrics.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qguiapplication.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qimage.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qinputmethod.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qkeysequence.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qmatrix.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qpagedpaintdevice.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qpagelayout.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qpagesize.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qpaintdevice.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qpalette.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qpixelformat.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qpixmap.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qpolygon.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qregion.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qrgb.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qrgba64.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qtgui-config.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qtguiglobal.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qtouchdevice.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qtransform.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qvector2d.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qwindowdefs.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qwindowdefs_win.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtPrintSupport/QPrintDialog
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtPrintSupport/QPrinter
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtPrintSupport/qabstractprintdialog.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtPrintSupport/qprintdialog.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtPrintSupport/qprinter.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtPrintSupport/qtprintsupport-config.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtPrintSupport/qtprintsupportglobal.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QAbstractScrollArea
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QApplication
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QGesture
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QGestureEvent
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qabstractscrollarea.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qapplication.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qdesktopwidget.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qdialog.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qframe.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qgesture.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qsizepolicy.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qtwidgets-config.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qtwidgetsglobal.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qwidget.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: aconf.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: aconf2.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: goo/FixedPoint.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: goo/GList.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: goo/GMutex.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: goo/GString.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: goo/gfile.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: goo/gmem.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: goo/gmempp.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: goo/gtypes.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: splash/SplashBitmap.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: splash/SplashTypes.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: xpdf/AcroForm.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: xpdf/Annot.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: xpdf/Array.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: xpdf/Catalog.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: xpdf/CharTypes.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: xpdf/Dict.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: xpdf/DisplayState.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: xpdf/Function.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: xpdf/GfxFont.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: xpdf/GfxState.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: xpdf/GlobalParams.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: xpdf/Link.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: xpdf/Object.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: xpdf/OptionalContent.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: xpdf/Outline.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: xpdf/OutputDev.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: xpdf/PDFCore.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: xpdf/PDFDoc.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: xpdf/Page.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: xpdf/SplashOutputDev.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: xpdf/Stream.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: xpdf/TextOutputDev.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: xpdf/TextString.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: xpdf/XRef.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o: xpdf/config.h
+
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: xpdf-qt/XpdfWidget.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: xpdf-qt/XpdfWidgetPrint.cc
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qalgorithms.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qarraydata.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qatomic.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qatomic_bootstrap.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qatomic_cxx11.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qatomic_msvc.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qbasicatomic.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qbytearray.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qbytearraylist.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qchar.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qcompilerdetection.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qconfig-bootstrapped.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qconfig.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qcontainerfwd.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qcontainertools_impl.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qcontiguouscache.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qcoreevent.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qdatastream.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qdebug.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qfile.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qfiledevice.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qflags.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qgenericatomic.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qglobal.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qglobalstatic.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qhash.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qhashfunctions.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qiodevice.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qiterator.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qline.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qlist.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qlocale.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qlogging.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qmap.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qmargins.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qmetatype.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qmutex.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qnamespace.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qnumeric.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qobject.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qobject_impl.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qobjectdefs.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qobjectdefs_impl.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qpair.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qpoint.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qprocessordetection.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qrect.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qrefcount.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qregexp.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qscopedpointer.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qset.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qshareddata.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qsharedpointer.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qsharedpointer_impl.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qsize.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qstring.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringalgorithms.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringbuilder.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringlist.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringliteral.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringmatcher.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringview.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qsysinfo.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qsystemdetection.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qtcore-config.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qtextstream.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qtypeinfo.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qurl.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qurlquery.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qvariant.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qvarlengtharray.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qvector.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qversiontagging.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qbrush.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qcolor.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qcursor.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qevent.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qfont.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qfontinfo.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qfontmetrics.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qimage.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qkeysequence.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qmatrix.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qpagedpaintdevice.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qpagelayout.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qpagesize.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qpaintdevice.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qpalette.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qpixelformat.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qpixmap.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qpolygon.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qregion.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qrgb.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qrgba64.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qtgui-config.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qtguiglobal.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qtouchdevice.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qtransform.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qvector2d.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qwindowdefs.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qwindowdefs_win.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtPrintSupport/QPrinter
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtPrintSupport/qprinter.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtPrintSupport/qtprintsupport-config.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtPrintSupport/qtprintsupportglobal.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QAbstractScrollArea
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qabstractscrollarea.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qframe.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qsizepolicy.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qtwidgets-config.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qtwidgetsglobal.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qwidget.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: aconf.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: aconf2.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: goo/GMutex.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: goo/GString.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: goo/gfile.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: goo/gmem.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: goo/gmempp.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: goo/gtypes.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: xpdf/Array.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: xpdf/Catalog.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: xpdf/CharTypes.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: xpdf/Dict.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: xpdf/ErrorCodes.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: xpdf/GlobalParams.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: xpdf/Object.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: xpdf/OutputDev.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: xpdf/PDFDoc.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: xpdf/PSOutputDev.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: xpdf/Page.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: xpdf/Stream.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: xpdf/XRef.h
+xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o: xpdf/config.h
+
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: xpdf-qt/XpdfApp.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: xpdf-qt/moc_XpdfApp.cpp
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/QDateTime
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qalgorithms.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qarraydata.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qatomic.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qatomic_bootstrap.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qatomic_cxx11.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qatomic_msvc.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qbasicatomic.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qbytearray.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qbytearraylist.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qchar.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qcompilerdetection.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qconfig-bootstrapped.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qconfig.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qcontainerfwd.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qcontainertools_impl.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qcontiguouscache.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qcoreapplication.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qcoreevent.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qdatastream.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qdatetime.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qdebug.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qeventloop.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qfile.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qfiledevice.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qflags.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qgenericatomic.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qglobal.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qglobalstatic.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qhash.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qhashfunctions.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qiodevice.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qiterator.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qline.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qlist.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qlocale.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qlogging.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qmap.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qmargins.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qmetatype.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qmutex.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qnamespace.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qnumeric.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qobject.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qobject_impl.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qobjectdefs.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qobjectdefs_impl.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qpair.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qpoint.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qprocessordetection.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qrect.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qrefcount.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qregexp.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qscopedpointer.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qset.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qshareddata.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qsharedpointer.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qsharedpointer_impl.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qsize.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qstring.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringalgorithms.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringbuilder.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringlist.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringliteral.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringmatcher.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringview.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qsysinfo.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qsystemdetection.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qtcore-config.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qtextstream.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qtypeinfo.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qurl.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qurlquery.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qvariant.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qvarlengtharray.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qvector.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qversiontagging.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/QColor
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qbrush.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qcolor.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qcursor.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qevent.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qfont.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qfontinfo.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qfontmetrics.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qguiapplication.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qimage.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qinputmethod.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qkeysequence.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qmatrix.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qpaintdevice.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qpalette.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qpixelformat.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qpixmap.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qpolygon.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qregion.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qrgb.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qrgba64.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qtgui-config.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qtguiglobal.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qtouchdevice.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qtransform.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qvector2d.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qwindowdefs.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qwindowdefs_win.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QApplication
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qapplication.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qdesktopwidget.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qsizepolicy.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qtwidgets-config.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qtwidgetsglobal.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qwidget.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: aconf.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: aconf2.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o: goo/gtypes.h
+
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: xpdf-qt/XpdfViewer.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: xpdf-qt/XpdfWidget.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: xpdf-qt/moc_XpdfViewer.cpp
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qalgorithms.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qarraydata.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qatomic.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qatomic_bootstrap.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qatomic_cxx11.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qatomic_msvc.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qbasicatomic.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qbytearray.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qbytearraylist.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qchar.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qcompilerdetection.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qconfig-bootstrapped.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qconfig.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qcontainerfwd.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qcontainertools_impl.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qcontiguouscache.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qcoreevent.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qdatastream.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qdebug.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qfile.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qfiledevice.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qflags.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qgenericatomic.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qglobal.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qglobalstatic.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qhash.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qhashfunctions.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qiodevice.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qiterator.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qline.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qlist.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qlocale.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qlogging.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qmap.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qmargins.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qmetatype.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qmutex.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qnamespace.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qnumeric.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qobject.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qobject_impl.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qobjectdefs.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qobjectdefs_impl.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qpair.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qpoint.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qprocessordetection.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qrect.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qrefcount.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qregexp.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qscopedpointer.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qset.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qshareddata.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qsharedpointer.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qsharedpointer_impl.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qsize.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qstring.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringalgorithms.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringbuilder.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringlist.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringliteral.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringmatcher.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringview.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qsysinfo.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qsystemdetection.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qtcore-config.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qtextstream.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qtypeinfo.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qurl.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qurlquery.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qvariant.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qvarlengtharray.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qvector.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qversiontagging.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/QIcon
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qbrush.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qcolor.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qcursor.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qevent.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qfont.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qfontinfo.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qfontmetrics.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qicon.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qimage.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qkeysequence.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qmatrix.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qpaintdevice.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qpalette.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qpixelformat.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qpixmap.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qpolygon.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qregion.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qrgb.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qrgba64.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qtgui-config.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qtguiglobal.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qtouchdevice.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qtransform.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qvector2d.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qwindowdefs.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qwindowdefs_win.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtNetwork/QLocalServer
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtNetwork/qabstractsocket.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtNetwork/qlocalserver.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtNetwork/qtnetwork-config.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtNetwork/qtnetworkglobal.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QAbstractScrollArea
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QDialog
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QMainWindow
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QToolButton
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qabstractbutton.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qabstractscrollarea.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qdialog.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qframe.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qmainwindow.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qsizepolicy.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qtabwidget.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qtoolbutton.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qtwidgets-config.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qtwidgetsglobal.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qwidget.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: aconf.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: aconf2.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: goo/gfile.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: goo/gtypes.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: xpdf/Error.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o: xpdf/config.h
+
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: xpdf-qt/XpdfWidget.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: xpdf-qt/moc_XpdfWidget.cpp
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qalgorithms.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qarraydata.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qatomic.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qatomic_bootstrap.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qatomic_cxx11.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qatomic_msvc.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qbasicatomic.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qbytearray.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qbytearraylist.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qchar.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qcompilerdetection.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qconfig-bootstrapped.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qconfig.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qcontainerfwd.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qcontainertools_impl.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qcontiguouscache.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qcoreevent.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qdatastream.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qdebug.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qfile.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qfiledevice.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qflags.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qgenericatomic.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qglobal.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qglobalstatic.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qhash.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qhashfunctions.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qiodevice.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qiterator.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qline.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qlist.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qlocale.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qlogging.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qmap.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qmargins.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qmetatype.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qmutex.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qnamespace.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qnumeric.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qobject.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qobject_impl.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qobjectdefs.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qobjectdefs_impl.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qpair.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qpoint.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qprocessordetection.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qrect.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qrefcount.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qregexp.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qscopedpointer.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qset.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qshareddata.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qsharedpointer.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qsharedpointer_impl.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qsize.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qstring.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringalgorithms.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringbuilder.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringlist.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringliteral.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringmatcher.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringview.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qsysinfo.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qsystemdetection.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qtcore-config.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qtextstream.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qtypeinfo.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qurl.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qurlquery.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qvariant.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qvarlengtharray.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qvector.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qversiontagging.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qbrush.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qcolor.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qcursor.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qevent.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qfont.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qfontinfo.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qfontmetrics.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qimage.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qkeysequence.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qmatrix.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qpaintdevice.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qpalette.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qpixelformat.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qpixmap.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qpolygon.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qregion.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qrgb.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qrgba64.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qtgui-config.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qtguiglobal.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qtouchdevice.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qtransform.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qvector2d.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qwindowdefs.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qwindowdefs_win.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QAbstractScrollArea
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qabstractscrollarea.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qframe.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qsizepolicy.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qtwidgets-config.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qtwidgetsglobal.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qwidget.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: aconf.h
+xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o: aconf2.h
+
+xpdf-qt/CMakeFiles/xpdf.dir/qrc_icons.cpp.o: xpdf-qt/qrc_icons.cpp
+
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: xpdf-qt/XpdfApp.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: xpdf-qt/xpdf.cc
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/QDateTime
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qalgorithms.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qarraydata.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qatomic.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qatomic_bootstrap.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qatomic_cxx11.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qatomic_msvc.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qbasicatomic.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qbytearray.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qbytearraylist.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qchar.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qcompilerdetection.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qconfig-bootstrapped.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qconfig.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qcontainerfwd.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qcontainertools_impl.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qcontiguouscache.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qcoreapplication.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qcoreevent.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qdatastream.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qdatetime.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qdebug.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qeventloop.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qfile.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qfiledevice.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qflags.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qgenericatomic.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qglobal.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qglobalstatic.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qhash.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qhashfunctions.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qiodevice.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qiterator.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qline.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qlist.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qlocale.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qlogging.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qmap.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qmargins.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qmetatype.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qmutex.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qnamespace.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qnumeric.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qobject.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qobject_impl.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qobjectdefs.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qobjectdefs_impl.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qpair.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qpoint.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qprocessordetection.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qrect.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qrefcount.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qregexp.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qscopedpointer.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qset.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qshareddata.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qsharedpointer.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qsharedpointer_impl.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qsize.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qstring.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringalgorithms.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringbuilder.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringlist.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringliteral.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringmatcher.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qstringview.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qsysinfo.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qsystemdetection.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qtcore-config.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qtextstream.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qtypeinfo.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qurl.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qurlquery.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qvariant.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qvarlengtharray.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qvector.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtCore/qversiontagging.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/QColor
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qbrush.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qcolor.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qcursor.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qevent.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qfont.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qfontinfo.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qfontmetrics.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qguiapplication.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qimage.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qinputmethod.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qkeysequence.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qmatrix.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qpaintdevice.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qpalette.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qpixelformat.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qpixmap.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qpolygon.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qregion.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qrgb.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qrgba64.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qtgui-config.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qtguiglobal.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qtouchdevice.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qtransform.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qvector2d.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qwindowdefs.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtGui/qwindowdefs_win.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QApplication
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qapplication.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qdesktopwidget.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qsizepolicy.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qtwidgets-config.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qtwidgetsglobal.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: /usr/include/x86_64-linux-gnu/qt5/QtWidgets/qwidget.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: aconf.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: aconf2.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: goo/GMutex.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: goo/GString.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: goo/gfile.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: goo/gmem.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: goo/gtypes.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: xpdf/Array.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: xpdf/Dict.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: xpdf/Object.h
+xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o: xpdf/Stream.h
+
diff --git a/xpdf-qt/CMakeFiles/xpdf.dir/flags.make b/xpdf-qt/CMakeFiles/xpdf.dir/flags.make
new file mode 100644
index 0000000..f1b4973
--- /dev/null
+++ b/xpdf-qt/CMakeFiles/xpdf.dir/flags.make
@@ -0,0 +1,17 @@
+# CMAKE generated file: DO NOT EDIT!
+# Generated by "Unix Makefiles" Generator, CMake Version 3.18
+
+# compile C with /usr/bin/cc
+# compile CXX with /usr/bin/c++
+C_DEFINES = -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_NO_DEBUG -DQT_PRINTSUPPORT_LIB -DQT_WIDGETS_LIB -DXPDFWIDGET_PRINTING=1
+
+C_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 -I/home/calvin/src/xpdf-4.04/xpdf -isystem /usr/include/x86_64-linux-gnu/qt5 -isystem /usr/include/x86_64-linux-gnu/qt5/QtWidgets -isystem /usr/include/x86_64-linux-gnu/qt5/QtGui -isystem /usr/include/x86_64-linux-gnu/qt5/QtCore -isystem "/usr/lib/x86_64-linux-gnu/qt5/mkspecs/linux-g++ /usr/include/x86_64-linux-gnu/qt5" -isystem /usr/include/x86_64-linux-gnu/qt5/QtNetwork -isystem /usr/include/x86_64-linux-gnu/qt5/QtPrintSupport -isystem /usr/lib/x86_64-linux-gnu/qt5/mkspecs/linux-g++
+
+C_FLAGS = -DQT_CORE_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_PRINTSUPPORT_LIB -fPIC
+
+CXX_DEFINES = -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_NO_DEBUG -DQT_PRINTSUPPORT_LIB -DQT_WIDGETS_LIB -DXPDFWIDGET_PRINTING=1
+
+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 -I/home/calvin/src/xpdf-4.04/xpdf -isystem /usr/include/x86_64-linux-gnu/qt5 -isystem /usr/include/x86_64-linux-gnu/qt5/QtWidgets -isystem /usr/include/x86_64-linux-gnu/qt5/QtGui -isystem /usr/include/x86_64-linux-gnu/qt5/QtCore -isystem "/usr/lib/x86_64-linux-gnu/qt5/mkspecs/linux-g++ /usr/include/x86_64-linux-gnu/qt5" -isystem /usr/include/x86_64-linux-gnu/qt5/QtNetwork -isystem /usr/include/x86_64-linux-gnu/qt5/QtPrintSupport -isystem /usr/lib/x86_64-linux-gnu/qt5/mkspecs/linux-g++
+
+CXX_FLAGS = -DQT_CORE_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_PRINTSUPPORT_LIB -fPIC -std=gnu++11
+
diff --git a/xpdf-qt/CMakeFiles/xpdf.dir/link.txt b/xpdf-qt/CMakeFiles/xpdf.dir/link.txt
new file mode 100644
index 0000000..7a5165a
--- /dev/null
+++ b/xpdf-qt/CMakeFiles/xpdf.dir/link.txt
@@ -0,0 +1 @@
+/usr/bin/c++ -rdynamic CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o CMakeFiles/xpdf.dir/QtPDFCore.cc.o CMakeFiles/xpdf.dir/XpdfApp.cc.o CMakeFiles/xpdf.dir/XpdfViewer.cc.o CMakeFiles/xpdf.dir/XpdfWidget.cc.o CMakeFiles/xpdf.dir/xpdf.cc.o CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o CMakeFiles/xpdf.dir/qrc_icons.cpp.o ../goo/CMakeFiles/goo_objs.dir/FixedPoint.cc.o ../goo/CMakeFiles/goo_objs.dir/GHash.cc.o ../goo/CMakeFiles/goo_objs.dir/GList.cc.o ../goo/CMakeFiles/goo_objs.dir/GString.cc.o ../goo/CMakeFiles/goo_objs.dir/gfile.cc.o ../goo/CMakeFiles/goo_objs.dir/gmem.cc.o ../goo/CMakeFiles/goo_objs.dir/gmempp.cc.o ../goo/CMakeFiles/goo_objs.dir/parseargs.c.o ../goo/CMakeFiles/goo_objs.dir/Trace.cc.o ../fofi/CMakeFiles/fofi_objs.dir/FoFiBase.cc.o ../fofi/CMakeFiles/fofi_objs.dir/FoFiEncodings.cc.o ../fofi/CMakeFiles/fofi_objs.dir/FoFiIdentifier.cc.o ../fofi/CMakeFiles/fofi_objs.dir/FoFiTrueType.cc.o ../fofi/CMakeFiles/fofi_objs.dir/FoFiType1.cc.o ../fofi/CMakeFiles/fofi_objs.dir/FoFiType1C.cc.o ../splash/CMakeFiles/splash_objs.dir/Splash.cc.o ../splash/CMakeFiles/splash_objs.dir/SplashBitmap.cc.o ../splash/CMakeFiles/splash_objs.dir/SplashClip.cc.o ../splash/CMakeFiles/splash_objs.dir/SplashFTFont.cc.o ../splash/CMakeFiles/splash_objs.dir/SplashFTFontEngine.cc.o ../splash/CMakeFiles/splash_objs.dir/SplashFTFontFile.cc.o ../splash/CMakeFiles/splash_objs.dir/SplashFont.cc.o ../splash/CMakeFiles/splash_objs.dir/SplashFontEngine.cc.o ../splash/CMakeFiles/splash_objs.dir/SplashFontFile.cc.o ../splash/CMakeFiles/splash_objs.dir/SplashFontFileID.cc.o ../splash/CMakeFiles/splash_objs.dir/SplashPath.cc.o ../splash/CMakeFiles/splash_objs.dir/SplashPattern.cc.o ../splash/CMakeFiles/splash_objs.dir/SplashScreen.cc.o ../splash/CMakeFiles/splash_objs.dir/SplashState.cc.o ../splash/CMakeFiles/splash_objs.dir/SplashXPath.cc.o ../splash/CMakeFiles/splash_objs.dir/SplashXPathScanner.cc.o ../xpdf/CMakeFiles/xpdf_objs.dir/AcroForm.cc.o ../xpdf/CMakeFiles/xpdf_objs.dir/Annot.cc.o ../xpdf/CMakeFiles/xpdf_objs.dir/Array.cc.o ../xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFont.cc.o ../xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFontTables.cc.o ../xpdf/CMakeFiles/xpdf_objs.dir/Catalog.cc.o ../xpdf/CMakeFiles/xpdf_objs.dir/CharCodeToUnicode.cc.o ../xpdf/CMakeFiles/xpdf_objs.dir/CMap.cc.o ../xpdf/CMakeFiles/xpdf_objs.dir/Decrypt.cc.o ../xpdf/CMakeFiles/xpdf_objs.dir/Dict.cc.o ../xpdf/CMakeFiles/xpdf_objs.dir/Error.cc.o ../xpdf/CMakeFiles/xpdf_objs.dir/FontEncodingTables.cc.o ../xpdf/CMakeFiles/xpdf_objs.dir/Function.cc.o ../xpdf/CMakeFiles/xpdf_objs.dir/Gfx.cc.o ../xpdf/CMakeFiles/xpdf_objs.dir/GfxFont.cc.o ../xpdf/CMakeFiles/xpdf_objs.dir/GfxState.cc.o ../xpdf/CMakeFiles/xpdf_objs.dir/GlobalParams.cc.o ../xpdf/CMakeFiles/xpdf_objs.dir/JArithmeticDecoder.cc.o ../xpdf/CMakeFiles/xpdf_objs.dir/JBIG2Stream.cc.o ../xpdf/CMakeFiles/xpdf_objs.dir/JPXStream.cc.o ../xpdf/CMakeFiles/xpdf_objs.dir/Lexer.cc.o ../xpdf/CMakeFiles/xpdf_objs.dir/Link.cc.o ../xpdf/CMakeFiles/xpdf_objs.dir/NameToCharCode.cc.o ../xpdf/CMakeFiles/xpdf_objs.dir/Object.cc.o ../xpdf/CMakeFiles/xpdf_objs.dir/OptionalContent.cc.o ../xpdf/CMakeFiles/xpdf_objs.dir/Outline.cc.o ../xpdf/CMakeFiles/xpdf_objs.dir/OutputDev.cc.o ../xpdf/CMakeFiles/xpdf_objs.dir/Page.cc.o ../xpdf/CMakeFiles/xpdf_objs.dir/Parser.cc.o ../xpdf/CMakeFiles/xpdf_objs.dir/PDF417Barcode.cc.o ../xpdf/CMakeFiles/xpdf_objs.dir/PDFDoc.cc.o ../xpdf/CMakeFiles/xpdf_objs.dir/PDFDocEncoding.cc.o ../xpdf/CMakeFiles/xpdf_objs.dir/PSTokenizer.cc.o ../xpdf/CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.o ../xpdf/CMakeFiles/xpdf_objs.dir/Stream.cc.o ../xpdf/CMakeFiles/xpdf_objs.dir/TextString.cc.o ../xpdf/CMakeFiles/xpdf_objs.dir/UnicodeMap.cc.o ../xpdf/CMakeFiles/xpdf_objs.dir/UnicodeRemapping.cc.o ../xpdf/CMakeFiles/xpdf_objs.dir/UnicodeTypeTable.cc.o ../xpdf/CMakeFiles/xpdf_objs.dir/UTF8.cc.o ../xpdf/CMakeFiles/xpdf_objs.dir/XFAScanner.cc.o ../xpdf/CMakeFiles/xpdf_objs.dir/XRef.cc.o ../xpdf/CMakeFiles/xpdf_objs.dir/Zoox.cc.o ../xpdf/CMakeFiles/xpdf_widget_objs.dir/DisplayState.cc.o ../xpdf/CMakeFiles/xpdf_widget_objs.dir/PDFCore.cc.o ../xpdf/CMakeFiles/xpdf_widget_objs.dir/PreScanOutputDev.cc.o ../xpdf/CMakeFiles/xpdf_widget_objs.dir/PSOutputDev.cc.o ../xpdf/CMakeFiles/xpdf_widget_objs.dir/ShadingImage.cc.o ../xpdf/CMakeFiles/xpdf_widget_objs.dir/SplashOutputDev.cc.o ../xpdf/CMakeFiles/xpdf_widget_objs.dir/TextOutputDev.cc.o ../xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCache.cc.o ../xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCompositor.cc.o ../xpdf/CMakeFiles/xpdf_widget_objs.dir/TileMap.cc.o -o xpdf /usr/lib/x86_64-linux-gnu/libQt5Network.so.5.15.2 /usr/lib/x86_64-linux-gnu/libQt5PrintSupport.so.5.15.2 -lcups -lfreetype -lfontconfig -lpthread /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5.15.2 /usr/lib/x86_64-linux-gnu/libQt5Gui.so.5.15.2 /usr/lib/x86_64-linux-gnu/libQt5Core.so.5.15.2
diff --git a/xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o b/xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o
new file mode 100644
index 0000000..e7c954f
--- /dev/null
+++ b/xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o
Binary files differ
diff --git a/xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o b/xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o
new file mode 100644
index 0000000..93d9182
--- /dev/null
+++ b/xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o
Binary files differ
diff --git a/xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o b/xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o
new file mode 100644
index 0000000..9a400ef
--- /dev/null
+++ b/xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o
Binary files differ
diff --git a/xpdf-qt/CMakeFiles/xpdf.dir/progress.make b/xpdf-qt/CMakeFiles/xpdf.dir/progress.make
new file mode 100644
index 0000000..722f47a
--- /dev/null
+++ b/xpdf-qt/CMakeFiles/xpdf.dir/progress.make
@@ -0,0 +1,16 @@
+CMAKE_PROGRESS_1 = 50
+CMAKE_PROGRESS_2 = 51
+CMAKE_PROGRESS_3 =
+CMAKE_PROGRESS_4 = 52
+CMAKE_PROGRESS_5 = 53
+CMAKE_PROGRESS_6 = 54
+CMAKE_PROGRESS_7 =
+CMAKE_PROGRESS_8 = 55
+CMAKE_PROGRESS_9 = 56
+CMAKE_PROGRESS_10 = 57
+CMAKE_PROGRESS_11 =
+CMAKE_PROGRESS_12 = 58
+CMAKE_PROGRESS_13 = 59
+CMAKE_PROGRESS_14 = 60
+CMAKE_PROGRESS_15 =
+
diff --git a/xpdf-qt/CMakeFiles/xpdf.dir/qrc_icons.cpp.o b/xpdf-qt/CMakeFiles/xpdf.dir/qrc_icons.cpp.o
new file mode 100644
index 0000000..61c8121
--- /dev/null
+++ b/xpdf-qt/CMakeFiles/xpdf.dir/qrc_icons.cpp.o
Binary files differ
diff --git a/xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o b/xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o
new file mode 100644
index 0000000..3a3f454
--- /dev/null
+++ b/xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o
Binary files differ
diff --git a/xpdf-qt/CMakeLists.txt b/xpdf-qt/CMakeLists.txt
new file mode 100644
index 0000000..026174a
--- /dev/null
+++ b/xpdf-qt/CMakeLists.txt
@@ -0,0 +1,115 @@
+#========================================================================
+#
+# xpdf-qt/cmake-xpdf.txt
+#
+# CMake script for the xpdf application.
+#
+# Copyright 2015 Glyph & Cog, LLC
+#
+#========================================================================
+
+if ((QT4_FOUND OR Qt5Widgets_FOUND OR Qt6Widgets_FOUND)
+ AND HAVE_SPLASH AND MULTITHREADED AND USE_EXCEPTIONS)
+ 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")
+ include_directories("${PROJECT_SOURCE_DIR}/xpdf")
+ if (QT4_FOUND)
+ include(${QT_USE_FILE})
+ else ()
+ include_directories(SYSTEM "${QT_INCLUDES}")
+ add_definitions(${QT_DEFINITIONS})
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${QT_CFLAGS}")
+ endif ()
+ cmake_policy(SET CMP0020 NEW)
+
+ if (Qt5Widgets_FOUND AND NOT (Qt5Widgets_VERSION VERSION_LESS 5.7.0))
+ set(CMAKE_CXX_STANDARD 11)
+ set(CMAKE_CXX_STANDARD_REQUIRED ON)
+ endif ()
+
+ if (WIN32)
+ set(XPDF_MANIFEST "${PROJECT_SOURCE_DIR}/xpdf/winLongPath.exe.manifest")
+ else ()
+ set(XPDF_MANIFEST "")
+ endif ()
+
+ if (XPDFWIDGET_PRINTING)
+ if (WIN32)
+ if (EXISTS ${PROJECT_SOURCE_DIR}/xpdf/WinPDFPrinter.cc)
+ add_definitions(-DXPDFWIDGET_PRINTING=1)
+ add_definitions(-DXPDFWIDGET_WIN32_PRINTING=1)
+ set(XPDFWIDGET_PRINT_MODULES XpdfWidgetPrint.cc
+ ${PROJECT_SOURCE_DIR}/xpdf/GDIOutputDev.cc
+ ${PROJECT_SOURCE_DIR}/xpdf/WinPDFPrinter.cc)
+ endif ()
+ else ()
+ add_definitions(-DXPDFWIDGET_PRINTING=1)
+ set(XPDFWIDGET_PRINT_MODULES XpdfWidgetPrint.cc)
+ endif ()
+ else ()
+ set(XPDFWIDGET_PRINT_MODULES "")
+ endif ()
+
+ if (QT4_FOUND)
+ qt4_wrap_cpp(XPDFWIDGET_MOC XpdfWidget.h)
+ qt4_wrap_cpp(XPDFVIEWER_MOC XpdfViewer.h)
+ qt4_wrap_cpp(XPDFAPP_MOC XpdfApp.h)
+ qt4_add_resources(XPDF_ICONS icons.qrc)
+ elseif (Qt5Widgets_FOUND)
+ qt5_wrap_cpp(XPDFWIDGET_MOC XpdfWidget.h)
+ qt5_wrap_cpp(XPDFVIEWER_MOC XpdfViewer.h)
+ qt5_wrap_cpp(XPDFAPP_MOC XpdfApp.h)
+ qt5_add_resources(XPDF_ICONS icons.qrc)
+ else ()
+ qt6_wrap_cpp(XPDFWIDGET_MOC XpdfWidget.h)
+ qt6_wrap_cpp(XPDFVIEWER_MOC XpdfViewer.h)
+ qt6_wrap_cpp(XPDFAPP_MOC XpdfApp.h)
+ qt6_add_resources(XPDF_ICONS icons.qrc)
+ endif ()
+
+ # workaround for a conflict between the Qt5/6 QDateTime and windows.h
+ if (WIN32)
+ add_definitions(-DNOMINMAX)
+ endif ()
+
+ add_executable(xpdf
+ $<TARGET_OBJECTS:goo_objs>
+ $<TARGET_OBJECTS:fofi_objs>
+ $<TARGET_OBJECTS:splash_objs>
+ $<TARGET_OBJECTS:xpdf_objs>
+ $<TARGET_OBJECTS:xpdf_widget_objs>
+ ${XPDFWIDGET_PRINT_MODULES}
+ QtPDFCore.cc
+ XpdfApp.cc
+ XpdfViewer.cc
+ XpdfWidget.cc
+ xpdf.cc
+ xpdf.rc
+ ${XPDFAPP_MOC}
+ ${XPDFVIEWER_MOC}
+ ${XPDFWIDGET_MOC}
+ ${XPDF_ICONS}
+ ${XPDF_MANIFEST}
+ )
+ target_link_libraries(xpdf ${QT_LIBRARIES} ${EXTRA_QT_LIBRARIES}
+ ${PAPER_LIBRARY}
+ ${FREETYPE_LIBRARY} ${FREETYPE_OTHER_LIBS}
+ ${DTYPE_LIBRARY}
+ ${LCMS_LIBRARY}
+ ${FONTCONFIG_LIBRARY}
+ ${CMAKE_THREAD_LIBS_INIT})
+ set_property(TARGET xpdf PROPERTY WIN32_EXECUTABLE 1)
+ if (QT4_FOUND)
+ set_property(TARGET xpdf PROPERTY QT4_NO_LINK_QTMAIN ON)
+ elseif (Qt5Widgets_FOUND)
+ set_property(TARGET xpdf PROPERTY Qt5_NO_LINK_QTMAIN ON)
+ else ()
+ set_property(TARGET xpdf PROPERTY Qt6_NO_LINK_QTMAIN ON)
+ endif ()
+
+ install(TARGETS xpdf RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
+ install(FILES ${PROJECT_SOURCE_DIR}/doc/xpdf.1 DESTINATION ${CMAKE_INSTALL_MANDIR}/man1)
+endif ()
diff --git a/xpdf-qt/Makefile b/xpdf-qt/Makefile
new file mode 100644
index 0000000..69bd17f
--- /dev/null
+++ b/xpdf-qt/Makefile
@@ -0,0 +1,519 @@
+# 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 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 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 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-qt//CMakeFiles/progress.marks
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 xpdf-qt/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-qt/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-qt/preinstall
+.PHONY : preinstall
+
+# Prepare targets for installation.
+preinstall/fast:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 xpdf-qt/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-qt/CMakeFiles/xpdf.dir/rule:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 xpdf-qt/CMakeFiles/xpdf.dir/rule
+.PHONY : xpdf-qt/CMakeFiles/xpdf.dir/rule
+
+# Convenience name for target.
+xpdf: xpdf-qt/CMakeFiles/xpdf.dir/rule
+
+.PHONY : xpdf
+
+# fast build rule for target.
+xpdf/fast:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf-qt/CMakeFiles/xpdf.dir/build.make xpdf-qt/CMakeFiles/xpdf.dir/build
+.PHONY : xpdf/fast
+
+QtPDFCore.o: QtPDFCore.cc.o
+
+.PHONY : QtPDFCore.o
+
+# target to build an object file
+QtPDFCore.cc.o:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf-qt/CMakeFiles/xpdf.dir/build.make xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.o
+.PHONY : QtPDFCore.cc.o
+
+QtPDFCore.i: QtPDFCore.cc.i
+
+.PHONY : QtPDFCore.i
+
+# target to preprocess a source file
+QtPDFCore.cc.i:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf-qt/CMakeFiles/xpdf.dir/build.make xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.i
+.PHONY : QtPDFCore.cc.i
+
+QtPDFCore.s: QtPDFCore.cc.s
+
+.PHONY : QtPDFCore.s
+
+# target to generate assembly for a file
+QtPDFCore.cc.s:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf-qt/CMakeFiles/xpdf.dir/build.make xpdf-qt/CMakeFiles/xpdf.dir/QtPDFCore.cc.s
+.PHONY : QtPDFCore.cc.s
+
+XpdfApp.o: XpdfApp.cc.o
+
+.PHONY : XpdfApp.o
+
+# target to build an object file
+XpdfApp.cc.o:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf-qt/CMakeFiles/xpdf.dir/build.make xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.o
+.PHONY : XpdfApp.cc.o
+
+XpdfApp.i: XpdfApp.cc.i
+
+.PHONY : XpdfApp.i
+
+# target to preprocess a source file
+XpdfApp.cc.i:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf-qt/CMakeFiles/xpdf.dir/build.make xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.i
+.PHONY : XpdfApp.cc.i
+
+XpdfApp.s: XpdfApp.cc.s
+
+.PHONY : XpdfApp.s
+
+# target to generate assembly for a file
+XpdfApp.cc.s:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf-qt/CMakeFiles/xpdf.dir/build.make xpdf-qt/CMakeFiles/xpdf.dir/XpdfApp.cc.s
+.PHONY : XpdfApp.cc.s
+
+XpdfViewer.o: XpdfViewer.cc.o
+
+.PHONY : XpdfViewer.o
+
+# target to build an object file
+XpdfViewer.cc.o:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf-qt/CMakeFiles/xpdf.dir/build.make xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.o
+.PHONY : XpdfViewer.cc.o
+
+XpdfViewer.i: XpdfViewer.cc.i
+
+.PHONY : XpdfViewer.i
+
+# target to preprocess a source file
+XpdfViewer.cc.i:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf-qt/CMakeFiles/xpdf.dir/build.make xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.i
+.PHONY : XpdfViewer.cc.i
+
+XpdfViewer.s: XpdfViewer.cc.s
+
+.PHONY : XpdfViewer.s
+
+# target to generate assembly for a file
+XpdfViewer.cc.s:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf-qt/CMakeFiles/xpdf.dir/build.make xpdf-qt/CMakeFiles/xpdf.dir/XpdfViewer.cc.s
+.PHONY : XpdfViewer.cc.s
+
+XpdfWidget.o: XpdfWidget.cc.o
+
+.PHONY : XpdfWidget.o
+
+# target to build an object file
+XpdfWidget.cc.o:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf-qt/CMakeFiles/xpdf.dir/build.make xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.o
+.PHONY : XpdfWidget.cc.o
+
+XpdfWidget.i: XpdfWidget.cc.i
+
+.PHONY : XpdfWidget.i
+
+# target to preprocess a source file
+XpdfWidget.cc.i:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf-qt/CMakeFiles/xpdf.dir/build.make xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.i
+.PHONY : XpdfWidget.cc.i
+
+XpdfWidget.s: XpdfWidget.cc.s
+
+.PHONY : XpdfWidget.s
+
+# target to generate assembly for a file
+XpdfWidget.cc.s:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf-qt/CMakeFiles/xpdf.dir/build.make xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidget.cc.s
+.PHONY : XpdfWidget.cc.s
+
+XpdfWidgetPrint.o: XpdfWidgetPrint.cc.o
+
+.PHONY : XpdfWidgetPrint.o
+
+# target to build an object file
+XpdfWidgetPrint.cc.o:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf-qt/CMakeFiles/xpdf.dir/build.make xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.o
+.PHONY : XpdfWidgetPrint.cc.o
+
+XpdfWidgetPrint.i: XpdfWidgetPrint.cc.i
+
+.PHONY : XpdfWidgetPrint.i
+
+# target to preprocess a source file
+XpdfWidgetPrint.cc.i:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf-qt/CMakeFiles/xpdf.dir/build.make xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.i
+.PHONY : XpdfWidgetPrint.cc.i
+
+XpdfWidgetPrint.s: XpdfWidgetPrint.cc.s
+
+.PHONY : XpdfWidgetPrint.s
+
+# target to generate assembly for a file
+XpdfWidgetPrint.cc.s:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf-qt/CMakeFiles/xpdf.dir/build.make xpdf-qt/CMakeFiles/xpdf.dir/XpdfWidgetPrint.cc.s
+.PHONY : XpdfWidgetPrint.cc.s
+
+moc_XpdfApp.o: moc_XpdfApp.cpp.o
+
+.PHONY : moc_XpdfApp.o
+
+# target to build an object file
+moc_XpdfApp.cpp.o:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf-qt/CMakeFiles/xpdf.dir/build.make xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.o
+.PHONY : moc_XpdfApp.cpp.o
+
+moc_XpdfApp.i: moc_XpdfApp.cpp.i
+
+.PHONY : moc_XpdfApp.i
+
+# target to preprocess a source file
+moc_XpdfApp.cpp.i:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf-qt/CMakeFiles/xpdf.dir/build.make xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.i
+.PHONY : moc_XpdfApp.cpp.i
+
+moc_XpdfApp.s: moc_XpdfApp.cpp.s
+
+.PHONY : moc_XpdfApp.s
+
+# target to generate assembly for a file
+moc_XpdfApp.cpp.s:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf-qt/CMakeFiles/xpdf.dir/build.make xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfApp.cpp.s
+.PHONY : moc_XpdfApp.cpp.s
+
+moc_XpdfViewer.o: moc_XpdfViewer.cpp.o
+
+.PHONY : moc_XpdfViewer.o
+
+# target to build an object file
+moc_XpdfViewer.cpp.o:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf-qt/CMakeFiles/xpdf.dir/build.make xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.o
+.PHONY : moc_XpdfViewer.cpp.o
+
+moc_XpdfViewer.i: moc_XpdfViewer.cpp.i
+
+.PHONY : moc_XpdfViewer.i
+
+# target to preprocess a source file
+moc_XpdfViewer.cpp.i:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf-qt/CMakeFiles/xpdf.dir/build.make xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.i
+.PHONY : moc_XpdfViewer.cpp.i
+
+moc_XpdfViewer.s: moc_XpdfViewer.cpp.s
+
+.PHONY : moc_XpdfViewer.s
+
+# target to generate assembly for a file
+moc_XpdfViewer.cpp.s:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf-qt/CMakeFiles/xpdf.dir/build.make xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfViewer.cpp.s
+.PHONY : moc_XpdfViewer.cpp.s
+
+moc_XpdfWidget.o: moc_XpdfWidget.cpp.o
+
+.PHONY : moc_XpdfWidget.o
+
+# target to build an object file
+moc_XpdfWidget.cpp.o:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf-qt/CMakeFiles/xpdf.dir/build.make xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.o
+.PHONY : moc_XpdfWidget.cpp.o
+
+moc_XpdfWidget.i: moc_XpdfWidget.cpp.i
+
+.PHONY : moc_XpdfWidget.i
+
+# target to preprocess a source file
+moc_XpdfWidget.cpp.i:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf-qt/CMakeFiles/xpdf.dir/build.make xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.i
+.PHONY : moc_XpdfWidget.cpp.i
+
+moc_XpdfWidget.s: moc_XpdfWidget.cpp.s
+
+.PHONY : moc_XpdfWidget.s
+
+# target to generate assembly for a file
+moc_XpdfWidget.cpp.s:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf-qt/CMakeFiles/xpdf.dir/build.make xpdf-qt/CMakeFiles/xpdf.dir/moc_XpdfWidget.cpp.s
+.PHONY : moc_XpdfWidget.cpp.s
+
+qrc_icons.o: qrc_icons.cpp.o
+
+.PHONY : qrc_icons.o
+
+# target to build an object file
+qrc_icons.cpp.o:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf-qt/CMakeFiles/xpdf.dir/build.make xpdf-qt/CMakeFiles/xpdf.dir/qrc_icons.cpp.o
+.PHONY : qrc_icons.cpp.o
+
+qrc_icons.i: qrc_icons.cpp.i
+
+.PHONY : qrc_icons.i
+
+# target to preprocess a source file
+qrc_icons.cpp.i:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf-qt/CMakeFiles/xpdf.dir/build.make xpdf-qt/CMakeFiles/xpdf.dir/qrc_icons.cpp.i
+.PHONY : qrc_icons.cpp.i
+
+qrc_icons.s: qrc_icons.cpp.s
+
+.PHONY : qrc_icons.s
+
+# target to generate assembly for a file
+qrc_icons.cpp.s:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf-qt/CMakeFiles/xpdf.dir/build.make xpdf-qt/CMakeFiles/xpdf.dir/qrc_icons.cpp.s
+.PHONY : qrc_icons.cpp.s
+
+xpdf.o: xpdf.cc.o
+
+.PHONY : xpdf.o
+
+# target to build an object file
+xpdf.cc.o:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf-qt/CMakeFiles/xpdf.dir/build.make xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.o
+.PHONY : xpdf.cc.o
+
+xpdf.i: xpdf.cc.i
+
+.PHONY : xpdf.i
+
+# target to preprocess a source file
+xpdf.cc.i:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf-qt/CMakeFiles/xpdf.dir/build.make xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.i
+.PHONY : xpdf.cc.i
+
+xpdf.s: xpdf.cc.s
+
+.PHONY : xpdf.s
+
+# target to generate assembly for a file
+xpdf.cc.s:
+ cd /home/calvin/src/xpdf-4.04 && $(MAKE) $(MAKESILENT) -f xpdf-qt/CMakeFiles/xpdf.dir/build.make xpdf-qt/CMakeFiles/xpdf.dir/xpdf.cc.s
+.PHONY : xpdf.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 "... xpdf"
+ @echo "... QtPDFCore.o"
+ @echo "... QtPDFCore.i"
+ @echo "... QtPDFCore.s"
+ @echo "... XpdfApp.o"
+ @echo "... XpdfApp.i"
+ @echo "... XpdfApp.s"
+ @echo "... XpdfViewer.o"
+ @echo "... XpdfViewer.i"
+ @echo "... XpdfViewer.s"
+ @echo "... XpdfWidget.o"
+ @echo "... XpdfWidget.i"
+ @echo "... XpdfWidget.s"
+ @echo "... XpdfWidgetPrint.o"
+ @echo "... XpdfWidgetPrint.i"
+ @echo "... XpdfWidgetPrint.s"
+ @echo "... moc_XpdfApp.o"
+ @echo "... moc_XpdfApp.i"
+ @echo "... moc_XpdfApp.s"
+ @echo "... moc_XpdfViewer.o"
+ @echo "... moc_XpdfViewer.i"
+ @echo "... moc_XpdfViewer.s"
+ @echo "... moc_XpdfWidget.o"
+ @echo "... moc_XpdfWidget.i"
+ @echo "... moc_XpdfWidget.s"
+ @echo "... qrc_icons.o"
+ @echo "... qrc_icons.i"
+ @echo "... qrc_icons.s"
+ @echo "... xpdf.o"
+ @echo "... xpdf.i"
+ @echo "... xpdf.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-qt/QtPDFCore.cc b/xpdf-qt/QtPDFCore.cc
new file mode 100644
index 0000000..e945f88
--- /dev/null
+++ b/xpdf-qt/QtPDFCore.cc
@@ -0,0 +1,1176 @@
+//========================================================================
+//
+// QtPDFCore.cc
+//
+// Copyright 2009-2014 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <math.h>
+#include <string.h>
+#include <QApplication>
+#include <QClipboard>
+#include <QDesktopServices>
+#include <QFileInfo>
+#include <QImage>
+#include <QInputDialog>
+#include <QMessageBox>
+#include <QPainter>
+#include <QProcess>
+#include <QScrollBar>
+#include <QStyle>
+#include <QUrl>
+#include <QWidget>
+#include "gmem.h"
+#include "gmempp.h"
+#include "gfile.h"
+#include "GString.h"
+#include "GList.h"
+#include "Error.h"
+#include "GlobalParams.h"
+#include "PDFDoc.h"
+#include "Link.h"
+#include "ErrorCodes.h"
+#include "GfxState.h"
+#include "PSOutputDev.h"
+#include "TextOutputDev.h"
+#include "SplashBitmap.h"
+#include "DisplayState.h"
+#include "TileMap.h"
+#include "QtPDFCore.h"
+
+//------------------------------------------------------------------------
+// QtPDFCore
+//------------------------------------------------------------------------
+
+QtPDFCore::QtPDFCore(QWidget *viewportA,
+ QScrollBar *hScrollBarA, QScrollBar *vScrollBarA,
+ SplashColorPtr paperColor, SplashColorPtr matteColor,
+ GBool reverseVideo):
+ PDFCore(splashModeRGB8, 4, reverseVideo, paperColor)
+{
+ int dpiX, dpiY;
+
+ viewport = viewportA;
+ hScrollBar = hScrollBarA;
+ vScrollBar = vScrollBarA;
+ hScrollBar->setRange(0, 0);
+ hScrollBar->setSingleStep(16);
+ vScrollBar->setRange(0, 0);
+ vScrollBar->setSingleStep(16);
+ viewport->setMouseTracking(true);
+
+ state->setMatteColor(matteColor);
+
+ oldFirstPage = -1;
+ oldMidPage = -1;
+
+ linkAction = NULL;
+ lastLinkAction = NULL;
+
+ dragging = gFalse;
+
+ panning = gFalse;
+
+ inUpdateScrollbars = gFalse;
+
+ updateCbk = NULL;
+ midPageChangedCbk = NULL;
+ preLoadCbk = NULL;
+ postLoadCbk = NULL;
+ actionCbk = NULL;
+ linkCbk = NULL;
+ selectDoneCbk = NULL;
+
+ // optional features default to on
+ hyperlinksEnabled = gTrue;
+ externalHyperlinksEnabled = gTrue;
+ selectEnabled = gTrue;
+ panEnabled = gTrue;
+ showPasswordDialog = gTrue;
+
+ // get Qt's HiDPI scale factor
+#if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)
+ scaleFactor = viewport->devicePixelRatioF();
+#elif QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
+ scaleFactor = viewport->devicePixelRatio();
+#else
+ scaleFactor = 1;
+#endif
+
+ // get the display resolution (used for HiDPI scaling)
+ dpiX = viewport->logicalDpiX();
+ dpiY = viewport->logicalDpiY();
+ displayDpi = dpiX < dpiY ? dpiX : dpiY;
+ displayDpi = (int)(displayDpi * scaleFactor);
+}
+
+QtPDFCore::~QtPDFCore() {
+}
+
+//------------------------------------------------------------------------
+// loadFile / displayPage / displayDest
+//------------------------------------------------------------------------
+
+int QtPDFCore::loadFile(GString *fileName, GString *ownerPassword,
+ GString *userPassword) {
+ int err;
+
+ err = PDFCore::loadFile(fileName, ownerPassword, userPassword);
+ if (err == errNone) {
+ // save the modification time
+ modTime = QFileInfo(doc->getFileName()->getCString()).lastModified();
+
+ // update the parent window
+ if (updateCbk) {
+ (*updateCbk)(updateCbkData, doc->getFileName(), -1,
+ doc->getNumPages(), NULL);
+ }
+ oldFirstPage = oldMidPage = -1;
+ }
+ return err;
+}
+
+#ifdef _WIN32
+int QtPDFCore::loadFile(wchar_t *fileName, int fileNameLen,
+ GString *ownerPassword,
+ GString *userPassword) {
+ int err;
+
+ err = PDFCore::loadFile(fileName, fileNameLen, ownerPassword, userPassword);
+ if (err == errNone) {
+ // save the modification time
+ modTime = QFileInfo(doc->getFileName()->getCString()).lastModified();
+
+ // update the parent window
+ if (updateCbk) {
+ (*updateCbk)(updateCbkData, doc->getFileName(), -1,
+ doc->getNumPages(), NULL);
+ }
+ oldFirstPage = oldMidPage = -1;
+ }
+ return err;
+}
+#endif
+
+int QtPDFCore::loadFile(BaseStream *stream, GString *ownerPassword,
+ GString *userPassword) {
+ int err;
+
+ err = PDFCore::loadFile(stream, ownerPassword, userPassword);
+ if (err == errNone) {
+ // no file
+ modTime = QDateTime();
+
+ // update the parent window
+ if (updateCbk) {
+ (*updateCbk)(updateCbkData, doc->getFileName(), -1,
+ doc->getNumPages(), NULL);
+ }
+ oldFirstPage = oldMidPage = -1;
+ }
+ return err;
+}
+
+void QtPDFCore::loadDoc(PDFDoc *docA) {
+ PDFCore::loadDoc(docA);
+
+ // save the modification time
+ if (doc->getFileName()) {
+ modTime = QFileInfo(doc->getFileName()->getCString()).lastModified();
+ } else {
+ modTime = QDateTime();
+ }
+
+ // update the parent window
+ if (updateCbk) {
+ (*updateCbk)(updateCbkData, doc->getFileName(), -1,
+ doc->getNumPages(), NULL);
+ }
+ oldFirstPage = oldMidPage = -1;
+}
+
+int QtPDFCore::reload() {
+ int err;
+
+ err = PDFCore::reload();
+ if (err == errNone) {
+ // save the modification time
+ modTime = QFileInfo(doc->getFileName()->getCString()).lastModified();
+
+ // update the parent window
+ if (updateCbk) {
+ (*updateCbk)(updateCbkData, doc->getFileName(), -1,
+ doc->getNumPages(), NULL);
+ }
+ oldFirstPage = oldMidPage = -1;
+ }
+ return err;
+}
+
+void QtPDFCore::finishUpdate(GBool addToHist, GBool checkForChangedFile) {
+ int firstPage, midPage;
+
+ PDFCore::finishUpdate(addToHist, checkForChangedFile);
+ firstPage = getPageNum();
+ if (doc && firstPage != oldFirstPage && updateCbk) {
+ (*updateCbk)(updateCbkData, NULL, firstPage, -1, "");
+ }
+ oldFirstPage = firstPage;
+ midPage = getMidPageNum();
+ if (doc && midPage != oldMidPage && midPageChangedCbk) {
+ (*midPageChangedCbk)(midPageChangedCbkData, midPage);
+ }
+ oldMidPage = midPage;
+
+ linkAction = NULL;
+ lastLinkAction = NULL;
+}
+
+//------------------------------------------------------------------------
+// panning and selection
+//------------------------------------------------------------------------
+
+void QtPDFCore::startPan(int wx, int wy) {
+ if (!panEnabled) {
+ return;
+ }
+ panning = gTrue;
+ panMX = wx;
+ panMY = wy;
+}
+
+void QtPDFCore::endPan(int wx, int wy) {
+ panning = gFalse;
+}
+
+void QtPDFCore::startSelection(int wx, int wy, GBool extend) {
+ int pg, x, y;
+
+ takeFocus();
+ if (!doc || doc->getNumPages() == 0 || !selectEnabled) {
+ return;
+ }
+ if (!cvtWindowToDev(wx, wy, &pg, &x, &y)) {
+ return;
+ }
+ if (extend && hasSelection()) {
+ moveSelectionDrag(pg, x, y);
+ } else {
+ startSelectionDrag(pg, x, y);
+ }
+ if (getSelectMode() == selectModeBlock) {
+ doSetCursor(Qt::CrossCursor);
+ }
+ dragging = gTrue;
+}
+
+void QtPDFCore::endSelection(int wx, int wy) {
+ LinkAction *action;
+ int pg, x, y;
+ double xu, yu;
+ GBool ok;
+
+ if (!doc || doc->getNumPages() == 0) {
+ return;
+ }
+ ok = cvtWindowToDev(wx, wy, &pg, &x, &y);
+ if (dragging) {
+ dragging = gFalse;
+ doUnsetCursor();
+ if (ok) {
+ moveSelectionDrag(pg, x, y);
+ }
+ finishSelectionDrag();
+ if (selectDoneCbk) {
+ (*selectDoneCbk)(selectDoneCbkData);
+ }
+#ifndef NO_TEXT_SELECT
+ if (hasSelection()) {
+ copySelection(gFalse);
+ }
+#endif
+ }
+ if (ok) {
+ if (hasSelection()) {
+ action = NULL;
+ } else {
+ cvtDevToUser(pg, x, y, &xu, &yu);
+ action = findLink(pg, xu, yu);
+ }
+ if (linkCbk && action) {
+ doLinkCbk(action);
+ }
+ if (hyperlinksEnabled && action) {
+ doAction(action);
+ }
+ }
+}
+
+void QtPDFCore::mouseMove(int wx, int wy) {
+ LinkAction *action;
+ int pg, x, y;
+ double xu, yu;
+ const char *s;
+ GBool ok, mouseOverText;
+
+ if (!doc || doc->getNumPages() == 0) {
+ return;
+ }
+ ok = cvtWindowToDev(wx, wy, &pg, &x, &y);
+ if (dragging) {
+ if (ok) {
+ moveSelectionDrag(pg, x, y);
+ }
+ } else {
+ cvtDevToUser(pg, x, y, &xu, &yu);
+
+ // check for a link
+ action = NULL;
+ if (hyperlinksEnabled && ok) {
+ action = findLink(pg, xu, yu);
+ }
+
+ // check for text
+ mouseOverText = gFalse;
+ if (!action && getSelectMode() == selectModeLinear && ok) {
+ mouseOverText = overText(pg, x, y);
+ }
+
+ // update the cursor
+ if (action) {
+ doSetCursor(Qt::PointingHandCursor);
+ } else if (mouseOverText) {
+ doSetCursor(Qt::IBeamCursor);
+ } else {
+ doUnsetCursor();
+ }
+
+ // update the link info
+ if (action != linkAction) {
+ linkAction = action;
+ if (updateCbk) {
+ //~ should pass a QString to updateCbk()
+ if (linkAction) {
+ s = getLinkInfo(linkAction).toLocal8Bit().constData();
+ } else {
+ s = "";
+ }
+ (*updateCbk)(updateCbkData, NULL, -1, -1, s);
+ }
+ }
+ }
+
+ if (panning) {
+ scrollTo(getScrollX() - (wx - panMX),
+ getScrollY() - (wy - panMY));
+ panMX = wx;
+ panMY = wy;
+ }
+}
+
+void QtPDFCore::selectWord(int wx, int wy) {
+ int pg, x, y;
+
+ takeFocus();
+ if (!doc || doc->getNumPages() == 0 || !selectEnabled) {
+ return;
+ }
+ if (getSelectMode() != selectModeLinear) {
+ return;
+ }
+ if (!cvtWindowToDev(wx, wy, &pg, &x, &y)) {
+ return;
+ }
+ PDFCore::selectWord(pg, x, y);
+#ifndef NO_TEXT_SELECT
+ if (hasSelection()) {
+ copySelection(gFalse);
+ }
+#endif
+}
+
+void QtPDFCore::selectLine(int wx, int wy) {
+ int pg, x, y;
+
+ takeFocus();
+ if (!doc || doc->getNumPages() == 0 || !selectEnabled) {
+ return;
+ }
+ if (getSelectMode() != selectModeLinear) {
+ return;
+ }
+ if (!cvtWindowToDev(wx, wy, &pg, &x, &y)) {
+ return;
+ }
+ PDFCore::selectLine(pg, x, y);
+#ifndef NO_TEXT_SELECT
+ if (hasSelection()) {
+ copySelection(gFalse);
+ }
+#endif
+}
+
+void QtPDFCore::doLinkCbk(LinkAction *action) {
+ LinkDest *dest;
+ GString *namedDest;
+ Ref pageRef;
+ int pg;
+ GString *cmd, *params;
+ char *s;
+
+ if (!linkCbk) {
+ return;
+ }
+
+ switch (action->getKind()) {
+
+ case actionGoTo:
+ dest = NULL;
+ if ((dest = ((LinkGoTo *)action)->getDest())) {
+ dest = dest->copy();
+ } else if ((namedDest = ((LinkGoTo *)action)->getNamedDest())) {
+ dest = doc->findDest(namedDest);
+ }
+ pg = 0;
+ if (dest) {
+ if (dest->isPageRef()) {
+ pageRef = dest->getPageRef();
+ pg = doc->findPage(pageRef.num, pageRef.gen);
+ } else {
+ pg = dest->getPageNum();
+ }
+ delete dest;
+ }
+ (*linkCbk)(linkCbkData, "goto", NULL, pg);
+ break;
+
+ case actionGoToR:
+ (*linkCbk)(linkCbkData, "pdf",
+ ((LinkGoToR *)action)->getFileName()->getCString(), 0);
+ break;
+
+ case actionLaunch:
+ cmd = ((LinkLaunch *)action)->getFileName()->copy();
+ s = cmd->getCString();
+ if (strcmp(s + cmd->getLength() - 4, ".pdf") &&
+ strcmp(s + cmd->getLength() - 4, ".PDF") &&
+ (params = ((LinkLaunch *)action)->getParams())) {
+ cmd->append(' ')->append(params);
+ }
+ (*linkCbk)(linkCbkData, "launch", cmd->getCString(), 0);
+ delete cmd;
+ break;
+
+ case actionURI:
+ (*linkCbk)(linkCbkData, "url",
+ ((LinkURI *)action)->getURI()->getCString(), 0);
+ break;
+
+ case actionNamed:
+ (*linkCbk)(linkCbkData, "named",
+ ((LinkNamed *)action)->getName()->getCString(), 0);
+ break;
+
+ case actionMovie:
+ case actionJavaScript:
+ case actionSubmitForm:
+ case actionHide:
+ case actionUnknown:
+ (*linkCbk)(linkCbkData, "unknown", NULL, 0);
+ break;
+ }
+}
+
+QString QtPDFCore::getSelectedTextQString() {
+ GString *s, *enc;
+ QString qs;
+ int i;
+
+ if (!(s = getSelectedText())) {
+ return "";
+ }
+ enc = globalParams->getTextEncodingName();
+ if (!enc->cmp("UTF-8")) {
+ qs = QString::fromUtf8(s->getCString());
+ } else if (!enc->cmp("UCS-2")) {
+ for (i = 0; i+1 < s->getLength(); i += 2) {
+ qs.append((QChar)(((s->getChar(i) & 0xff) << 8) +
+ (s->getChar(i+1) & 0xff)));
+ }
+ } else {
+ qs = QString(s->getCString());
+ }
+ delete s;
+ delete enc;
+ return qs;
+}
+
+void QtPDFCore::copySelection(GBool toClipboard) {
+ QString qs;
+
+ if (hasSelection()) {
+ QApplication::clipboard()->setText(getSelectedTextQString(),
+ toClipboard ? QClipboard::Clipboard
+ : QClipboard::Selection);
+ }
+}
+
+//------------------------------------------------------------------------
+// hyperlinks
+//------------------------------------------------------------------------
+
+GBool QtPDFCore::doAction(LinkAction *action) {
+ LinkActionKind kind;
+ LinkDest *dest;
+ GString *namedDest;
+ char *s;
+ GString *fileName, *fileName2, *params;
+ GString *cmd;
+ GString *actionName;
+ Object movieAnnot, obj1, obj2;
+ GString *msg;
+ int i;
+
+ switch (kind = action->getKind()) {
+
+ // GoTo / GoToR action
+ case actionGoTo:
+ case actionGoToR:
+ if (kind == actionGoTo) {
+ dest = NULL;
+ namedDest = NULL;
+ if ((dest = ((LinkGoTo *)action)->getDest())) {
+ dest = dest->copy();
+ } else if ((namedDest = ((LinkGoTo *)action)->getNamedDest())) {
+ namedDest = namedDest->copy();
+ }
+ } else {
+ if (!externalHyperlinksEnabled) {
+ return gFalse;
+ }
+ dest = NULL;
+ namedDest = NULL;
+ if ((dest = ((LinkGoToR *)action)->getDest())) {
+ dest = dest->copy();
+ } else if ((namedDest = ((LinkGoToR *)action)->getNamedDest())) {
+ namedDest = namedDest->copy();
+ }
+ s = ((LinkGoToR *)action)->getFileName()->getCString();
+ if (isAbsolutePath(s)) {
+ fileName = new GString(s);
+ } else {
+ fileName = appendToPath(grabPath(doc->getFileName()->getCString()), s);
+ }
+ if (loadFile(fileName) != errNone) {
+ if (dest) {
+ delete dest;
+ }
+ if (namedDest) {
+ delete namedDest;
+ }
+ delete fileName;
+ return gFalse;
+ }
+ delete fileName;
+ }
+ if (namedDest) {
+ dest = doc->findDest(namedDest);
+ delete namedDest;
+ }
+ if (dest) {
+ displayDest(dest);
+ delete dest;
+ } else {
+ if (kind == actionGoToR) {
+ displayPage(1, gFalse, gFalse, gTrue);
+ }
+ }
+ break;
+
+ // Launch action
+ case actionLaunch:
+ if (!externalHyperlinksEnabled) {
+ return gFalse;
+ }
+ fileName = ((LinkLaunch *)action)->getFileName();
+ s = fileName->getCString();
+ if (fileName->getLength() >= 4 &&
+ (!strcmp(s + fileName->getLength() - 4, ".pdf") ||
+ !strcmp(s + fileName->getLength() - 4, ".PDF"))) {
+ if (isAbsolutePath(s)) {
+ fileName = fileName->copy();
+ } else {
+ fileName = appendToPath(grabPath(doc->getFileName()->getCString()), s);
+ }
+ if (loadFile(fileName) != errNone) {
+ delete fileName;
+ return gFalse;
+ }
+ delete fileName;
+ displayPage(1, gFalse, gFalse, gTrue);
+ } else {
+ cmd = fileName->copy();
+ if ((params = ((LinkLaunch *)action)->getParams())) {
+ cmd->append(' ')->append(params);
+ }
+ if (globalParams->getLaunchCommand()) {
+ cmd->insert(0, ' ');
+ cmd->insert(0, globalParams->getLaunchCommand());
+#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
+ QString cmdStr(cmd->getCString());
+ QStringList tokens = QProcess::splitCommand(cmdStr);
+ if (!tokens.isEmpty()) {
+ QString program = tokens[0];
+ tokens.removeFirst();
+ QProcess::startDetached(program, tokens);
+ }
+#else
+ QProcess::startDetached(cmd->getCString());
+#endif
+ } else {
+ msg = new GString("About to execute the command:\n");
+ msg->append(cmd);
+ if (QMessageBox::question(viewport, "PDF Launch Link",
+ msg->getCString(),
+ QMessageBox::Ok | QMessageBox::Cancel,
+ QMessageBox::Ok)
+ == QMessageBox::Ok) {
+#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
+ QString cmdStr(cmd->getCString());
+ QStringList tokens = QProcess::splitCommand(cmdStr);
+ if (!tokens.isEmpty()) {
+ QString program = tokens[0];
+ tokens.removeFirst();
+ QProcess::startDetached(program, tokens);
+ }
+#else
+ QProcess::startDetached(cmd->getCString());
+#endif
+ }
+ delete msg;
+ }
+ delete cmd;
+ }
+ break;
+
+ // URI action
+ case actionURI:
+ if (!externalHyperlinksEnabled) {
+ return gFalse;
+ }
+ QDesktopServices::openUrl(QUrl(((LinkURI *)action)->getURI()->getCString(),
+ QUrl::TolerantMode));
+ break;
+
+ // Named action
+ case actionNamed:
+ actionName = ((LinkNamed *)action)->getName();
+ if (!actionName->cmp("NextPage")) {
+ gotoNextPage(1, gTrue);
+ } else if (!actionName->cmp("PrevPage")) {
+ gotoPrevPage(1, gTrue, gFalse);
+ } else if (!actionName->cmp("FirstPage")) {
+ displayPage(1, gTrue, gFalse, gTrue);
+ } else if (!actionName->cmp("LastPage")) {
+ displayPage(doc->getNumPages(), gTrue, gFalse, gTrue);
+ } else if (!actionName->cmp("GoBack")) {
+ goBackward();
+ } else if (!actionName->cmp("GoForward")) {
+ goForward();
+ } else if (!actionName->cmp("Quit")) {
+ if (actionCbk) {
+ (*actionCbk)(actionCbkData, actionName->getCString());
+ }
+ } else {
+ error(errSyntaxError, -1,
+ "Unknown named action: '{0:t}'", actionName);
+ return gFalse;
+ }
+ break;
+
+ // Movie action
+ case actionMovie:
+ if (!externalHyperlinksEnabled) {
+ return gFalse;
+ }
+ if (!(cmd = globalParams->getMovieCommand())) {
+ error(errConfig, -1, "No movieCommand defined in config file");
+ return gFalse;
+ }
+ if (((LinkMovie *)action)->hasAnnotRef()) {
+ doc->getXRef()->fetch(((LinkMovie *)action)->getAnnotRef()->num,
+ ((LinkMovie *)action)->getAnnotRef()->gen,
+ &movieAnnot);
+ } else {
+ //~ need to use the correct page num here
+ doc->getCatalog()->getPage(tileMap->getFirstPage())->getAnnots(&obj1);
+ if (obj1.isArray()) {
+ for (i = 0; i < obj1.arrayGetLength(); ++i) {
+ if (obj1.arrayGet(i, &movieAnnot)->isDict()) {
+ if (movieAnnot.dictLookup("Subtype", &obj2)->isName("Movie")) {
+ obj2.free();
+ break;
+ }
+ obj2.free();
+ }
+ movieAnnot.free();
+ }
+ obj1.free();
+ }
+ }
+ if (movieAnnot.isDict()) {
+ if (movieAnnot.dictLookup("Movie", &obj1)->isDict()) {
+ if (obj1.dictLookup("F", &obj2)) {
+ if ((fileName = LinkAction::getFileSpecName(&obj2))) {
+ if (!isAbsolutePath(fileName->getCString())) {
+ fileName2 = appendToPath(
+ grabPath(doc->getFileName()->getCString()),
+ fileName->getCString());
+ delete fileName;
+ fileName = fileName2;
+ }
+ runCommand(cmd, fileName);
+ delete fileName;
+ }
+ obj2.free();
+ }
+ obj1.free();
+ }
+ }
+ movieAnnot.free();
+ break;
+
+ // unimplemented actions
+ case actionJavaScript:
+ case actionSubmitForm:
+ case actionHide:
+ return gFalse;
+
+ // unknown action type
+ case actionUnknown:
+ error(errSyntaxError, -1, "Unknown link action type: '{0:t}'",
+ ((LinkUnknown *)action)->getAction());
+ return gFalse;
+ }
+
+ return gTrue;
+}
+
+QString QtPDFCore::getLinkInfo(LinkAction *action) {
+ LinkDest *dest;
+ GString *namedDest;
+ Ref pageRef;
+ int pg;
+ QString info;
+
+ if (action == lastLinkAction && !lastLinkActionInfo.isEmpty()) {
+ return lastLinkActionInfo;
+ }
+
+ switch (action->getKind()) {
+ case actionGoTo:
+ dest = NULL;
+ if ((dest = ((LinkGoTo *)action)->getDest())) {
+ dest = dest->copy();
+ } else if ((namedDest = ((LinkGoTo *)action)->getNamedDest())) {
+ dest = doc->findDest(namedDest);
+ }
+ pg = 0;
+ if (dest) {
+ if (dest->isPageRef()) {
+ pageRef = dest->getPageRef();
+ pg = doc->findPage(pageRef.num, pageRef.gen);
+ } else {
+ pg = dest->getPageNum();
+ }
+ delete dest;
+ }
+ if (pg) {
+ info = QString("[page ") + QString::number(pg) + QString("]");
+ } else {
+ info = "[internal]";
+ }
+ break;
+ case actionGoToR:
+ info = QString(((LinkGoToR *)action)->getFileName()->getCString());
+ break;
+ case actionLaunch:
+ info = QString(((LinkLaunch *)action)->getFileName()->getCString());
+ break;
+ case actionURI:
+ info = QString(((LinkURI *)action)->getURI()->getCString());
+ break;
+ case actionNamed:
+ info = QString(((LinkNamed *)action)->getName()->getCString());
+ break;
+ case actionMovie:
+ info = "[movie]";
+ break;
+ case actionJavaScript:
+ case actionSubmitForm:
+ case actionHide:
+ case actionUnknown:
+ default:
+ info = "[unknown]";
+ break;
+ }
+
+ lastLinkAction = action;
+ lastLinkActionInfo = info;
+
+ return info;
+}
+
+// Run a command, given a <cmdFmt> string with one '%s' in it, and an
+// <arg> string to insert in place of the '%s'.
+void QtPDFCore::runCommand(GString *cmdFmt, GString *arg) {
+ GString *cmd;
+ char *s;
+
+ if ((s = strstr(cmdFmt->getCString(), "%s"))) {
+ cmd = mungeURL(arg);
+ cmd->insert(0, cmdFmt->getCString(),
+ (int)(s - cmdFmt->getCString()));
+ cmd->append(s + 2);
+ } else {
+ cmd = cmdFmt->copy();
+ }
+#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
+ QString cmdStr(cmd->getCString());
+ QStringList tokens = QProcess::splitCommand(cmdStr);
+ if (!tokens.isEmpty()) {
+ QString program = tokens[0];
+ tokens.removeFirst();
+ QProcess::startDetached(program, tokens);
+ }
+#else
+ QProcess::startDetached(cmd->getCString());
+#endif
+ delete cmd;
+}
+
+// Escape any characters in a URL which might cause problems when
+// calling system().
+GString *QtPDFCore::mungeURL(GString *url) {
+ static const char *allowed = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz"
+ "0123456789"
+ "-_.~/?:@&=+,#%";
+ GString *newURL;
+ char c;
+ int i;
+
+ newURL = new GString();
+ for (i = 0; i < url->getLength(); ++i) {
+ c = url->getChar(i);
+ if (strchr(allowed, c)) {
+ newURL->append(c);
+ } else {
+ newURL->appendf("%{0:02x}", c & 0xff);
+ }
+ }
+ return newURL;
+}
+
+//------------------------------------------------------------------------
+// find
+//------------------------------------------------------------------------
+
+GBool QtPDFCore::find(char *s, GBool caseSensitive, GBool next,
+ GBool backward, GBool wholeWord, GBool onePageOnly) {
+ if (!PDFCore::find(s, caseSensitive, next,
+ backward, wholeWord, onePageOnly)) {
+ return gFalse;
+ }
+#ifndef NO_TEXT_SELECT
+ copySelection(gFalse);
+#endif
+ return gTrue;
+}
+
+GBool QtPDFCore::findU(Unicode *u, int len, GBool caseSensitive,
+ GBool next, GBool backward,
+ GBool wholeWord, GBool onePageOnly) {
+ if (!PDFCore::findU(u, len, caseSensitive, next,
+ backward, wholeWord, onePageOnly)) {
+ return gFalse;
+ }
+#ifndef NO_TEXT_SELECT
+ copySelection(gFalse);
+#endif
+ return gTrue;
+}
+
+//------------------------------------------------------------------------
+// misc access
+//------------------------------------------------------------------------
+
+void QtPDFCore::setBusyCursor(GBool busy) {
+ if (busy) {
+ doSetCursor(Qt::WaitCursor);
+ } else {
+ doUnsetCursor();
+ }
+}
+
+void QtPDFCore::doSetCursor(const QCursor &cursor) {
+#ifndef QT_NO_CURSOR
+ viewport->setCursor(cursor);
+#endif
+}
+
+void QtPDFCore::doUnsetCursor() {
+#ifndef QT_NO_CURSOR
+ viewport->unsetCursor();
+#endif
+}
+
+void QtPDFCore::takeFocus() {
+ viewport->setFocus(Qt::OtherFocusReason);
+}
+
+QSize QtPDFCore::getBestSize() {
+ DisplayMode mode;
+ double zoomPercent;
+ int w, h, pg, rot;
+
+ if (!doc || doc->getNumPages() == 0) {
+ //~ what should this return?
+ return QSize(612, 792);
+ }
+ mode = state->getDisplayMode();
+ pg = tileMap->getFirstPage();
+ rot = (state->getRotate() + doc->getPageRotate(pg)) % 360;
+ zoomPercent = state->getZoom();
+ if (zoomPercent < 0) {
+ zoomPercent = globalParams->getDefaultFitZoom();
+ if (zoomPercent <= 0) {
+ zoomPercent = (int)((100 * displayDpi) / 72.0 + 0.5);
+ if (zoomPercent < 100) {
+ zoomPercent = 100;
+ }
+ }
+ }
+ if (rot == 90 || rot == 270) {
+ w = (int)(doc->getPageCropHeight(pg) * 0.01 * zoomPercent + 0.5);
+ h = (int)(doc->getPageCropWidth(pg) * 0.01 * zoomPercent + 0.5);
+ } else {
+ w = (int)(doc->getPageCropWidth(pg) * 0.01 * zoomPercent + 0.5);
+ h = (int)(doc->getPageCropHeight(pg) * 0.01 * zoomPercent + 0.5);
+ }
+ if (mode == displayContinuous) {
+ w += QApplication::style()->pixelMetric(QStyle::PM_ScrollBarExtent);
+ h += tileMap->getContinuousPageSpacing();
+ } else if (mode == displaySideBySideContinuous) {
+ w = w * 2
+ + tileMap->getHorizContinuousPageSpacing()
+ + QApplication::style()->pixelMetric(QStyle::PM_ScrollBarExtent);
+ h += tileMap->getContinuousPageSpacing();
+ } else if (mode == displayHorizontalContinuous) {
+ w += tileMap->getHorizContinuousPageSpacing();
+ h += QApplication::style()->pixelMetric(QStyle::PM_ScrollBarExtent);
+ } else if (mode == displaySideBySideSingle) {
+ w = w * 2 + tileMap->getHorizContinuousPageSpacing();
+ }
+ //~ these additions are a kludge to make this work -- 2 pixels are
+ //~ padding in the QAbstractScrollArea; not sure where the rest go
+#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
+ w += 6;
+ h += 2;
+#else
+ w += 10;
+ h += 4;
+#endif
+ return QSize((int)(w / scaleFactor), (int)(h / scaleFactor));
+}
+
+//------------------------------------------------------------------------
+// GUI code
+//------------------------------------------------------------------------
+
+void QtPDFCore::resizeEvent() {
+ setWindowSize((int)(viewport->width() * scaleFactor),
+ (int)(viewport->height() * scaleFactor));
+}
+
+void QtPDFCore::paintEvent(int x, int y, int w, int h) {
+ SplashBitmap *bitmap;
+ GBool wholeWindow;
+
+ QPainter painter(viewport);
+ wholeWindow = x == 0 && y == 0 &&
+ w == viewport->width() && h == viewport->height();
+ bitmap = getWindowBitmap(wholeWindow);
+ QImage image(bitmap->getDataPtr(), bitmap->getWidth(),
+ bitmap->getHeight(), QImage::Format_RGB888);
+ if (scaleFactor == 1) {
+ painter.drawImage(QRect(x, y, w, h), image, QRect(x, y, w, h));
+ } else {
+ painter.drawImage(QRectF(x, y, w, h), image,
+ QRectF(x * scaleFactor, y * scaleFactor,
+ w * scaleFactor, h * scaleFactor));
+ }
+ if (paintDoneCbk) {
+ (*paintDoneCbk)(paintDoneCbkData, (bool)isBitmapFinished());
+ }
+}
+
+void QtPDFCore::scrollEvent() {
+ // avoid loops, e.g., scrollTo -> finishUpdate -> updateScrollbars ->
+ // hScrollbar.setValue -> scrollContentsBy -> scrollEvent -> scrollTo
+ if (inUpdateScrollbars) {
+ return;
+ }
+ scrollTo(hScrollBar->value(), vScrollBar->value());
+}
+
+void QtPDFCore::tick() {
+ PDFCore::tick();
+}
+
+void QtPDFCore::invalidate(int x, int y, int w, int h) {
+ int xx, yy, ww, hh;
+
+ if (scaleFactor == 1) {
+ viewport->update(x, y, w, h);
+ } else {
+ xx = (int)(x / scaleFactor);
+ yy = (int)(y / scaleFactor);
+ ww = (int)ceil((x + w) / scaleFactor) - xx;
+ hh = (int)ceil((y + h) / scaleFactor) - yy;
+ viewport->update(xx, yy, ww, hh);
+ }
+}
+
+void QtPDFCore::updateScrollbars() {
+ int winW, winH, horizLimit, vertLimit, horizMax, vertMax;
+ bool vScrollBarVisible, hScrollBarVisible;
+
+ inUpdateScrollbars = gTrue;
+
+ winW = state->getWinW();
+ winH = state->getWinH();
+ tileMap->getScrollLimits(&horizLimit, &vertLimit);
+
+ if (horizLimit > winW) {
+ horizMax = horizLimit - winW;
+ } else {
+ horizMax = 0;
+ }
+ if (vertLimit > winH) {
+ vertMax = vertLimit - winH;
+ } else {
+ vertMax = 0;
+ }
+
+ // Problem case A: in fixed zoom, there is a case where the page
+ // just barely fits in the window; if the scrollbars are visible,
+ // they reduce the available window size enough that they are
+ // necessary, i.e., the scrollbars are only necessary if they're
+ // visible -- so check for that situation and force the scrollbars
+ // to be hidden.
+ // NB: {h,v}ScrollBar->isVisible() are unreliable at startup, so
+ // we compare the viewport size to the ScrollArea size (with
+ // some slack for margins)
+ vScrollBarVisible =
+ viewport->parentWidget()->width() - viewport->width() > 8;
+ hScrollBarVisible =
+ viewport->parentWidget()->height() - viewport->height() > 8;
+ if (state->getZoom() >= 0 &&
+ vScrollBarVisible &&
+ hScrollBarVisible &&
+ horizMax <= vScrollBar->width() &&
+ vertMax <= hScrollBar->height()) {
+ horizMax = 0;
+ vertMax = 0;
+ }
+
+ // Problem case B: in fit-to-width mode, with the vertical scrollbar
+ // visible, if the window is just tall enough to fit the page, then
+ // the vertical scrollbar will be hidden, resulting in a wider
+ // window, resulting in a taller page (because of fit-to-width),
+ // resulting in the scrollbar being unhidden, in an infinite loop --
+ // so always force the vertical scroll bar to be visible in
+ // fit-to-width mode (and in fit-to-page cases where the vertical
+ // scrollbar is potentially visible).
+ if (state->getZoom() == zoomWidth ||
+ (state->getZoom() == zoomPage &&
+ (state->getDisplayMode() == displayContinuous ||
+ state->getDisplayMode() == displaySideBySideContinuous))) {
+ if (vertMax == 0) {
+ vertMax = 1;
+ }
+
+ // Problem case C: same as case B, but for fit-to-height mode and
+ // the horizontal scrollbar.
+ } else if (state->getZoom() == zoomHeight ||
+ (state->getZoom() == zoomPage &&
+ state->getDisplayMode() == displayHorizontalContinuous)) {
+ if (horizMax == 0) {
+ horizMax = 1;
+ }
+ }
+
+ hScrollBar->setMaximum(horizMax);
+ hScrollBar->setPageStep(winW);
+ hScrollBar->setValue(state->getScrollX());
+
+ vScrollBar->setMaximum(vertMax);
+ vScrollBar->setPageStep(winH);
+ vScrollBar->setValue(state->getScrollY());
+
+ inUpdateScrollbars = gFalse;
+}
+
+GBool QtPDFCore::checkForNewFile() {
+ QDateTime newModTime;
+
+ if (doc->getFileName()) {
+ newModTime = QFileInfo(doc->getFileName()->getCString()).lastModified();
+ if (newModTime != modTime) {
+ modTime = newModTime;
+ return gTrue;
+ }
+ }
+ return gFalse;
+}
+
+void QtPDFCore::preLoad() {
+ if (preLoadCbk) {
+ (*preLoadCbk)(preLoadCbkData);
+ }
+}
+
+void QtPDFCore::postLoad() {
+ if (postLoadCbk) {
+ (*postLoadCbk)(postLoadCbkData);
+ }
+}
+
+//------------------------------------------------------------------------
+// password dialog
+//------------------------------------------------------------------------
+
+GString *QtPDFCore::getPassword() {
+ QString s;
+ bool ok;
+
+ if (!showPasswordDialog) {
+ return NULL;
+ }
+ s = QInputDialog::getText(viewport, "PDF Password",
+ "This document requires a password",
+ QLineEdit::Password, "", &ok, Qt::Dialog);
+ if (ok) {
+ return new GString(s.toLocal8Bit().constData());
+ } else {
+ return NULL;
+ }
+}
diff --git a/xpdf-qt/QtPDFCore.h b/xpdf-qt/QtPDFCore.h
new file mode 100644
index 0000000..cbd1e3b
--- /dev/null
+++ b/xpdf-qt/QtPDFCore.h
@@ -0,0 +1,227 @@
+//========================================================================
+//
+// QtPDFCore.h
+//
+// Copyright 2009-2014 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef QTPDFCORE_H
+#define QTPDFCORE_H
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include <QDateTime>
+#include "gtypes.h"
+#include "SplashTypes.h"
+#include "PDFCore.h"
+
+class GString;
+class BaseStream;
+class PDFDoc;
+class LinkAction;
+
+class QWidget;
+class QScrollBar;
+
+//------------------------------------------------------------------------
+// callbacks
+//------------------------------------------------------------------------
+
+typedef void (*QtPDFUpdateCbk)(void *data, GString *fileName,
+ int pageNum, int numPages,
+ const char *linkLabel);
+
+typedef void (*QtPDFMidPageChangedCbk)(void *data, int pageNum);
+
+typedef void (*QtPDFLoadCbk)(void *data);
+
+typedef void (*QtPDFActionCbk)(void *data, char *action);
+
+typedef void (*QtPDFLinkCbk)(void *data, const char *type,
+ const char *dest, int page);
+
+typedef void (*QtPDFSelectDoneCbk)(void *data);
+
+typedef void (*QtPDFPaintDoneCbk)(void *data, bool finished);
+
+
+//------------------------------------------------------------------------
+// QtPDFCore
+//------------------------------------------------------------------------
+
+class QtPDFCore: public PDFCore {
+public:
+
+ // Create viewer core in <viewportA>.
+ QtPDFCore(QWidget *viewportA,
+ QScrollBar *hScrollBarA, QScrollBar *vScrollBarA,
+ SplashColorPtr paperColor, SplashColorPtr matteColor,
+ GBool reverseVideo);
+
+ ~QtPDFCore();
+
+ //----- 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();
+
+ // Called after any update is complete.
+ virtual void finishUpdate(GBool addToHist, GBool checkForChangedFile);
+
+ //----- panning and selection
+
+ void startPan(int wx, int wy);
+ void endPan(int wx, int wy);
+ void startSelection(int wx, int wy, GBool extend);
+ void endSelection(int wx, int wy);
+ void mouseMove(int wx, int wy);
+ void selectWord(int wx, int wy);
+ void selectLine(int wx, int wy);
+ QString getSelectedTextQString();
+ void copySelection(GBool toClipboard);
+
+ //----- hyperlinks
+
+ GBool doAction(LinkAction *action);
+ LinkAction *getLinkAction() { return linkAction; }
+ QString getLinkInfo(LinkAction *action);
+ GString *mungeURL(GString *url);
+
+ //----- 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);
+
+ //----- password dialog
+
+ virtual GString *getPassword();
+
+ //----- misc access
+
+ virtual void setBusyCursor(GBool busy);
+ void doSetCursor(const QCursor &cursor);
+ void doUnsetCursor();
+ void takeFocus();
+ QSize getBestSize();
+ int getDisplayDpi() { return displayDpi; }
+ double getScaleFactor() { return scaleFactor; }
+ void enableHyperlinks(GBool on) { hyperlinksEnabled = on; }
+ GBool getHyperlinksEnabled() { return hyperlinksEnabled; }
+ void enableExternalHyperlinks(GBool on) { externalHyperlinksEnabled = on; }
+ GBool getExternalHyperlinksEnabled() { return externalHyperlinksEnabled; }
+ void enableSelect(GBool on) { selectEnabled = on; }
+ void enablePan(GBool on) { panEnabled = on; }
+ void setShowPasswordDialog(GBool show) { showPasswordDialog = show; }
+ void setUpdateCbk(QtPDFUpdateCbk cbk, void *data)
+ { updateCbk = cbk; updateCbkData = data; }
+ void setMidPageChangedCbk(QtPDFMidPageChangedCbk cbk, void *data)
+ { midPageChangedCbk = cbk; midPageChangedCbkData = data; }
+ void setPreLoadCbk(QtPDFLoadCbk cbk, void *data)
+ { preLoadCbk = cbk; preLoadCbkData = data; }
+ void setPostLoadCbk(QtPDFLoadCbk cbk, void *data)
+ { postLoadCbk = cbk; postLoadCbkData = data; }
+ void setActionCbk(QtPDFActionCbk cbk, void *data)
+ { actionCbk = cbk; actionCbkData = data; }
+ void setLinkCbk(QtPDFLinkCbk cbk, void *data)
+ { linkCbk = cbk; linkCbkData = data; }
+ void setSelectDoneCbk(QtPDFSelectDoneCbk cbk, void *data)
+ { selectDoneCbk = cbk; selectDoneCbkData = data; }
+ void setPaintDoneCbk(QtPDFPaintDoneCbk cbk, void *data)
+ { paintDoneCbk = cbk; paintDoneCbkData = data; }
+
+ //----- GUI events
+ void resizeEvent();
+ void paintEvent(int x, int y, int w, int h);
+ void scrollEvent();
+ virtual void tick();
+
+private:
+
+ //----- hyperlinks
+ void doLinkCbk(LinkAction *action);
+ void runCommand(GString *cmdFmt, GString *arg);
+
+ //----- PDFCore callbacks
+ virtual void invalidate(int x, int y, int w, int h);
+ virtual void updateScrollbars();
+ virtual GBool checkForNewFile();
+ virtual void preLoad();
+ virtual void postLoad();
+
+ QWidget *viewport;
+ QScrollBar *hScrollBar;
+ QScrollBar *vScrollBar;
+
+ int displayDpi;
+ double scaleFactor;
+
+ GBool dragging;
+
+ GBool panning;
+ int panMX, panMY;
+
+ GBool inUpdateScrollbars;
+
+ int oldFirstPage;
+ int oldMidPage;
+
+ LinkAction *linkAction; // mouse cursor is over this link
+
+ LinkAction *lastLinkAction; // getLinkInfo() caches an action
+ QString lastLinkActionInfo;
+
+ QDateTime modTime; // last modification time of PDF file
+
+ QtPDFUpdateCbk updateCbk;
+ void *updateCbkData;
+ QtPDFMidPageChangedCbk midPageChangedCbk;
+ void *midPageChangedCbkData;
+ QtPDFLoadCbk preLoadCbk;
+ void *preLoadCbkData;
+ QtPDFLoadCbk postLoadCbk;
+ void *postLoadCbkData;
+ QtPDFActionCbk actionCbk;
+ void *actionCbkData;
+ QtPDFLinkCbk linkCbk;
+ void *linkCbkData;
+ QtPDFSelectDoneCbk selectDoneCbk;
+ void *selectDoneCbkData;
+ QtPDFPaintDoneCbk paintDoneCbk;
+ void *paintDoneCbkData;
+
+ GBool hyperlinksEnabled;
+ GBool externalHyperlinksEnabled;
+ GBool selectEnabled;
+ GBool panEnabled;
+ GBool showPasswordDialog;
+};
+
+#endif
diff --git a/xpdf-qt/XpdfApp.cc b/xpdf-qt/XpdfApp.cc
new file mode 100644
index 0000000..fdcaea5
--- /dev/null
+++ b/xpdf-qt/XpdfApp.cc
@@ -0,0 +1,499 @@
+//========================================================================
+//
+// XpdfApp.cc
+//
+// Copyright 2015 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <aconf.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <QFileInfo>
+#include <QLocalSocket>
+#ifdef _WIN32
+# include <shlobj.h>
+#endif
+#include "config.h"
+#include "parseargs.h"
+#include "GString.h"
+#include "GList.h"
+#include "gfile.h"
+#include "GlobalParams.h"
+#include "XpdfViewer.h"
+#include "XpdfApp.h"
+#include "gmempp.h"
+
+//------------------------------------------------------------------------
+// command line options
+//------------------------------------------------------------------------
+
+static GBool openArg = gFalse;
+static GBool reverseVideoArg = gFalse;
+static char paperColorArg[256] = "";
+static char matteColorArg[256] = "";
+static char fsMatteColorArg[256] = "";
+static char initialZoomArg[256] = "";
+static int rotateArg = 0;
+static char antialiasArg[16] = "";
+static char vectorAntialiasArg[16] = "";
+static char textEncArg[128] = "";
+static char passwordArg[33] = "";
+static GBool fullScreen = gFalse;
+static char remoteServerArg[256] = "";
+static char tabStateFile[256] = "";
+static char cfgFileArg[256] = "";
+static GBool printCommandsArg = gFalse;
+static GBool printVersionArg = gFalse;
+static GBool printHelpArg = gFalse;
+
+static ArgDesc argDesc[] = {
+ {"-open", argFlag, &openArg, 0, "open file using a default remote server"},
+ {"-rv", argFlag, &reverseVideoArg, 0, "reverse video"},
+ {"-papercolor", argString, paperColorArg, sizeof(paperColorArg), "color of paper background"},
+ {"-mattecolor", argString, matteColorArg, sizeof(matteColorArg), "color of matte background"},
+ {"-fsmattecolor", argString, fsMatteColorArg, sizeof(fsMatteColorArg), "color of matte background in full-screen mode"},
+ {"-z", argString, initialZoomArg, sizeof(initialZoomArg), "initial zoom level (percent, 'page', 'width')"},
+ {"-rot", argInt, &rotateArg, 0, "initial page rotation: 0, 90, 180, or 270"},
+ {"-aa", argString, antialiasArg, sizeof(antialiasArg), "enable font anti-aliasing: yes, no"},
+ {"-aaVector", argString, vectorAntialiasArg, sizeof(vectorAntialiasArg), "enable vector anti-aliasing: yes, no"},
+ {"-enc", argString, textEncArg, sizeof(textEncArg), "output text encoding name"},
+ {"-pw", argString, passwordArg, sizeof(passwordArg), "password (for encrypted files)"},
+ {"-fullscreen", argFlag, &fullScreen, 0, "run in full-screen (presentation) mode"},
+ {"-remote", argString, remoteServerArg, sizeof(remoteServerArg), "remote server mode - remaining args are commands"},
+ {"-cmd", argFlag, &printCommandsArg, 0, "print commands as they're executed"},
+ {"-tabstate", argString, tabStateFile, sizeof(tabStateFile), "file for saving/loading tab state"},
+ {"-cfg", argString, cfgFileArg, sizeof(cfgFileArg), "configuration file to use in place of .xpdfrc"},
+ {"-v", argFlag, &printVersionArg, 0, "print copyright and version info"},
+ {"-h", argFlag, &printHelpArg, 0, "print usage information"},
+ {"-help", argFlag, &printHelpArg, 0, "print usage information"},
+ {"--help", argFlag, &printHelpArg, 0, "print usage information"},
+ {"-?", argFlag, &printHelpArg, 0, "print usage information"},
+ {NULL}
+};
+
+//------------------------------------------------------------------------
+// XpdfApp
+//------------------------------------------------------------------------
+
+static void mungeOpenFileName(const char *fileName, GString *cmd);
+
+XpdfApp::XpdfApp(int &argc, char **argv):
+ QApplication(argc, argv)
+{
+ XpdfViewer *viewer;
+ QLocalSocket *sock;
+ QString sockName;
+ const char *fileName, *dest;
+ GString *color, *cmd;
+ GBool ok;
+ int pg, i;
+
+ setApplicationName("XpdfReader");
+ setApplicationVersion(xpdfVersion);
+
+ ok = parseArgs(argDesc, &argc, argv);
+ if (!ok || printVersionArg || printHelpArg) {
+ fprintf(stderr, "xpdf version %s [www.xpdfreader.com]\n", xpdfVersion);
+ fprintf(stderr, "%s\n", xpdfCopyright);
+ if (!printVersionArg) {
+ printUsage("xpdf", "[<PDF-file> [:<page> | +<dest>]] ...", argDesc);
+ }
+ ::exit(99);
+ }
+
+ //--- set up GlobalParams; handle command line arguments
+ GlobalParams::defaultTextEncoding = "UCS-2";
+ globalParams = new GlobalParams(cfgFileArg);
+#ifdef _WIN32
+ QString dir = applicationDirPath();
+ globalParams->setBaseDir(dir.toLocal8Bit().constData());
+ dir += "/t1fonts";
+ globalParams->setupBaseFonts(dir.toLocal8Bit().constData());
+#else
+ globalParams->setupBaseFonts(NULL);
+#endif
+ if (initialZoomArg[0]) {
+ globalParams->setInitialZoom(initialZoomArg);
+ }
+ reverseVideo = reverseVideoArg;
+ if (paperColorArg[0]) {
+ paperColor = QColor(paperColorArg);
+ } else {
+ color = globalParams->getPaperColor();
+ paperColor = QColor(color->getCString());
+ delete color;
+ }
+ if (reverseVideo) {
+ paperColor = QColor(255 - paperColor.red(),
+ 255 - paperColor.green(),
+ 255 - paperColor.blue());
+ }
+ if (matteColorArg[0]) {
+ matteColor = QColor(matteColorArg);
+ } else {
+ color = globalParams->getMatteColor();
+ matteColor = QColor(color->getCString());
+ delete color;
+ }
+ if (fsMatteColorArg[0]) {
+ fsMatteColor = QColor(fsMatteColorArg);
+ } else {
+ color = globalParams->getFullScreenMatteColor();
+ fsMatteColor = QColor(color->getCString());
+ delete color;
+ }
+ color = globalParams->getSelectionColor();
+ selectionColor = QColor(color->getCString());
+ delete color;
+ if (antialiasArg[0]) {
+ if (!globalParams->setAntialias(antialiasArg)) {
+ fprintf(stderr, "Bad '-aa' value on command line\n");
+ }
+ }
+ if (vectorAntialiasArg[0]) {
+ if (!globalParams->setVectorAntialias(vectorAntialiasArg)) {
+ fprintf(stderr, "Bad '-aaVector' value on command line\n");
+ }
+ }
+ if (textEncArg[0]) {
+ globalParams->setTextEncoding(textEncArg);
+ }
+ if (tabStateFile[0]) {
+ globalParams->setTabStateFile(tabStateFile);
+ }
+ if (printCommandsArg) {
+ globalParams->setPrintCommands(gTrue);
+ }
+
+ errorEventType = QEvent::registerEventType();
+
+ viewers = new GList();
+
+ //--- remote server mode
+ if (remoteServerArg[0]) {
+ sock = new QLocalSocket(this);
+ sockName = "xpdf_";
+ sockName += remoteServerArg;
+ sock->connectToServer(sockName, QIODevice::WriteOnly);
+ if (sock->waitForConnected(5000)) {
+ for (i = 1; i < argc; ++i) {
+ sock->write(argv[i]);
+ sock->write("\n");
+ }
+ while (sock->bytesToWrite()) {
+ sock->waitForBytesWritten(5000);
+ }
+ delete sock;
+ ::exit(0);
+ } else {
+ delete sock;
+ viewer = newWindow(gFalse, remoteServerArg);
+ for (i = 1; i < argc; ++i) {
+ viewer->execCmd(argv[i], NULL);
+ }
+ return;
+ }
+ }
+
+ //--- default remote server
+ if (openArg) {
+ sock = new QLocalSocket(this);
+ sockName = "xpdf_default";
+ sock->connectToServer(sockName, QIODevice::WriteOnly);
+ if (sock->waitForConnected(5000)) {
+ if (argc >= 2) {
+ cmd = new GString("openFileIn(");
+ mungeOpenFileName(argv[1], cmd);
+ cmd->append(",tab)\nraise\n");
+ sock->write(cmd->getCString());
+ delete cmd;
+ while (sock->bytesToWrite()) {
+ sock->waitForBytesWritten(5000);
+ }
+ }
+ delete sock;
+ ::exit(0);
+ } else {
+ delete sock;
+ if (argc >= 2) {
+ // on Windows: xpdf.cc converts command line args to UTF-8
+ // on Linux: command line args are in the local 8-bit charset
+#ifdef _WIN32
+ QString qFileName = QString::fromUtf8(argv[1]);
+#else
+ QString qFileName = QString::fromLocal8Bit(argv[1]);
+#endif
+ openInNewWindow(qFileName, 1, "", rotateArg, passwordArg,
+ fullScreen, "default");
+ } else {
+ newWindow(fullScreen, "default");
+ }
+ return;
+ }
+ }
+
+ //--- load PDF file(s) requested on the command line
+ if (argc >= 2) {
+ i = 1;
+ while (i < argc) {
+ pg = -1;
+ dest = "";
+ if (i+1 < argc && argv[i+1][0] == ':') {
+ fileName = argv[i];
+ pg = atoi(argv[i+1] + 1);
+ i += 2;
+ } else if (i+1 < argc && argv[i+1][0] == '+') {
+ fileName = argv[i];
+ dest = argv[i+1] + 1;
+ i += 2;
+ } else {
+ fileName = argv[i];
+ ++i;
+ }
+ // on Windows: xpdf.cc converts command line args to UTF-8
+ // on Linux: command line args are in the local 8-bit charset
+#ifdef _WIN32
+ QString qFileName = QString::fromUtf8(fileName);
+#else
+ QString qFileName = QString::fromLocal8Bit(fileName);
+#endif
+ if (viewers->getLength() > 0) {
+ ok = ((XpdfViewer *)viewers->get(0))
+ ->openInNewTab(qFileName, pg, dest, rotateArg,
+ passwordArg, gFalse);
+ } else {
+ ok = openInNewWindow(qFileName, pg, dest, rotateArg,
+ passwordArg, fullScreen);
+ }
+ }
+ } else {
+ newWindow(fullScreen);
+ }
+}
+
+// Process the file name for the "-open" flag: convert a relative path
+// to absolute, and add escape chars as needed. Append the modified
+// name to [cmd].
+static void mungeOpenFileName(const char *fileName, GString *cmd) {
+ GString *path = new GString(fileName);
+ makePathAbsolute(path);
+ for (int i = 0; i < path->getLength(); ++i) {
+ char c = path->getChar(i);
+ if (c == '(' || c == ')' || c == ',' || c == '\x01') {
+ cmd->append('\x01');
+ }
+ cmd->append(c);
+ }
+ delete path;
+}
+
+XpdfApp::~XpdfApp() {
+ delete viewers;
+ delete globalParams;
+}
+
+int XpdfApp::getNumViewers() {
+ return viewers->getLength();
+}
+
+XpdfViewer *XpdfApp::newWindow(GBool fullScreen,
+ const char *remoteServerName) {
+ XpdfViewer *viewer = new XpdfViewer(this, fullScreen);
+ viewers->append(viewer);
+ if (remoteServerName) {
+ viewer->startRemoteServer(remoteServerName);
+ }
+ viewer->tweakSize();
+ viewer->show();
+ return viewer;
+}
+
+GBool XpdfApp::openInNewWindow(QString fileName, int page, QString dest,
+ int rotate, QString password, GBool fullScreen,
+ const char *remoteServerName) {
+ XpdfViewer *viewer;
+
+ viewer = XpdfViewer::create(this, fileName, page, dest, rotate,
+ password, fullScreen);
+ if (!viewer) {
+ return gFalse;
+ }
+ viewers->append(viewer);
+ if (remoteServerName) {
+ viewer->startRemoteServer(remoteServerName);
+ }
+ viewer->tweakSize();
+ viewer->show();
+ return gTrue;
+}
+
+void XpdfApp::closeWindowOrQuit(XpdfViewer *viewer) {
+ int i;
+
+ viewer->close();
+ for (i = 0; i < viewers->getLength(); ++i) {
+ if ((XpdfViewer *)viewers->get(i) == viewer) {
+ viewers->del(i);
+ break;
+ }
+ }
+}
+
+void XpdfApp::quit() {
+ XpdfViewer *viewer;
+
+ while (viewers->getLength()) {
+ viewer = (XpdfViewer *)viewers->del(0);
+ viewer->close();
+ }
+ QApplication::quit();
+}
+
+//------------------------------------------------------------------------
+
+void XpdfApp::startUpdatePagesFile() {
+ if (!globalParams->getSavePageNumbers()) {
+ return;
+ }
+ readPagesFile();
+ savedPagesFileChanged = gFalse;
+}
+
+void XpdfApp::updatePagesFile(const QString &fileName, int pageNumber) {
+ if (!globalParams->getSavePageNumbers()) {
+ return;
+ }
+ if (fileName.isEmpty()) {
+ return;
+ }
+ QString canonicalFileName = QFileInfo(fileName).canonicalFilePath();
+ if (canonicalFileName.isEmpty()) {
+ return;
+ }
+ XpdfSavedPageNumber s(canonicalFileName, pageNumber);
+ for (int i = 0; i < maxSavedPageNumbers; ++i) {
+ XpdfSavedPageNumber next = savedPageNumbers[i];
+ savedPageNumbers[i] = s;
+ if (next.fileName == canonicalFileName) {
+ break;
+ }
+ s = next;
+ }
+ savedPagesFileChanged = gTrue;
+}
+
+void XpdfApp::finishUpdatePagesFile() {
+ if (!globalParams->getSavePageNumbers()) {
+ return;
+ }
+ if (savedPagesFileChanged) {
+ writePagesFile();
+ }
+}
+
+int XpdfApp::getSavedPageNumber(const QString &fileName) {
+ if (!globalParams->getSavePageNumbers()) {
+ return 1;
+ }
+ readPagesFile();
+ QString canonicalFileName = QFileInfo(fileName).canonicalFilePath();
+ if (canonicalFileName.isEmpty()) {
+ return 1;
+ }
+ for (int i = 0; i < maxSavedPageNumbers; ++i) {
+ if (savedPageNumbers[i].fileName == canonicalFileName) {
+ return savedPageNumbers[i].pageNumber;
+ }
+ }
+ return 1;
+}
+
+void XpdfApp::readPagesFile() {
+ // construct the file name (first time only)
+ if (savedPagesFileName.isEmpty()) {
+#ifdef _WIN32
+ char path[MAX_PATH];
+ if (SHGetFolderPath(NULL, CSIDL_APPDATA, NULL,
+ SHGFP_TYPE_CURRENT, path) != S_OK) {
+ return;
+ }
+ savedPagesFileName = QString::fromLocal8Bit(path);
+ savedPagesFileName.append("/xpdf");
+ CreateDirectory(savedPagesFileName.toLocal8Bit().constData(), NULL);
+ savedPagesFileName.append("/xpdf.pages");
+#else
+ GString *path = getHomeDir();
+ savedPagesFileName = QString::fromUtf8(path->getCString());
+ delete path;
+ savedPagesFileName.append("/.xpdf.pages");
+#endif
+ }
+
+ // no change since last read, so no need to re-read
+ if (savedPagesFileTimestamp.isValid() &&
+ QFileInfo(savedPagesFileName).lastModified() == savedPagesFileTimestamp) {
+ return;
+ }
+
+ // mark all entries invalid
+ for (int i = 0; i < maxSavedPageNumbers; ++i) {
+ savedPageNumbers[i].fileName.clear();
+ savedPageNumbers[i].pageNumber = 1;
+ }
+
+ // read the file
+ FILE *f = openFile(savedPagesFileName.toUtf8().constData(), "rb");
+ if (!f) {
+ return;
+ }
+ char buf[1024];
+ if (!fgets(buf, sizeof(buf), f) ||
+ strcmp(buf, "xpdf.pages-1\n") != 0) {
+ fclose(f);
+ return;
+ }
+ int i = 0;
+ while (i < maxSavedPageNumbers && fgets(buf, sizeof(buf), f)) {
+ int n = (int)strlen(buf);
+ if (n > 0 && buf[n-1] == '\n') {
+ buf[n-1] = '\0';
+ }
+ char *p = buf;
+ while (*p != ' ' && *p) {
+ ++p;
+ }
+ if (!*p) {
+ continue;
+ }
+ *p++ = '\0';
+ savedPageNumbers[i].pageNumber = atoi(buf);
+ savedPageNumbers[i].fileName = QString::fromUtf8(p);
+ ++i;
+ }
+ fclose(f);
+
+ // save the timestamp
+ savedPagesFileTimestamp = QFileInfo(savedPagesFileName).lastModified();
+}
+
+void XpdfApp::writePagesFile() {
+ if (savedPagesFileName.isEmpty()) {
+ return;
+ }
+ FILE *f = openFile(savedPagesFileName.toUtf8().constData(), "wb");
+ if (!f) {
+ return;
+ }
+ fprintf(f, "xpdf.pages-1\n");
+ for (int i = 0; i < maxSavedPageNumbers; ++i) {
+ if (!savedPageNumbers[i].fileName.isEmpty()) {
+ fprintf(f, "%d %s\n",
+ savedPageNumbers[i].pageNumber,
+ savedPageNumbers[i].fileName.toUtf8().constData());
+ }
+ }
+ fclose(f);
+ savedPagesFileTimestamp = QFileInfo(savedPagesFileName).lastModified();
+}
diff --git a/xpdf-qt/XpdfApp.h b/xpdf-qt/XpdfApp.h
new file mode 100644
index 0000000..3ac2d2f
--- /dev/null
+++ b/xpdf-qt/XpdfApp.h
@@ -0,0 +1,99 @@
+//========================================================================
+//
+// XpdfApp.h
+//
+// Copyright 2015 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef XPDFAPP_H
+#define XPDFAPP_H
+
+#include <aconf.h>
+
+#include <QApplication>
+#include <QColor>
+#include <QDateTime>
+#include "gtypes.h"
+
+class GList;
+class XpdfViewer;
+
+//------------------------------------------------------------------------
+
+struct XpdfSavedPageNumber {
+ XpdfSavedPageNumber(): pageNumber(1) {}
+ XpdfSavedPageNumber(const QString &fileNameA, int pageNumberA)
+ : fileName(fileNameA), pageNumber(pageNumberA) {}
+ QString fileName;
+ int pageNumber;
+};
+
+#define maxSavedPageNumbers 100
+
+//------------------------------------------------------------------------
+// XpdfApp
+//------------------------------------------------------------------------
+
+class XpdfApp: public QApplication {
+ Q_OBJECT
+
+public:
+
+ XpdfApp(int &argc, char **argv);
+ virtual ~XpdfApp();
+
+ int getNumViewers();
+
+ XpdfViewer *newWindow(GBool fullScreen = gFalse,
+ const char *remoteServerName = NULL);
+
+ GBool openInNewWindow(QString fileName, int page = 1,
+ QString dest = QString(),
+ int rotate = 0,
+ QString password = QString(),
+ GBool fullScreen = gFalse,
+ const char *remoteServerName = NULL);
+
+ void closeWindowOrQuit(XpdfViewer *viewer);
+
+ // Called just before closing one or more PDF files.
+ void startUpdatePagesFile();
+ void updatePagesFile(const QString &fileName, int pageNumber);
+ void finishUpdatePagesFile();
+
+ // Return the saved page number for [fileName].
+ int getSavedPageNumber(const QString &fileName);
+
+ void quit();
+
+ //--- for use by XpdfViewer
+
+ int getErrorEventType() { return errorEventType; }
+ const QColor &getPaperColor() { return paperColor; }
+ const QColor &getMatteColor() { return matteColor; }
+ const QColor &getFullScreenMatteColor() { return fsMatteColor; }
+ const QColor &getSelectionColor() { return selectionColor; }
+ GBool getReverseVideo() { return reverseVideo; }
+
+private:
+
+ void readPagesFile();
+ void writePagesFile();
+
+ int errorEventType;
+ QColor paperColor;
+ QColor matteColor;
+ QColor fsMatteColor;
+ QColor selectionColor;
+ GBool reverseVideo;
+
+ GList *viewers; // [XpdfViewer]
+
+ QString savedPagesFileName;
+ QDateTime savedPagesFileTimestamp;
+ XpdfSavedPageNumber savedPageNumbers[maxSavedPageNumbers];
+ GBool savedPagesFileChanged;
+};
+
+#endif
diff --git a/xpdf-qt/XpdfViewer.cc b/xpdf-qt/XpdfViewer.cc
new file mode 100644
index 0000000..b7de5e4
--- /dev/null
+++ b/xpdf-qt/XpdfViewer.cc
@@ -0,0 +1,4940 @@
+//========================================================================
+//
+// XpdfViewer.cc
+//
+// Copyright 2015 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <aconf.h>
+
+#include <math.h>
+#include <QAbstractItemModel>
+#include <QAction>
+#include <QActionGroup>
+#include <QButtonGroup>
+#include <QClipboard>
+#include <QComboBox>
+#include <QDesktopServices>
+#include <QFileDialog>
+#include <QFrame>
+#include <QGridLayout>
+#include <QHBoxLayout>
+#include <QHeaderView>
+#include <QKeyEvent>
+#include <QLabel>
+#include <QLineEdit>
+#include <QListWidget>
+#include <QLocalSocket>
+#include <QMenu>
+#include <QMenuBar>
+#include <QMessageBox>
+#include <QMimeData>
+#include <QMouseEvent>
+#include <QProcess>
+#include <QProgressDialog>
+#include <QPropertyAnimation>
+#include <QPushButton>
+#include <QRadioButton>
+#include <QScreen>
+#include <QScrollBar>
+#include <QSignalMapper>
+#include <QSplitter>
+#include <QStackedLayout>
+#include <QStackedWidget>
+#include <QTabWidget>
+#include <QTableWidget>
+#include <QTextBrowser>
+#include <QTimer>
+#include <QToolBar>
+#include <QTreeView>
+#include <QVBoxLayout>
+#include "GString.h"
+#include "GList.h"
+#include "GlobalParams.h"
+#include "QtPDFCore.h"
+#include "PDFDoc.h"
+#include "AcroForm.h"
+#include "Annot.h"
+#include "TextString.h"
+#include "Zoox.h"
+#include "XpdfApp.h"
+#include "XpdfViewer.h"
+#include "gmempp.h"
+
+//------------------------------------------------------------------------
+
+static const char *aboutHTML =
+ "<h3><img align=\"middle\" src=\"qrc:/xpdf-icon\"> "
+ "Xpdf"
+ "</h3>"
+ "Version " xpdfVersion "<br>"
+ "<br>"
+ "<a href=\"http://www.xpdfreader.com/\">www.xpdfreader.com</a><br>"
+ "<br>"
+ "Based on the <b>XpdfWidget/Qt</b> toolkit from Glyph & Cog.<br>"
+ "For information on commercial licensing:<br>"
+ "<a href=\"http://www.glyphandcog.com/XpdfWidgetQt.html\">www.glyphandcog.com/XpdfWidgetQt.html</a><br>"
+ "<br>"
+ xpdfCopyright ".<br>"
+ "Xpdf is licensed under the GNU General Public License (GPL), version 2 or 3.<br>"
+ "<hr><br>"
+ "The PDF data structures, operators, and specification are documented in ISO 32000-2:2020.<br>"
+ "<br>"
+ "XpdfReader uses the following open source libraries:"
+ "<ul>"
+ "FreeType is copyright 2006-2020 David Turner, Robert Wilhelm, and Werner Lemberg. FreeType is used here under the terms of the FreeType Project License."
+ "<li>The Qt Toolkit is Copyright 2015 The Qt Company Ltd. Qt is used here under the terms of the LGPL v2.1."
+ "</ul>";
+
+const char *helpURL = "http://www.xpdfreader.com/help";
+
+//------------------------------------------------------------------------
+
+#define nZoomComboBoxVals 13
+static int zoomComboBoxVals[nZoomComboBoxVals] = {
+ 25, 50, 75, 100, 110, 125, 150, 175, 200, 300, 400, 600, 800
+};
+
+#define maxZoom 2000
+
+// Maximum number of errors to show in the error window. Beyond this
+// limit, old errors are removed from the window.
+#define errorWindowMaxErrors 100
+
+//------------------------------------------------------------------------
+// command table
+//------------------------------------------------------------------------
+
+#define cmdMaxArgs 8
+
+// |- requires -|
+// command nArgs doc event function
+XpdfViewerCmd XpdfViewer::cmdTab[] = {
+ { "about", 0, gFalse, gFalse, &XpdfViewer::cmdAbout },
+ { "blockSelectMode", 0, gFalse, gFalse, &XpdfViewer::cmdBlockSelectMode },
+ { "checkOpenFile", 1, gFalse, gFalse, &XpdfViewer::cmdCheckOpenFile },
+ { "checkOpenFileAtDest", 2, gFalse, gFalse, &XpdfViewer::cmdCheckOpenFileAtDest },
+ { "checkOpenFileAtPage", 2, gFalse, gFalse, &XpdfViewer::cmdCheckOpenFileAtPage },
+ { "closeSidebar", 0, gFalse, gFalse, &XpdfViewer::cmdCloseSidebar },
+ { "closeSidebarMoveResizeWin", 0, gFalse, gFalse, &XpdfViewer::cmdCloseSidebarMoveResizeWin },
+ { "closeSidebarResizeWin", 0, gFalse, gFalse, &XpdfViewer::cmdCloseSidebarResizeWin },
+ { "closeTabOrQuit", 0, gFalse, gFalse, &XpdfViewer::cmdCloseTabOrQuit },
+ { "closeWindowOrQuit", 0, gFalse, gFalse, &XpdfViewer::cmdCloseWindowOrQuit },
+ { "continuousMode", 0, gFalse, gFalse, &XpdfViewer::cmdContinuousMode },
+ { "copy", 0, gTrue, gFalse, &XpdfViewer::cmdCopy },
+ { "copyLinkTarget", 0, gTrue, gFalse, &XpdfViewer::cmdCopyLinkTarget },
+#if 0 // for debugging
+ { "debug1", 0, gTrue, gTrue, &XpdfViewer::cmdDebug1 },
+#endif
+ { "endPan", 0, gTrue, gTrue, &XpdfViewer::cmdEndPan },
+ { "endSelection", 0, gTrue, gTrue, &XpdfViewer::cmdEndSelection },
+ { "expandSidebar", 1, gFalse, gFalse, &XpdfViewer::cmdExpandSidebar },
+ { "find", 0, gTrue, gFalse, &XpdfViewer::cmdFind },
+ { "findFirst", 0, gTrue, gFalse, &XpdfViewer::cmdFindFirst },
+ { "findNext", 0, gTrue, gFalse, &XpdfViewer::cmdFindNext },
+ { "findPrevious", 0, gTrue, gFalse, &XpdfViewer::cmdFindPrevious },
+ { "focusToDocWin", 0, gFalse, gFalse, &XpdfViewer::cmdFocusToDocWin },
+ { "focusToPageNum", 0, gFalse, gFalse, &XpdfViewer::cmdFocusToPageNum },
+ { "followLink", 0, gTrue, gTrue, &XpdfViewer::cmdFollowLink },
+ { "followLinkInNewTab", 0, gTrue, gTrue, &XpdfViewer::cmdFollowLinkInNewTab },
+ { "followLinkInNewTabNoSel", 0, gTrue, gTrue, &XpdfViewer::cmdFollowLinkInNewTabNoSel },
+ { "followLinkInNewWin", 0, gTrue, gTrue, &XpdfViewer::cmdFollowLinkInNewWin },
+ { "followLinkInNewWinNoSel", 0, gTrue, gTrue, &XpdfViewer::cmdFollowLinkInNewWinNoSel },
+ { "followLinkNoSel", 0, gTrue, gTrue, &XpdfViewer::cmdFollowLinkNoSel },
+ { "fullScreenMode", 0, gFalse, gFalse, &XpdfViewer::cmdFullScreenMode },
+ { "goBackward", 0, gFalse, gFalse, &XpdfViewer::cmdGoBackward },
+ { "goForward", 0, gFalse, gFalse, &XpdfViewer::cmdGoForward },
+ { "gotoDest", 1, gTrue, gFalse, &XpdfViewer::cmdGotoDest },
+ { "gotoLastPage", 0, gTrue, gFalse, &XpdfViewer::cmdGotoLastPage },
+//~ { "gotoLastPageNoScroll", 0, gTrue, gFalse, &XpdfViewer::cmdGotoLastPageNoScroll },
+ { "gotoPage", 1, gTrue, gFalse, &XpdfViewer::cmdGotoPage },
+//~ { "gotoPageNoScroll", 1, gTrue, gFalse, &XpdfViewer::cmdGotoPageNoScroll },
+ { "help", 0, gFalse, gFalse, &XpdfViewer::cmdHelp },
+ { "hideMenuBar", 0, gFalse, gFalse, &XpdfViewer::cmdHideMenuBar },
+ { "hideToolbar", 0, gFalse, gFalse, &XpdfViewer::cmdHideToolbar },
+ { "horizontalContinuousMode",0, gFalse, gFalse, &XpdfViewer::cmdHorizontalContinuousMode },
+ { "linearSelectMode", 0, gFalse, gFalse, &XpdfViewer::cmdLinearSelectMode },
+ { "loadTabState", 0, gFalse, gFalse, &XpdfViewer::cmdLoadTabState },
+ { "newTab", 0, gFalse, gFalse, &XpdfViewer::cmdNewTab },
+ { "newWindow", 0, gFalse, gFalse, &XpdfViewer::cmdNewWindow },
+ { "nextPage", 0, gTrue, gFalse, &XpdfViewer::cmdNextPage },
+ { "nextPageNoScroll", 0, gTrue, gFalse, &XpdfViewer::cmdNextPageNoScroll },
+ { "nextTab", 0, gFalse, gFalse, &XpdfViewer::cmdNextTab },
+ { "open", 0, gFalse, gFalse, &XpdfViewer::cmdOpen },
+ { "openErrorWindow", 0, gFalse, gFalse, &XpdfViewer::cmdOpenErrorWindow },
+ { "openFile", 1, gFalse, gFalse, &XpdfViewer::cmdOpenFile },
+ { "openFile2", 5, gFalse, gFalse, &XpdfViewer::cmdOpenFile2 },
+ { "openFileAtDest", 2, gFalse, gFalse, &XpdfViewer::cmdOpenFileAtDest },
+ { "openFileAtDestIn", 3, gFalse, gFalse, &XpdfViewer::cmdOpenFileAtDestIn },
+ { "openFileAtPage", 2, gFalse, gFalse, &XpdfViewer::cmdOpenFileAtPage },
+ { "openFileAtPageIn", 3, gFalse, gFalse, &XpdfViewer::cmdOpenFileAtPageIn },
+ { "openFileIn", 2, gFalse, gFalse, &XpdfViewer::cmdOpenFileIn },
+ { "openIn", 1, gFalse, gFalse, &XpdfViewer::cmdOpenIn },
+ { "openSidebar", 0, gFalse, gFalse, &XpdfViewer::cmdOpenSidebar },
+ { "openSidebarMoveResizeWin", 0, gFalse, gFalse, &XpdfViewer::cmdOpenSidebarMoveResizeWin },
+ { "openSidebarResizeWin", 0, gFalse, gFalse, &XpdfViewer::cmdOpenSidebarResizeWin },
+ { "pageDown", 0, gTrue, gFalse, &XpdfViewer::cmdPageDown },
+ { "pageUp", 0, gTrue, gFalse, &XpdfViewer::cmdPageUp },
+ { "postPopupMenu", 0, gFalse, gTrue, &XpdfViewer::cmdPostPopupMenu },
+ { "prevPage", 0, gTrue, gFalse, &XpdfViewer::cmdPrevPage },
+ { "prevPageNoScroll", 0, gTrue, gFalse, &XpdfViewer::cmdPrevPageNoScroll },
+ { "prevTab", 0, gFalse, gFalse, &XpdfViewer::cmdPrevTab },
+#if XPDFWIDGET_PRINTING
+ { "print", 0, gTrue, gFalse, &XpdfViewer::cmdPrint },
+#endif
+ { "quit", 0, gFalse, gFalse, &XpdfViewer::cmdQuit },
+ { "raise", 0, gFalse, gFalse, &XpdfViewer::cmdRaise },
+//~ { "redraw", 0, gTrue, gFalse, &XpdfViewer::cmdRedraw },
+ { "reload", 0, gTrue, gFalse, &XpdfViewer::cmdReload },
+ { "rotateCCW", 0, gTrue, gFalse, &XpdfViewer::cmdRotateCCW },
+ { "rotateCW", 0, gTrue, gFalse, &XpdfViewer::cmdRotateCW },
+ { "run", 1, gFalse, gFalse, &XpdfViewer::cmdRun },
+ { "saveAs", 0, gTrue, gFalse, &XpdfViewer::cmdSaveAs },
+ { "saveImage", 0, gTrue, gFalse, &XpdfViewer::cmdSaveImage },
+ { "saveTabState", 0, gFalse, gFalse, &XpdfViewer::cmdSaveTabState },
+ { "scrollDown", 1, gTrue, gFalse, &XpdfViewer::cmdScrollDown },
+ { "scrollDownNextPage", 1, gTrue, gFalse, &XpdfViewer::cmdScrollDownNextPage },
+ { "scrollLeft", 1, gTrue, gFalse, &XpdfViewer::cmdScrollLeft },
+ { "scrollOutlineDown", 1, gTrue, gFalse, &XpdfViewer::cmdScrollOutlineDown },
+ { "scrollOutlineUp", 1, gTrue, gFalse, &XpdfViewer::cmdScrollOutlineUp },
+ { "scrollRight", 1, gTrue, gFalse, &XpdfViewer::cmdScrollRight },
+ { "scrollToBottomEdge", 0, gTrue, gFalse, &XpdfViewer::cmdScrollToBottomEdge },
+ { "scrollToBottomRight", 0, gTrue, gFalse, &XpdfViewer::cmdScrollToBottomRight },
+ { "scrollToLeftEdge", 0, gTrue, gFalse, &XpdfViewer::cmdScrollToLeftEdge },
+ { "scrollToRightEdge", 0, gTrue, gFalse, &XpdfViewer::cmdScrollToRightEdge },
+ { "scrollToTopEdge", 0, gTrue, gFalse, &XpdfViewer::cmdScrollToTopEdge },
+ { "scrollToTopLeft", 0, gTrue, gFalse, &XpdfViewer::cmdScrollToTopLeft },
+ { "scrollUp", 1, gTrue, gFalse, &XpdfViewer::cmdScrollUp },
+ { "scrollUpPrevPage", 1, gTrue, gFalse, &XpdfViewer::cmdScrollUpPrevPage },
+ { "selectLine", 0, gTrue, gTrue, &XpdfViewer::cmdSelectLine },
+ { "selectWord", 0, gTrue, gTrue, &XpdfViewer::cmdSelectWord },
+ { "setSelection", 5, gTrue, gFalse, &XpdfViewer::cmdSetSelection },
+ { "showAttachmentsPane", 0, gFalse, gFalse, &XpdfViewer::cmdShowAttachmentsPane },
+ { "showDocumentInfo", 0, gTrue, gFalse, &XpdfViewer::cmdShowDocumentInfo },
+ { "showKeyBindings", 0, gFalse, gFalse, &XpdfViewer::cmdShowKeyBindings },
+ { "showLayersPane", 0, gFalse, gFalse, &XpdfViewer::cmdShowLayersPane },
+ { "showMenuBar", 0, gFalse, gFalse, &XpdfViewer::cmdShowMenuBar },
+ { "showOutlinePane", 0, gFalse, gFalse, &XpdfViewer::cmdShowOutlinePane },
+ { "showToolbar", 0, gFalse, gFalse, &XpdfViewer::cmdShowToolbar },
+ { "shrinkSidebar", 1, gFalse, gFalse, &XpdfViewer::cmdShrinkSidebar },
+ { "sideBySideContinuousMode",0, gFalse, gFalse, &XpdfViewer::cmdSideBySideContinuousMode },
+ { "sideBySideSingleMode", 0, gFalse, gFalse, &XpdfViewer::cmdSideBySideSingleMode },
+ { "singlePageMode", 0, gFalse, gFalse, &XpdfViewer::cmdSinglePageMode },
+ { "startExtendedSelection", 0, gTrue, gTrue, &XpdfViewer::cmdStartExtendedSelection },
+ { "startPan", 0, gTrue, gTrue, &XpdfViewer::cmdStartPan },
+ { "startSelection", 0, gTrue, gTrue, &XpdfViewer::cmdStartSelection },
+ { "toggleContinuousMode", 0, gFalse, gFalse, &XpdfViewer::cmdToggleContinuousMode },
+ { "toggleFullScreenMode", 0, gFalse, gFalse, &XpdfViewer::cmdToggleFullScreenMode },
+ { "toggleMenuBar", 0, gFalse, gFalse, &XpdfViewer::cmdToggleMenuBar },
+ { "toggleSelectMode", 0, gFalse, gFalse, &XpdfViewer::cmdToggleSelectMode },
+ { "toggleSidebar", 0, gFalse, gFalse, &XpdfViewer::cmdToggleSidebar },
+ { "toggleSidebarMoveResizeWin", 0, gFalse, gFalse, &XpdfViewer::cmdToggleSidebarMoveResizeWin },
+ { "toggleSidebarResizeWin", 0, gFalse, gFalse, &XpdfViewer::cmdToggleSidebarResizeWin },
+ { "toggleToolbar", 0, gFalse, gFalse, &XpdfViewer::cmdToggleToolbar },
+ { "viewPageLabels", 0, gFalse, gFalse, &XpdfViewer::cmdViewPageLabels },
+ { "viewPageNumbers", 0, gFalse, gFalse, &XpdfViewer::cmdViewPageNumbers },
+ { "windowMode", 0, gFalse, gFalse, &XpdfViewer::cmdWindowMode },
+ { "zoomFitPage", 0, gFalse, gFalse, &XpdfViewer::cmdZoomFitPage },
+ { "zoomFitWidth", 0, gFalse, gFalse, &XpdfViewer::cmdZoomFitWidth },
+ { "zoomIn", 0, gFalse, gFalse, &XpdfViewer::cmdZoomIn },
+ { "zoomOut", 0, gFalse, gFalse, &XpdfViewer::cmdZoomOut },
+ { "zoomPercent", 1, gFalse, gFalse, &XpdfViewer::cmdZoomPercent },
+ { "zoomToSelection", 0, gTrue, gFalse, &XpdfViewer::cmdZoomToSelection }
+};
+
+#define nCmds (sizeof(cmdTab) / sizeof(XpdfViewerCmd))
+
+//------------------------------------------------------------------------
+// XpdfMenuButton
+//------------------------------------------------------------------------
+
+XpdfMenuButton::XpdfMenuButton(QMenu *menuA) {
+ menu = menuA;
+ connect(this, SIGNAL(pressed()), this, SLOT(btnPressed()));
+}
+
+void XpdfMenuButton::btnPressed() {
+ QSize menuSize = menu->sizeHint();
+ QPoint pos = mapToGlobal(QPoint(width(), height()));
+ pos -= QPoint(menuSize.width(), 0);
+ menu->exec(pos);
+ setDown(false);
+ setAttribute(Qt::WA_UnderMouse, false);
+}
+
+//------------------------------------------------------------------------
+// XpdfErrorWindow
+//------------------------------------------------------------------------
+
+class XpdfErrorEvent: public QEvent {
+public:
+
+ XpdfErrorEvent(int eventType, QString msgA):
+ QEvent((Type)eventType), msg(msgA) {}
+ QString getMessage() { return msg; }
+
+private:
+
+ QString msg;
+};
+
+XpdfErrorWindow::XpdfErrorWindow(XpdfViewer *viewerA, int errorEventTypeA) {
+ viewer = viewerA;
+ errorEventType = errorEventTypeA;
+
+ QVBoxLayout *topLayout = new QVBoxLayout();
+
+ QHBoxLayout *btnLayout = new QHBoxLayout();
+ topLayout->addLayout(btnLayout);
+
+ QPushButton *clearBtn = new QPushButton("Clear");
+ connect(clearBtn, SIGNAL(clicked()), this, SLOT(clearBtnPressed()));
+ btnLayout->addWidget(clearBtn);
+
+ btnLayout->addStretch(1);
+
+ list = new QListWidget();
+ topLayout->addWidget(list);
+
+ setLayout(topLayout);
+
+#if QT_VERSION >= QT_VERSION_CHECK(5, 11, 0)
+ lastSize = QSize(list->fontMetrics().horizontalAdvance("m") * 50,
+ list->fontMetrics().lineSpacing() * 16);
+#else
+ lastSize = QSize(list->fontMetrics().width("m") * 50,
+ list->fontMetrics().lineSpacing() * 16);
+#endif
+
+ setErrorCallback(&errorCbk, this);
+}
+
+XpdfErrorWindow::~XpdfErrorWindow() {
+ // If the user quits while a page is rendering, we want any
+ // subsequent error messages to vanish -- they shouldn't try to
+ // update the error window (which has been deleted), and they
+ // shouldn't get dumped to stderr.
+ setErrorCallback(dummyErrorCbk, NULL);
+}
+
+QSize XpdfErrorWindow::sizeHint() const {
+ return lastSize;
+}
+
+void XpdfErrorWindow::clearBtnPressed() {
+ list->clear();
+ viewer->statusIndicatorOk();
+}
+
+void XpdfErrorWindow::closeEvent(QCloseEvent *event) {
+ lastSize = size();
+}
+
+void XpdfErrorWindow::keyPressEvent(QKeyEvent *event) {
+ if (event->key() == Qt::Key_Escape) {
+ close();
+ }
+}
+
+void XpdfErrorWindow::errorCbk(void *data, ErrorCategory category,
+ int pos, char *msg) {
+ XpdfErrorWindow *errWin = (XpdfErrorWindow *)data;
+ GString *s;
+
+ if (pos >= 0) {
+ s = GString::format("{0:s} ({1:d}): {2:s}",
+ errorCategoryNames[category], pos, msg);
+ } else {
+ s = GString::format("{0:s}: {1:s}",
+ errorCategoryNames[category], msg);
+ }
+ XpdfApp::postEvent(errWin, new XpdfErrorEvent(errWin->errorEventType,
+ s->getCString()));
+ delete s;
+}
+
+void XpdfErrorWindow::dummyErrorCbk(void *data, ErrorCategory category,
+ int pos, char *msg) {
+}
+
+void XpdfErrorWindow::customEvent(QEvent *event) {
+ XpdfErrorEvent *errEvent;
+
+ if (event->type() == errorEventType) {
+ errEvent = (XpdfErrorEvent *)event;
+ if (list->count() < errorWindowMaxErrors) {
+ list->addItem(errEvent->getMessage());
+ list->scrollToBottom();
+ viewer->statusIndicatorError();
+ } else if (list->count() == errorWindowMaxErrors) {
+ list->addItem("... additional errors not logged ...");
+ list->scrollToBottom();
+ viewer->statusIndicatorError();
+ }
+ }
+}
+
+//------------------------------------------------------------------------
+// ZoomValidator
+//------------------------------------------------------------------------
+
+class ZoomValidator: public QValidator {
+public:
+
+ ZoomValidator(QObject *parent = NULL): QValidator(parent) {}
+ virtual State validate(QString &input, int &pos) const;
+ virtual void fixup(QString &input) const;
+};
+
+QValidator::State ZoomValidator::validate(QString &input, int &pos) const {
+ QChar c;
+ int n, i;
+
+ n = input.length();
+ if (n == 0) {
+ return QValidator::Intermediate;
+ }
+ for (i = 0; i < n - 1; ++i) {
+ c = input[i];
+ if (c < '0' || c > '9') {
+ return QValidator::Invalid;
+ }
+ }
+ c = input[n - 1];
+ if (c == '%') {
+ if (n > 1) {
+ return QValidator::Acceptable;
+ }
+ return QValidator::Intermediate;
+ }
+ if (c < '0' || c > '9') {
+ return QValidator::Invalid;
+ }
+ return QValidator::Intermediate;
+}
+
+void ZoomValidator::fixup(QString &input) const {
+ if (!input.endsWith("%")) {
+ input.append('%');
+ }
+}
+
+//------------------------------------------------------------------------
+// PropertyListAnimation
+//------------------------------------------------------------------------
+
+class PropertyListAnimation: public QPropertyAnimation {
+public:
+
+ PropertyListAnimation(QObject *target, const QByteArray &propertyName,
+ QList<QVariant> valueListA, QObject *parent = 0):
+ QPropertyAnimation(target, propertyName, parent), valueList(valueListA) {}
+
+ virtual QVariant interpolated(const QVariant &from, const QVariant &to,
+ qreal progress) const;
+
+ QList<QVariant> values() { return valueList; }
+ void setValues(QList<QVariant> valueListA);
+
+private:
+
+ QList<QVariant> valueList;
+};
+
+QVariant PropertyListAnimation::interpolated(const QVariant &from,
+ const QVariant &to,
+ qreal progress) const {
+ int i;
+
+ i = (int)(progress * valueList.size());
+ if (i < 0) {
+ i = 0;
+ } else if (i >= valueList.size()) {
+ i = valueList.size() - 1;
+ }
+ return valueList[i];
+}
+
+void PropertyListAnimation::setValues(QList<QVariant> valueListA) {
+ qreal progress;
+
+ valueList = valueListA;
+ progress = easingCurve().valueForProgress(qreal(currentTime())
+ / qreal(totalDuration()));
+ updateCurrentValue(interpolated(0, 0, progress));
+}
+
+//------------------------------------------------------------------------
+// OutlineModel
+//------------------------------------------------------------------------
+
+class OutlineModel: public QAbstractItemModel {
+public:
+
+ OutlineModel(XpdfWidget *pdfA);
+ virtual QModelIndex index(int row, int column,
+ const QModelIndex &par = QModelIndex()) const;
+ virtual QModelIndex parent(const QModelIndex &idx) const;
+ virtual int rowCount(const QModelIndex &par = QModelIndex()) const;
+ virtual int columnCount(const QModelIndex &par = QModelIndex()) const;
+ virtual QVariant data(const QModelIndex &idx, int role) const;
+
+ QModelIndex findPageIndex(int pg, QTreeView *tree,
+ const QModelIndex &idx = QModelIndex());
+
+ void beginOpenNewDoc();
+ void endOpenNewDoc();
+
+private:
+
+ int getItemRow(XpdfOutlineHandle item) const;
+ XpdfWidget *pdf;
+};
+
+OutlineModel::OutlineModel(XpdfWidget *pdfA) {
+ pdf = pdfA;
+}
+
+QModelIndex OutlineModel::index(int row, int column,
+ const QModelIndex &par) const {
+ XpdfOutlineHandle item;
+ int nChildren;
+
+ if (par.isValid()) {
+ // children of an outline item
+ item = (XpdfOutlineHandle)par.internalPointer();
+ } else {
+ // root outline items
+ item = NULL;
+ }
+ nChildren = pdf->getOutlineNumChildren(item);
+ if (row < 0 || row >= nChildren || column != 0) {
+ return QModelIndex();
+ }
+ return createIndex(row, 0, pdf->getOutlineChild(item, row));
+}
+
+QModelIndex OutlineModel::parent(const QModelIndex &idx) const {
+ XpdfOutlineHandle item, par;
+ int row;
+
+ if (!idx.isValid()) {
+ return QModelIndex();
+ }
+ item = (XpdfOutlineHandle)idx.internalPointer();
+ if (!(par = pdf->getOutlineParent(item))) {
+ return QModelIndex();
+ }
+ if ((row = getItemRow(par)) < 0) {
+ return QModelIndex();
+ }
+ return createIndex(row, 0, par);
+}
+
+int OutlineModel::rowCount(const QModelIndex &par) const {
+ XpdfOutlineHandle item;
+
+ if (par.isValid()) {
+ // children of an outline item
+ item = (XpdfOutlineHandle)par.internalPointer();
+ } else {
+ // root outline items
+ item = NULL;
+ }
+ return pdf->getOutlineNumChildren(item);
+}
+
+int OutlineModel::columnCount(const QModelIndex &par) const {
+ return 1;
+}
+
+QVariant OutlineModel::data(const QModelIndex &idx, int role) const {
+ XpdfOutlineHandle item;
+
+ if (role != Qt::DisplayRole) {
+ return QVariant();
+ }
+ item = (XpdfOutlineHandle)idx.internalPointer();
+ return QVariant(pdf->getOutlineTitle(item));
+}
+
+int OutlineModel::getItemRow(XpdfOutlineHandle item) const {
+ XpdfOutlineHandle par;
+ int nChildren, i;
+
+ par = pdf->getOutlineParent(item);
+ nChildren = pdf->getOutlineNumChildren(par);
+ for (i = 0; i < nChildren; ++i) {
+ if (item == pdf->getOutlineChild(par, i)) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+QModelIndex OutlineModel::findPageIndex(int pg, QTreeView *tree,
+ const QModelIndex &idx) {
+ QModelIndex childIdx, lastIdx;
+ XpdfOutlineHandle thisItem, childItem;
+ int thisPage, lastPage, childPage, i;
+
+ if (idx.isValid()) {
+ thisItem = (XpdfOutlineHandle)idx.internalPointer();
+ thisPage = pdf->getOutlineTargetPage(thisItem);
+ if (thisPage == pg) {
+ return idx;
+ }
+ if (thisPage > pg) {
+ return QModelIndex();
+ }
+ if (!tree->isExpanded(idx)) {
+ return idx;
+ }
+ } else {
+ thisPage = 0;
+ }
+
+ lastPage = thisPage;
+ lastIdx = idx;
+ for (i = 0; i < rowCount(idx); ++i) {
+ childIdx = findPageIndex(pg, tree, index(i, 0, idx));
+ if (!childIdx.isValid()) {
+ break;
+ }
+ childItem = (XpdfOutlineHandle)childIdx.internalPointer();
+ childPage = pdf->getOutlineTargetPage(childItem);
+ if (childPage > lastPage) {
+ lastPage = childPage;
+ lastIdx = childIdx;
+ }
+ }
+ if (lastPage == 0) {
+ return QModelIndex();
+ }
+ return lastIdx;
+}
+
+void OutlineModel::beginOpenNewDoc() {
+ beginResetModel();
+}
+
+void OutlineModel::endOpenNewDoc() {
+ endResetModel();
+}
+
+//------------------------------------------------------------------------
+// LayerModel
+//------------------------------------------------------------------------
+
+class LayerModel: public QAbstractItemModel {
+public:
+
+ LayerModel(XpdfWidget *pdfA);
+ virtual QModelIndex index(int row, int column,
+ const QModelIndex &par = QModelIndex()) const;
+ virtual QModelIndex parent(const QModelIndex &idx) const;
+ virtual int rowCount(const QModelIndex &par = QModelIndex()) const;
+ virtual int columnCount(const QModelIndex &par = QModelIndex()) const;
+ virtual QVariant data(const QModelIndex &idx, int role) const;
+ virtual bool setData(const QModelIndex &idx, const QVariant &value,
+ int role);
+ virtual Qt::ItemFlags flags(const QModelIndex &idx) const;
+
+ void beginOpenNewDoc();
+ void endOpenNewDoc();
+
+private:
+
+ int getOrderRow(XpdfLayerOrderHandle order) const;
+
+ XpdfWidget *pdf;
+};
+
+LayerModel::LayerModel(XpdfWidget *pdfA) {
+ pdf = pdfA;
+}
+
+QModelIndex LayerModel::index(int row, int column,
+ const QModelIndex &par) const {
+ XpdfLayerOrderHandle order;
+ int nChildren;
+
+ if (par.isValid()) {
+ // children of a layer display order tree node
+ order = (XpdfLayerOrderHandle)par.internalPointer();
+ } else {
+ // children of display order tree root
+ order = pdf->getLayerOrderRoot();
+ }
+ nChildren = pdf->getLayerOrderNumChildren(order);
+ if (row < 0 || row >= nChildren || column != 0) {
+ return QModelIndex();
+ }
+ return createIndex(row, 0, pdf->getLayerOrderChild(order, row));
+}
+
+QModelIndex LayerModel::parent(const QModelIndex &idx) const {
+ XpdfLayerOrderHandle order, par;
+ int row;
+
+ if (!idx.isValid()) {
+ return QModelIndex();
+ }
+ order = (XpdfLayerOrderHandle)idx.internalPointer();
+ if (!(par = pdf->getLayerOrderParent(order))) {
+ return QModelIndex();
+ }
+ if ((row = getOrderRow(par)) < 0) {
+ return QModelIndex();
+ }
+ return createIndex(row, 0, par);
+}
+
+int LayerModel::rowCount(const QModelIndex &par) const {
+ XpdfLayerOrderHandle order;
+
+ if (par.isValid()) {
+ // children of a layer display order tree node
+ order = (XpdfLayerOrderHandle)par.internalPointer();
+ } else {
+ // children of display order tree root
+ order = pdf->getLayerOrderRoot();
+ }
+ return pdf->getLayerOrderNumChildren(order);
+}
+
+int LayerModel::columnCount(const QModelIndex &par) const {
+ return 1;
+}
+
+QVariant LayerModel::data(const QModelIndex &idx, int role) const {
+ XpdfLayerOrderHandle order;
+ XpdfLayerHandle layer;
+
+ if (!idx.isValid()) {
+ return false;
+ }
+ if (role == Qt::DisplayRole) {
+ order = (XpdfLayerOrderHandle)idx.internalPointer();
+ if (pdf->getLayerOrderIsName(order)) {
+ return QVariant(pdf->getLayerOrderName(order));
+ } else {
+ return QVariant(pdf->getLayerName(pdf->getLayerOrderLayer(order)));
+ }
+ } else if (role == Qt::CheckStateRole) {
+ order = (XpdfLayerOrderHandle)idx.internalPointer();
+ layer = pdf->getLayerOrderLayer(order);
+ if (!layer) {
+ return QVariant();
+ }
+ return pdf->getLayerVisibility(layer) ? Qt::Checked : Qt::Unchecked;
+ } else {
+ return QVariant();
+ }
+}
+
+bool LayerModel::setData(const QModelIndex &idx, const QVariant &value,
+ int role) {
+ XpdfLayerOrderHandle order;
+ XpdfLayerHandle layer;
+ bool vis;
+
+ if (!idx.isValid()) {
+ return false;
+ }
+ if (role != Qt::CheckStateRole) {
+ return false;
+ }
+ order = (XpdfLayerOrderHandle)idx.internalPointer();
+ layer = pdf->getLayerOrderLayer(order);
+ if (!layer) {
+ return false;
+ }
+ vis = value == Qt::Checked;
+ if (vis != pdf->getLayerVisibility(layer)) {
+ pdf->setLayerVisibility(layer, vis);
+ }
+ emit dataChanged(idx, idx);
+ return true;
+}
+
+Qt::ItemFlags LayerModel::flags(const QModelIndex &idx) const {
+ if (!idx.isValid()) {
+ return Qt::NoItemFlags;
+ }
+ // NB: this does not include Qt::ItemIsUserCheckable because we use
+ // the QTreeView::clicked signal to toggle the checkbox -- which
+ // handles clicks anywhere in the item, including in the checkbox
+ return Qt::ItemIsEnabled;
+}
+
+int LayerModel::getOrderRow(XpdfLayerOrderHandle order) const {
+ XpdfLayerOrderHandle par;
+ int nChildren, i;
+
+ par = pdf->getLayerOrderParent(order);
+ if (par) {
+ nChildren = pdf->getLayerOrderNumChildren(par);
+ for (i = 0; i < nChildren; ++i) {
+ if (order == pdf->getLayerOrderChild(par, i)) {
+ return i;
+ }
+ }
+ return -1;
+ } else {
+ return 0;
+ }
+}
+
+void LayerModel::beginOpenNewDoc() {
+ beginResetModel();
+}
+
+void LayerModel::endOpenNewDoc() {
+ endResetModel();
+}
+
+//------------------------------------------------------------------------
+// XpdfTabInfo
+//------------------------------------------------------------------------
+
+class XpdfTabInfo {
+public:
+
+ XpdfTabInfo(QListWidgetItem *listItemA, XpdfWidget *pdfA,
+ QTreeView *outlineTreeA, QTreeView *layerTreeA,
+ QTableWidget *attachmentListA):
+ listItem(listItemA), pdf(pdfA), outlineTree(outlineTreeA),
+ layerTree(layerTreeA), attachmentList(attachmentListA) {}
+
+ QListWidgetItem *listItem;
+ XpdfWidget *pdf;
+ QTreeView *outlineTree;
+ QTreeView *layerTree;
+ QTableWidget *attachmentList;
+};
+
+//------------------------------------------------------------------------
+// XpdfViewer
+//------------------------------------------------------------------------
+
+XpdfViewer::XpdfViewer(XpdfApp *appA, GBool fullScreen) {
+ setAttribute(Qt::WA_DeleteOnClose, true);
+ app = appA;
+ createWindow();
+ if (fullScreen) {
+ move(0, 0);
+ enterFullScreenMode();
+ }
+ remoteServer = NULL;
+}
+
+XpdfViewer *XpdfViewer::create(XpdfApp *app, QString fileName, int page,
+ QString destName, int rot, QString password,
+ GBool fullScreen) {
+ XpdfViewer *viewer;
+
+ viewer = new XpdfViewer(app, fullScreen);
+ if (!viewer->open(fileName, page, destName, rot, password)) {
+ viewer->close();
+ delete viewer;
+ return NULL;
+ }
+ return viewer;
+}
+
+XpdfViewer::~XpdfViewer() {
+ destroyWindow();
+}
+
+// QSplitter::sizeHint() doesn't take into account collapsed children,
+// which leads to an incorrect window size when we start with
+// initialSidebarState=no. So sizeHint() is reimplemented to subtract
+// out the sidebar width if needed. This also handles the case where
+// initialSidebarWidth is set.
+QSize XpdfViewer::sizeHint() const {
+ int toolBarWidth, mainWidth, height;
+
+ toolBarWidth = toolBar->sizeHint().width();
+ mainWidth = sidebarSplitter->sizeHint().width();
+ QList<int> sizes = sidebarSplitter->sizes();
+ if (sizes[0] == 0 && sizes[1] > 0) {
+ mainWidth -= sidebarSplitter->widget(0)->sizeHint().width();
+ } else if (initialSidebarWidth > 0) {
+ mainWidth -= sidebarSplitter->widget(0)->sizeHint().width();
+ mainWidth += initialSidebarWidth;
+ }
+ height = QMainWindow::sizeHint().height();
+ return QSize(qMax(toolBarWidth, mainWidth), height);
+}
+
+// Tweak the window size before showing a new window. This does two
+// things:
+// (1) By default, Qt won't allow windows larger than 2/3 of the
+// screen size. This function kludges around that by resizing to
+// the sizeHint, with a max of 60 pixels smaller than the screen
+// size.
+// (2) Sets the sidebar splitter sizes. This has to be done after the
+// PDF file is loaded and before the window is shown.
+void XpdfViewer::tweakSize() {
+ if (initialSidebarWidth > 0) {
+ QList<int> sidebarSplitterSizes = sidebarSplitter->sizes();
+ sidebarSplitterSizes[0] = initialSidebarWidth;
+ sidebarSplitterSizes[1] = sidebarSplitter->widget(1)->sizeHint().width();
+ sidebarSplitter->setSizes(sidebarSplitterSizes);
+ }
+
+ QSize hint = sizeHint();
+ QRect screen = QGuiApplication::primaryScreen()->availableGeometry();
+ int w = hint.width();
+ int h = hint.height();
+ if (w > screen.width() - 60) {
+ w = screen.width() - 60;
+ }
+ if (h > screen.height() - 60) {
+ h = screen.height() - 60;
+ }
+ resize(w, h);
+}
+
+bool XpdfViewer::close() {
+ if (tabInfo->getLength() > 0) {
+ app->startUpdatePagesFile();
+ for (int i = 0; i < tabInfo->getLength(); ++i) {
+ XpdfTabInfo *tab = (XpdfTabInfo *)tabInfo->get(i);
+ app->updatePagesFile(tab->pdf->getFileName(), tab->pdf->getMidPage());
+ }
+ app->finishUpdatePagesFile();
+ }
+ return QMainWindow::close();
+}
+
+//------------------------------------------------------------------------
+
+GBool XpdfViewer::open(QString fileName, int page, QString destName,
+ int rot, QString password) {
+ XpdfWidget::ErrorCode err;
+
+ if (currentTab->pdf->hasOpenDocument()) {
+ app->startUpdatePagesFile();
+ app->updatePagesFile(currentTab->pdf->getFileName(),
+ currentTab->pdf->getMidPage());
+ app->finishUpdatePagesFile();
+ }
+ err = currentTab->pdf->loadFile(fileName, password);
+ if (err != XpdfWidget::pdfOk) {
+ QMessageBox::warning(NULL, "Xpdf Error",
+ "Couldn't open file '" + fileName + "'");
+ return gFalse;
+ }
+ if (!destName.isEmpty()) {
+ currentTab->pdf->gotoNamedDestination(destName);
+ } else {
+ if (page < 0) {
+ page = app->getSavedPageNumber(fileName);
+ }
+ currentTab->pdf->gotoPage(page);
+ }
+ if (rot != 0) {
+ currentTab->pdf->setRotate(rot);
+ }
+ // after opening a document, focus goes to the XpdfWidget
+ currentTab->pdf->setFocus(Qt::OtherFocusReason);
+ lastOpenedTab = currentTab;
+ lastFileOpened = fileName;
+ return gTrue;
+}
+
+GBool XpdfViewer::openInNewTab(QString fileName, int page, QString destName,
+ int rot, QString password, GBool switchToTab) {
+ GBool ok;
+ int oldTabIndex;
+
+ oldTabIndex = tabList->currentRow();
+ addTab();
+ updateModeInfo();
+ ok = open(fileName, page, destName, rot, password);
+ if (!ok) {
+ if (tabInfo->getLength() > 1) {
+ closeTab(currentTab);
+ }
+ return gFalse;
+ }
+ lastOpenedTab = currentTab;
+ if (!switchToTab) {
+ tabList->setCurrentRow(oldTabIndex);
+ }
+ lastFileOpened = fileName;
+ return gTrue;
+}
+
+GBool XpdfViewer::checkOpen(QString fileName, int page, QString destName,
+ QString password) {
+ XpdfWidget::ErrorCode err;
+
+ if (fileName != currentTab->pdf->getFileName()) {
+ if (currentTab->pdf->hasOpenDocument()) {
+ app->startUpdatePagesFile();
+ app->updatePagesFile(currentTab->pdf->getFileName(),
+ currentTab->pdf->getMidPage());
+ app->finishUpdatePagesFile();
+ }
+ err = currentTab->pdf->loadFile(fileName, password);
+ if (err != XpdfWidget::pdfOk) {
+ QMessageBox::warning(NULL, "Xpdf Error",
+ "Couldn't open file '" + fileName + "'");
+ return gFalse;
+ }
+ }
+ if (!destName.isEmpty()) {
+ currentTab->pdf->gotoNamedDestination(destName);
+ } else {
+ if (page < 0) {
+ page = app->getSavedPageNumber(fileName);
+ }
+ currentTab->pdf->gotoPage(page);
+ }
+ // after opening a document, focus goes to the XpdfWidget
+ currentTab->pdf->setFocus(Qt::OtherFocusReason);
+ lastFileOpened = fileName;
+ lastOpenedTab = currentTab;
+ return gTrue;
+}
+
+// Disable the default popup menu (which shows a toggle to hide the
+// toolbar).
+QMenu *XpdfViewer::createPopupMenu() {
+ return NULL;
+}
+
+//------------------------------------------------------------------------
+// remote server
+//------------------------------------------------------------------------
+
+void XpdfViewer::startRemoteServer(const QString &remoteServerName) {
+ remoteServer = new QLocalServer(this);
+ connect(remoteServer, SIGNAL(newConnection()),
+ this, SLOT(remoteServerConnection()));
+ if (!remoteServer->listen("xpdf_" + remoteServerName)) {
+ error(errIO, -1, "Couldn't set up the remote server socket");
+ }
+}
+
+void XpdfViewer::remoteServerConnection() {
+ QLocalSocket *sock;
+
+ sock = remoteServer->nextPendingConnection();
+ connect(sock, SIGNAL(readyRead()), this, SLOT(remoteServerRead()));
+}
+
+void XpdfViewer::remoteServerRead() {
+ QLocalSocket *sock;
+ char buf[1024];
+ qint64 n;
+
+ sock = (QLocalSocket *)sender();
+ while (sock->canReadLine()) {
+ n = sock->readLine(buf, sizeof(buf));
+ if (n > 0) {
+ if (buf[n-1] == '\n') {
+ buf[n-1] = '\0';
+ }
+ execCmd(buf, NULL);
+ }
+ }
+}
+
+//------------------------------------------------------------------------
+// commands
+//------------------------------------------------------------------------
+
+void XpdfViewer::execCmd(const char *cmd, QInputEvent *event) {
+ GString *name;
+ GString *args[cmdMaxArgs];
+ const char *p0, *p1;
+ int nArgs, i;
+ int a, b, m, cmp;
+
+ //----- parse the command
+ name = NULL;
+ nArgs = 0;
+ for (i = 0; i < cmdMaxArgs; ++i) {
+ args[i] = NULL;
+ }
+ p0 = cmd;
+ for (p1 = p0; *p1 && isalnum(*p1); ++p1) ;
+ if (p1 == p0) {
+ goto err1;
+ }
+ name = new GString(p0, (int)(p1 - p0));
+ if (*p1 == '(') {
+ while (nArgs < cmdMaxArgs) {
+ ++p1;
+ args[nArgs] = new GString();
+ while (*p1 && *p1 != ',' && *p1 != ')') {
+ if (*p1 == '\x01' && p1[1]) {
+ ++p1;
+ }
+ args[nArgs]->append(*p1++);
+ }
+ ++nArgs;
+ if (*p1 != ',') {
+ break;
+ }
+ }
+ if (*p1 != ')') {
+ goto err1;
+ }
+ ++p1;
+ }
+ if (*p1) {
+ goto err1;
+ }
+
+ //----- find the command
+ a = -1;
+ b = nCmds;
+ // invariant: cmdTab[a].name < name < cmdTab[b].name
+ while (b - a > 1) {
+ m = (a + b) / 2;
+ cmp = strcmp(cmdTab[m].name, name->getCString());
+ if (cmp < 0) {
+ a = m;
+ } else if (cmp > 0) {
+ b = m;
+ } else {
+ a = b = m;
+ }
+ }
+ if (cmp != 0) {
+ goto err1;
+ }
+
+ //----- execute the command
+ if (nArgs != cmdTab[a].nArgs ||
+ (cmdTab[a].requiresEvent && !event)) {
+ goto err1;
+ }
+ if (cmdTab[a].requiresDoc && !currentTab->pdf->hasOpenDocument()) {
+ // don't issue an error message for this -- it happens, e.g., when
+ // clicking in a window with no open PDF file
+ goto err2;
+ }
+ (this->*cmdTab[a].func)(args, nArgs, event);
+
+ //----- clean up
+ delete name;
+ for (i = 0; i < nArgs; ++i) {
+ if (args[i]) {
+ delete args[i];
+ }
+ }
+ return;
+
+ err1:
+ error(errConfig, -1, "Invalid command syntax: '{0:s}'", cmd);
+ err2:
+ if (name) {
+ delete name;
+ }
+ for (i = 0; i < nArgs; ++i) {
+ if (args[i]) {
+ delete args[i];
+ }
+ }
+}
+
+int XpdfViewer::mouseX(QInputEvent *event) {
+ QEvent::Type eventType;
+
+ if (!event) {
+ return 0;
+ }
+ eventType = event->type();
+ if (eventType == QEvent::MouseButtonPress ||
+ eventType == QEvent::MouseButtonRelease ||
+ eventType == QEvent::MouseButtonDblClick ||
+ eventType == QEvent::MouseMove) {
+ return (int)(((QMouseEvent *)event)->pos().x() * scaleFactor);
+ } else if (eventType == QEvent::Wheel) {
+#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
+ return (int)(((QWheelEvent *)event)->position().x() * scaleFactor);
+#else
+ return (int)(((QWheelEvent *)event)->x() * scaleFactor);
+#endif
+ } else {
+ return 0;
+ }
+}
+
+int XpdfViewer::mouseY(QInputEvent *event) {
+ QEvent::Type eventType;
+
+ if (!event) {
+ return 0;
+ }
+ eventType = event->type();
+ if (eventType == QEvent::MouseButtonPress ||
+ eventType == QEvent::MouseButtonRelease ||
+ eventType == QEvent::MouseButtonDblClick ||
+ eventType == QEvent::MouseMove) {
+ return (int)(((QMouseEvent *)event)->pos().y() * scaleFactor);
+ } else if (eventType == QEvent::Wheel) {
+#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
+ return (int)(((QWheelEvent *)event)->position().y() * scaleFactor);
+#else
+ return (int)(((QWheelEvent *)event)->y() * scaleFactor);
+#endif
+ } else {
+ return 0;
+ }
+}
+
+void XpdfViewer::cmdAbout(GString *args[], int nArgs, QInputEvent *event) {
+ if (!aboutDialog) {
+ createAboutDialog();
+ }
+ aboutDialog->show();
+ aboutDialog->raise();
+}
+
+void XpdfViewer::cmdBlockSelectMode(GString *args[], int nArgs,
+ QInputEvent *event) {
+ currentTab->pdf->setBlockSelectMode();
+ updateSelectModeInfo();
+}
+
+void XpdfViewer::cmdCheckOpenFile(GString *args[], int nArgs,
+ QInputEvent *event) {
+ checkOpen(args[0]->getCString(), -1, "", "");
+}
+
+void XpdfViewer::cmdCheckOpenFileAtDest(GString *args[], int nArgs,
+ QInputEvent *event) {
+ checkOpen(args[0]->getCString(), 1, args[1]->getCString(), "");
+}
+
+void XpdfViewer::cmdCheckOpenFileAtPage(GString *args[], int nArgs,
+ QInputEvent *event) {
+ checkOpen(args[0]->getCString(), atoi(args[1]->getCString()), "", "");
+}
+
+void XpdfViewer::cmdCloseSidebar(GString *args[], int nArgs,
+ QInputEvent *event) {
+ QList<int> sizes = sidebarSplitter->sizes();
+ if (sizes[0] == 0) {
+ return;
+ }
+ sidebarWidth = sizes[0];
+ sizes[0] = 0;
+ sizes[1] += sidebarWidth;
+ sidebarSplitter->setSizes(sizes);
+ toggleSidebarMenuItem->setChecked(false);
+}
+
+void XpdfViewer::cmdCloseSidebarMoveResizeWin(GString *args[], int nArgs,
+ QInputEvent *event) {
+ int newWidth;
+ QList<int> sizes = sidebarSplitter->sizes();
+ if (sizes[0] == 0) {
+ return;
+ }
+ sidebarWidth = sizes[0];
+ newWidth = width() - sidebarWidth;
+ sizes[0] = 0;
+ sidebarSplitter->setSizes(sizes);
+ setGeometry(geometry().x() + sidebarWidth, geometry().y(),
+ newWidth, height());
+ toggleSidebarMenuItem->setChecked(false);
+}
+
+void XpdfViewer::cmdCloseSidebarResizeWin(GString *args[], int nArgs,
+ QInputEvent *event) {
+ int newWidth;
+ QList<int> sizes = sidebarSplitter->sizes();
+ if (sizes[0] == 0) {
+ return;
+ }
+ sidebarWidth = sizes[0];
+ newWidth = width() - sidebarWidth;
+ sizes[0] = 0;
+ sidebarSplitter->setSizes(sizes);
+ resize(newWidth, height());
+ toggleSidebarMenuItem->setChecked(false);
+}
+
+void XpdfViewer::cmdCloseTabOrQuit(GString *args[], int nArgs,
+ QInputEvent *event) {
+ closeTab(currentTab);
+ if (tabInfo->getLength() == 0) {
+ app->closeWindowOrQuit(this);
+ return;
+ }
+}
+
+void XpdfViewer::cmdCloseWindowOrQuit(GString *args[], int nArgs,
+ QInputEvent *event) {
+ app->closeWindowOrQuit(this);
+}
+
+
+void XpdfViewer::cmdContinuousMode(GString *args[], int nArgs,
+ QInputEvent *event) {
+ currentTab->pdf->setDisplayMode(XpdfWidget::pdfDisplayContinuous);
+ updateModeInfo();
+}
+
+void XpdfViewer::cmdCopy(GString *args[], int nArgs, QInputEvent *event) {
+ currentTab->pdf->copySelection();
+}
+
+void XpdfViewer::cmdCopyLinkTarget(GString *args[], int nArgs,
+ QInputEvent *event) {
+ QApplication::clipboard()->setText(linkTargetInfo);
+}
+
+#if 0 // for debugging
+void XpdfViewer::cmdDebug1(GString *args[], int nArgs, QInputEvent *event) {
+}
+#endif
+
+void XpdfViewer::cmdEndPan(GString *args[], int nArgs, QInputEvent *event) {
+ currentTab->pdf->getCore()->endPan(mouseX(event), mouseY(event));
+}
+
+void XpdfViewer::cmdEndSelection(GString *args[], int nArgs,
+ QInputEvent *event) {
+ currentTab->pdf->getCore()->endSelection(mouseX(event), mouseY(event));
+}
+
+void XpdfViewer::cmdExpandSidebar(GString *args[], int nArgs,
+ QInputEvent *event) {
+ QList<int> sizes = sidebarSplitter->sizes();
+ int nPixels = atoi(args[0]->getCString());
+ if (nPixels > sizes[1]) {
+ nPixels = sizes[1];
+ }
+ sizes[0] += nPixels;
+ sizes[1] -= nPixels;
+ sidebarSplitter->setSizes(sizes);
+ toggleSidebarMenuItem->setChecked(true);
+}
+
+void XpdfViewer::cmdFind(GString *args[], int nArgs, QInputEvent *event) {
+ clearFindError();
+ findEdit->setFocus(Qt::OtherFocusReason);
+ findEdit->selectAll();
+}
+
+void XpdfViewer::cmdFindFirst(GString *args[], int nArgs, QInputEvent *event) {
+ int flags;
+
+ clearFindError();
+ flags = 0;
+ if (findCaseSensitiveAction->isChecked()) {
+ flags |= XpdfWidget::findCaseSensitive;
+ }
+ if (findWholeWordsAction->isChecked()) {
+ flags |= XpdfWidget::findWholeWord;
+ }
+ if (!currentTab->pdf->find(findEdit->text(), flags)) {
+ showFindError();
+ }
+}
+
+void XpdfViewer::cmdFindNext(GString *args[], int nArgs, QInputEvent *event) {
+ int flags;
+
+ clearFindError();
+ flags = XpdfWidget::findNext;
+ if (findCaseSensitiveAction->isChecked()) {
+ flags |= XpdfWidget::findCaseSensitive;
+ }
+ if (findWholeWordsAction->isChecked()) {
+ flags |= XpdfWidget::findWholeWord;
+ }
+ if (!currentTab->pdf->find(findEdit->text(), flags)) {
+ showFindError();
+ }
+}
+
+void XpdfViewer::cmdFindPrevious(GString *args[], int nArgs,
+ QInputEvent *event) {
+ int flags;
+
+ clearFindError();
+ flags = XpdfWidget::findBackward | XpdfWidget::findNext;
+ if (findCaseSensitiveAction->isChecked()) {
+ flags |= XpdfWidget::findCaseSensitive;
+ }
+ if (findWholeWordsAction->isChecked()) {
+ flags |= XpdfWidget::findWholeWord;
+ }
+ if (!currentTab->pdf->find(findEdit->text(), flags)) {
+ showFindError();
+ }
+}
+
+void XpdfViewer::cmdFocusToDocWin(GString *args[], int nArgs,
+ QInputEvent *event) {
+ currentTab->pdf->setFocus(Qt::OtherFocusReason);
+}
+
+void XpdfViewer::cmdFocusToPageNum(GString *args[], int nArgs,
+ QInputEvent *event) {
+ pageNumber->setFocus(Qt::OtherFocusReason);
+ pageNumber->selectAll();
+}
+
+void XpdfViewer::cmdFollowLink(GString *args[], int nArgs,
+ QInputEvent *event) {
+ followLink(event, gFalse, gFalse, gFalse);
+}
+
+void XpdfViewer::cmdFollowLinkInNewTab(GString *args[], int nArgs,
+ QInputEvent *event) {
+ followLink(event, gFalse, gTrue, gFalse);
+}
+
+void XpdfViewer::cmdFollowLinkInNewTabNoSel(GString *args[], int nArgs,
+ QInputEvent *event) {
+ followLink(event, gTrue, gTrue, gFalse);
+}
+
+void XpdfViewer::cmdFollowLinkInNewWin(GString *args[], int nArgs,
+ QInputEvent *event) {
+ followLink(event, gFalse, gFalse, gTrue);
+}
+
+void XpdfViewer::cmdFollowLinkInNewWinNoSel(GString *args[], int nArgs,
+ QInputEvent *event) {
+ followLink(event, gTrue, gFalse, gTrue);
+}
+
+void XpdfViewer::cmdFollowLinkNoSel(GString *args[], int nArgs,
+ QInputEvent *event) {
+ followLink(event, gTrue, gFalse, gFalse);
+}
+
+void XpdfViewer::cmdFullScreenMode(GString *args[], int nArgs,
+ QInputEvent *event) {
+ if (!(windowState() & Qt::WindowFullScreen)) {
+ enterFullScreenMode();
+ }
+}
+
+void XpdfViewer::cmdGotoDest(GString *args[], int nArgs, QInputEvent *event) {
+ currentTab->pdf->gotoNamedDestination(args[0]->getCString());
+ updateZoomInfo();
+}
+
+void XpdfViewer::cmdGotoLastPage(GString *args[], int nArgs,
+ QInputEvent *event) {
+ currentTab->pdf->gotoLastPage();
+}
+
+void XpdfViewer::cmdGoBackward(GString *args[], int nArgs, QInputEvent *event) {
+ currentTab->pdf->goBackward();
+}
+
+void XpdfViewer::cmdGoForward(GString *args[], int nArgs, QInputEvent *event) {
+ currentTab->pdf->goForward();
+}
+
+void XpdfViewer::cmdGotoPage(GString *args[], int nArgs, QInputEvent *event) {
+ int pg;
+
+ pg = atoi(args[0]->getCString());
+ if (pg < 1 || pg > currentTab->pdf->getNumPages()) {
+ return;
+ }
+ currentTab->pdf->gotoPage(pg);
+}
+
+void XpdfViewer::cmdHelp(GString *args[], int nArgs, QInputEvent *event) {
+ QDesktopServices::openUrl(QUrl(helpURL, QUrl::TolerantMode));
+}
+
+void XpdfViewer::cmdHideMenuBar(GString *args[], int nArgs,
+ QInputEvent *event) {
+ mainMenu->hide();
+}
+
+void XpdfViewer::cmdHideToolbar(GString *args[], int nArgs,
+ QInputEvent *event) {
+ toolBar->hide();
+ toggleToolbarMenuItem->setChecked(false);
+}
+
+void XpdfViewer::cmdHorizontalContinuousMode(GString *args[], int nArgs,
+ QInputEvent *event) {
+ currentTab->pdf->setDisplayMode(XpdfWidget::pdfDisplayHorizontalContinuous);
+}
+
+void XpdfViewer::cmdLinearSelectMode(GString *args[], int nArgs,
+ QInputEvent *event) {
+ currentTab->pdf->setLinearSelectMode();
+ updateSelectModeInfo();
+}
+
+void XpdfViewer::cmdLoadTabState(GString *args[], int nArgs,
+ QInputEvent *event) {
+ GString *path = globalParams->getTabStateFile();
+ FILE *f = openFile(path->getCString(), "rb");
+ if (!f) {
+ GString *msg = GString::format("Couldn't read the tab file '{0:t}'", path);
+ QMessageBox::warning(NULL, "Xpdf Error", msg->getCString());
+ delete msg;
+ delete path;
+ return;
+ }
+ delete path;
+
+ char line1[1024], line2[1024];
+ if (!fgets(line1, sizeof(line1), f)) {
+ fclose(f);
+ return;
+ }
+ size_t n = strlen(line1);
+ if (n > 0 && line1[n-1] == '\n') {
+ line1[--n] = '\0';
+ }
+ if (n > 0 && line1[n-1] == '\r') {
+ line1[--n] = '\0';
+ }
+ int format = 1;
+ if (!strcmp(line1, "xpdf-tabstate-2")) {
+ format = 2;
+ }
+
+ GBool first = gTrue;
+ while (((first && format == 1) || fgets(line1, sizeof(line1), f)) &&
+ fgets(line2, sizeof(line2), f)) {
+ n = strlen(line1);
+ if (n > 0 && line1[n-1] == '\n') {
+ line1[--n] = '\0';
+ }
+ if (n > 0 && line1[n-1] == '\r') {
+ line1[--n] = '\0';
+ }
+ n = strlen(line2);
+ if (n > 0 && line2[n-1] == '\n') {
+ line2[--n] = '\0';
+ }
+ if (n > 0 && line2[n-1] == '\r') {
+ line2[--n] = '\0';
+ }
+ char displayModeChar;
+ int page, rotate, scrollX, scrollY;
+ double zoom;
+ if (format == 2) {
+ sscanf(line2, "%c %d %lf %d %d %d",
+ &displayModeChar, &page, &zoom, &rotate, &scrollX, &scrollY);
+ } else {
+ page = atoi(line2);
+ rotate = 0;
+ // the rest are unused, but set to make gcc happy
+ displayModeChar = 'c';
+ zoom = zoomWidth;
+ scrollX = scrollY = 0;
+ }
+ GBool ok;
+ if (first && !currentTab->pdf->hasOpenDocument()) {
+ ok = open(line1, page, "", rotate, "");
+ } else {
+ ok = openInNewTab(line1, page, "", rotate, "", gFalse);
+ }
+ if (ok && format == 2) {
+ XpdfWidget *pdf = lastOpenedTab->pdf;
+ switch (displayModeChar) {
+ case 's':
+ pdf->setDisplayMode(XpdfWidget::pdfDisplaySingle);
+ break;
+ case 'c':
+ pdf->setDisplayMode(XpdfWidget::pdfDisplayContinuous);
+ break;
+ case 'b':
+ pdf->setDisplayMode(XpdfWidget::pdfDisplaySideBySideSingle);
+ break;
+ case 'B':
+ pdf->setDisplayMode(XpdfWidget::pdfDisplaySideBySideContinuous);
+ break;
+ case 'h':
+ pdf->setDisplayMode(XpdfWidget::pdfDisplayHorizontalContinuous);
+ break;
+ default: break;
+ }
+ pdf->setRotate(rotate);
+ pdf->setZoom(zoom);
+ pdf->scrollTo(scrollX, scrollY);
+ }
+ first = gFalse;
+ }
+
+ fclose(f);
+}
+
+void XpdfViewer::cmdNewTab(GString *args[], int nArgs, QInputEvent *event) {
+ addTab();
+ updateModeInfo();
+ updateDocInfo();
+}
+
+void XpdfViewer::cmdNewWindow(GString *args[], int nArgs, QInputEvent *event) {
+ app->newWindow();
+}
+
+void XpdfViewer::cmdNextPage(GString *args[], int nArgs, QInputEvent *event) {
+ currentTab->pdf->gotoNextPage();
+}
+
+void XpdfViewer::cmdNextPageNoScroll(GString *args[], int nArgs,
+ QInputEvent *event) {
+ currentTab->pdf->gotoNextPage(false);
+}
+
+void XpdfViewer::cmdNextTab(GString *args[], int nArgs, QInputEvent *event) {
+ int i;
+
+ if (tabInfo->getLength() == 1) {
+ return;
+ }
+ for (i = 0; i < tabInfo->getLength(); ++i) {
+ if ((XpdfTabInfo *)tabInfo->get(i) == currentTab) {
+ ++i;
+ if (i >= tabInfo->getLength()) {
+ i = 0;
+ }
+ tabList->setCurrentRow(i);
+ return;
+ }
+ }
+}
+
+void XpdfViewer::cmdOpen(GString *args[], int nArgs,
+ QInputEvent *event) {
+ QString startFile, fileName;
+ QDir startDir;
+
+ if (!(startFile = currentTab->pdf->getFileName()).isEmpty()) {
+ startDir = QDir(startFile);
+ startDir.cdUp();
+ } else if (!lastFileOpened.isEmpty()) {
+ startDir = QDir(lastFileOpened);
+ startDir.cdUp();
+ } else {
+ startDir = QDir(".");
+ }
+ fileName = QFileDialog::getOpenFileName(this, "Open PDF File",
+ startDir.canonicalPath(),
+ "PDF files (*.pdf)");
+ if (fileName.isEmpty()) {
+ return;
+ }
+ open(fileName, -1, "", 0, "");
+}
+
+void XpdfViewer::cmdOpenErrorWindow(GString *args[], int nArgs,
+ QInputEvent *event) {
+ errorWindow->show();
+ errorWindow->raise();
+}
+
+void XpdfViewer::cmdOpenFile(GString *args[], int nArgs, QInputEvent *event) {
+ open(args[0]->getCString(), -1, "", 0, "");
+}
+
+void XpdfViewer::cmdOpenFile2(GString *args[], int nArgs, QInputEvent *event) {
+ char *file = args[0]->getCString();
+ int page;
+ if (args[1]->getLength() == 0) {
+ page = -1;
+ } else {
+ page = atoi(args[1]->getCString());
+ }
+ char *dest = args[2]->getCString();
+ char *password = args[3]->getCString();
+ GString *location = args[4];
+ if (location->cmp("win") == 0) {
+ app->openInNewWindow(file, page, dest, 0, password);
+ } else if (location->cmp("tab") == 0) {
+ openInNewTab(file, page, dest, 0, password, gTrue);
+ } else if (location->cmp("check") == 0) {
+ checkOpen(file, page, dest, password);
+ } else {
+ open(file, page, dest, 0, password);
+ }
+}
+
+void XpdfViewer::cmdOpenFileAtDest(GString *args[], int nArgs,
+ QInputEvent *event) {
+ open(args[0]->getCString(), 1, args[1]->getCString(), 0, "");
+}
+
+void XpdfViewer::cmdOpenFileAtDestIn(GString *args[], int nArgs,
+ QInputEvent *event) {
+ if (!args[2]->cmp("win")) {
+ app->openInNewWindow(args[0]->getCString(), 1, args[1]->getCString());
+ } else if (!args[2]->cmp("tab")) {
+ openInNewTab(args[0]->getCString(), 1, args[1]->getCString(), 0, "", gTrue);
+ } else {
+ open(args[0]->getCString(), 1, args[1]->getCString(), 0, "");
+ }
+}
+
+void XpdfViewer::cmdOpenFileAtPage(GString *args[], int nArgs,
+ QInputEvent *event) {
+ open(args[0]->getCString(), atoi(args[1]->getCString()), "", 0, "");
+}
+
+void XpdfViewer::cmdOpenFileAtPageIn(GString *args[], int nArgs,
+ QInputEvent *event) {
+ if (!args[2]->cmp("win")) {
+ app->openInNewWindow(args[0]->getCString(), atoi(args[1]->getCString()));
+ } else if (!args[2]->cmp("tab")) {
+ openInNewTab(args[0]->getCString(), atoi(args[1]->getCString()),
+ "", 0, "", gTrue);
+ } else {
+ open(args[0]->getCString(), atoi(args[1]->getCString()), "", 0, "");
+ }
+}
+
+void XpdfViewer::cmdOpenFileIn(GString *args[], int nArgs,
+ QInputEvent *event) {
+ if (!args[1]->cmp("win")) {
+ app->openInNewWindow(args[0]->getCString(), -1);
+ } else if (!args[1]->cmp("tab")) {
+ openInNewTab(args[0]->getCString(), -1, "", 0, "", gTrue);
+ } else {
+ open(args[0]->getCString(), -1, "", 0, "");
+ }
+}
+
+void XpdfViewer::cmdOpenIn(GString *args[], int nArgs, QInputEvent *event) {
+ QString startFile, fileName;
+ QDir startDir;
+
+ if (!(startFile = currentTab->pdf->getFileName()).isEmpty()) {
+ startDir = QDir(startFile);
+ startDir.cdUp();
+ } else if (!lastFileOpened.isEmpty()) {
+ startDir = QDir(lastFileOpened);
+ startDir.cdUp();
+ } else {
+ startDir = QDir(".");
+ }
+ fileName = QFileDialog::getOpenFileName(this, "Open PDF File",
+ startDir.canonicalPath(),
+ "PDF files (*.pdf)");
+ if (fileName.isEmpty()) {
+ return;
+ }
+ if (!args[0]->cmp("win")) {
+ app->openInNewWindow(fileName, -1);
+ } else if (!args[0]->cmp("tab")) {
+ openInNewTab(fileName, -1, "", 0, "", gTrue);
+ } else {
+ open(fileName, -1, "", 0, "");
+ }
+}
+
+void XpdfViewer::cmdOpenSidebar(GString *args[], int nArgs,
+ QInputEvent *event) {
+ QList<int> sizes = sidebarSplitter->sizes();
+ if (sizes[0] > 0) {
+ return;
+ }
+ sizes[0] = sidebarWidth;
+ sizes[1] -= sidebarWidth;
+ sidebarSplitter->setSizes(sizes);
+ toggleSidebarMenuItem->setChecked(true);
+}
+
+void XpdfViewer::cmdOpenSidebarMoveResizeWin(GString *args[], int nArgs,
+ QInputEvent *event) {
+ int newWidth;
+ QList<int> sizes = sidebarSplitter->sizes();
+ if (sizes[0] > 0) {
+ return;
+ }
+ sizes[0] = sidebarWidth;
+ newWidth = width() + sidebarWidth;
+ sidebarSplitter->setSizes(sizes);
+ setGeometry(geometry().x() - sidebarWidth, geometry().y(),
+ newWidth, height());
+ toggleSidebarMenuItem->setChecked(true);
+}
+
+void XpdfViewer::cmdOpenSidebarResizeWin(GString *args[], int nArgs,
+ QInputEvent *event) {
+ int newWidth;
+ QList<int> sizes = sidebarSplitter->sizes();
+ if (sizes[0] > 0) {
+ return;
+ }
+ sizes[0] = sidebarWidth;
+ newWidth = width() + sidebarWidth;
+ sidebarSplitter->setSizes(sizes);
+ resize(newWidth, height());
+ toggleSidebarMenuItem->setChecked(true);
+}
+
+void XpdfViewer::cmdPageDown(GString *args[], int nArgs, QInputEvent *event) {
+ currentTab->pdf->scrollPageDown();
+}
+
+void XpdfViewer::cmdPageUp(GString *args[], int nArgs, QInputEvent *event) {
+ currentTab->pdf->scrollPageUp();
+}
+
+void XpdfViewer::cmdPostPopupMenu(GString *args[], int nArgs,
+ QInputEvent *event) {
+ if (!popupMenu) {
+ return;
+ }
+ popupMenu->exec(currentTab->pdf->mapToGlobal(QPoint(mouseX(event),
+ mouseY(event))));
+}
+
+void XpdfViewer::cmdPrevPage(GString *args[], int nArgs, QInputEvent *event) {
+ currentTab->pdf->gotoPreviousPage();
+}
+
+void XpdfViewer::cmdPrevPageNoScroll(GString *args[], int nArgs,
+ QInputEvent *event) {
+ currentTab->pdf->gotoPreviousPage(false);
+}
+
+void XpdfViewer::cmdPrevTab(GString *args[], int nArgs, QInputEvent *event) {
+ int i;
+
+ if (tabInfo->getLength() == 1) {
+ return;
+ }
+ for (i = 0; i < tabInfo->getLength(); ++i) {
+ if ((XpdfTabInfo *)tabInfo->get(i) == currentTab) {
+ --i;
+ if (i < 0) {
+ i = tabInfo->getLength() - 1;
+ }
+ tabList->setCurrentRow(i);
+ return;
+ }
+ }
+}
+
+
+#if XPDFWIDGET_PRINTING
+void XpdfViewer::cmdPrint(GString *args[], int nArgs, QInputEvent *event) {
+ currentTab->pdf->print(true);
+}
+#endif
+
+void XpdfViewer::cmdQuit(GString *args[], int nArgs,
+ QInputEvent *event) {
+ app->quit();
+}
+
+void XpdfViewer::cmdRaise(GString *args[], int nArgs,
+ QInputEvent *event) {
+ show();
+ activateWindow();
+ raise();
+}
+
+void XpdfViewer::cmdReload(GString *args[], int nArgs, QInputEvent *event) {
+ if (currentTab->pdf->reload() != XpdfWidget::pdfOk) {
+ QMessageBox::warning(NULL, "Xpdf Error", "Couldn't reload file");
+ }
+}
+
+void XpdfViewer::cmdRotateCW(GString *args[], int nArgs, QInputEvent *event) {
+ currentTab->pdf->setRotate((currentTab->pdf->getRotate() + 90) % 360);
+}
+
+void XpdfViewer::cmdRotateCCW(GString *args[], int nArgs, QInputEvent *event) {
+ currentTab->pdf->setRotate((currentTab->pdf->getRotate() + 270) % 360);
+}
+
+static QString mungeURL(QString url) {
+ static const char *allowed = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz"
+ "0123456789"
+ "-_.~/?:@&=+,#%";
+ QString newURL;
+ char c;
+ char buf[4];
+ int i;
+
+ for (i = 0; i < url.length(); ++i) {
+ c = url.at(i).toLatin1();
+ if (strchr(allowed, c)) {
+ newURL += c;
+ } else {
+ snprintf(buf, sizeof(buf), "%%%02x", c & 0xff);
+ newURL += buf;
+ }
+ }
+ return newURL;
+}
+
+void XpdfViewer::cmdRun(GString *args[], int nArgs, QInputEvent *event) {
+ GString *fmt, *cmd;
+ QString s;
+ QPoint pt;
+ double selLRX, selLRY, selURX, selURY, mX, mY;
+ int selPage, mPage;
+ GBool gotSel, gotMouse;
+ const char *p, *q;
+ char c0, c1;
+ int i;
+
+ cmd = new GString();
+ fmt = args[0];
+ i = 0;
+ gotSel = gotMouse = gFalse;
+ while (i < fmt->getLength()) {
+ c0 = fmt->getChar(i);
+ if (c0 == '%' && i+1 < fmt->getLength()) {
+ c1 = fmt->getChar(i+1);
+ switch (c1) {
+ case 'f':
+ cmd->append(currentTab->pdf->getFileName().toLocal8Bit().constData());
+ break;
+ case 'b':
+ p = currentTab->pdf->getFileName().toLocal8Bit().constData();
+ if ((q = strrchr(p, '.'))) {
+ cmd->append(p, (int)(q - p));
+ } else {
+ cmd->append(p);
+ }
+ break;
+ case 'u':
+ s = mungeURL(linkTargetInfo);
+ cmd->append(s.toLocal8Bit().constData());
+ break;
+ case 'p':
+ cmd->appendf("{0:d}", currentTab->pdf->getMidPage());
+ break;
+ case 'x':
+ case 'y':
+ case 'X':
+ case 'Y':
+ if (!gotSel) {
+ if (!currentTab->pdf->getCurrentSelection(&selPage, &selURX, &selURY,
+ &selLRX, &selLRY)) {
+ selPage = 0;
+ selURX = selURY = selLRX = selLRY = 0;
+ }
+ gotSel = gTrue;
+ }
+ cmd->appendf("{0:.2g}",
+ (c1 == 'x') ? selURX :
+ (c1 == 'y') ? selURY :
+ (c1 == 'X') ? selLRX : selLRY);
+ break;
+ case 'i':
+ case 'j':
+ case 'k':
+ if (!gotMouse) {
+ if (event->type() == QEvent::MouseButtonPress ||
+ event->type() == QEvent::MouseButtonRelease ||
+ event->type() == QEvent::MouseButtonDblClick ||
+ event->type() == QEvent::MouseMove ||
+ event->type() == QEvent::Wheel) {
+ currentTab->pdf->convertWindowToPDFCoords(mouseX(event),
+ mouseY(event),
+ &mPage, &mX, &mY);
+ } else {
+ pt = currentTab->pdf->mapFromGlobal(QCursor::pos());
+ currentTab->pdf->convertWindowToPDFCoords(pt.x(), pt.y(),
+ &mPage, &mX, &mY);
+ }
+ gotMouse = gTrue;
+ }
+ if (c1 == 'i') {
+ cmd->appendf("{0:d}", mPage);
+ } else {
+ cmd->appendf("{0:.2g}", (c1 == 'j') ? mX : mY);
+ }
+ break;
+ default:
+ cmd->append(c1);
+ break;
+ }
+ i += 2;
+ } else {
+ cmd->append(c0);
+ ++i;
+ }
+ }
+
+#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
+ QString cmdStr(cmd->getCString());
+ QStringList tokens = QProcess::splitCommand(cmdStr);
+ if (!tokens.isEmpty()) {
+ QString program = tokens[0];
+ tokens.removeFirst();
+ QProcess::startDetached(program, tokens);
+ }
+#else
+ QProcess::startDetached(cmd->getCString());
+#endif
+ delete cmd;
+}
+
+void XpdfViewer::cmdSaveAs(GString *args[], int nArgs, QInputEvent *event) {
+ QString startFile, fileName;
+ QDir startDir;
+
+ if (!(startFile = currentTab->pdf->getFileName()).isEmpty()) {
+ startDir = QDir(startFile);
+ } else {
+ startDir = QDir(".");
+ }
+ fileName = QFileDialog::getSaveFileName(this, "Save PDF File",
+ startDir.canonicalPath(),
+ "PDF files (*.pdf)");
+ if (fileName.isEmpty()) {
+ return;
+ }
+ currentTab->pdf->saveAs(fileName);
+}
+
+void XpdfViewer::cmdSaveImage(GString *args[], int nArgs, QInputEvent *event) {
+ execSaveImageDialog();
+}
+
+void XpdfViewer::cmdSaveTabState(GString *args[], int nArgs,
+ QInputEvent *event) {
+ GString *path = globalParams->getTabStateFile();
+ FILE *f = openFile(path->getCString(), "wb");
+ if (!f) {
+ GString *msg = GString::format("Couldn't write the tab file '{0:t}'",
+ path);
+ QMessageBox::warning(NULL, "Xpdf Error", msg->getCString());
+ delete msg;
+ delete path;
+ return;
+ }
+ delete path;
+
+ fprintf(f, "xpdf-tabstate-2\n");
+
+ for (int i = 0; i < tabInfo->getLength(); ++i) {
+ XpdfWidget *pdf = ((XpdfTabInfo *)tabInfo->get(i))->pdf;
+ QString fileName = pdf->getFileName();
+ if (!fileName.isEmpty()) {
+ fprintf(f, "%s\n", fileName.toUtf8().constData());
+ char displayModeChar;
+ switch (pdf->getDisplayMode()) {
+ case XpdfWidget::pdfDisplaySingle:
+ displayModeChar = 's';
+ break;
+ case XpdfWidget::pdfDisplayContinuous:
+ displayModeChar = 'c';
+ break;
+ case XpdfWidget::pdfDisplaySideBySideSingle:
+ displayModeChar = 'b';
+ break;
+ case XpdfWidget::pdfDisplaySideBySideContinuous:
+ displayModeChar = 'B';
+ break;
+ case XpdfWidget::pdfDisplayHorizontalContinuous:
+ displayModeChar = 'h';
+ break;
+ default:
+ displayModeChar = 'c';
+ break;
+ }
+ fprintf(f, "%c %d %g %d %d %d\n",
+ displayModeChar, pdf->getMidPage(), pdf->getZoom(),
+ pdf->getRotate(), pdf->getScrollX(), pdf->getScrollY());
+ }
+ }
+
+ fclose(f);
+}
+
+void XpdfViewer::cmdScrollDown(GString *args[], int nArgs,
+ QInputEvent *event) {
+ int dy = scaleScroll(atoi(args[0]->getCString()));
+ currentTab->pdf->scrollBy(0, dy);
+}
+
+void XpdfViewer::cmdScrollDownNextPage(GString *args[], int nArgs,
+ QInputEvent *event) {
+ int dy = scaleScroll(atoi(args[0]->getCString()));
+ currentTab->pdf->getCore()->scrollDownNextPage(dy);
+}
+
+void XpdfViewer::cmdScrollLeft(GString *args[], int nArgs,
+ QInputEvent *event) {
+ int dx = scaleScroll(atoi(args[0]->getCString()));
+ currentTab->pdf->scrollBy(-dx, 0);
+}
+
+void XpdfViewer::cmdScrollOutlineDown(GString *args[], int nArgs,
+ QInputEvent *event) {
+ QScrollBar *sb = currentTab->outlineTree->verticalScrollBar();
+ sb->setValue(sb->value() + atoi(args[0]->getCString()));
+}
+
+void XpdfViewer::cmdScrollOutlineUp(GString *args[], int nArgs,
+ QInputEvent *event) {
+ QScrollBar *sb = currentTab->outlineTree->verticalScrollBar();
+ sb->setValue(sb->value() - atoi(args[0]->getCString()));
+}
+
+void XpdfViewer::cmdScrollRight(GString *args[], int nArgs,
+ QInputEvent *event) {
+ int dx = scaleScroll(atoi(args[0]->getCString()));
+ currentTab->pdf->scrollBy(dx, 0);
+}
+
+void XpdfViewer::cmdScrollToBottomEdge(GString *args[], int nArgs,
+ QInputEvent *event) {
+ currentTab->pdf->getCore()->scrollToBottomEdge();
+}
+
+void XpdfViewer::cmdScrollToBottomRight(GString *args[], int nArgs,
+ QInputEvent *event) {
+ currentTab->pdf->getCore()->scrollToBottomRight();
+}
+
+void XpdfViewer::cmdScrollToLeftEdge(GString *args[], int nArgs,
+ QInputEvent *event) {
+ currentTab->pdf->getCore()->scrollToLeftEdge();
+}
+
+void XpdfViewer::cmdScrollToRightEdge(GString *args[], int nArgs,
+ QInputEvent *event) {
+ currentTab->pdf->getCore()->scrollToRightEdge();
+}
+
+void XpdfViewer::cmdScrollToTopEdge(GString *args[], int nArgs,
+ QInputEvent *event) {
+ currentTab->pdf->getCore()->scrollToTopEdge();
+}
+
+void XpdfViewer::cmdScrollToTopLeft(GString *args[], int nArgs,
+ QInputEvent *event) {
+ currentTab->pdf->getCore()->scrollToTopLeft();
+}
+
+void XpdfViewer::cmdScrollUp(GString *args[], int nArgs,
+ QInputEvent *event) {
+ int dy = scaleScroll(atoi(args[0]->getCString()));
+ currentTab->pdf->scrollBy(0, -dy);
+}
+
+void XpdfViewer::cmdScrollUpPrevPage(GString *args[], int nArgs,
+ QInputEvent *event) {
+ int dy = scaleScroll(atoi(args[0]->getCString()));
+ currentTab->pdf->getCore()->scrollUpPrevPage(dy);
+}
+
+void XpdfViewer::cmdSelectLine(GString *args[], int nArgs, QInputEvent *event) {
+ currentTab->pdf->getCore()->selectLine(mouseX(event), mouseY(event));
+}
+
+void XpdfViewer::cmdSelectWord(GString *args[], int nArgs, QInputEvent *event) {
+ currentTab->pdf->getCore()->selectWord(mouseX(event), mouseY(event));
+}
+
+void XpdfViewer::cmdSetSelection(GString *args[], int nArgs,
+ QInputEvent *event) {
+ currentTab->pdf->setCurrentSelection(atoi(args[0]->getCString()),
+ atof(args[1]->getCString()),
+ atof(args[2]->getCString()),
+ atof(args[3]->getCString()),
+ atof(args[4]->getCString()));
+}
+
+void XpdfViewer::cmdShowAttachmentsPane(GString *args[], int nArgs,
+ QInputEvent *event) {
+ infoComboBox->setCurrentIndex(2);
+}
+
+void XpdfViewer::cmdShowDocumentInfo(GString *args[], int nArgs,
+ QInputEvent *event) {
+ if (!currentTab->pdf->hasOpenDocument()) {
+ return;
+ }
+ updateDocumentInfoDialog(currentTab->pdf);
+ documentInfoDialog->show();
+ documentInfoDialog->raise();
+}
+
+void XpdfViewer::cmdShowKeyBindings(GString *args[], int nArgs,
+ QInputEvent *event) {
+ if (!keyBindingsDialog) {
+ createKeyBindingsDialog();
+ }
+ keyBindingsDialog->show();
+ keyBindingsDialog->raise();
+}
+
+void XpdfViewer::cmdShowLayersPane(GString *args[], int nArgs,
+ QInputEvent *event) {
+ infoComboBox->setCurrentIndex(1);
+}
+
+void XpdfViewer::cmdShowMenuBar(GString *args[], int nArgs,
+ QInputEvent *event) {
+ mainMenu->show();
+}
+
+void XpdfViewer::cmdShowOutlinePane(GString *args[], int nArgs,
+ QInputEvent *event) {
+ infoComboBox->setCurrentIndex(0);
+}
+
+void XpdfViewer::cmdShowToolbar(GString *args[], int nArgs,
+ QInputEvent *event) {
+ toolBar->show();
+ toggleToolbarMenuItem->setChecked(true);
+}
+
+void XpdfViewer::cmdShrinkSidebar(GString *args[], int nArgs,
+ QInputEvent *event) {
+ QList<int> sizes = sidebarSplitter->sizes();
+ if (sizes[0] == 0) {
+ return;
+ }
+ int nPixels = atoi(args[0]->getCString());
+ if (sizes[0] - nPixels
+ < sidebarSplitter->widget(0)->minimumSizeHint().width()) {
+ cmdCloseSidebar(args, nArgs, event);
+ return;
+ }
+ sizes[0] -= nPixels;
+ sizes[1] += nPixels;
+ sidebarSplitter->setSizes(sizes);
+}
+
+void XpdfViewer::cmdSideBySideContinuousMode(GString *args[], int nArgs,
+ QInputEvent *event) {
+ currentTab->pdf->setDisplayMode(XpdfWidget::pdfDisplaySideBySideContinuous);
+}
+
+void XpdfViewer::cmdSideBySideSingleMode(GString *args[], int nArgs,
+ QInputEvent *event) {
+ currentTab->pdf->setDisplayMode(XpdfWidget::pdfDisplaySideBySideSingle);
+}
+
+void XpdfViewer::cmdSinglePageMode(GString *args[], int nArgs,
+ QInputEvent *event) {
+ currentTab->pdf->setDisplayMode(XpdfWidget::pdfDisplaySingle);
+ updateModeInfo();
+}
+
+void XpdfViewer::cmdStartExtendedSelection(GString *args[], int nArgs,
+ QInputEvent *event) {
+ currentTab->pdf->getCore()->startSelection(mouseX(event), mouseY(event),
+ gTrue);
+}
+
+void XpdfViewer::cmdStartPan(GString *args[], int nArgs, QInputEvent *event) {
+ currentTab->pdf->getCore()->startPan(mouseX(event), mouseY(event));
+}
+
+void XpdfViewer::cmdStartSelection(GString *args[], int nArgs,
+ QInputEvent *event) {
+ currentTab->pdf->getCore()->startSelection(mouseX(event), mouseY(event),
+ gFalse);
+}
+
+void XpdfViewer::cmdToggleContinuousMode(GString *args[], int nArgs,
+ QInputEvent *event) {
+ XpdfWidget::DisplayMode mode = currentTab->pdf->getDisplayMode();
+ if (mode == XpdfWidget::pdfDisplaySingle) {
+ currentTab->pdf->setDisplayMode(XpdfWidget::pdfDisplayContinuous);
+ } else {
+ currentTab->pdf->setDisplayMode(XpdfWidget::pdfDisplaySingle);
+ }
+ updateModeInfo();
+}
+
+void XpdfViewer::cmdToggleFullScreenMode(GString *args[], int nArgs,
+ QInputEvent *event) {
+ if (windowState() & Qt::WindowFullScreen) {
+ exitFullScreenMode();
+ } else {
+ enterFullScreenMode();
+ }
+}
+
+void XpdfViewer::cmdToggleMenuBar(GString *args[], int nArgs,
+ QInputEvent *event) {
+ if (mainMenu->isVisible()) {
+ cmdHideMenuBar(args, nArgs, event);
+ } else {
+ cmdShowMenuBar(args, nArgs, event);
+ }
+}
+
+void XpdfViewer::cmdToggleSelectMode(GString *args[], int nArgs,
+ QInputEvent *event) {
+ if (currentTab->pdf->isBlockSelectMode()) {
+ currentTab->pdf->setLinearSelectMode();
+ } else {
+ currentTab->pdf->setBlockSelectMode();
+ }
+ updateSelectModeInfo();
+}
+
+void XpdfViewer::cmdToggleSidebar(GString *args[], int nArgs,
+ QInputEvent *event) {
+ QList<int> sizes = sidebarSplitter->sizes();
+ if (sizes[0] == 0) {
+ cmdOpenSidebar(args, nArgs, event);
+ } else {
+ cmdCloseSidebar(args, nArgs, event);
+ }
+}
+
+void XpdfViewer::cmdToggleSidebarMoveResizeWin(GString *args[], int nArgs,
+ QInputEvent *event) {
+ QList<int> sizes = sidebarSplitter->sizes();
+ if (sizes[0] == 0) {
+ cmdOpenSidebarMoveResizeWin(args, nArgs, event);
+ } else {
+ cmdCloseSidebarMoveResizeWin(args, nArgs, event);
+ }
+}
+
+void XpdfViewer::cmdToggleSidebarResizeWin(GString *args[], int nArgs,
+ QInputEvent *event) {
+ QList<int> sizes = sidebarSplitter->sizes();
+ if (sizes[0] == 0) {
+ cmdOpenSidebarResizeWin(args, nArgs, event);
+ } else {
+ cmdCloseSidebarResizeWin(args, nArgs, event);
+ }
+}
+
+void XpdfViewer::cmdToggleToolbar(GString *args[], int nArgs,
+ QInputEvent *event) {
+ if (toolBar->isVisible()) {
+ cmdHideToolbar(args, nArgs, event);
+ } else {
+ cmdShowToolbar(args, nArgs, event);
+ }
+}
+
+void XpdfViewer::cmdViewPageLabels(GString *args[], int nArgs,
+ QInputEvent *event) {
+ viewPageLabelsMenuItem->setChecked(true);
+ updatePageNumberOrLabel(currentTab->pdf->getMidPage());
+}
+
+void XpdfViewer::cmdViewPageNumbers(GString *args[], int nArgs,
+ QInputEvent *event) {
+ viewPageLabelsMenuItem->setChecked(false);
+ updatePageNumberOrLabel(currentTab->pdf->getMidPage());
+}
+
+void XpdfViewer::cmdWindowMode(GString *args[], int nArgs,
+ QInputEvent *event) {
+ if (windowState() & Qt::WindowFullScreen) {
+ exitFullScreenMode();
+ }
+}
+
+void XpdfViewer::cmdZoomFitPage(GString *args[], int nArgs,
+ QInputEvent *event) {
+ currentTab->pdf->zoomCentered(XpdfWidget::zoomToPage);
+ updateZoomInfo();
+}
+
+void XpdfViewer::cmdZoomFitWidth(GString *args[], int nArgs,
+ QInputEvent *event) {
+ currentTab->pdf->zoomCentered(XpdfWidget::zoomToWidth);
+ updateZoomInfo();
+}
+
+void XpdfViewer::cmdZoomIn(GString *args[], int nArgs, QInputEvent *event) {
+ double z;
+ int i;
+
+ z = currentTab->pdf->getZoomPercent(currentTab->pdf->getMidPage());
+ for (i = 0; i < zoomComboBox->count(); ++i) {
+ if (zoomComboBoxVals[i] > z) {
+ currentTab->pdf->zoomCentered(zoomComboBoxVals[i]);
+ zoomComboBox->setCurrentIndex(i);
+ updateZoomInfo();
+ break;
+ }
+ }
+}
+
+void XpdfViewer::cmdZoomOut(GString *args[], int nArgs, QInputEvent *event) {
+ double z;
+ int i;
+
+ z = currentTab->pdf->getZoomPercent(currentTab->pdf->getMidPage());
+ for (i = zoomComboBox->count() - 1; i >= 0; --i) {
+ if (zoomComboBoxVals[i] < z) {
+ currentTab->pdf->zoomCentered(zoomComboBoxVals[i]);
+ zoomComboBox->setCurrentIndex(i);
+ updateZoomInfo();
+ break;
+ }
+ }
+}
+
+void XpdfViewer::cmdZoomPercent(GString *args[], int nArgs,
+ QInputEvent *event) {
+ QString zoomStr;
+ int z;
+
+ z = (int)floor(atof(args[0]->getCString()) + 0.5);
+ if (z > maxZoom) {
+ z = maxZoom;
+ }
+ currentTab->pdf->zoomCentered(z);
+ updateZoomInfo();
+}
+
+void XpdfViewer::cmdZoomToSelection(GString *args[], int nArgs,
+ QInputEvent *event) {
+ double x0, y0, x1, y1, rx, ry, z, w, h, t;
+ int pg, xx0, yy0, xx1, yy1;
+
+ if (currentTab->pdf->getCurrentSelection(&pg, &x0, &y0, &x1, &y1)) {
+ z = currentTab->pdf->getZoomPercent(pg);
+ currentTab->pdf->getCore()->cvtUserToDev(pg, x0, y0, &xx0, &yy0);
+ currentTab->pdf->getCore()->cvtUserToDev(pg, x1, y1, &xx1, &yy1);
+ rx = (double)currentTab->pdf->getCore()->getWindowWidth()
+ / (double)abs(xx1 - xx0);
+ ry = (double)currentTab->pdf->getCore()->getWindowHeight()
+ / (double)abs(yy1 - yy0);
+ z *= rx < ry ? rx : ry;
+ if (z > maxZoom) {
+ w = 0.5 * (z / maxZoom) * (x1 - x0);
+ h = 0.5 * (z / maxZoom) * (y1 - y0);
+ t = 0.5 * (x0 + x1);
+ x0 = t - w;
+ x1 = t + w;
+ t = 0.5 * (y0 + y1);
+ y0 = t - h;
+ y1 = t + h;
+ }
+ currentTab->pdf->zoomToRect(pg, x0, y0, x1, y1);
+ updateZoomInfo();
+ }
+}
+
+int XpdfViewer::scaleScroll(int delta) {
+ int scaledDelta;
+
+ scaledDelta = (delta * currentTab->pdf->getCore()->getDisplayDpi()) / 96;
+ if (delta >= 0) {
+ if (scaledDelta < delta) {
+ scaledDelta = delta;
+ }
+ } else {
+ if (scaledDelta > delta) {
+ scaledDelta = delta;
+ }
+ }
+ return scaledDelta;
+}
+
+void XpdfViewer::followLink(QInputEvent *event, GBool onlyIfNoSel,
+ GBool newTab, GBool newWindow) {
+ int pg, targetPage;
+ double x, y;
+ QString targetFileName, targetDest;
+
+ if (onlyIfNoSel && currentTab->pdf->hasSelection()) {
+ return;
+ }
+ if (!currentTab->pdf->convertWindowToPDFCoords(mouseX(event), mouseY(event),
+ &pg, &x, &y)) {
+ return;
+ }
+ if ((newTab || newWindow) &&
+ currentTab->pdf->getLinkTarget(pg, x, y, targetFileName,
+ targetPage, targetDest)) {
+ if (newTab) {
+ openInNewTab(targetFileName, targetPage, targetDest, 0, "", gTrue);
+ } else {
+ app->openInNewWindow(targetFileName, targetPage, targetDest, 0, "");
+ }
+ } else {
+ if (!currentTab->pdf->gotoLinkAt(pg, x, y)) {
+ QMessageBox::warning(NULL,
+ "Xpdf Error",
+ "Couldn't follow link: '"
+ + currentTab->pdf->getLinkInfo(pg, x, y)
+ + "'");
+ }
+ }
+}
+
+//------------------------------------------------------------------------
+// GUI events
+//------------------------------------------------------------------------
+
+void XpdfViewer::pdfResized() {
+ updateZoomInfo();
+}
+
+void XpdfViewer::pdfPaintDone(bool finished) {
+ if (finished) {
+ statusIndicatorStop();
+ } else {
+ statusIndicatorStart();
+ }
+}
+
+void XpdfViewer::preLoad() {
+ ((OutlineModel *)currentTab->outlineTree->model())->beginOpenNewDoc();
+ ((LayerModel *)currentTab->layerTree->model())->beginOpenNewDoc();
+}
+
+void XpdfViewer::postLoad() {
+ ((LayerModel *)currentTab->layerTree->model())->endOpenNewDoc();
+ ((OutlineModel *)currentTab->outlineTree->model())->endOpenNewDoc();
+ setOutlineOpenItems(QModelIndex());
+ fillAttachmentList();
+ updateDocInfo();
+}
+
+void XpdfViewer::keyPress(QKeyEvent *e) {
+ GList *cmds;
+ int mods, qtKey, keyCode, i;
+
+ mods = getModifiers(e->modifiers());
+
+ qtKey = e->key();
+ if (qtKey >= 0x20 && qtKey <= 0xfe) {
+ keyCode = qtKey;
+ if (keyCode >= 'A' && keyCode <= 'Z' && !(mods & xpdfKeyModShift)) {
+ keyCode += 'a' - 'A';
+ }
+ } else if (qtKey == Qt::Key_Tab || qtKey == Qt::Key_Backtab) {
+ // backtab = shift-tab
+ keyCode = xpdfKeyCodeTab;
+ } else if (qtKey == Qt::Key_Return) {
+ keyCode = xpdfKeyCodeReturn;
+ } else if (qtKey == Qt::Key_Enter) {
+ keyCode = xpdfKeyCodeEnter;
+ } else if (qtKey == Qt::Key_Backspace) {
+ keyCode = xpdfKeyCodeBackspace;
+ } else if (qtKey == Qt::Key_Insert) {
+ keyCode = xpdfKeyCodeInsert;
+ } else if (qtKey == Qt::Key_Delete) {
+ keyCode = xpdfKeyCodeDelete;
+ } else if (qtKey == Qt::Key_Home) {
+ keyCode = xpdfKeyCodeHome;
+ } else if (qtKey == Qt::Key_End) {
+ keyCode = xpdfKeyCodeEnd;
+ } else if (qtKey == Qt::Key_PageUp) {
+ keyCode = xpdfKeyCodePgUp;
+ } else if (qtKey == Qt::Key_PageDown) {
+ keyCode = xpdfKeyCodePgDn;
+ } else if (qtKey == Qt::Key_Left) {
+ keyCode = xpdfKeyCodeLeft;
+ } else if (qtKey == Qt::Key_Right) {
+ keyCode = xpdfKeyCodeRight;
+ } else if (qtKey == Qt::Key_Up) {
+ keyCode = xpdfKeyCodeUp;
+ } else if (qtKey == Qt::Key_Down) {
+ keyCode = xpdfKeyCodeDown;
+ } else if (qtKey == Qt::Key_Escape) {
+ keyCode = xpdfKeyCodeEsc;
+ } else if (qtKey >= Qt::Key_F1 && qtKey <= Qt::Key_F35) {
+ keyCode = xpdfKeyCodeF1 + (qtKey - Qt::Key_F1);
+ } else {
+ return;
+ }
+
+ if ((cmds = globalParams->getKeyBinding(keyCode, mods,
+ getContext(e->modifiers())))) {
+ for (i = 0; i < cmds->getLength(); ++i) {
+ execCmd(((GString *)cmds->get(i))->getCString(), e);
+ }
+ deleteGList(cmds, GString);
+ }
+}
+
+void XpdfViewer::mousePress(QMouseEvent *e) {
+ GList *cmds;
+ int btn, keyCode, i;
+
+ if (!(btn = getMouseButton(e->button()))) {
+ return;
+ }
+ keyCode = xpdfKeyCodeMousePress1 + (btn - 1);
+ if ((cmds = globalParams->getKeyBinding(keyCode,
+ getModifiers(e->modifiers()),
+ getContext(e->modifiers())))) {
+ for (i = 0; i < cmds->getLength(); ++i) {
+ execCmd(((GString *)cmds->get(i))->getCString(), e);
+ }
+ deleteGList(cmds, GString);
+ }
+}
+
+void XpdfViewer::mouseRelease(QMouseEvent *e) {
+ GList *cmds;
+ int btn, keyCode, i;
+
+ if (!(btn = getMouseButton(e->button()))) {
+ return;
+ }
+ keyCode = xpdfKeyCodeMouseRelease1 + (btn - 1);
+ if ((cmds = globalParams->getKeyBinding(keyCode,
+ getModifiers(e->modifiers()),
+ getContext(e->modifiers())))) {
+ for (i = 0; i < cmds->getLength(); ++i) {
+ execCmd(((GString *)cmds->get(i))->getCString(), e);
+ }
+ deleteGList(cmds, GString);
+ }
+}
+
+void XpdfViewer::mouseClick(QMouseEvent *e) {
+ GList *cmds;
+ int btn, keyCode, i;
+
+ if (!(btn = getMouseButton(e->button()))) {
+ return;
+ }
+ keyCode = xpdfKeyCodeMouseClick1 + (btn - 1);
+ if ((cmds = globalParams->getKeyBinding(keyCode,
+ getModifiers(e->modifiers()),
+ getContext(e->modifiers())))) {
+ for (i = 0; i < cmds->getLength(); ++i) {
+ execCmd(((GString *)cmds->get(i))->getCString(), e);
+ }
+ deleteGList(cmds, GString);
+ }
+}
+
+void XpdfViewer::mouseDoubleClick(QMouseEvent *e) {
+ GList *cmds;
+ int btn, keyCode, i;
+
+ if (!(btn = getMouseButton(e->button()))) {
+ return;
+ }
+ keyCode = xpdfKeyCodeMouseDoubleClick1 + (btn - 1);
+ if ((cmds = globalParams->getKeyBinding(keyCode,
+ getModifiers(e->modifiers()),
+ getContext(e->modifiers())))) {
+ for (i = 0; i < cmds->getLength(); ++i) {
+ execCmd(((GString *)cmds->get(i))->getCString(), e);
+ }
+ deleteGList(cmds, GString);
+ }
+}
+
+void XpdfViewer::mouseTripleClick(QMouseEvent *e) {
+ GList *cmds;
+ int btn, keyCode, i;
+
+ if (!(btn = getMouseButton(e->button()))) {
+ return;
+ }
+ keyCode = xpdfKeyCodeMouseTripleClick1 + (btn - 1);
+ if ((cmds = globalParams->getKeyBinding(keyCode,
+ getModifiers(e->modifiers()),
+ getContext(e->modifiers())))) {
+ for (i = 0; i < cmds->getLength(); ++i) {
+ execCmd(((GString *)cmds->get(i))->getCString(), e);
+ }
+ deleteGList(cmds, GString);
+ }
+}
+
+void XpdfViewer::mouseWheel(QWheelEvent *e) {
+ GList *cmds;
+ int keyCode, i;
+
+ // for historical reasons xpdf uses X11 button numbering for mouse
+ // wheel events
+ QPoint delta = e->angleDelta();
+ if (delta.y() > 0) {
+ keyCode = xpdfKeyCodeMousePress4;
+ } else if (delta.y() < 0) {
+ keyCode = xpdfKeyCodeMousePress5;
+ } else if (delta.x() > 0) {
+ keyCode = xpdfKeyCodeMousePress6;
+ } else if (delta.x() < 0) {
+ keyCode = xpdfKeyCodeMousePress7;
+ }
+ if ((cmds = globalParams->getKeyBinding(keyCode,
+ getModifiers(e->modifiers()),
+ getContext(e->modifiers())))) {
+ for (i = 0; i < cmds->getLength(); ++i) {
+ execCmd(((GString *)cmds->get(i))->getCString(), e);
+ }
+ deleteGList(cmds, GString);
+ }
+}
+
+void XpdfViewer::mouseMove(QMouseEvent *e) {
+ int pg, xx;
+ double x, y;
+ QString info;
+
+ currentTab->pdf->convertWindowToPDFCoords(mouseX(e), mouseY(e), &pg, &x, &y);
+ info = currentTab->pdf->getLinkInfo(pg, x, y);
+ if (info == linkTargetInfo) {
+ // QtPDFCore sets the cursor in linear text selection mode
+ if (!linkTargetInfo.isEmpty()) {
+ currentTab->pdf->setCursor(Qt::PointingHandCursor);
+ }
+ return;
+ }
+ linkTargetInfo = info;
+ if (linkTargetInfo.isEmpty()) {
+ currentTab->pdf->unsetCursor();
+ linkTargetBar->hide();
+ } else {
+ currentTab->pdf->setCursor(Qt::PointingHandCursor);
+ linkTargetBar->setText(linkTargetInfo);
+ linkTargetBar->resize(linkTargetBar->sizeHint());
+ if (mouseX(e) > viewerStack->width() / 2) {
+ xx = viewerStack->x();
+ } else {
+ xx = width() - linkTargetBar->width();
+ if (xx < viewerStack->x()) {
+ xx = viewerStack->x();
+ }
+ }
+ linkTargetBar->move(xx, height() - linkTargetBar->height());
+ linkTargetBar->show();
+ }
+}
+
+int XpdfViewer::getModifiers(Qt::KeyboardModifiers qtMods) {
+ int mods;
+
+ mods = 0;
+ if (qtMods & Qt::ShiftModifier) {
+ mods |= xpdfKeyModShift;
+ }
+ if (qtMods & Qt::ControlModifier) {
+ mods |= xpdfKeyModCtrl;
+ }
+ if (qtMods & Qt::AltModifier) {
+ mods |= xpdfKeyModAlt;
+ }
+ return mods;
+}
+
+int XpdfViewer::getContext(Qt::KeyboardModifiers qtMods) {
+ XpdfWidget::DisplayMode mode;
+ GBool contin;
+ int context;
+
+ mode = currentTab->pdf->getDisplayMode();
+ contin = mode == XpdfWidget::pdfDisplayContinuous ||
+ mode == XpdfWidget::pdfDisplaySideBySideContinuous ||
+ mode == XpdfWidget::pdfDisplayHorizontalContinuous;
+ context = ((windowState() & Qt::WindowFullScreen) ? xpdfKeyContextFullScreen
+ : xpdfKeyContextWindow) |
+ (contin ? xpdfKeyContextContinuous
+ : xpdfKeyContextSinglePage) |
+ (currentTab->pdf->mouseOverLink() ? xpdfKeyContextOverLink
+ : xpdfKeyContextOffLink) |
+ xpdfKeyContextScrLockOff;
+ return context;
+}
+
+int XpdfViewer::getMouseButton(Qt::MouseButton qtBtn) {
+ if (qtBtn & Qt::LeftButton) {
+ return 1;
+ }
+ if (qtBtn & Qt::MiddleButton) {
+ return 2;
+ }
+ if (qtBtn & Qt::RightButton) {
+ return 3;
+ }
+ return 0;
+}
+
+// Grab any keyboard events that filter down to the window, and feed
+// them to the main key processing function.
+void XpdfViewer::keyPressEvent(QKeyEvent *e) {
+ keyPress(e);
+}
+
+void XpdfViewer::dragEnterEvent(QDragEnterEvent *e) {
+ if (e->mimeData()->hasUrls() &&
+ e->mimeData()->urls().front().isLocalFile()) {
+ e->acceptProposedAction();
+ }
+}
+
+void XpdfViewer::dropEvent(QDropEvent *e) {
+ if (e->mimeData()->hasUrls()) {
+ QUrl url = e->mimeData()->urls().front();
+ if (url.isLocalFile()) {
+ openInNewTab(url.toLocalFile(), -1, "", 0, "", gTrue);
+ }
+ }
+}
+
+bool XpdfViewer::eventFilter(QObject *watched, QEvent *event) {
+ // if the user clicks in the find edit box, clear the find error
+ // indicator (if any)
+ if (watched == findEdit && event->type() == QEvent::MouseButtonPress) {
+ clearFindError();
+ }
+ return false;
+}
+
+void XpdfViewer::pageChange(int pg) {
+ updatePageNumberOrLabel(pg);
+ updateZoomInfo();
+ updateOutline(pg);
+}
+
+void XpdfViewer::sidebarSplitterMoved(int pos, int index) {
+ toggleSidebarMenuItem->setChecked(pos > 0);
+}
+
+#if XPDFWIDGET_PRINTING
+void XpdfViewer::printStatus(int nextPage, int firstPage, int lastPage) {
+ if (!printStatusDialog) {
+ printStatusDialog = new QProgressDialog("Printing...", "Cancel",
+ firstPage, lastPage + 1, this);
+ printStatusDialog->setWindowModality(Qt::WindowModal);
+ printStatusDialog->setMinimumDuration(0);
+ printStatusDialog->setAutoClose(false);
+ printStatusDialog->setAutoReset(false);
+ connect(printStatusDialog, SIGNAL(canceled()), this, SLOT(cancelPrint()));
+ printStatusDialog->move(
+ pos().x() + (width() - printStatusDialog->width()) / 2,
+ pos().y() + (height() - printStatusDialog->height()) / 2);
+ printStatusDialog->show();
+ }
+ printStatusDialog->setValue(nextPage);
+ if (nextPage > lastPage) {
+ printStatusDialog->cancel();
+ delete printStatusDialog;
+ printStatusDialog = NULL;
+ }
+ QApplication::processEvents();
+}
+
+void XpdfViewer::cancelPrint() {
+ currentTab->pdf->cancelPrint();
+}
+#endif
+
+//------------------------------------------------------------------------
+// menu/toolbar actions
+//------------------------------------------------------------------------
+
+void XpdfViewer::openMenuAction() {
+ execCmd("open", NULL);
+}
+
+void XpdfViewer::openInNewWinMenuAction() {
+ execCmd("openIn(win)", NULL);
+}
+
+void XpdfViewer::reloadMenuAction() {
+ execCmd("reload", NULL);
+}
+
+void XpdfViewer::saveAsMenuAction() {
+ execCmd("saveAs", NULL);
+}
+
+void XpdfViewer::saveImageMenuAction() {
+ execCmd("saveImage", NULL);
+}
+
+#if XPDFWIDGET_PRINTING
+void XpdfViewer::printMenuAction() {
+ execCmd("print", NULL);
+}
+#endif
+
+void XpdfViewer::quitMenuAction() {
+ execCmd("quit", NULL);
+}
+
+void XpdfViewer::copyMenuAction() {
+ execCmd("copy", NULL);
+}
+
+void XpdfViewer::singlePageModeMenuAction() {
+ execCmd("singlePageMode", NULL);
+}
+
+void XpdfViewer::continuousModeMenuAction() {
+ execCmd("continuousMode", NULL);
+}
+
+void XpdfViewer::sideBySideSingleModeMenuAction() {
+ execCmd("sideBySideSingleMode", NULL);
+}
+
+void XpdfViewer::sideBySideContinuousModeMenuAction() {
+ execCmd("sideBySideContinuousMode", NULL);
+}
+
+void XpdfViewer::horizontalContinuousModeMenuAction() {
+ execCmd("horizontalContinuousMode", NULL);
+}
+
+void XpdfViewer::fullScreenMenuAction(bool checked) {
+ execCmd(checked ? "fullScreenMode" : "windowMode", NULL);
+}
+
+void XpdfViewer::rotateClockwiseMenuAction() {
+ execCmd("rotateCW", NULL);
+}
+
+void XpdfViewer::rotateCounterclockwiseMenuAction() {
+ execCmd("rotateCCW", NULL);
+}
+
+void XpdfViewer::zoomToSelectionMenuAction() {
+ execCmd("zoomToSelection", NULL);
+}
+
+void XpdfViewer::toggleToolbarMenuAction(bool checked) {
+ execCmd(checked ? "showToolbar" : "hideToolbar", NULL);
+}
+
+void XpdfViewer::toggleSidebarMenuAction(bool checked) {
+ execCmd(checked ? "openSidebar" : "closeSidebar", NULL);
+}
+
+void XpdfViewer::viewPageLabelsMenuAction(bool checked) {
+ execCmd(checked ? "viewPageLabels" : "viewPageNumbers", NULL);
+}
+
+void XpdfViewer::documentInfoMenuAction() {
+ execCmd("showDocumentInfo", NULL);
+}
+
+
+
+void XpdfViewer::newTabMenuAction() {
+ execCmd("newTab", NULL);
+}
+
+void XpdfViewer::newWindowMenuAction() {
+ execCmd("newWindow", NULL);
+}
+
+void XpdfViewer::closeTabMenuAction() {
+ execCmd("closeTabOrQuit", NULL);
+}
+
+void XpdfViewer::closeWindowMenuAction() {
+ execCmd("closeWindowOrQuit", NULL);
+}
+
+void XpdfViewer::openErrorWindowMenuAction() {
+ execCmd("openErrorWindow", NULL);
+}
+
+void XpdfViewer::helpMenuAction() {
+ execCmd("help", NULL);
+}
+
+void XpdfViewer::keyBindingsMenuAction() {
+ execCmd("showKeyBindings", NULL);
+}
+
+void XpdfViewer::aboutMenuAction() {
+ execCmd("about", NULL);
+}
+
+void XpdfViewer::popupMenuAction(int idx) {
+ PopupMenuCmd *cmd;
+ int i;
+
+ cmd = globalParams->getPopupMenuCmd(idx);
+ for (i = 0; i < cmd->cmds->getLength(); ++i) {
+ execCmd(((GString *)cmd->cmds->get(i))->getCString(), NULL);
+ }
+}
+
+void XpdfViewer::toggleSidebarButtonPressed() {
+ execCmd("toggleSidebar", NULL);
+}
+
+void XpdfViewer::pageNumberChanged() {
+ GString *cmd;
+ int pg;
+
+ if (viewPageLabelsMenuItem->isChecked() &&
+ currentTab->pdf->hasPageLabels()) {
+ pg = currentTab->pdf->getPageNumFromPageLabel(pageNumber->text());
+ if (pg <= 0) {
+ return;
+ }
+ } else {
+ pg = pageNumber->text().toInt();
+ }
+ cmd = GString::format("gotoPage({0:d})", pg);
+ execCmd(cmd->getCString(), NULL);
+ delete cmd;
+ // after moving to a new page, focus goes to the XpdfWidget
+ currentTab->pdf->setFocus(Qt::OtherFocusReason);
+}
+
+void XpdfViewer::backButtonPressed() {
+ execCmd("goBackward", NULL);
+}
+
+void XpdfViewer::forwardButtonPressed() {
+ execCmd("goForward", NULL);
+}
+
+void XpdfViewer::zoomOutButtonPressed() {
+ execCmd("zoomOut", NULL);
+}
+
+void XpdfViewer::zoomInButtonPressed() {
+ execCmd("zoomIn", NULL);
+}
+
+void XpdfViewer::zoomIndexChanged(int idx) {
+ QString zoomText = zoomComboBox->itemText(idx);
+ QString z;
+ if (zoomText.endsWith("%")) {
+ z = zoomText.left(zoomText.size() - 1);
+ } else {
+ z = zoomText;
+ }
+ GString *cmd = GString::format("zoomPercent({0:s})",
+ z.toLatin1().constData());
+ execCmd(cmd->getCString(), NULL);
+ delete cmd;
+}
+
+void XpdfViewer::zoomEditingFinished() {
+ QString z;
+ GString *cmd;
+
+ z = zoomComboBox->currentText();
+ if (z.endsWith("%")) {
+ z = z.left(z.size() - 1);
+ }
+ cmd = GString::format("zoomPercent({0:s})", z.toLatin1().constData());
+ execCmd(cmd->getCString(), NULL);
+ delete cmd;
+}
+
+void XpdfViewer::fitWidthButtonPressed() {
+ execCmd("zoomFitWidth", NULL);
+}
+
+void XpdfViewer::fitPageButtonPressed() {
+ execCmd("zoomFitPage", NULL);
+}
+
+void XpdfViewer::selectModeButtonPressed() {
+ execCmd("toggleSelectMode", NULL);
+}
+
+void XpdfViewer::statusIndicatorPressed() {
+ execCmd("openErrorWindow", NULL);
+}
+
+void XpdfViewer::findTextChanged() {
+ execCmd("findFirst", NULL);
+}
+
+void XpdfViewer::findNextButtonPressed() {
+ execCmd("findNext", NULL);
+}
+
+void XpdfViewer::findPrevButtonPressed() {
+ execCmd("findPrevious", NULL);
+}
+
+void XpdfViewer::newTabButtonPressed() {
+ execCmd("newTab", NULL);
+}
+
+void XpdfViewer::switchTab(QListWidgetItem *current,
+ QListWidgetItem *previous) {
+ XpdfTabInfo *tab;
+ int i;
+
+ for (i = 0; i < tabInfo->getLength(); ++i) {
+ tab = (XpdfTabInfo *)tabInfo->get(i);
+ if (tab->listItem == current) {
+ gotoTab(i);
+ return;
+ }
+ }
+}
+
+void XpdfViewer::tabsReordered(const QModelIndex &srcParent,
+ int srcStart, int srcEnd,
+ const QModelIndex &destParent,
+ int destRow) {
+ // these conditions should always be true, but check just in case
+ if (srcStart == srcEnd &&
+ srcStart >= 0 && srcStart < tabInfo->getLength() &&
+ destRow >= 0 && destRow <= tabInfo->getLength()) {
+ XpdfTabInfo *tab = (XpdfTabInfo *)tabInfo->del(srcStart);
+ int i = destRow;
+ if (i >= srcStart) {
+ --i;
+ }
+ tabInfo->insert(i, tab);
+ }
+}
+
+void XpdfViewer::infoComboBoxChanged(int idx) {
+ updateInfoPane();
+}
+
+void XpdfViewer::outlineItemClicked(const QModelIndex& idx) {
+ currentTab->pdf->gotoOutlineTarget((XpdfOutlineHandle)idx.internalPointer());
+ updateModeInfo();
+}
+
+void XpdfViewer::layerItemClicked(const QModelIndex& idx) {
+ if (idx.data(Qt::CheckStateRole) == Qt::Checked) {
+ currentTab->layerTree->model()->setData(idx, Qt::Unchecked,
+ Qt::CheckStateRole);
+ } else {
+ currentTab->layerTree->model()->setData(idx, Qt::Checked,
+ Qt::CheckStateRole);
+ }
+}
+
+void XpdfViewer::attachmentSaveClicked(int idx) {
+ QString fileName;
+
+ fileName = QFileDialog::getSaveFileName(this, "Save Attachment");
+ if (fileName.isEmpty()) {
+ return;
+ }
+ currentTab->pdf->saveEmbeddedFile(idx, fileName);
+}
+
+//------------------------------------------------------------------------
+// GUI setup
+//------------------------------------------------------------------------
+
+void XpdfViewer::createWindow() {
+ errorWindow = new XpdfErrorWindow(this, app->getErrorEventType());
+
+ setWindowIcon(QIcon(":/xpdf-icon"));
+
+ setAcceptDrops(true);
+
+ createMainMenu();
+
+ createXpdfPopupMenu();
+
+ createToolBar();
+ addToolBar(toolBar);
+ setUnifiedTitleAndToolBarOnMac(true);
+ if (globalParams->getInitialToolbarState()) {
+ toggleToolbarMenuItem->setChecked(true);
+ } else {
+ toolBar->hide();
+ toggleToolbarMenuItem->setChecked(false);
+ }
+
+ sidebarSplitter = new QSplitter(Qt::Horizontal);
+ setCentralWidget(sidebarSplitter);
+ connect(sidebarSplitter, SIGNAL(splitterMoved(int, int)),
+ this, SLOT(sidebarSplitterMoved(int, int)));
+
+ QSplitter *vSplitter = new QSplitter(Qt::Vertical);
+ sidebarSplitter->addWidget(vSplitter);
+
+ QWidget *tabPane = createTabPane();
+ vSplitter->addWidget(tabPane);
+
+ QWidget *infoPane = createInfoPane();
+ vSplitter->addWidget(infoPane);
+
+ QList<int> vSplitterSizes;
+ vSplitterSizes.append(200);
+ vSplitterSizes.append(600);
+ vSplitter->setSizes(vSplitterSizes);
+
+ viewerStack = new QStackedWidget();
+ sidebarSplitter->addWidget(viewerStack);
+
+ initialSidebarWidth = 0;
+ QList<int> sidebarSplitterSizes = sidebarSplitter->sizes();
+ if (globalParams->getInitialSidebarState()) {
+ toggleSidebarMenuItem->setChecked(true);
+ initialSidebarWidth = globalParams->getInitialSidebarWidth();
+ } else {
+ sidebarSplitterSizes[0] = 0;
+ sidebarSplitterSizes[1] = 1;
+ sidebarSplitter->setSizes(sidebarSplitterSizes);
+ toggleSidebarMenuItem->setChecked(false);
+ }
+ // note: this is just an arbitrary initial value for sidebarWidth;
+ // it will be updated by open/close/toggleSidebar
+ sidebarWidth = 200;
+
+ linkTargetBar = new QLabel(this);
+ linkTargetBar->setStyleSheet("padding:2px; background:#00ffff;");
+ linkTargetBar->setAttribute(Qt::WA_TransparentForMouseEvents, true);
+
+ findErrorTimer = new QTimer(this);
+ findErrorTimer->setSingleShot(true);
+ connect(findErrorTimer, SIGNAL(timeout()), this, SLOT(clearFindError()));
+
+ documentInfoDialog = NULL;
+ keyBindingsDialog = NULL;
+ aboutDialog = NULL;
+#if XPDFWIDGET_PRINTING
+ printStatusDialog = NULL;
+#endif
+
+ scaleFactor = 1;
+
+ tabInfo = new GList();
+ addTab();
+ updateModeInfo();
+ updateDocInfo();
+}
+
+void XpdfViewer::createToolBar() {
+ QString zoomVal;
+ int i;
+
+ toolBar = new QToolBar();
+ toolBar->setFloatable(false);
+ toolBar->setMovable(false);
+
+ //--- toolbar icon size
+ pageNumber = new QLineEdit();
+ toolBarFontSize = pageNumber->sizeHint().height();
+ toolBar->setIconSize(QSize(toolBarFontSize - 2, toolBarFontSize - 2));
+ //~ not sure why the magic "+6" is needed
+
+ //--- toggle sidebar button
+ addToolBarButton(QIcon(":/toggleSidebar-button"),
+ SLOT(toggleSidebarButtonPressed()), "show/hide sidebar");
+
+ //--- status indicator
+ QToolButton *indicatorBtn =
+ addToolBarButton(QIcon(":/indicator-icon0"),
+ SLOT(statusIndicatorPressed()),
+ "click to open error window");
+ indicatorIcons.append(QIcon(":/indicator-icon0"));
+ indicatorIcons.append(QIcon(":/indicator-icon1"));
+ indicatorIcons.append(QIcon(":/indicator-icon2"));
+ indicatorIcons.append(QIcon(":/indicator-icon3"));
+ indicatorIcons.append(QIcon(":/indicator-icon4"));
+ indicatorIcons.append(QIcon(":/indicator-icon5"));
+ indicatorIcons.append(QIcon(":/indicator-icon6"));
+ indicatorIcons.append(QIcon(":/indicator-icon7"));
+ indicatorErrIcons.append(QIcon(":/indicator-icon-err0"));
+ indicatorErrIcons.append(QIcon(":/indicator-icon-err1"));
+ indicatorErrIcons.append(QIcon(":/indicator-icon-err2"));
+ indicatorErrIcons.append(QIcon(":/indicator-icon-err3"));
+ indicatorErrIcons.append(QIcon(":/indicator-icon-err4"));
+ indicatorErrIcons.append(QIcon(":/indicator-icon-err5"));
+ indicatorErrIcons.append(QIcon(":/indicator-icon-err6"));
+ indicatorErrIcons.append(QIcon(":/indicator-icon-err7"));
+ indicatorAnimation = new PropertyListAnimation(indicatorBtn, "icon",
+ indicatorIcons);
+ indicatorAnimation->setDuration(1000);
+ indicatorAnimation->setLoopCount(-1);
+ indicatorAnimation->setStartValue(indicatorIcons[0]);
+ indicatorAnimation->setEndValue(indicatorIcons[7]);
+ indicatorAnimation->start();
+ indicatorAnimation->pause();
+
+ //--- selection mode toggle
+ selectModeBtn = addToolBarButton(QIcon(":/selectModeLinear-button"),
+ SLOT(selectModeButtonPressed()),
+ "toggle selection mode");
+
+ addToolBarSeparator();
+
+ //--- page number and page count
+ // note: the pageNumber widget was created earlier because we need
+ // to look at its font size
+#if QT_VERSION >= QT_VERSION_CHECK(5, 11, 0)
+ pageNumber->setFixedWidth(
+ pageNumber->fontMetrics().horizontalAdvance("00000") + 6);
+#else
+ pageNumber->setFixedWidth(pageNumber->fontMetrics().width("00000") + 6);
+#endif
+ pageNumber->setToolTip("current page number");
+ toolBar->addWidget(pageNumber);
+ addToolBarSpacing(2);
+ toolBar->addWidget(new QLabel("/"));
+ addToolBarSpacing(2);
+ connect(pageNumber, SIGNAL(returnPressed()), this, SLOT(pageNumberChanged()));
+ pageCount = new QLabel("");
+ pageCount->setToolTip("page count");
+ toolBar->addWidget(pageCount);
+ addToolBarSpacing(4);
+
+ //--- back / forward buttons
+ addToolBarButton(QIcon(":/back-button"),
+ SLOT(backButtonPressed()), "back to previous view");
+ addToolBarButton(QIcon(":/forward-button"),
+ SLOT(forwardButtonPressed()), "forward to next view");
+
+ addToolBarSeparator();
+
+ //--- zoom controls
+ addToolBarButton(QIcon(":/zoomOut-button"),
+ SLOT(zoomOutButtonPressed()), "zoom out");
+ addToolBarButton(QIcon(":/zoomIn-button"),
+ SLOT(zoomInButtonPressed()), "zoom in");
+ addToolBarSpacing(4);
+ zoomComboBox = new QComboBox();
+ zoomComboBox->setToolTip("change zoom level");
+ for (i = 0; i < nZoomComboBoxVals; ++i) {
+ zoomVal.setNum(zoomComboBoxVals[i]);
+ zoomVal.append('%');
+ zoomComboBox->addItem(zoomVal);
+ }
+ zoomComboBox->setEditable(true);
+ zoomComboBox->setInsertPolicy(QComboBox::NoInsert);
+ zoomComboBox->setValidator(new ZoomValidator(this));
+ connect(zoomComboBox, SIGNAL(currentIndexChanged(int)),
+ this, SLOT(zoomIndexChanged(int)));
+ // this could use the editingFinished signal, but that's emitted
+ // every time the popup is opened and closed, which causes the zoom
+ // level to be reset
+ connect(zoomComboBox->lineEdit(), SIGNAL(returnPressed()),
+ this, SLOT(zoomEditingFinished()));
+ toolBar->addWidget(zoomComboBox);
+ addToolBarSpacing(4);
+ fitWidthBtn = addToolBarButton(QIcon(":/fitWidth-button"),
+ SLOT(fitWidthButtonPressed()),
+ "fit page width to window");
+ fitPageBtn = addToolBarButton(QIcon(":/fitPage-button"),
+ SLOT(fitPageButtonPressed()),
+ "fit page to window");
+
+ addToolBarSeparator();
+
+ //--- find controls
+ addToolBarStretch();
+ findEdit = new QLineEdit();
+ findEdit->setPlaceholderText("find");
+#if QT_VERSION >= QT_VERSION_CHECK(5, 11, 0)
+ findEdit->setFixedWidth(20 * findEdit->fontMetrics().horizontalAdvance("0"));
+#else
+ findEdit->setFixedWidth(20 * findEdit->fontMetrics().width("0"));
+#endif
+ findEdit->installEventFilter(this);
+ toolBar->addWidget(findEdit);
+ connect(findEdit, SIGNAL(returnPressed()), this, SLOT(findTextChanged()));
+ connect(findEdit, SIGNAL(cursorPositionChanged(int, int)),
+ this, SLOT(clearFindError()));
+ connect(findEdit, SIGNAL(selectionChanged()), this, SLOT(clearFindError()));
+ connect(findEdit, SIGNAL(textChanged(const QString&)),
+ this, SLOT(clearFindError()));
+ addToolBarButton(QIcon(":/findNext-button"),
+ SLOT(findNextButtonPressed()), "find next occurrence");
+ addToolBarButton(QIcon(":/findPrevious-button"),
+ SLOT(findPrevButtonPressed()), "find previous occurrence");
+ QMenu *findSettingsMenu = new QMenu(this);
+ findCaseSensitiveAction = findSettingsMenu->addAction("case sensitive");
+ findCaseSensitiveAction->setCheckable(true);
+ findWholeWordsAction = findSettingsMenu->addAction("whole words");
+ findWholeWordsAction->setCheckable(true);
+ addToolBarMenuButton(QIcon(":/findSettings-button"),
+ "change find settings", findSettingsMenu);
+}
+
+QToolButton *XpdfViewer::addToolBarButton(const QIcon &icon,
+ const char *slot, const char *tip) {
+ QAction *action = new QAction(icon, "", this);
+ action->setToolTip(tip);
+ QToolButton *button = new QToolButton();
+ button->setDefaultAction(action);
+ button->setAutoRaise(true);
+ toolBar->addWidget(button);
+ connect(action, SIGNAL(triggered()), this, slot);
+ return button;
+}
+
+XpdfMenuButton *XpdfViewer::addToolBarMenuButton(const QIcon &icon,
+ const char *tip,
+ QMenu *menu) {
+ QAction *action = new QAction(icon, "", this);
+ action->setToolTip(tip);
+ XpdfMenuButton *button = new XpdfMenuButton(menu);
+ button->setDefaultAction(action);
+ button->setAutoRaise(true);
+ button->setToolTip(tip);
+ toolBar->addWidget(button);
+ return button;
+}
+
+void XpdfViewer::addToolBarSeparator() {
+ addToolBarSpacing(8);
+ toolBar->addSeparator();
+ addToolBarSpacing(8);
+}
+
+void XpdfViewer::addToolBarSpacing(int w) {
+ QWidget *space = new QWidget();
+ space->setFixedWidth((toolBarFontSize * w) / 20);
+ toolBar->addWidget(space);
+}
+
+void XpdfViewer::addToolBarStretch() {
+ QWidget *stretch = new QWidget();
+ stretch->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
+ toolBar->addWidget(stretch);
+}
+
+void XpdfViewer::createMainMenu() {
+ mainMenu = menuBar();
+
+ QMenu *fileSubmenu = mainMenu->addMenu("&File");
+ fileSubmenu->addAction("&Open...", this, SLOT(openMenuAction()));
+ fileSubmenu->addAction("Open in new window...",
+ this, SLOT(openInNewWinMenuAction()));
+ fileSubmenu->addAction("Reload", this, SLOT(reloadMenuAction()));
+ fileSubmenu->addAction("&Save as...", this, SLOT(saveAsMenuAction()));
+ fileSubmenu->addSeparator();
+ fileSubmenu->addAction("Save image...", this, SLOT(saveImageMenuAction()));
+#if XPDFWIDGET_PRINTING
+ fileSubmenu->addSeparator();
+ fileSubmenu->addAction("&Print...", this, SLOT(printMenuAction()));
+#endif
+ fileSubmenu->addSeparator();
+#ifdef _WIN32
+ fileSubmenu->addAction("E&xit", this, SLOT(quitMenuAction()));
+#else
+ fileSubmenu->addAction("&Quit", this, SLOT(quitMenuAction()));
+#endif
+
+ QMenu *editSubmenu = mainMenu->addMenu("&Edit");
+ editSubmenu->addAction("Copy", this, SLOT(copyMenuAction()));
+
+ QMenu *viewSubmenu = mainMenu->addMenu("&View");
+ toggleToolbarMenuItem =
+ viewSubmenu->addAction("Toolbar", this,
+ SLOT(toggleToolbarMenuAction(bool)));
+ toggleToolbarMenuItem->setCheckable(true);
+ toggleSidebarMenuItem =
+ viewSubmenu->addAction("Sidebar", this,
+ SLOT(toggleSidebarMenuAction(bool)));
+ toggleSidebarMenuItem->setCheckable(true);
+ viewPageLabelsMenuItem =
+ viewSubmenu->addAction("Page labels", this,
+ SLOT(viewPageLabelsMenuAction(bool)));
+ viewPageLabelsMenuItem->setCheckable(true);
+ viewSubmenu->addSeparator();
+ displayModeSubmenu = new QMenu(this);
+ QActionGroup *displayModeGroup = new QActionGroup(this);
+ QAction *action;
+ action = displayModeSubmenu->addAction(
+ "Single page",
+ this, SLOT(singlePageModeMenuAction()));
+ action->setCheckable(true);
+ displayModeGroup->addAction(action);
+ action = displayModeSubmenu->addAction(
+ "Continuous",
+ this, SLOT(continuousModeMenuAction()));
+ action->setCheckable(true);
+ displayModeGroup->addAction(action);
+ action = displayModeSubmenu->addAction(
+ "Side-by-side single",
+ this, SLOT(sideBySideSingleModeMenuAction()));
+ action->setCheckable(true);
+ displayModeGroup->addAction(action);
+ action = displayModeSubmenu->addAction(
+ "Side-by-side continuous",
+ this, SLOT(sideBySideContinuousModeMenuAction()));
+ action->setCheckable(true);
+ displayModeGroup->addAction(action);
+ action = displayModeSubmenu->addAction(
+ "Horizontal continuous",
+ this, SLOT(horizontalContinuousModeMenuAction()));
+ action->setCheckable(true);
+ displayModeGroup->addAction(action);
+ viewSubmenu->addAction("Display mode")->setMenu(displayModeSubmenu);
+ fullScreenMenuItem = viewSubmenu->addAction("Full screen", this,
+ SLOT(fullScreenMenuAction(bool)));
+ fullScreenMenuItem->setCheckable(true);
+ viewSubmenu->addSeparator();
+ viewSubmenu->addAction("Rotate clockwise",
+ this, SLOT(rotateClockwiseMenuAction()));
+ viewSubmenu->addAction("Rotate counterclockwise",
+ this, SLOT(rotateCounterclockwiseMenuAction()));
+ viewSubmenu->addSeparator();
+ viewSubmenu->addAction("Zoom to selection",
+ this, SLOT(zoomToSelectionMenuAction()));
+
+ QMenu *toolsSubmenu = mainMenu->addMenu("&Tools");
+ toolsSubmenu->addAction("Document info",
+ this, SLOT(documentInfoMenuAction()));
+
+ QMenu *windowSubmenu = mainMenu->addMenu("&Window");
+ windowSubmenu->addAction("New tab", this, SLOT(newTabMenuAction()));
+ windowSubmenu->addAction("New window", this, SLOT(newWindowMenuAction()));
+ windowSubmenu->addSeparator();
+ windowSubmenu->addAction("Close tab", this, SLOT(closeTabMenuAction()));
+ windowSubmenu->addAction("Close window", this, SLOT(closeWindowMenuAction()));
+ windowSubmenu->addSeparator();
+ windowSubmenu->addAction("Open error window...",
+ this, SLOT(openErrorWindowMenuAction()));
+
+ QMenu *helpSubmenu = mainMenu->addMenu("&Help");
+ helpSubmenu->addAction("Help...", this, SLOT(helpMenuAction()));
+ helpSubmenu->addAction("Key bindings...",
+ this, SLOT(keyBindingsMenuAction()));
+ helpSubmenu->addAction("About XpdfReader...", this, SLOT(aboutMenuAction()));
+}
+
+// This can't be named createPopupMenu because there's a QMainWindow
+// function of that name.
+void XpdfViewer::createXpdfPopupMenu() {
+ PopupMenuCmd *cmd;
+ QAction *action;
+ int n, i;
+
+ popupMenu = new QMenu(this);
+ popupMenuSignalMapper = new QSignalMapper(this);
+#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
+ connect(popupMenuSignalMapper, SIGNAL(mappedInt(int)),
+ this, SLOT(popupMenuAction(int)));
+#else
+ connect(popupMenuSignalMapper, SIGNAL(mapped(int)),
+ this, SLOT(popupMenuAction(int)));
+#endif
+
+ n = globalParams->getNumPopupMenuCmds();
+ if (n == 0) {
+ popupMenu->addAction("use 'popupMenuCmd' to add items to this menu");
+ popupMenu->addAction("see the xpdfrc(5) documentation");
+ } else {
+ for (i = 0; i < n; ++i) {
+ cmd = globalParams->getPopupMenuCmd(i);
+ action = popupMenu->addAction(cmd->label->getCString(),
+ popupMenuSignalMapper, SLOT(map()));
+ popupMenuSignalMapper->setMapping(action, i);
+ }
+ }
+}
+
+QWidget *XpdfViewer::createTabPane() {
+ QWidget *tabPane = new QWidget();
+
+ QVBoxLayout *tabPaneLayout = new QVBoxLayout();
+ tabPaneLayout->setContentsMargins(0, 0, 0, 0);
+ tabPaneLayout->setSpacing(0);
+ tabPane->setLayout(tabPaneLayout);
+
+ tabList = new QListWidget();
+ tabList->setSelectionMode(QAbstractItemView::SingleSelection);
+ tabList->setDragEnabled(true);
+ tabList->setDragDropMode(QAbstractItemView::InternalMove);
+ tabList->viewport()->setAcceptDrops(true);
+ tabList->setDropIndicatorShown(true);
+ connect(tabList, SIGNAL(currentItemChanged(QListWidgetItem*,
+ QListWidgetItem*)),
+ this, SLOT(switchTab(QListWidgetItem*, QListWidgetItem*)));
+ connect(tabList->model(), SIGNAL(rowsMoved(const QModelIndex&, int, int,
+ const QModelIndex, int)),
+ this, SLOT(tabsReordered(const QModelIndex&, int, int,
+ const QModelIndex&, int)));
+ tabPaneLayout->addWidget(tabList);
+
+ QPushButton *newTabBtn = new QPushButton("+ tab");
+ connect(newTabBtn, SIGNAL(clicked()), this, SLOT(newTabButtonPressed()));
+ tabPaneLayout->addWidget(newTabBtn);
+
+ return tabPane;
+}
+
+QWidget *XpdfViewer::createInfoPane() {
+ QWidget *infoPane = new QWidget();
+
+ QVBoxLayout *infoLayout = new QVBoxLayout();
+ infoLayout->setContentsMargins(0, 0, 0, 0);
+ infoLayout->setSpacing(0);
+ infoPane->setLayout(infoLayout);
+
+ // NB: order here must match order in updateInfoPane().
+ infoComboBox = new QComboBox();
+ infoComboBox->setEditable(false);
+ infoComboBox->addItem("outline");
+ infoComboBox->addItem("layers");
+ infoComboBox->addItem("attachments");
+ infoLayout->addWidget(infoComboBox);
+ connect(infoComboBox, SIGNAL(currentIndexChanged(int)),
+ this, SLOT(infoComboBoxChanged(int)));
+
+ infoStack = new QStackedLayout();
+ infoLayout->addLayout(infoStack);
+
+ return infoPane;
+}
+
+void XpdfViewer::updateInfoPane() {
+ // NB: order here must match order in createInfoPane().
+ switch (infoComboBox->currentIndex()) {
+ case 0:
+ infoStack->setCurrentWidget(currentTab->outlineTree);
+ break;
+ case 1:
+ infoStack->setCurrentWidget(currentTab->layerTree);
+ break;
+ case 2:
+ infoStack->setCurrentWidget(currentTab->attachmentList);
+ break;
+ }
+}
+
+void XpdfViewer::destroyWindow() {
+ int i;
+
+ delete errorWindow;
+
+ // QTreeView doesn't take ownership of the model, so we need to
+ // explicitly delete those
+ for (i = 0; i < tabInfo->getLength(); ++i) {
+ delete ((XpdfTabInfo *)tabInfo->get(i))->outlineTree->model();
+ delete ((XpdfTabInfo *)tabInfo->get(i))->layerTree->model();
+ }
+
+ deleteGList(tabInfo, XpdfTabInfo);
+
+ delete indicatorAnimation;
+}
+
+void XpdfViewer::enterFullScreenMode() {
+ mainMenu->hide();
+ toolBar->hide();
+ sidebarSplitter->widget(0)->hide();
+
+ fullScreenPreviousDisplayMode = currentTab->pdf->getDisplayMode();
+ currentTab->pdf->setDisplayMode(XpdfWidget::pdfDisplaySingle);
+ updateModeInfo();
+
+ fullScreenPreviousZoom = currentTab->pdf->getZoom();
+ currentTab->pdf->setZoom(XpdfWidget::zoomToPage);
+ updateZoomInfo();
+
+ currentTab->pdf->setMatteColor(app->getFullScreenMatteColor());
+ currentTab->pdf->setFrameStyle(QFrame::NoFrame);
+
+ showFullScreen();
+
+ fullScreenMenuItem->setChecked(true);
+}
+
+void XpdfViewer::exitFullScreenMode() {
+ mainMenu->show();
+ toolBar->show();
+ sidebarSplitter->widget(0)->show();
+
+ currentTab->pdf->setDisplayMode(fullScreenPreviousDisplayMode);
+ updateModeInfo();
+
+ currentTab->pdf->setZoom(fullScreenPreviousZoom);
+ updateZoomInfo();
+
+ currentTab->pdf->setMatteColor(app->getMatteColor());
+ currentTab->pdf->setFrameStyle(QFrame::Sunken | QFrame::StyledPanel);
+
+ showNormal();
+
+ fullScreenMenuItem->setChecked(false);
+}
+
+void XpdfViewer::addTab() {
+ QListWidgetItem *listItem;
+ XpdfWidget *pdf;
+ QTreeView *outlineTree, *layerTree;
+ QTableWidget *attachmentList;
+ GString *initialSelectMode;
+
+ pdf = new XpdfWidget(NULL, app->getPaperColor(), app->getMatteColor(),
+ app->getReverseVideo());
+ pdf->setSelectionColor(app->getSelectionColor());
+ pdf->enableHyperlinks(false);
+ pdf->setKeyPassthrough(true);
+ pdf->setMousePassthrough(true);
+ initialSelectMode = globalParams->getInitialSelectMode();
+ if (!initialSelectMode->cmp("block")) {
+ pdf->setBlockSelectMode();
+ } else {
+ pdf->setLinearSelectMode();
+ }
+ delete initialSelectMode;
+ connect(pdf, SIGNAL(resized()), this, SLOT(pdfResized()));
+ connect(pdf, SIGNAL(paintDone(bool)), this, SLOT(pdfPaintDone(bool)));
+ connect(pdf, SIGNAL(preLoad()), this, SLOT(preLoad()));
+ connect(pdf, SIGNAL(postLoad()), this, SLOT(postLoad()));
+ connect(pdf, SIGNAL(keyPress(QKeyEvent*)),
+ this, SLOT(keyPress(QKeyEvent*)));
+ connect(pdf, SIGNAL(mousePress(QMouseEvent*)),
+ this, SLOT(mousePress(QMouseEvent*)));
+ connect(pdf, SIGNAL(mouseRelease(QMouseEvent*)),
+ this, SLOT(mouseRelease(QMouseEvent*)));
+ connect(pdf, SIGNAL(mouseClick(QMouseEvent*)),
+ this, SLOT(mouseClick(QMouseEvent*)));
+ connect(pdf, SIGNAL(mouseDoubleClick(QMouseEvent*)),
+ this, SLOT(mouseDoubleClick(QMouseEvent*)));
+ connect(pdf, SIGNAL(mouseTripleClick(QMouseEvent*)),
+ this, SLOT(mouseTripleClick(QMouseEvent*)));
+ connect(pdf, SIGNAL(mouseWheel(QWheelEvent*)),
+ this, SLOT(mouseWheel(QWheelEvent*)));
+ connect(pdf, SIGNAL(mouseMove(QMouseEvent*)),
+ this, SLOT(mouseMove(QMouseEvent*)));
+ connect(pdf, SIGNAL(midPageChange(int)), this, SLOT(pageChange(int)));
+#if XPDFWIDGET_PRINTING
+ connect(pdf, SIGNAL(printStatus(int, int, int)),
+ this, SLOT(printStatus(int, int, int)));
+#endif
+ viewerStack->addWidget(pdf);
+ viewerStack->setCurrentWidget(pdf);
+ // after adding a tab, focus goes to the XpdfWidget
+ pdf->setFocus(Qt::OtherFocusReason);
+
+ //--- create tab pane item
+ listItem = new QListWidgetItem();
+ tabList->addItem(listItem);
+ tabList->setCurrentItem(listItem);
+
+ //--- create outline view
+ outlineTree = new QTreeView();
+ outlineTree->setModel(new OutlineModel(pdf));
+ outlineTree->setHeaderHidden(true);
+ outlineTree->setUniformRowHeights(true);
+ outlineTree->setSelectionMode(QAbstractItemView::SingleSelection);
+ connect(outlineTree, SIGNAL(clicked(const QModelIndex&)),
+ this, SLOT(outlineItemClicked(const QModelIndex&)));
+ infoStack->addWidget(outlineTree);
+
+ //--- create layer view
+ layerTree = new QTreeView();
+ layerTree->setModel(new LayerModel(pdf));
+ layerTree->setHeaderHidden(true);
+ layerTree->setUniformRowHeights(true);
+ layerTree->setSelectionMode(QAbstractItemView::NoSelection);
+ connect(layerTree, SIGNAL(clicked(const QModelIndex&)),
+ this, SLOT(layerItemClicked(const QModelIndex&)));
+ infoStack->addWidget(layerTree);
+
+ //--- create attachment list
+ attachmentList = new QTableWidget(4, 2);
+ attachmentList->horizontalHeader()->hide();
+ attachmentList->verticalHeader()->hide();
+ attachmentList->setShowGrid(false);
+ attachmentList->setWordWrap(false);
+ attachmentList->setSelectionMode(QAbstractItemView::NoSelection);
+ infoStack->addWidget(attachmentList);
+
+ currentTab = new XpdfTabInfo(listItem, pdf, outlineTree, layerTree,
+ attachmentList);
+ tabInfo->append(currentTab);
+
+ updateInfoPane();
+
+ scaleFactor = pdf->getCore()->getScaleFactor();
+}
+
+void XpdfViewer::closeTab(XpdfTabInfo *tab) {
+ int i;
+
+ app->startUpdatePagesFile();
+ app->updatePagesFile(tab->pdf->getFileName(), tab->pdf->getMidPage());
+ app->finishUpdatePagesFile();
+
+ for (i = 0; i < tabInfo->getLength(); ++i) {
+ if ((XpdfTabInfo *)tabInfo->get(i) == tab) {
+ break;
+ }
+ }
+ if (i == tabInfo->getLength()) {
+ // this shouldn't happen
+ return;
+ }
+ tabInfo->del(i);
+
+ for (i = 0; i < tabList->count(); ++i) {
+ if (tabList->item(i) == tab->listItem) {
+ delete tabList->takeItem(i);
+ break;
+ }
+ }
+
+ infoStack->removeWidget(tab->outlineTree);
+ delete tab->outlineTree->model();
+ delete tab->outlineTree;
+ infoStack->removeWidget(tab->layerTree);
+ delete tab->layerTree->model();
+ delete tab->layerTree;
+ infoStack->removeWidget(tab->attachmentList);
+
+ viewerStack->removeWidget(tab->pdf);
+ tab->pdf->closeFile();
+ delete tab->pdf;
+
+ delete tab;
+
+ if (tabInfo->getLength() > 0) {
+ updateModeInfo();
+ updateDocInfo();
+ }
+}
+
+void XpdfViewer::gotoTab(int idx) {
+ XpdfTabInfo *tab;
+
+ tab = (XpdfTabInfo *)tabInfo->get(idx);
+ currentTab = tab;
+ viewerStack->setCurrentWidget(currentTab->pdf);
+ // after switching tabs, focus goes to the XpdfWidget
+ currentTab->pdf->setFocus(Qt::OtherFocusReason);
+ updateInfoPane();
+ updateModeInfo();
+ updateDocInfo();
+}
+
+// Update the display mode checkboxes, based on the current XpdfWidget
+// settings.
+void XpdfViewer::updateModeInfo() {
+ switch (currentTab->pdf->getDisplayMode()) {
+ case XpdfWidget::pdfDisplaySingle:
+ displayModeSubmenu->actions()[0]->setChecked(true);
+ break;
+ case XpdfWidget::pdfDisplayContinuous:
+ displayModeSubmenu->actions()[1]->setChecked(true);
+ break;
+ case XpdfWidget::pdfDisplaySideBySideSingle:
+ displayModeSubmenu->actions()[2]->setChecked(true);
+ break;
+ case XpdfWidget::pdfDisplaySideBySideContinuous:
+ displayModeSubmenu->actions()[3]->setChecked(true);
+ break;
+ case XpdfWidget::pdfDisplayHorizontalContinuous:
+ displayModeSubmenu->actions()[4]->setChecked(true);
+ break;
+ }
+}
+
+// Update the displayed zoom percentage, based on the current
+// XpdfWidget settings.
+void XpdfViewer::updateZoomInfo() {
+ int pg;
+ double z;
+ QString zoomStr;
+
+ if (currentTab->pdf->hasOpenDocument()) {
+ pg = currentTab->pdf->getMidPage();
+ } else {
+ pg = 1;
+ }
+ z = (int)floor(currentTab->pdf->getZoomPercent(pg) + 0.5);
+ zoomStr.setNum(z);
+ zoomStr.append('%');
+ zoomComboBox->setEditText(zoomStr);
+
+ z = currentTab->pdf->getZoom();
+ if (z == XpdfWidget::zoomToWidth) {
+ fitWidthBtn->setIcon(QIcon(":/fitWidthOn-button"));
+ fitPageBtn->setIcon(QIcon(":/fitPage-button"));
+ } else if (z == XpdfWidget::zoomToPage) {
+ fitWidthBtn->setIcon(QIcon(":/fitWidth-button"));
+ fitPageBtn->setIcon(QIcon(":/fitPageOn-button"));
+ } else {
+ fitWidthBtn->setIcon(QIcon(":/fitWidth-button"));
+ fitPageBtn->setIcon(QIcon(":/fitPage-button"));
+ }
+}
+
+void XpdfViewer::updateSelectModeInfo() {
+ if (currentTab->pdf->isBlockSelectMode()) {
+ selectModeBtn->setIcon(QIcon(":/selectModeBlock-button"));
+ } else {
+ selectModeBtn->setIcon(QIcon(":/selectModeLinear-button"));
+ }
+}
+
+// This is called when:
+// - when the GUI is initially created
+// - a document is opened or closed
+// - a tab switch happens
+// It updates all visible info related to the document.
+void XpdfViewer::updateDocInfo() {
+ //--- window title
+ QString windowTitle;
+ if (currentTab->pdf->hasOpenDocument()) {
+ windowTitle = currentTab->pdf->getFileName();
+ windowTitle += " - XpdfReader";
+ } else {
+ windowTitle = "XpdfReader";
+ }
+ setWindowTitle(windowTitle);
+
+ //--- tab title
+ QString tabTitle;
+ if (currentTab->pdf->hasOpenDocument()) {
+ tabTitle = currentTab->pdf->getFileName();
+ int i = tabTitle.lastIndexOf('/');
+#ifdef _WIN32
+ int j = tabTitle.lastIndexOf('\\');
+ if (j > i) {
+ i = j;
+ }
+#endif
+ if (i >= 0) {
+ tabTitle = tabTitle.mid(i + 1) + " [" + tabTitle.left(i + 1) + "]";
+ }
+ } else {
+ tabTitle = "(empty)";
+ }
+ currentTab->listItem->setText(tabTitle);
+ currentTab->listItem->setToolTip(tabTitle);
+
+ //--- page number
+ updatePageNumberOrLabel(currentTab->pdf->getMidPage());
+
+ //--- page count
+ QString nPages;
+ if (currentTab->pdf->hasOpenDocument()) {
+ nPages.setNum(currentTab->pdf->getNumPages());
+ }
+ pageCount->setText(nPages);
+
+ //--- zoom
+ // NB: in fit-{page,width,height} modes zoom percent depends on page
+ // size, so we need to update whenever a new doc is loaded
+ updateZoomInfo();
+
+ //--- selection mode
+ updateSelectModeInfo();
+
+ //--- hide the link target bar
+ currentTab->pdf->unsetCursor();
+ linkTargetBar->hide();
+ linkTargetInfo = QString();
+}
+
+void XpdfViewer::updatePageNumberOrLabel(int pg) {
+ QString qs;
+
+ if (!viewPageLabelsMenuItem->isChecked() ||
+ !currentTab->pdf->getCore()->getDoc() ||
+ (qs = currentTab->pdf->getPageLabelFromPageNum(pg)).isEmpty()) {
+ qs.setNum(pg);
+ }
+ pageNumber->setText(qs);
+}
+
+void XpdfViewer::updateOutline(int pg) {
+ QModelIndex idx;
+
+ idx = ((OutlineModel *)currentTab->outlineTree->model())
+ ->findPageIndex(pg, currentTab->outlineTree);
+ if (idx.isValid()) {
+ currentTab->outlineTree->setCurrentIndex(idx);
+ }
+}
+
+void XpdfViewer::setOutlineOpenItems(const QModelIndex &idx) {
+ OutlineModel *model;
+ XpdfOutlineHandle item;
+ QModelIndex child;
+ int n, i;
+
+ if (idx.isValid()) {
+ item = (XpdfOutlineHandle)idx.internalPointer();
+ if (!currentTab->pdf->getOutlineStartsOpen(item)) {
+ return;
+ }
+ currentTab->outlineTree->expand(idx);
+ }
+ model = (OutlineModel *)currentTab->outlineTree->model();
+ n = model->rowCount(idx);
+ for (i = 0; i < n; ++i) {
+ child = model->index(i, 0, idx);
+ setOutlineOpenItems(child);
+ }
+}
+
+void XpdfViewer::fillAttachmentList() {
+ QButtonGroup *btnGroup;
+ QPushButton *saveBtn;
+ QTableWidgetItem *item;
+ int n, i;
+
+ n = currentTab->pdf->getNumEmbeddedFiles();
+ currentTab->attachmentList->setRowCount(n);
+ currentTab->attachmentList->setColumnCount(2);
+ btnGroup = new QButtonGroup(currentTab->attachmentList);
+ for (i = 0; i < n; ++i) {
+ saveBtn = new QPushButton("save");
+ saveBtn->setStyleSheet("padding-left:4px; padding-right:4px;");
+ btnGroup->addButton(saveBtn, i);
+ btnGroup->setId(saveBtn, i);
+ currentTab->attachmentList->setCellWidget(i, 0, saveBtn);
+ item = new QTableWidgetItem(currentTab->pdf->getEmbeddedFileName(i));
+ currentTab->attachmentList->setItem(i, 1, item);
+ }
+#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
+ connect(btnGroup, SIGNAL(idClicked(int)),
+ this, SLOT(attachmentSaveClicked(int)));
+#else
+ connect(btnGroup, SIGNAL(buttonClicked(int)),
+ this, SLOT(attachmentSaveClicked(int)));
+#endif
+ currentTab->attachmentList->resizeRowsToContents();
+ currentTab->attachmentList->resizeColumnsToContents();
+}
+
+void XpdfViewer::statusIndicatorStart() {
+ if (indicatorAnimation->state() == QAbstractAnimation::Paused) {
+ indicatorAnimation->resume();
+ }
+}
+
+void XpdfViewer::statusIndicatorStop() {
+ if (indicatorAnimation->state() == QAbstractAnimation::Running) {
+ indicatorAnimation->pause();
+ indicatorAnimation->setCurrentTime(0);
+ }
+}
+
+void XpdfViewer::statusIndicatorOk() {
+ if (indicatorAnimation->values() != indicatorIcons) {
+ indicatorAnimation->setValues(indicatorIcons);
+ }
+}
+
+void XpdfViewer::statusIndicatorError() {
+ if (indicatorAnimation->values() != indicatorErrIcons) {
+ indicatorAnimation->setValues(indicatorErrIcons);
+ }
+}
+
+void XpdfViewer::showFindError() {
+ findEdit->setStyleSheet("background: #ff8080;");
+ findErrorTimer->start(1000);
+}
+
+void XpdfViewer::clearFindError() {
+ findErrorTimer->stop();
+ findEdit->setStyleSheet("");
+}
+
+void XpdfViewer::createDocumentInfoDialog() {
+ documentInfoDialog = new QDialog(this);
+ documentInfoDialog->setWindowTitle("XpdfReader Document Info");
+
+ QVBoxLayout *vbox = new QVBoxLayout();
+ documentInfoDialog->setLayout(vbox);
+
+ QTabWidget *tabs = new QTabWidget();
+ vbox->addWidget(tabs);
+
+ documentInfoMetadataTab = new QTextBrowser();
+ documentInfoMetadataTab->setLineWrapMode(QTextEdit::NoWrap);
+ tabs->addTab(documentInfoMetadataTab, "Metadata");
+
+ documentInfoFontsTab = new QTextBrowser();
+ documentInfoFontsTab->setLineWrapMode(QTextEdit::NoWrap);
+ tabs->addTab(documentInfoFontsTab, "Fonts");
+}
+
+void XpdfViewer::updateDocumentInfoDialog(XpdfWidget *view) {
+ if (!view->hasOpenDocument()) {
+ return;
+ }
+
+ if (!documentInfoDialog) {
+ createDocumentInfoDialog();
+ }
+
+ documentInfoDialog->setWindowTitle(view->getFileName() +
+ " - XpdfReader Document Info");
+ documentInfoMetadataTab->setHtml(createDocumentInfoMetadataHTML(view));
+ documentInfoFontsTab->setHtml(createDocumentInfoFontsHTML(view));
+
+ //--- tweak the dialog size
+ int w = documentInfoMetadataTab->contentsMargins().left() +
+ (int)documentInfoMetadataTab->document()->idealWidth() +
+ documentInfoMetadataTab->contentsMargins().right() +
+ 50;
+ int w1 = documentInfoFontsTab->contentsMargins().left() +
+ (int)documentInfoFontsTab->document()->idealWidth() +
+ documentInfoFontsTab->contentsMargins().right() +
+ 50;
+ if (w1 > w) {
+ w = w1;
+ }
+ int h = 20 * documentInfoMetadataTab->fontMetrics().lineSpacing() + 75;
+ documentInfoDialog->resize(w, h);
+}
+
+static QString parseInfoDate(GString *s) {
+ char *p = s->getCString();
+ if (p[0] == 'D' && p[1] == ':') {
+ p += 2;
+ }
+ int year, mon, day, hour, min, sec, n;
+ if ((n = sscanf(p, "%4d%2d%2d%2d%2d%2d",
+ &year, &mon, &day, &hour, &min, &sec)) < 1) {
+ return QString();
+ }
+ switch (n) {
+ case 1: mon = 1;
+ case 2: day = 1;
+ case 3: hour = 0;
+ case 4: min = 0;
+ case 5: sec = 0;
+ }
+ struct tm tmStruct;
+ 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
+ char buf[256];
+ if (!(mktime(&tmStruct) != (time_t)-1 &&
+ strftime(buf, sizeof(buf), "%c", &tmStruct))) {
+ return QString();
+ }
+ return QString(buf);
+}
+
+static QString parseXMPDate(GString *s) {
+ int year, mon, day, hour, min, sec, tz;
+ char buf[256];
+ char *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 QString();
+ }
+ 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;
+ }
+ }
+ }
+ }
+ }
+
+ struct tm tmStruct;
+ 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 QString();
+ }
+ return QString(buf);
+}
+
+static QString createInfoString(Object *infoDict, const char *infoKey,
+ ZxDoc *xmp, const char *xmpKey1,
+ const char *xmpKey2, GBool parseDate) {
+ //-- check the XMP metadata
+ if (xmp) {
+ ZxElement *rdf = xmp->getRoot();
+ if (rdf->isElement("x:xmpmeta")) {
+ rdf = rdf->findFirstChildElement("rdf:RDF");
+ }
+ if (rdf && rdf->isElement("rdf:RDF")) {
+ for (ZxNode *node = rdf->getFirstChild();
+ node;
+ node = node->getNextChild()) {
+ if (node->isElement("rdf:Description")) {
+ ZxElement *elem;
+ if ((elem = node->findFirstChildElement(xmpKey1)) ||
+ (xmpKey2 && (elem = node->findFirstChildElement(xmpKey2)))) {
+ ZxElement *child;
+ ZxNode *node2;
+ 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()) {
+ QString value;
+ if (parseDate) {
+ value = parseXMPDate(((ZxCharData *)node2)->getData());
+ }
+ if (value.isEmpty()) {
+ value = QString::fromUtf8(
+ ((ZxCharData *)node2)->getData()->getCString());
+ }
+ return QString("<tr><td>") + infoKey + ":&nbsp;</td><td>"
+ + value + "</td></tr>\n";
+ }
+ }
+ }
+ }
+ }
+ }
+
+ //-- check the info dictionary
+ if (infoDict->isDict()) {
+ Object obj;
+ if (infoDict->dictLookup(infoKey, &obj)->isString()) {
+ QString value;
+ if (parseDate) {
+ value = parseInfoDate(obj.getString());
+ }
+ if (value.isEmpty()) {
+ TextString *ts = new TextString(obj.getString());
+ GString *utf8 = ts->toUTF8();
+ value = QString::fromUtf8(utf8->getCString());
+ delete utf8;
+ delete ts;
+ }
+ obj.free();
+ return QString("<tr><td>") + infoKey + ":&nbsp;</td><td>"
+ + value + "</td></tr>\n";
+ }
+ obj.free();
+ }
+
+ return QString();
+}
+
+QString XpdfViewer::createDocumentInfoMetadataHTML(XpdfWidget *view) {
+ PDFDoc *doc = view->getCore()->getDoc();
+ QString html("<table>\n");
+
+ // doc info
+ Object info;
+ doc->getDocInfo(&info);
+ GString *metadata;
+ ZxDoc *xmp;
+ if ((metadata = doc->readMetadata())) {
+ xmp = ZxDoc::loadMem(metadata->getCString(), metadata->getLength());
+ } else {
+ xmp = NULL;
+ }
+ html += createInfoString(&info, "Title", xmp, "dc:title", NULL, gFalse);
+ html += createInfoString(&info, "Subject", xmp, "dc:description", NULL, gFalse);
+ html += createInfoString(&info, "Keywords", xmp, "pdf:Keywords", NULL, gFalse);
+ html += createInfoString(&info, "Author", xmp, "dc:creator", NULL, gFalse);
+ html += createInfoString(&info, "Creator", xmp, "xmp:CreatorTool", NULL, gFalse);
+ html += createInfoString(&info, "Producer", xmp, "pdf:Producer", NULL, gFalse);
+ html += createInfoString(&info, "CreationDate", xmp, "xap:CreateDate", "xmp:CreateDate", gTrue);
+ html += createInfoString(&info, "ModDate", xmp, "xap:ModifyDate", "xmp:ModifyDate", gTrue);
+ if (xmp) {
+ delete xmp;
+ }
+ if (metadata) {
+ delete metadata;
+ }
+ info.free();
+
+ // tagging info
+ if (doc->getStructTreeRoot()->isDict()) {
+ html += "<tr><td>Tagged:&nbsp;</td><td>yes</td></tr>\n";
+ } else {
+ html += "<tr><td>Tagged:&nbsp;</td><td>no</td></tr>\n";
+ }
+
+ // form info
+ Object *acroForm = doc->getCatalog()->getAcroForm();
+ if (acroForm->isDict()) {
+ Object xfa;
+ acroForm->dictLookup("XFA", &xfa);
+ if (xfa.isStream() || xfa.isArray()) {
+ if (doc->getCatalog()->getNeedsRendering()) {
+ html += "<tr><td>Form:&nbsp;</td><td>dynamic XFA</td></tr>\n";
+ } else {
+ html += "<tr><td>Form:&nbsp;</td><td>static XFA</td></tr>\n";
+ }
+ } else {
+ html += "<tr><td>Form:&nbsp;</td><td>AcroForm</td></tr>\n";
+ }
+ xfa.free();
+ } else {
+ html += "<tr><td>Form:&nbsp;</td><td>none</td></tr>\n";
+ }
+
+ // page count
+ html += QString("<tr><td>Pages:&nbsp;</td><td>%1</td></tr>\n")
+ .arg(doc->getNumPages());
+
+ // encryption info
+ if (doc->isEncrypted()) {
+ int permFlags, keyLength, encVersion;
+ GBool ownerPasswordOk;
+ CryptAlgorithm encAlgorithm;
+ doc->getXRef()->getEncryption(&permFlags, &ownerPasswordOk, &keyLength,
+ &encVersion, &encAlgorithm);
+ html += QString("<tr><td>Encrypted:&nbsp;</td><td>%1 %2-bit</td></tr>\n")
+ .arg(encAlgorithm == cryptRC4 ? "RC4" : "AES")
+ .arg(keyLength * 8);
+ html += QString("<tr><td>Permissions:&nbsp;</td><td>print:%1 copy:%2 change:%3 addNotes:%4</td></tr>\n")
+ .arg(doc->okToPrint(gTrue) ? "yes" : "no")
+ .arg(doc->okToCopy(gTrue) ? "yes" : "no")
+ .arg(doc->okToChange(gTrue) ? "yes" : "no")
+ .arg(doc->okToAddNotes(gTrue) ? "yes" : "no");
+ } else {
+ html += QString("<tr><td>Encrypted:&nbsp;</td><td>no</td></tr>\n");
+ }
+
+ // page size
+ html += QString("<tr><td>Page size:&nbsp;</td><td>%1 x %2 pts (rotated %3 degrees)</td></tr>\n")
+ .arg(doc->getPageCropWidth(1), 0, 'g')
+ .arg(doc->getPageCropHeight(1), 0, 'g')
+ .arg(doc->getPageRotate(1));
+
+ // linearization info
+ html += QString("<tr><td>Optimized:&nbsp;</td><td>%1</td></tr>\n")
+ .arg(doc->isLinearized() ? "yes" : "no");
+
+ // PDF version
+ html += QString("<tr><td>PDF version:&nbsp;</td><td>%1</td></tr>\n")
+ .arg(doc->getPDFVersion(), 0, 'f', 1);
+
+ html += "</table>\n";
+
+ return html;
+}
+
+static GBool scanFontsCheckObject(Object *in, Object *out,
+ PDFDoc *doc, char *seenObjs) {
+ if (!in->isRef()) {
+ in->copy(out);
+ return gTrue;
+ }
+ int objNum = in->getRefNum();
+ if (objNum < 0 || objNum >= doc->getXRef()->getNumObjects()) {
+ out->initNull();
+ return gTrue;
+ }
+ if (seenObjs[objNum]) {
+ out->initNull();
+ return gFalse;
+ }
+ seenObjs[objNum] = (char)1;
+ in->fetch(doc->getXRef(), out);
+ return gTrue;
+}
+
+static QString scanFont(Dict *fontDict, PDFDoc *doc) {
+ Ref ref;
+ ref.num = ref.gen = 0;
+ GfxFont *font = GfxFont::makeFont(doc->getXRef(), "F0", ref, fontDict);
+ if (!font) {
+ return QString();
+ }
+
+ // font name
+ GString *name = font->getName();
+
+ // font type
+ const char *type;
+ switch (font->getType()) {
+ case fontUnknownType:
+ default: type = "unknown"; break;
+ case fontType1: type = "Type 1"; break;
+ case fontType1C: type = "Type 1C"; break;
+ case fontType1COT: type = "Type 1C (OT)"; break;
+ case fontType3: type = "Type 3"; break;
+ case fontTrueType: type = "TrueType"; break;
+ case fontTrueTypeOT: type = "TrueType (OT)"; break;
+ case fontCIDType0: type = "CID Type 0"; break;
+ case fontCIDType0C: type = "CID Type 0C"; break;
+ case fontCIDType0COT: type = "CID Type 0C (OT)"; break;
+ case fontCIDType2: type = "CID TrueType"; break;
+ case fontCIDType2OT: type = "CID TrueType (OT)"; break;
+ }
+
+ // check for an embedded font
+ GBool emb;
+ if (font->getType() == fontType3) {
+ emb = gTrue;
+ } else {
+ Ref embRef;
+ emb = font->getEmbeddedFontID(&embRef);
+ }
+
+ // problematic for text extraction
+ GBool prob = font->problematicForUnicode();
+
+ QString html = QString("<tr><td>%1&nbsp;</td><td>%2&nbsp;</td><td align=\"center\">%3</td><td align=\"center\">%4</td></tr>\n")
+ .arg(name ? name->getCString() : "[none]")
+ .arg(type)
+ .arg(emb ? "yes" : "no")
+ .arg(prob ? "X" : "");
+
+ delete font;
+
+ return html;
+}
+
+static QString scanFonts(Dict *resDict, PDFDoc *doc, char *seenObjs);
+
+static QString scanFonts(Object *obj, PDFDoc *doc, char *seenObjs) {
+ QString html;
+ Object obj2;
+ if (scanFontsCheckObject(obj, &obj2, doc, seenObjs) && obj2.isDict()) {
+ html += scanFonts(obj2.getDict(), doc, seenObjs);
+ }
+ obj2.free();
+ return html;
+}
+
+static QString scanFonts(Dict *resDict, PDFDoc *doc, char *seenObjs) {
+ QString html;
+
+ // scan the fonts in this resource dictionary
+ Object fontDict1, fontDict2;
+ resDict->lookupNF("Font", &fontDict1);
+ if (scanFontsCheckObject(&fontDict1, &fontDict2, doc, seenObjs) &&
+ fontDict2.isDict()) {
+ for (int i = 0; i < fontDict2.dictGetLength(); ++i) {
+ Object font1, font2;
+ fontDict2.dictGetValNF(i, &font1);
+ if (scanFontsCheckObject(&font1, &font2, doc, seenObjs) &&
+ font2.isDict()) {
+ html += scanFont(font2.getDict(), doc);
+ }
+ font2.free();
+ font1.free();
+ }
+ }
+ fontDict2.free();
+ fontDict1.free();
+
+ // recursively scan any resource dictionaries in XObjects in this
+ // resource dictionary
+ Object xObjDict1, xObjDict2;
+ resDict->lookupNF("XObject", &xObjDict1);
+ if (scanFontsCheckObject(&xObjDict1, &xObjDict2, doc, seenObjs) &&
+ xObjDict2.isDict()) {
+ for (int i = 0; i < xObjDict2.dictGetLength(); ++i) {
+ Object xObj1, xObj2;
+ xObjDict2.dictGetValNF(i, &xObj1);
+ if (scanFontsCheckObject(&xObj1, &xObj2, doc, seenObjs) &&
+ xObj2.isStream()) {
+ Object resObj;
+ xObj2.streamGetDict()->lookupNF("Resources", &resObj);
+ html += scanFonts(&resObj, doc, seenObjs);
+ resObj.free();
+ }
+ xObj2.free();
+ xObj1.free();
+ }
+ }
+ xObjDict2.free();
+ xObjDict1.free();
+
+ // recursively scan any resource dictionaries in Patterns in this
+ // resource dictionary
+ Object patternDict1, patternDict2;
+ resDict->lookupNF("Pattern", &patternDict1);
+ if (scanFontsCheckObject(&patternDict1, &patternDict2, doc, seenObjs) &&
+ patternDict2.isDict()) {
+ for (int i = 0; i < patternDict2.dictGetLength(); ++i) {
+ Object pattern1, pattern2;
+ patternDict2.dictGetValNF(i, &pattern1);
+ if (scanFontsCheckObject(&pattern1, &pattern2, doc, seenObjs) &&
+ pattern2.isStream()) {
+ Object resObj;
+ pattern2.streamGetDict()->lookupNF("Resources", &resObj);
+ html += scanFonts(&resObj, doc, seenObjs);
+ resObj.free();
+ }
+ pattern2.free();
+ pattern1.free();
+ }
+ }
+ patternDict2.free();
+ patternDict1.free();
+
+ // recursively scan any resource dictionaries in ExtGStates in this
+ // resource dictionary
+ Object gsDict1, gsDict2;
+ resDict->lookupNF("ExtGState", &gsDict1);
+ if (scanFontsCheckObject(&gsDict1, &gsDict2, doc, seenObjs) &&
+ gsDict2.isDict()) {
+ for (int i = 0; i < gsDict2.dictGetLength(); ++i) {
+ Object gs1, gs2;
+ gsDict2.dictGetValNF(i, &gs1);
+ if (scanFontsCheckObject(&gs1, &gs2, doc, seenObjs) &&
+ gs2.isDict()) {
+ Object smask1, smask2;
+ gs2.dictLookupNF("SMask", &smask1);
+ if (scanFontsCheckObject(&smask1, &smask2, doc, seenObjs) &&
+ smask2.isDict()) {
+ Object smaskGroup1, smaskGroup2;
+ smask2.dictLookupNF("G", &smaskGroup1);
+ if (scanFontsCheckObject(&smaskGroup1, &smaskGroup2, doc, seenObjs) &&
+ smaskGroup2.isStream()) {
+ Object resObj;
+ smaskGroup2.streamGetDict()->lookupNF("Resources", &resObj);
+ html += scanFonts(&resObj, doc, seenObjs);
+ resObj.free();
+ }
+ smaskGroup2.free();
+ smaskGroup1.free();
+ }
+ smask2.free();
+ smask1.free();
+ }
+ gs2.free();
+ gs1.free();
+ }
+ }
+ gsDict2.free();
+ gsDict1.free();
+
+ return html;
+}
+
+QString XpdfViewer::createDocumentInfoFontsHTML(XpdfWidget *view) {
+ PDFDoc *doc = view->getCore()->getDoc();
+
+ QString html("<table>\n");
+ html += "<tr bgcolor=\"#aaffaa\"><th>&nbsp;name&nbsp;</th><th>&nbsp;type&nbsp;</th><th>&nbsp;embedded&nbsp;</th><th>&nbsp;problematic&nbsp;</th></tr>\n";
+
+ int numObjects = doc->getXRef()->getNumObjects();
+ char *seenObjs = (char *)gmalloc(numObjects);
+ memset(seenObjs, 0, numObjects);
+
+ for (int pg = 1; pg <= doc->getNumPages(); ++pg) {
+ Page *page = doc->getCatalog()->getPage(pg);
+ Dict *resDict = page->getResourceDict();
+ if (resDict) {
+ html += scanFonts(resDict, doc, seenObjs);
+ }
+ Object obj1, obj2;
+ Annots *annots = new Annots(doc, page->getAnnots(&obj1));
+ obj1.free();
+ for (int i = 0; i < annots->getNumAnnots(); ++i) {
+ if (annots->getAnnot(i)->getAppearance(&obj1)->isStream()) {
+ obj1.streamGetDict()->lookupNF("Resources", &obj2);
+ html += scanFonts(&obj2, doc, seenObjs);
+ obj2.free();
+ }
+ obj1.free();
+ }
+ delete annots;
+ }
+ AcroForm *form = doc->getCatalog()->getForm();
+ if (form) {
+ Object obj1, obj2;
+ for (int i = 0; i < form->getNumFields(); ++i) {
+ form->getField(i)->getResources(&obj1);
+ if (obj1.isArray()) {
+ for (int j = 0; j < obj1.arrayGetLength(); ++j) {
+ obj1.arrayGetNF(j, &obj2);
+ html += scanFonts(&obj2, doc, seenObjs);
+ obj2.free();
+ }
+ } else if (obj1.isDict()) {
+ html += scanFonts(obj1.getDict(), doc, seenObjs);
+ }
+ obj1.free();
+ }
+ }
+
+ gfree(seenObjs);
+
+ html += "</table>\n";
+ return html;
+}
+
+void XpdfViewer::createKeyBindingsDialog() {
+ keyBindingsDialog = new QDialog(this);
+ keyBindingsDialog->setWindowTitle("XpdfReader Key Bindings");
+
+ QVBoxLayout *vbox = new QVBoxLayout();
+ keyBindingsDialog->setLayout(vbox);
+
+ QString html = createKeyBindingsHTML();
+
+ QTextBrowser *text = new QTextBrowser();
+ text->setHtml(html);
+ text->setReadOnly(true);
+ text->setMinimumSize(QSize(500, 300));
+ vbox->addWidget(text);
+
+ QHBoxLayout *btnBox = new QHBoxLayout();
+ vbox->addLayout(btnBox);
+
+ QPushButton *closeBtn = new QPushButton("Close");
+ closeBtn->setDefault(true);
+ btnBox->addStretch(1);
+ btnBox->addWidget(closeBtn);
+ btnBox->addStretch(1);
+ connect(closeBtn, SIGNAL(clicked()), keyBindingsDialog, SLOT(accept()));
+}
+
+QString XpdfViewer::createKeyBindingsHTML() {
+ QString html;
+ GList *bindings = globalParams->getAllKeyBindings();
+ html += "<h3>Key Bindings:</h3>\n";
+ html += "<ul>\n";
+ html += "<li><i>modifiers-key (context): command / command / ...</i>\n";
+ html += "<br>";
+ for (int i = 0; i < bindings->getLength(); ++i) {
+ KeyBinding *binding = (KeyBinding *)bindings->get(i);
+ html += "<li>";
+ if (binding->mods & xpdfKeyModShift) {
+ html += "shift-";
+ }
+ if (binding->mods & xpdfKeyModCtrl) {
+ html += "ctrl-";
+ }
+ if (binding->mods & xpdfKeyModAlt) {
+ html += "alt-";
+ }
+ if (binding->code == 0x20) {
+ html += "space";
+ } else if (binding->code >= 0x21 && binding->code <= 0xfe) {
+ html += (QChar)binding->code;
+ } else if (binding->code >= xpdfKeyCodeMousePress1 &&
+ binding->code <= xpdfKeyCodeMousePress32) {
+ html += QString("mousePress%1")
+ .arg(binding->code - xpdfKeyCodeMousePress1 + 1);
+ } else if (binding->code >= xpdfKeyCodeMouseRelease1 &&
+ binding->code <= xpdfKeyCodeMouseRelease32) {
+ html += QString("mouseRelease%1")
+ .arg(binding->code - xpdfKeyCodeMouseRelease1 + 1);
+ } else if (binding->code >= xpdfKeyCodeMouseClick1 &&
+ binding->code <= xpdfKeyCodeMouseClick32) {
+ html += QString("mouseClick%1")
+ .arg(binding->code - xpdfKeyCodeMouseClick1 + 1);
+ } else if (binding->code >= xpdfKeyCodeMouseDoubleClick1 &&
+ binding->code <= xpdfKeyCodeMouseDoubleClick32) {
+ html += QString("mouseDoubleClick%1")
+ .arg(binding->code - xpdfKeyCodeMouseDoubleClick1 + 1);
+ } else if (binding->code >= xpdfKeyCodeMouseTripleClick1 &&
+ binding->code <= xpdfKeyCodeMouseTripleClick32) {
+ html += QString("mouseTripleClick%1")
+ .arg(binding->code - xpdfKeyCodeMouseTripleClick1 + 1);
+ } else if (binding->code >= xpdfKeyCodeF1 &&
+ binding->code <= xpdfKeyCodeF35) {
+ html += QString("f%1").arg(binding->code - xpdfKeyCodeF1 + 1);
+ } else {
+ switch (binding->code) {
+ case xpdfKeyCodeTab: html += "tab"; break;
+ case xpdfKeyCodeReturn: html += "return"; break;
+ case xpdfKeyCodeEnter: html += "enter"; break;
+ case xpdfKeyCodeBackspace: html += "backspace"; break;
+ case xpdfKeyCodeEsc: html += "esc"; break;
+ case xpdfKeyCodeInsert: html += "insert"; break;
+ case xpdfKeyCodeDelete: html += "delete"; break;
+ case xpdfKeyCodeHome: html += "home"; break;
+ case xpdfKeyCodeEnd: html += "end"; break;
+ case xpdfKeyCodePgUp: html += "pgup"; break;
+ case xpdfKeyCodePgDn: html += "pgdn"; break;
+ case xpdfKeyCodeLeft: html += "left"; break;
+ case xpdfKeyCodeRight: html += "right"; break;
+ case xpdfKeyCodeUp: html += "up"; break;
+ case xpdfKeyCodeDown: html += "down"; break;
+ default: html += "[unknown]"; break;
+ }
+ }
+ html += " (";
+ if (binding->context == xpdfKeyContextAny) {
+ html += "any";
+ } else {
+ QString mods = "";
+ if (binding->context & xpdfKeyContextFullScreen) {
+ if (!mods.isEmpty()) { mods += ","; }
+ mods += "fullScreen";
+ }
+ if (binding->context & xpdfKeyContextWindow) {
+ if (!mods.isEmpty()) { mods += ","; }
+ mods += "window";
+ }
+ if (binding->context & xpdfKeyContextContinuous) {
+ if (!mods.isEmpty()) { mods += ","; }
+ mods += "continuous";
+ }
+ if (binding->context & xpdfKeyContextSinglePage) {
+ if (!mods.isEmpty()) { mods += ","; }
+ mods += "singlePage";
+ }
+ if (binding->context & xpdfKeyContextOverLink) {
+ if (!mods.isEmpty()) { mods += ","; }
+ mods += "overLink";
+ }
+ if (binding->context & xpdfKeyContextOffLink) {
+ if (!mods.isEmpty()) { mods += ","; }
+ mods += "offLink";
+ }
+ if (binding->context & xpdfKeyContextOutline) {
+ if (!mods.isEmpty()) { mods += ","; }
+ mods += "outline";
+ }
+ if (binding->context & xpdfKeyContextMainWin) {
+ if (!mods.isEmpty()) { mods += ","; }
+ mods += "mainWin";
+ }
+ if (binding->context & xpdfKeyContextScrLockOn) {
+ if (!mods.isEmpty()) { mods += ","; }
+ mods += "scrLockOn";
+ }
+ if (binding->context & xpdfKeyContextScrLockOff) {
+ if (!mods.isEmpty()) { mods += ","; }
+ mods += "scrLockOff";
+ }
+ html += mods;
+ }
+ html += "): ";
+ for (int j = 0; j < binding->cmds->getLength(); ++j) {
+ GString *cmd = (GString *)binding->cmds->get(j);
+ if (j > 0) {
+ html += " / ";
+ }
+ html += cmd->getCString();
+ }
+ html += "\n";
+ }
+ html += "</ul>\n";
+ return html;
+}
+
+void XpdfViewer::createAboutDialog() {
+ aboutDialog = new QDialog(this);
+ aboutDialog->setWindowTitle("About XpdfReader");
+
+ QVBoxLayout *vbox = new QVBoxLayout();
+ aboutDialog->setLayout(vbox);
+
+ QTextBrowser *text = new QTextBrowser();
+ text->setOpenExternalLinks(true);
+ text->setHtml(aboutHTML);
+ text->setReadOnly(true);
+ text->setMinimumSize(QSize(500, 300));
+ vbox->addWidget(text);
+
+ QHBoxLayout *btnBox = new QHBoxLayout();
+ vbox->addLayout(btnBox);
+
+ QPushButton *closeBtn = new QPushButton("Close");
+ closeBtn->setDefault(true);
+ btnBox->addStretch(1);
+ btnBox->addWidget(closeBtn);
+ btnBox->addStretch(1);
+ connect(closeBtn, SIGNAL(clicked()), aboutDialog, SLOT(accept()));
+}
+
+#define nSaveImageFormats 3
+static struct {
+ const char *comboBoxText;
+ const char *fileFilter;
+ const char *qImageFormat;
+} saveImageFormats[nSaveImageFormats] = {
+ { "JPEG", "JPEG files (*.jpg)", "JPEG" },
+ { "PNG", "PNG files (*.png)", "PNG" },
+ { "TIFF", "TIFF files (*.tiff)", "TIFF" }
+};
+
+void XpdfViewer::execSaveImageDialog() {
+ int i;
+
+ QDialog *dialog = new QDialog();
+ dialog->setWindowTitle("XpdfReader: Save Image");
+
+ QVBoxLayout *vbox = new QVBoxLayout();
+ dialog->setLayout(vbox);
+
+ QGridLayout *grid = new QGridLayout();
+ vbox->addLayout(grid);
+
+ grid->addWidget(new QLabel("Region:"), 0, 0);
+
+ QHBoxLayout *regionBox = new QHBoxLayout();
+ grid->addLayout(regionBox, 0, 1);
+
+ QButtonGroup *regionBtnGroup = new QButtonGroup(dialog);
+
+ QRadioButton *pageBtn = new QRadioButton("Page:");
+ regionBtnGroup->addButton(pageBtn);
+ regionBox->addWidget(pageBtn);
+ pageBtn->setChecked(true);
+
+ QLineEdit *pageEdit = new QLineEdit();
+ regionBox->addWidget(pageEdit);
+#if QT_VERSION >= QT_VERSION_CHECK(5, 11, 0)
+ pageEdit->setFixedWidth(8 * pageEdit->fontMetrics().horizontalAdvance("0"));
+#else
+ pageEdit->setFixedWidth(8 * pageEdit->fontMetrics().width("0"));
+#endif
+ int pg = currentTab->pdf->getMidPage();
+ pageEdit->setText(QString().setNum(pg));
+ connect(pageEdit, SIGNAL(textChanged(const QString&)),
+ pageBtn, SLOT(click()));
+ connect(pageEdit, SIGNAL(cursorPositionChanged(int, int)),
+ pageBtn, SLOT(click()));
+ connect(pageEdit, SIGNAL(selectionChanged()), pageBtn, SLOT(click()));
+
+ regionBox->addSpacing(20);
+
+ QRadioButton *selectionBtn = new QRadioButton("Current selection");
+ regionBtnGroup->addButton(selectionBtn);
+ regionBox->addWidget(selectionBtn);
+ selectionBtn->setEnabled(currentTab->pdf->hasSelection());
+
+ grid->addWidget(new QLabel("Resolution:"), 2, 0);
+
+ QHBoxLayout *resolutionBox = new QHBoxLayout();
+ grid->addLayout(resolutionBox, 2, 1);
+
+ QLineEdit *resolutionEdit = new QLineEdit();
+ resolutionBox->addWidget(resolutionEdit);
+#if QT_VERSION >= QT_VERSION_CHECK(5, 11, 0)
+ resolutionEdit->setFixedWidth(
+ 8 * pageEdit->fontMetrics().horizontalAdvance("0"));
+#else
+ resolutionEdit->setFixedWidth(8 * pageEdit->fontMetrics().width("0"));
+#endif
+ int r = (int)floor(currentTab->pdf->getZoomPercent(pg) * 0.72 + 0.5);
+ resolutionEdit->setText(QString().setNum(r));
+
+ resolutionBox->addWidget(new QLabel("dpi"));
+
+ grid->addWidget(new QLabel("Format:"), 3, 0);
+
+ QHBoxLayout *formatBox = new QHBoxLayout();
+ grid->addLayout(formatBox, 3, 1);
+
+ QComboBox *formatCombo = new QComboBox();
+ formatBox->addWidget(formatCombo);
+ formatCombo->setEditable(false);
+ for (i = 0; i < nSaveImageFormats; ++i) {
+ formatCombo->addItem(saveImageFormats[i].comboBoxText);
+ }
+ formatCombo->setCurrentIndex(0);
+
+ formatBox->addStretch();
+
+ QHBoxLayout *btnBox = new QHBoxLayout();
+ vbox->addLayout(btnBox);
+
+ btnBox->addStretch();
+
+ QPushButton *cancelBtn = new QPushButton("Cancel");
+ btnBox->addWidget(cancelBtn);
+ connect(cancelBtn, SIGNAL(clicked()), dialog, SLOT(reject()));
+
+ QPushButton *okBtn = new QPushButton("Ok");
+ btnBox->addWidget(okBtn);
+ okBtn->setDefault(true);
+ connect(okBtn, SIGNAL(clicked()), dialog, SLOT(accept()));
+
+ dialog->setModal(true);
+
+ if (dialog->exec() == QDialog::Accepted) {
+ double res = resolutionEdit->text().toDouble();
+ bool wholePage = pageBtn->isChecked();
+ int page;
+ double x0, y0, x1, y1;
+ if (wholePage) {
+ page = pageEdit->text().toInt();
+ if (page < 1 || page > currentTab->pdf->getNumPages()) {
+ page = 1;
+ }
+ x0 = y0 = x1 = y1 = 0;
+ } else {
+ currentTab->pdf->getCurrentSelection(&page, &x0, &y0, &x1, &y1);
+ }
+ int fmt = formatCombo->currentIndex();
+ QString fileName =
+ QFileDialog::getSaveFileName(this, "Save Image",
+ QString(),
+ saveImageFormats[fmt].fileFilter);
+ if (!fileName.isEmpty()) {
+ QImage img;
+ if (wholePage) {
+ img = currentTab->pdf->convertPageToImage(page, res);
+ } else {
+ img = currentTab->pdf->convertRegionToImage(page, x0, y0, x1, y1, res);
+ }
+ img.save(fileName, saveImageFormats[fmt].qImageFormat);
+ }
+ }
+
+ delete dialog;
+}
diff --git a/xpdf-qt/XpdfViewer.h b/xpdf-qt/XpdfViewer.h
new file mode 100644
index 0000000..f957626
--- /dev/null
+++ b/xpdf-qt/XpdfViewer.h
@@ -0,0 +1,508 @@
+//========================================================================
+//
+// XpdfViewer.h
+//
+// Copyright 2015 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef XPDFVIEWER_H
+#define XPDFVIEWER_H
+
+#include <aconf.h>
+
+#include <QDialog>
+#include <QIcon>
+#include <QLocalServer>
+#include <QMainWindow>
+#include <QToolButton>
+#include "gtypes.h"
+#include "Error.h"
+#include "XpdfWidget.h"
+
+class GString;
+class GList;
+class PropertyListAnimation;
+class QComboBox;
+class QDialog;
+class QHBoxLayout;
+class QInputEvent;
+class QLabel;
+class QLineEdit;
+class QListWidget;
+class QListWidgetItem;
+class QMenu;
+class QModelIndex;
+class QProgressDialog;
+class QSignalMapper;
+class QSplitter;
+class QStackedLayout;
+class QStackedWidget;
+class QTextBrowser;
+class QTimer;
+class QToolBar;
+class QToolButton;
+class XpdfApp;
+class XpdfMenuButton;
+class XpdfTabInfo;
+class XpdfViewer;
+
+//------------------------------------------------------------------------
+
+struct XpdfViewerCmd {
+ const char *name;
+ int nArgs;
+ GBool requiresDoc;
+ GBool requiresEvent;
+ void (XpdfViewer::*func)(GString *args[], int nArgs, QInputEvent *event);
+};
+
+//------------------------------------------------------------------------
+// XpdfMenuButton
+//------------------------------------------------------------------------
+
+class XpdfMenuButton: public QToolButton {
+ Q_OBJECT
+
+public:
+
+ XpdfMenuButton(QMenu *menuA);
+
+private slots:
+
+ void btnPressed();
+
+private:
+
+ QMenu *menu;
+};
+
+//------------------------------------------------------------------------
+// XpdfErrorWindow
+//------------------------------------------------------------------------
+
+class XpdfErrorWindow: public QWidget {
+ Q_OBJECT
+
+public:
+
+ XpdfErrorWindow(XpdfViewer *viewerA, int errorEventTypeA);
+ virtual ~XpdfErrorWindow();
+ virtual QSize sizeHint() const;
+ virtual void closeEvent(QCloseEvent *event);
+ virtual void keyPressEvent(QKeyEvent *event);
+ virtual void customEvent(QEvent *event);
+
+private slots:
+
+ void clearBtnPressed();
+
+private:
+
+ static void errorCbk(void *data, ErrorCategory category,
+ int pos, char *msg);
+ static void dummyErrorCbk(void *data, ErrorCategory category,
+ int pos, char *msg);
+
+ XpdfViewer *viewer;
+ int errorEventType;
+ QListWidget *list;
+ QSize lastSize;
+};
+
+//------------------------------------------------------------------------
+// XpdfViewer
+//------------------------------------------------------------------------
+
+class XpdfViewer: public QMainWindow {
+ Q_OBJECT
+
+public:
+
+ XpdfViewer(XpdfApp *appA, GBool fullScreen);
+
+ static XpdfViewer *create(XpdfApp *app, QString fileName, int page,
+ QString destName, int rot, QString password,
+ GBool fullScreen);
+
+ virtual ~XpdfViewer();
+
+ virtual QSize sizeHint() const;
+
+ void tweakSize();
+
+ // Open a file in the current tab. Returns a boolean indicating
+ // success.
+ GBool open(QString fileName, int page, QString destName, int rot,
+ QString password);
+
+ // Open a file in a new tab. Returns a boolean indicating success.
+ GBool openInNewTab(QString fileName, int page, QString destName,
+ int rot, QString password, GBool switchToTab);
+
+ // Check that [fileName] is open in the current tab -- if not, open
+ // it. In either case, switch to [page] or [destName]. Returns a
+ // boolean indicating success.
+ GBool checkOpen(QString fileName, int page, QString destName,
+ QString password);
+
+ virtual QMenu *createPopupMenu();
+
+ // Start up the remote server socket.
+ void startRemoteServer(const QString &remoteServerName);
+
+ // Execute a command [cmd], with [event] for context.
+ void execCmd(const char *cmd, QInputEvent *event);
+
+public slots:
+
+ bool close();
+
+private slots:
+
+ void remoteServerConnection();
+ void remoteServerRead();
+
+ void pdfResized();
+ void pdfPaintDone(bool finished);
+ void preLoad();
+ void postLoad();
+ void keyPress(QKeyEvent *e);
+ void mousePress(QMouseEvent *e);
+ void mouseRelease(QMouseEvent *e);
+ void mouseClick(QMouseEvent *e);
+ void mouseDoubleClick(QMouseEvent *e);
+ void mouseTripleClick(QMouseEvent *e);
+ void mouseWheel(QWheelEvent *e);
+ void mouseMove(QMouseEvent *e);
+ void pageChange(int pg);
+ void sidebarSplitterMoved(int pos, int index);
+#if XPDFWIDGET_PRINTING
+ void printStatus(int nextPage, int firstPage, int lastPage);
+ void cancelPrint();
+#endif
+
+ void openMenuAction();
+ void openInNewWinMenuAction();
+ void reloadMenuAction();
+ void saveAsMenuAction();
+ void saveImageMenuAction();
+#if XPDFWIDGET_PRINTING
+ void printMenuAction();
+#endif
+ void quitMenuAction();
+ void copyMenuAction();
+ void singlePageModeMenuAction();
+ void continuousModeMenuAction();
+ void sideBySideSingleModeMenuAction();
+ void sideBySideContinuousModeMenuAction();
+ void horizontalContinuousModeMenuAction();
+ void fullScreenMenuAction(bool checked);
+ void rotateClockwiseMenuAction();
+ void rotateCounterclockwiseMenuAction();
+ void zoomToSelectionMenuAction();
+ void toggleToolbarMenuAction(bool checked);
+ void toggleSidebarMenuAction(bool checked);
+ void viewPageLabelsMenuAction(bool checked);
+ void documentInfoMenuAction();
+ void newTabMenuAction();
+ void newWindowMenuAction();
+ void closeTabMenuAction();
+ void closeWindowMenuAction();
+ void openErrorWindowMenuAction();
+ void helpMenuAction();
+ void keyBindingsMenuAction();
+ void aboutMenuAction();
+
+ void popupMenuAction(int idx);
+
+ void toggleSidebarButtonPressed();
+ void pageNumberChanged();
+ void backButtonPressed();
+ void forwardButtonPressed();
+ void zoomOutButtonPressed();
+ void zoomInButtonPressed();
+ void zoomIndexChanged(int idx);
+ void zoomEditingFinished();
+ void fitWidthButtonPressed();
+ void fitPageButtonPressed();
+ void selectModeButtonPressed();
+ void statusIndicatorPressed();
+ void findTextChanged();
+ void findNextButtonPressed();
+ void findPrevButtonPressed();
+ void newTabButtonPressed();
+
+ void switchTab(QListWidgetItem *current, QListWidgetItem *previous);
+ void tabsReordered(const QModelIndex &srcParent, int srcStart, int srcEnd,
+ const QModelIndex &destParent, int destRow);
+ void infoComboBoxChanged(int idx);
+ void outlineItemClicked(const QModelIndex& idx);
+ void layerItemClicked(const QModelIndex& idx);
+ void attachmentSaveClicked(int idx);
+
+ void clearFindError();
+
+private:
+
+ friend class XpdfErrorWindow;
+
+ //--- commands
+ int mouseX(QInputEvent *event);
+ int mouseY(QInputEvent *event);
+ void cmdAbout(GString *args[], int nArgs, QInputEvent *event);
+ void cmdBlockSelectMode(GString *args[], int nArgs, QInputEvent *event);
+ void cmdCheckOpenFile(GString *args[], int nArgs, QInputEvent *event);
+ void cmdCheckOpenFileAtDest(GString *args[], int nArgs, QInputEvent *event);
+ void cmdCheckOpenFileAtPage(GString *args[], int nArgs, QInputEvent *event);
+ void cmdCloseTabOrQuit(GString *args[], int nArgs, QInputEvent *event);
+ void cmdCloseSidebar(GString *args[], int nArgs, QInputEvent *event);
+ void cmdCloseSidebarMoveResizeWin(GString *args[], int nArgs, QInputEvent *event);
+ void cmdCloseSidebarResizeWin(GString *args[], int nArgs, QInputEvent *event);
+ void cmdCloseWindowOrQuit(GString *args[], int nArgs, QInputEvent *event);
+ void cmdContinuousMode(GString *args[], int nArgs, QInputEvent *event);
+ void cmdCopy(GString *args[], int nArgs, QInputEvent *event);
+ void cmdCopyLinkTarget(GString *args[], int nArgs, QInputEvent *event);
+#if 0 // for debugging
+ void cmdDebug1(GString *args[], int nArgs, QInputEvent *event);
+#endif
+ void cmdEndPan(GString *args[], int nArgs, QInputEvent *event);
+ void cmdEndSelection(GString *args[], int nArgs, QInputEvent *event);
+ void cmdExpandSidebar(GString *args[], int nArgs, QInputEvent *event);
+ void cmdFind(GString *args[], int nArgs, QInputEvent *event);
+ void cmdFindFirst(GString *args[], int nArgs, QInputEvent *event);
+ void cmdFindNext(GString *args[], int nArgs, QInputEvent *event);
+ void cmdFindPrevious(GString *args[], int nArgs, QInputEvent *event);
+ void cmdFocusToDocWin(GString *args[], int nArgs, QInputEvent *event);
+ void cmdFocusToPageNum(GString *args[], int nArgs, QInputEvent *event);
+ void cmdFollowLink(GString *args[], int nArgs, QInputEvent *event);
+ void cmdFollowLinkInNewTab(GString *args[], int nArgs, QInputEvent *event);
+ void cmdFollowLinkInNewTabNoSel(GString *args[], int nArgs, QInputEvent *event);
+ void cmdFollowLinkInNewWin(GString *args[], int nArgs, QInputEvent *event);
+ void cmdFollowLinkInNewWinNoSel(GString *args[], int nArgs, QInputEvent *event);
+ void cmdFollowLinkNoSel(GString *args[], int nArgs, QInputEvent *event);
+ void cmdFullScreenMode(GString *args[], int nArgs, QInputEvent *event);
+ void cmdGoBackward(GString *args[], int nArgs, QInputEvent *event);
+ void cmdGoForward(GString *args[], int nArgs, QInputEvent *event);
+ void cmdGotoDest(GString *args[], int nArgs, QInputEvent *event);
+ void cmdGotoLastPage(GString *args[], int nArgs, QInputEvent *event);
+ void cmdGotoPage(GString *args[], int nArgs, QInputEvent *event);
+ void cmdHelp(GString *args[], int nArgs, QInputEvent *event);
+ void cmdHideMenuBar(GString *args[], int nArgs, QInputEvent *event);
+ void cmdHideToolbar(GString *args[], int nArgs, QInputEvent *event);
+ void cmdHorizontalContinuousMode(GString *args[], int nArgs, QInputEvent *event);
+ void cmdLinearSelectMode(GString *args[], int nArgs, QInputEvent *event);
+ void cmdLoadTabState(GString *args[], int nArgs, QInputEvent *event);
+ void cmdNewTab(GString *args[], int nArgs, QInputEvent *event);
+ void cmdNewWindow(GString *args[], int nArgs, QInputEvent *event);
+ void cmdNextPage(GString *args[], int nArgs, QInputEvent *event);
+ void cmdNextPageNoScroll(GString *args[], int nArgs, QInputEvent *event);
+ void cmdNextTab(GString *args[], int nArgs, QInputEvent *event);
+ void cmdOpen(GString *args[], int nArgs, QInputEvent *event);
+ void cmdOpenErrorWindow(GString *args[], int nArgs, QInputEvent *event);
+ void cmdOpenFile(GString *args[], int nArgs, QInputEvent *event);
+ void cmdOpenFile2(GString *args[], int nArgs, QInputEvent *event);
+ void cmdOpenFileAtDest(GString *args[], int nArgs, QInputEvent *event);
+ void cmdOpenFileAtDestIn(GString *args[], int nArgs, QInputEvent *event);
+ void cmdOpenFileAtPage(GString *args[], int nArgs, QInputEvent *event);
+ void cmdOpenFileAtPageIn(GString *args[], int nArgs, QInputEvent *event);
+ void cmdOpenFileIn(GString *args[], int nArgs, QInputEvent *event);
+ void cmdOpenIn(GString *args[], int nArgs, QInputEvent *event);
+ void cmdOpenSidebar(GString *args[], int nArgs, QInputEvent *event);
+ void cmdOpenSidebarMoveResizeWin(GString *args[], int nArgs, QInputEvent *event);
+ void cmdOpenSidebarResizeWin(GString *args[], int nArgs, QInputEvent *event);
+ void cmdPageDown(GString *args[], int nArgs, QInputEvent *event);
+ void cmdPageUp(GString *args[], int nArgs, QInputEvent *event);
+ void cmdPostPopupMenu(GString *args[], int nArgs, QInputEvent *event);
+ void cmdPrevPage(GString *args[], int nArgs, QInputEvent *event);
+ void cmdPrevPageNoScroll(GString *args[], int nArgs, QInputEvent *event);
+ void cmdPrevTab(GString *args[], int nArgs, QInputEvent *event);
+#if XPDFWIDGET_PRINTING
+ void cmdPrint(GString *args[], int nArgs, QInputEvent *event);
+#endif
+ void cmdQuit(GString *args[], int nArgs, QInputEvent *event);
+ void cmdRaise(GString *args[], int nArgs, QInputEvent *event);
+ void cmdReload(GString *args[], int nArgs, QInputEvent *event);
+ void cmdRotateCW(GString *args[], int nArgs, QInputEvent *event);
+ void cmdRotateCCW(GString *args[], int nArgs, QInputEvent *event);
+ void cmdRun(GString *args[], int nArgs, QInputEvent *event);
+ void cmdSaveAs(GString *args[], int nArgs, QInputEvent *event);
+ void cmdSaveImage(GString *args[], int nArgs, QInputEvent *event);
+ void cmdSaveTabState(GString *args[], int nArgs, QInputEvent *event);
+ void cmdScrollDown(GString *args[], int nArgs, QInputEvent *event);
+ void cmdScrollDownNextPage(GString *args[], int nArgs, QInputEvent *event);
+ void cmdScrollLeft(GString *args[], int nArgs, QInputEvent *event);
+ void cmdScrollOutlineDown(GString *args[], int nArgs, QInputEvent *event);
+ void cmdScrollOutlineUp(GString *args[], int nArgs, QInputEvent *event);
+ void cmdScrollRight(GString *args[], int nArgs, QInputEvent *event);
+ void cmdScrollToBottomEdge(GString *args[], int nArgs, QInputEvent *event);
+ void cmdScrollToBottomRight(GString *args[], int nArgs, QInputEvent *event);
+ void cmdScrollToLeftEdge(GString *args[], int nArgs, QInputEvent *event);
+ void cmdScrollToRightEdge(GString *args[], int nArgs, QInputEvent *event);
+ void cmdScrollToTopEdge(GString *args[], int nArgs, QInputEvent *event);
+ void cmdScrollToTopLeft(GString *args[], int nArgs, QInputEvent *event);
+ void cmdScrollUp(GString *args[], int nArgs, QInputEvent *event);
+ void cmdScrollUpPrevPage(GString *args[], int nArgs, QInputEvent *event);
+ void cmdSelectLine(GString *args[], int nArgs, QInputEvent *event);
+ void cmdSelectWord(GString *args[], int nArgs, QInputEvent *event);
+ void cmdSetSelection(GString *args[], int nArgs, QInputEvent *event);
+ void cmdShowAttachmentsPane(GString *args[], int nArgs, QInputEvent *event);
+ void cmdShowDocumentInfo(GString *args[], int nArgs, QInputEvent *event);
+ void cmdShowKeyBindings(GString *args[], int nArgs, QInputEvent *event);
+ void cmdShowLayersPane(GString *args[], int nArgs, QInputEvent *event);
+ void cmdShowMenuBar(GString *args[], int nArgs, QInputEvent *event);
+ void cmdShowOutlinePane(GString *args[], int nArgs, QInputEvent *event);
+ void cmdShowToolbar(GString *args[], int nArgs, QInputEvent *event);
+ void cmdShrinkSidebar(GString *args[], int nArgs, QInputEvent *event);
+ void cmdSideBySideContinuousMode(GString *args[], int nArgs, QInputEvent *event);
+ void cmdSideBySideSingleMode(GString *args[], int nArgs, QInputEvent *event);
+ void cmdSinglePageMode(GString *args[], int nArgs, QInputEvent *event);
+ void cmdStartExtendedSelection(GString *args[], int nArgs, QInputEvent *event);
+ void cmdStartPan(GString *args[], int nArgs, QInputEvent *event);
+ void cmdStartSelection(GString *args[], int nArgs, QInputEvent *event);
+ void cmdToggleContinuousMode(GString *args[], int nArgs, QInputEvent *event);
+ void cmdToggleFullScreenMode(GString *args[], int nArgs, QInputEvent *event);
+ void cmdToggleMenuBar(GString *args[], int nArgs, QInputEvent *event);
+ void cmdToggleSelectMode(GString *args[], int nArgs, QInputEvent *event);
+ void cmdToggleSidebar(GString *args[], int nArgs, QInputEvent *event);
+ void cmdToggleSidebarMoveResizeWin(GString *args[], int nArgs, QInputEvent *event);
+ void cmdToggleSidebarResizeWin(GString *args[], int nArgs, QInputEvent *event);
+ void cmdToggleToolbar(GString *args[], int nArgs, QInputEvent *event);
+ void cmdViewPageLabels(GString *args[], int nArgs, QInputEvent *event);
+ void cmdViewPageNumbers(GString *args[], int nArgs, QInputEvent *event);
+ void cmdWindowMode(GString *args[], int nArgs, QInputEvent *event);
+ void cmdZoomFitPage(GString *args[], int nArgs, QInputEvent *event);
+ void cmdZoomFitWidth(GString *args[], int nArgs, QInputEvent *event);
+ void cmdZoomIn(GString *args[], int nArgs, QInputEvent *event);
+ void cmdZoomOut(GString *args[], int nArgs, QInputEvent *event);
+ void cmdZoomPercent(GString *args[], int nArgs, QInputEvent *event);
+ void cmdZoomToSelection(GString *args[], int nArgs, QInputEvent *event);
+ int scaleScroll(int delta);
+ void followLink(QInputEvent *event, GBool onlyIfNoSel,
+ GBool newTab, GBool newWindow);
+
+ //--- GUI events
+ int getModifiers(Qt::KeyboardModifiers qtMods);
+ int getContext(Qt::KeyboardModifiers qtMods);
+ int getMouseButton(Qt::MouseButton qtBtn);
+ virtual void keyPressEvent(QKeyEvent *e);
+ virtual void dragEnterEvent(QDragEnterEvent *e);
+ virtual void dropEvent(QDropEvent *e);
+ virtual bool eventFilter(QObject *watched, QEvent *event);
+
+ //--- GUI setup
+ void createWindow();
+ void createToolBar();
+ QToolButton *addToolBarButton(const QIcon &icon,
+ const char *slot, const char *tip);
+ XpdfMenuButton *addToolBarMenuButton(const QIcon &icon,
+ const char *tip, QMenu *menu);
+ void addToolBarSeparator();
+ void addToolBarSpacing(int w);
+ void addToolBarStretch();
+ void createMainMenu();
+ void createXpdfPopupMenu();
+ QWidget *createTabPane();
+ QWidget *createInfoPane();
+ void updateInfoPane();
+ void destroyWindow();
+ void enterFullScreenMode();
+ void exitFullScreenMode();
+ void addTab();
+ void closeTab(XpdfTabInfo *tab);
+ void gotoTab(int idx);
+ void updateModeInfo();
+ void updateZoomInfo();
+ void updateSelectModeInfo();
+ void updateDocInfo();
+ void updatePageNumberOrLabel(int pg);
+ void updateOutline(int pg);
+ void setOutlineOpenItems(const QModelIndex &idx);
+ void fillAttachmentList();
+ void statusIndicatorStart();
+ void statusIndicatorStop();
+ void statusIndicatorOk();
+ void statusIndicatorError();
+ void showFindError();
+ void createDocumentInfoDialog();
+ void updateDocumentInfoDialog(XpdfWidget *view);
+ QString createDocumentInfoMetadataHTML(XpdfWidget *view);
+ QString createDocumentInfoFontsHTML(XpdfWidget *view);
+ void createKeyBindingsDialog();
+ QString createKeyBindingsHTML();
+ void createAboutDialog();
+ void execSaveImageDialog();
+
+ static XpdfViewerCmd cmdTab[];
+
+ XpdfApp *app;
+
+ // menu
+ QMenuBar *mainMenu;
+ QMenu *displayModeSubmenu;
+ QAction *fullScreenMenuItem;
+ QAction *toggleToolbarMenuItem;
+ QAction *toggleSidebarMenuItem;
+ QAction *viewPageLabelsMenuItem;
+
+ // popup menu
+ QMenu *popupMenu;
+ QSignalMapper *popupMenuSignalMapper;
+
+ // toolbar
+ int toolBarFontSize; // used for HiDPI scaling
+ QToolBar *toolBar;
+ QLineEdit *pageNumber;
+ QLabel *pageCount;
+ QComboBox *zoomComboBox;
+ QToolButton *fitWidthBtn;
+ QToolButton *fitPageBtn;
+ QToolButton *selectModeBtn;
+ PropertyListAnimation *indicatorAnimation;
+ QList<QVariant> indicatorIcons;
+ QList<QVariant> indicatorErrIcons;
+ QLineEdit *findEdit;
+ QAction *findCaseSensitiveAction;
+ QAction *findWholeWordsAction;
+
+ // sidebar pane
+ QSplitter *sidebarSplitter;
+ int initialSidebarWidth;
+ int sidebarWidth;
+ QListWidget *tabList;
+ QComboBox *infoComboBox;
+ QStackedLayout *infoStack;
+
+ // viewer pane
+ QStackedWidget *viewerStack;
+
+ QLabel *linkTargetBar;
+ QString linkTargetInfo;
+
+ GList *tabInfo; // [XpdfTabInfo]
+ XpdfTabInfo *currentTab;
+ XpdfTabInfo *lastOpenedTab;
+
+ double scaleFactor;
+
+ XpdfWidget::DisplayMode fullScreenPreviousDisplayMode;
+ double fullScreenPreviousZoom;
+
+ QTimer *findErrorTimer;
+
+ XpdfErrorWindow *errorWindow;
+ QDialog *documentInfoDialog;
+ QTextBrowser *documentInfoMetadataTab;
+ QTextBrowser *documentInfoFontsTab;
+ QDialog *keyBindingsDialog;
+ QDialog *aboutDialog;
+#if XPDFWIDGET_PRINTING
+ QProgressDialog *printStatusDialog;
+#endif
+
+ QString lastFileOpened;
+
+ QLocalServer *remoteServer;
+};
+
+#endif
diff --git a/xpdf-qt/XpdfWidget.cc b/xpdf-qt/XpdfWidget.cc
new file mode 100644
index 0000000..f5ad763
--- /dev/null
+++ b/xpdf-qt/XpdfWidget.cc
@@ -0,0 +1,2256 @@
+//========================================================================
+//
+// XpdfWidget.cc
+//
+// Copyright 2009 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#ifdef _WIN32
+#include <windows.h>
+#endif
+#include <QApplication>
+#include <QMutex>
+#include <QKeyEvent>
+#include <QPaintEvent>
+#include <QTimer>
+#include <QAbstractScrollArea>
+#include <QGesture>
+#include <QGestureEvent>
+#if XPDFWIDGET_PRINTING
+# include <QPrinter>
+# include <QPrintDialog>
+#endif
+#include "gmem.h"
+#include "gmempp.h"
+#include "gfile.h"
+#include "GString.h"
+#include "GList.h"
+#include "SplashBitmap.h"
+#include "config.h"
+#include "GlobalParams.h"
+#include "PDFDoc.h"
+#include "Object.h"
+#include "SplashOutputDev.h"
+#include "Outline.h"
+#include "OptionalContent.h"
+#include "Link.h"
+#include "Annot.h"
+#include "AcroForm.h"
+#include "TextString.h"
+#include "QtPDFCore.h"
+#include "XpdfWidget.h"
+#if XPDFWIDGET_PRINTING
+# include "XpdfWidgetPrint.h"
+#endif
+
+//------------------------------------------------------------------------
+
+// Time (in ms) between incremental updates.
+#define incrementalUpdateInterval 100
+
+//------------------------------------------------------------------------
+
+QMutex XpdfWidget::initMutex;
+
+//------------------------------------------------------------------------
+
+XpdfWidget::XpdfWidget(const QColor &paperColor, const QColor &matteColor,
+ bool reverseVideo, QWidget *parentA):
+ QAbstractScrollArea(parentA)
+{
+ setup(paperColor, matteColor, reverseVideo);
+}
+
+XpdfWidget::XpdfWidget(QWidget *parentA, const QColor &paperColor,
+ const QColor &matteColor, bool reverseVideo):
+ QAbstractScrollArea(parentA)
+{
+ setup(paperColor, matteColor, reverseVideo);
+}
+
+void XpdfWidget::setup(const QColor &paperColor, const QColor &matteColor,
+ bool reverseVideo) {
+ SplashColor paperColor2, matteColor2;
+
+ init();
+
+ paperColor2[0] = (Guchar)paperColor.red();
+ paperColor2[1] = (Guchar)paperColor.green();
+ paperColor2[2] = (Guchar)paperColor.blue();
+ matteColor2[0] = (Guchar)matteColor.red();
+ matteColor2[1] = (Guchar)matteColor.green();
+ matteColor2[2] = (Guchar)matteColor.blue();
+ try {
+ core = new QtPDFCore(viewport(), horizontalScrollBar(),
+ verticalScrollBar(),
+ paperColor2, matteColor2, (GBool)reverseVideo);
+ core->setUpdateCbk(updateCbk, this);
+ core->setMidPageChangedCbk(midPageChangedCbk, this);
+ core->setPreLoadCbk(preLoadCbk, this);
+ core->setPostLoadCbk(postLoadCbk, this);
+ core->setLinkCbk(linkCbk, this);
+ core->setSelectDoneCbk(selectDoneCbk, this);
+ core->setPaintDoneCbk(paintDoneCbk, this);
+ core->setTileDoneCbk(tileDoneCbk, this);
+ connect(this, SIGNAL(tileDone()), viewport(), SLOT(update()));
+ scaleFactor = core->getScaleFactor();
+ } catch (GMemException e) {
+ //~ what should this do?
+ core = NULL;
+ }
+
+#if XPDFWIDGET_PRINTING
+ printerForDialog = NULL;
+ printDialog = NULL;
+ printHDPI = printVDPI = 0;
+#endif
+
+ keyPassthrough = false;
+ mousePassthrough = false;
+ lastMousePressX[0] = lastMousePressX[1] = lastMousePressX[2] = 0;
+ lastMousePressY[0] = lastMousePressY[1] = lastMousePressY[2] = 0;
+ lastMousePressTime[0] = lastMousePressTime[1] = lastMousePressTime[2] = 0;
+ lastMouseEventWasPress = false;
+
+ viewport()->installEventFilter(this);
+ touchPanEnabled = false;
+ touchZoomEnabled = false;
+ pinchZoomStart = 100;
+
+ tickTimer = new QTimer(this);
+ connect(tickTimer, SIGNAL(timeout()), this, SLOT(tick()));
+ tickTimer->start(incrementalUpdateInterval);
+}
+
+XpdfWidget::~XpdfWidget() {
+#if XPDFWIDGET_PRINTING
+ delete printerForDialog;
+ delete printDialog;
+#endif
+ delete tickTimer;
+ delete core;
+}
+
+void XpdfWidget::init(const QString &configFileName) {
+#ifdef _WIN32
+ char buf[512];
+ GString *dir, *path;
+ char *configFileName2;
+ int n;
+#endif
+
+ initMutex.lock();
+ if (!globalParams) {
+ try {
+#ifdef _WIN32
+ // get the executable directory
+ n = GetModuleFileNameA(NULL, buf, sizeof(buf));
+ if (n <= 0 || n >= sizeof(buf)) {
+ // error or path too long for buffer - just use the current dir
+ buf[0] = '\0';
+ }
+ dir = grabPath(buf);
+
+ // load the config file
+ path = NULL;
+ if (configFileName.isEmpty()) {
+ path = appendToPath(dir->copy(), xpdfSysConfigFile);
+ configFileName2 = path->getCString();
+ } else {
+ configFileName2 = (char *)configFileName.toLocal8Bit().constData();
+ }
+ globalParams = new GlobalParams(configFileName2);
+ globalParams->setBaseDir(dir->getCString());
+ globalParams->setErrQuiet(gTrue);
+ if (path) {
+ delete path;
+ }
+
+ // set up the base fonts
+ appendToPath(dir, "t1fonts");
+ globalParams->setupBaseFonts(dir->getCString());
+ delete dir;
+#else
+ globalParams = new GlobalParams(
+ (char *)configFileName.toLocal8Bit().constData());
+ globalParams->setErrQuiet(gTrue);
+ globalParams->setupBaseFonts(NULL);
+#endif
+ } catch (GMemException e) {
+ // there's no way to return an error code here
+ return;
+ }
+ }
+ initMutex.unlock();
+}
+
+void XpdfWidget::setConfig(const QString &command) {
+ GString *fileName;
+
+ init();
+ try {
+ fileName = new GString("(none)");
+ globalParams->parseLine((char *)command.toLocal8Bit().constData(),
+ fileName, 1);
+ delete fileName;
+ } catch (GMemException e) {
+ }
+}
+
+void XpdfWidget::enableHyperlinks(bool on) {
+ try {
+ core->enableHyperlinks((GBool)on);
+ } catch (GMemException e) {
+ }
+}
+
+void XpdfWidget::enableExternalHyperlinks(bool on) {
+ try {
+ core->enableExternalHyperlinks((GBool)on);
+ } catch (GMemException e) {
+ }
+}
+
+void XpdfWidget::enableSelect(bool on) {
+ try {
+ core->enableSelect((GBool)on);
+ } catch (GMemException e) {
+ }
+}
+
+void XpdfWidget::enablePan(bool on) {
+ try {
+ core->enablePan((GBool)on);
+ } catch (GMemException e) {
+ }
+}
+
+void XpdfWidget::enableTouchPan(bool on) {
+ touchPanEnabled = on;
+ if (touchPanEnabled) {
+ viewport()->grabGesture(Qt::PanGesture);
+ } else {
+ viewport()->ungrabGesture(Qt::PanGesture);
+ }
+}
+
+void XpdfWidget::enableTouchZoom(bool on) {
+ touchZoomEnabled = on;
+ if (touchZoomEnabled) {
+ viewport()->grabGesture(Qt::PinchGesture);
+ } else {
+ viewport()->ungrabGesture(Qt::PinchGesture);
+ }
+}
+
+void XpdfWidget::showPasswordDialog(bool showDlg) {
+ try {
+ core->setShowPasswordDialog((GBool)showDlg);
+ } catch (GMemException e) {
+ }
+}
+
+void XpdfWidget::setMatteColor(const QColor &matteColor) {
+ SplashColor matteColor2;
+
+ matteColor2[0] = (Guchar)matteColor.red();
+ matteColor2[1] = (Guchar)matteColor.green();
+ matteColor2[2] = (Guchar)matteColor.blue();
+ try {
+ core->setMatteColor(matteColor2);
+ } catch (GMemException e) {
+ }
+}
+
+void XpdfWidget::setReverseVideo(bool reverse) {
+ try {
+ core->setReverseVideo((GBool)reverse);
+ } catch (GMemException e) {
+ }
+}
+
+void XpdfWidget::setCursor(const QCursor &cursor) {
+ core->doSetCursor(cursor);
+}
+
+void XpdfWidget::unsetCursor() {
+ core->doUnsetCursor();
+}
+
+XpdfWidget::ErrorCode XpdfWidget::loadFile(const QString &fileName,
+ const QString &password) {
+ GString *passwordStr;
+#ifdef _WIN32
+ wchar_t *fileNameStr;
+ int n, i;
+#else
+ GString *fileNameStr;
+#endif
+ int err;
+
+ try {
+ if (password.isEmpty()) {
+ passwordStr = NULL;
+ } else {
+ passwordStr = new GString(password.toLocal8Bit().constData());
+ }
+#ifdef _WIN32
+ // this should use QString::toWCharArray(), but Qt builds their
+ // library with /Zc:wchar_t-, which confuses things
+ n = fileName.length();
+ fileNameStr = (wchar_t *)gmallocn(n, sizeof(wchar_t));
+ for (i = 0; i < n; ++i) {
+ fileNameStr[i] = (wchar_t)fileName[i].unicode();
+ }
+ err = core->loadFile(fileNameStr, n, passwordStr, passwordStr);
+ gfree(fileNameStr);
+#else
+ fileNameStr = new GString(fileName.toLocal8Bit().constData());
+ err = core->loadFile(fileNameStr, passwordStr, passwordStr);
+ delete fileNameStr;
+#endif
+ if (passwordStr) {
+ delete passwordStr;
+ }
+ if (!err) {
+ core->displayPage(1, gTrue, gFalse);
+ }
+ return (ErrorCode)err;
+ } catch (GMemException e) {
+ return pdfErrOutOfMemory;
+ }
+}
+
+XpdfWidget::ErrorCode XpdfWidget::loadMem(const char *buffer,
+ unsigned int bufferLength,
+ const QString &password) {
+ Object obj;
+ MemStream *stream;
+ GString *passwordStr;
+ int err;
+
+ try {
+ obj.initNull();
+ stream = new MemStream((char *)buffer, 0, bufferLength, &obj);
+ if (password.isEmpty()) {
+ passwordStr = NULL;
+ } else {
+ passwordStr = new GString(password.toLocal8Bit().constData());
+ }
+ err = core->loadFile(stream, passwordStr, passwordStr);
+ if (passwordStr) {
+ delete passwordStr;
+ }
+ if (!err) {
+ core->displayPage(1, gTrue, gFalse);
+ }
+ return (ErrorCode)err;
+ } catch (GMemException e) {
+ return pdfErrOutOfMemory;
+ }
+}
+
+XpdfWidget::ErrorCode XpdfWidget::readDoc(XpdfDocHandle *docPtr,
+ const QString &fileName,
+ const QString &password) {
+ GString *passwordStr;
+#ifdef _WIN32
+ wchar_t *fileNameStr;
+ int n, i;
+#else
+ GString *fileNameStr;
+#endif
+ PDFDoc *doc;
+ ErrorCode err;
+
+ *docPtr = NULL;
+ try {
+ if (password.isEmpty()) {
+ passwordStr = NULL;
+ } else {
+ passwordStr = new GString(password.toLocal8Bit().constData());
+ }
+#ifdef _WIN32
+ // this should use QString::toWCharArray(), but Qt builds their
+ // library with /Zc:wchar_t-, which confuses things
+ n = fileName.length();
+ fileNameStr = (wchar_t *)gmallocn(n, sizeof(wchar_t));
+ for (i = 0; i < n; ++i) {
+ fileNameStr[i] = (wchar_t)fileName[i].unicode();
+ }
+ doc = new PDFDoc(fileNameStr, n, passwordStr, passwordStr, core);
+ gfree(fileNameStr);
+#else
+ fileNameStr = new GString(fileName.toLocal8Bit().constData());
+ doc = new PDFDoc(fileNameStr, passwordStr, passwordStr, core);
+#endif
+ if (passwordStr) {
+ delete passwordStr;
+ }
+ if (doc->isOk()) {
+ *docPtr = doc;
+ err = pdfOk;
+ } else {
+ err = (ErrorCode)doc->getErrorCode();
+ delete doc;
+ }
+ } catch (GMemException e) {
+ err = pdfErrOutOfMemory;
+ }
+ return err;
+}
+
+XpdfWidget::ErrorCode XpdfWidget::loadDoc(XpdfDocHandle doc) {
+ if (!doc) {
+ return pdfErrNoHandle;
+ }
+ core->loadDoc((PDFDoc *)doc);
+ core->displayPage(1, gTrue, gFalse, gTrue);
+ return pdfOk;
+}
+
+void XpdfWidget::freeDoc(XpdfDocHandle doc) {
+ if (!doc) {
+ return;
+ }
+ delete (PDFDoc *)doc;
+}
+
+XpdfWidget::ErrorCode XpdfWidget::reload() {
+ try {
+ return (ErrorCode)core->reload();
+ } catch (GMemException e) {
+ return pdfErrOutOfMemory;
+ }
+}
+
+void XpdfWidget::closeFile() {
+ try {
+ core->clear();
+ } catch (GMemException e) {
+ }
+}
+
+XpdfWidget::ErrorCode XpdfWidget::saveAs(const QString &fileName) {
+ GString *s;
+
+ try {
+ if (!core->getDoc()) {
+ return pdfErrNoHandle;
+ }
+ s = new GString(fileName.toLocal8Bit().constData());
+ if (!core->getDoc()->saveAs(s)) {
+ delete s;
+ return pdfErrOpenFile;
+ }
+ delete s;
+ return pdfOk;
+ } catch (GMemException e) {
+ return pdfErrOutOfMemory;
+ }
+}
+
+bool XpdfWidget::hasOpenDocument() const {
+ try {
+ return core->getDoc() != NULL;
+ } catch (GMemException e) {
+ return false;
+ }
+}
+
+QString XpdfWidget::getFileName() const {
+ try {
+ if (!core->getDoc() || !core->getDoc()->getFileName()) {
+ return QString();
+ }
+#ifdef _WIN32
+ return QString::fromWCharArray(core->getDoc()->getFileNameU());
+#else
+ return QString::fromLocal8Bit(core->getDoc()->getFileName()->getCString());
+#endif
+ } catch (GMemException e) {
+ return QString();
+ }
+}
+
+int XpdfWidget::getNumPages() const {
+ try {
+ if (!core->getDoc()) {
+ return -1;
+ }
+ return core->getDoc()->getNumPages();
+ } catch (GMemException e) {
+ return -1;
+ }
+}
+
+int XpdfWidget::getCurrentPage() const {
+ try {
+ return core->getPageNum();
+ } catch (GMemException e) {
+ return -1;
+ }
+}
+
+int XpdfWidget::getMidPage() const {
+ try {
+ return core->getMidPageNum();
+ } catch (GMemException e) {
+ return -1;
+ }
+}
+
+void XpdfWidget::gotoPage(int pageNum) {
+ try {
+ core->displayPage(pageNum, gTrue, gFalse);
+ } catch (GMemException e) {
+ }
+}
+
+void XpdfWidget::gotoFirstPage() {
+ try {
+ core->displayPage(1, gTrue, gFalse);
+ } catch (GMemException e) {
+ }
+}
+
+void XpdfWidget::gotoLastPage() {
+ try {
+ if (!core->getDoc()) {
+ return;
+ }
+ core->displayPage(core->getDoc()->getNumPages(), gTrue, gFalse);
+ } catch (GMemException e) {
+ }
+}
+
+void XpdfWidget::gotoNextPage(bool scrollToTop) {
+ try {
+ core->gotoNextPage(1, scrollToTop);
+ } catch (GMemException e) {
+ }
+}
+
+void XpdfWidget::gotoPreviousPage(bool scrollToTop) {
+ try {
+ core->gotoPrevPage(1, scrollToTop, gFalse);
+ } catch (GMemException e) {
+ }
+}
+
+bool XpdfWidget::gotoNamedDestination(const QString &dest) {
+ GString *destStr;
+
+ try {
+ destStr = new GString(dest.toLocal8Bit().constData());
+ if (!core->gotoNamedDestination(destStr)) {
+ delete destStr;
+ return false;
+ }
+ delete destStr;
+ return true;
+ } catch (GMemException e) {
+ return false;
+ }
+}
+
+void XpdfWidget::goForward() {
+ try {
+ core->goForward();
+ } catch (GMemException e) {
+ }
+}
+
+void XpdfWidget::goBackward() {
+ try {
+ core->goBackward();
+ } catch (GMemException e) {
+ }
+}
+
+void XpdfWidget::scrollPageUp() {
+ try {
+ core->scrollPageUp();
+ } catch (GMemException e) {
+ }
+}
+
+void XpdfWidget::scrollPageDown() {
+ try {
+ core->scrollPageDown();
+ } catch (GMemException e) {
+ }
+}
+
+void XpdfWidget::scrollTo(int xx, int yy) {
+ try {
+ core->scrollTo(xx, yy);
+ } catch (GMemException e) {
+ }
+}
+
+void XpdfWidget::scrollBy(int dx, int dy) {
+ try {
+ core->scrollTo(core->getScrollX() + dx, core->getScrollY()+ dy);
+ } catch (GMemException e) {
+ }
+}
+
+int XpdfWidget::getScrollX() const {
+ try {
+ return core->getScrollX();
+ } catch (GMemException e) {
+ return 0;
+ }
+}
+
+int XpdfWidget::getScrollY() const {
+ try {
+ return core->getScrollY();
+ } catch (GMemException e) {
+ return 0;
+ }
+}
+
+void XpdfWidget::setZoom(double zoom) {
+ try {
+ core->setZoom(zoom);
+ } catch (GMemException e) {
+ }
+}
+
+double XpdfWidget::getZoom() const {
+ try {
+ return core->getZoom();
+ } catch (GMemException e) {
+ return 0;
+ }
+}
+
+double XpdfWidget::getZoomPercent(int page) const {
+ double zoom;
+
+ try {
+ if (!core->getDoc() ||
+ page < 1 || page > core->getDoc()->getNumPages()) {
+ return 0;
+ }
+ zoom = core->getZoom();
+ if (zoom <= 0) {
+ zoom = 100 * core->getZoomDPI(page) / 72;
+ }
+ return zoom;
+ } catch (GMemException e) {
+ return 0;
+ }
+}
+
+void XpdfWidget::zoomToRect(int page, double xMin, double yMin,
+ double xMax, double yMax) {
+ try {
+ core->zoomToRect(page, xMin, yMin, xMax, yMax);
+ } catch (GMemException e) {
+ }
+}
+
+void XpdfWidget::zoomCentered(double zoom) {
+ try {
+ core->zoomCentered(zoom);
+ } catch (GMemException e) {
+ }
+}
+
+void XpdfWidget::zoomToCurrentWidth() {
+ try {
+ core->zoomToCurrentWidth();
+ } catch (GMemException e) {
+ }
+}
+
+void XpdfWidget::setRotate(int rotate) {
+ if (!(rotate == 0 || rotate == 90 || rotate == 180 || rotate == 270)) {
+ return;
+ }
+ try {
+ core->setRotate(rotate);
+ } catch (GMemException e) {
+ }
+}
+
+int XpdfWidget::getRotate() const {
+ try {
+ return core->getRotate();
+ } catch (GMemException e) {
+ return 0;
+ }
+}
+
+void XpdfWidget::setContinuousMode(bool continuous) {
+ try {
+ core->setDisplayMode(continuous ? displayContinuous
+ : displaySingle);
+ } catch (GMemException e) {
+ }
+}
+
+bool XpdfWidget::getContinuousMode() const {
+ try {
+ return core->getDisplayMode() == displayContinuous;
+ } catch (GMemException e) {
+ return false;
+ }
+}
+
+void XpdfWidget::setDisplayMode(XpdfWidget::DisplayMode mode) {
+ try {
+ core->setDisplayMode((::DisplayMode)mode);
+ } catch (GMemException e) {
+ }
+}
+
+XpdfWidget::DisplayMode XpdfWidget::getDisplayMode() {
+ try {
+ return (XpdfWidget::DisplayMode)core->getDisplayMode();
+ } catch (GMemException e) {
+ return pdfDisplaySingle;
+ }
+}
+
+bool XpdfWidget::mouseOverLink() {
+ QPoint pt;
+ int page;
+ double xx, yy;
+
+ try {
+ if (core->getHyperlinksEnabled()) {
+ return core->getLinkAction() != NULL;
+ } else {
+ pt = mapFromGlobal(QCursor::pos());
+ if (!convertWindowToPDFCoords(pt.x(), pt.y(), &page, &xx, &yy)) {
+ return false;
+ }
+ return core->findLink(page, xx, yy) != NULL;
+ }
+ } catch (GMemException e) {
+ return false;
+ }
+}
+
+bool XpdfWidget::onLink(int page, double xx, double yy) {
+ try {
+ if (!core->getDoc()) {
+ return false;
+ }
+ if (page < 1 || page > core->getDoc()->getNumPages()) {
+ return false;
+ }
+ return core->findLink(page, xx, yy) != NULL;
+ } catch (GMemException e) {
+ return false;
+ }
+}
+
+QString XpdfWidget::getLinkInfo(int page, double xx, double yy) {
+ LinkAction *action;
+
+ try {
+ if (!core->getDoc()) {
+ return QString();
+ }
+ if (page < 1 || page > core->getDoc()->getNumPages()) {
+ return QString();
+ }
+ if (!(action = core->findLink(page, xx, yy))) {
+ return QString();
+ }
+ return core->getLinkInfo(action);
+ } catch (GMemException e) {
+ return QString();
+ }
+}
+
+QString XpdfWidget::getMouseLinkInfo() {
+ try {
+ if (!core->getLinkAction()) {
+ return QString();
+ }
+ return core->getLinkInfo(core->getLinkAction());
+ } catch (GMemException e) {
+ return QString();
+ }
+}
+
+bool XpdfWidget::gotoLinkAt(int page, double xx, double yy) {
+ LinkAction *action;
+
+ try {
+ if (!core->getDoc()) {
+ return false;
+ }
+ if (page < 1 || page > core->getDoc()->getNumPages()) {
+ return false;
+ }
+ if ((action = core->findLink(page, xx, yy))) {
+ if (!core->doAction(action)) {
+ return false;
+ }
+ }
+ } catch (GMemException e) {
+ }
+ return true;
+}
+
+bool XpdfWidget::getLinkTarget(int page, double xx, double yy,
+ QString &targetFileName, int &targetPage,
+ QString &targetDest) {
+ LinkAction *action;
+ LinkDest *dest;
+ GString *fileName, *namedDest, *path;
+ Ref pageRef;
+ char *s;
+
+ try {
+ if (!core->getDoc()) {
+ return false;
+ }
+ if (page < 1 || page > core->getDoc()->getNumPages()) {
+ return false;
+ }
+ if (!(action = core->findLink(page, xx, yy))) {
+ return false;
+ }
+ switch (action->getKind()) {
+ case actionGoTo:
+ if (!core->getDoc()->getFileName()) {
+ return false;
+ }
+ targetFileName = core->getDoc()->getFileName()->getCString();
+ if ((dest = ((LinkGoTo *)action)->getDest())) {
+ if (dest->isPageRef()) {
+ pageRef = dest->getPageRef();
+ targetPage = core->getDoc()->findPage(pageRef.num, pageRef.gen);
+ } else {
+ targetPage = dest->getPageNum();
+ }
+ targetDest = "";
+ } else if ((namedDest = ((LinkGoTo *)action)->getNamedDest())) {
+ targetDest = namedDest->getCString();
+ targetPage = 1;
+ }
+ return true;
+ case actionGoToR:
+ s = ((LinkGoToR *)action)->getFileName()->getCString();
+ if (isAbsolutePath(s)) {
+ targetFileName = s;
+ } else {
+ if (!core->getDoc()->getFileName()) {
+ return false;
+ }
+ path = appendToPath(
+ grabPath(core->getDoc()->getFileName()->getCString()), s);
+ targetFileName = path->getCString();
+ delete path;
+ }
+ if ((dest = ((LinkGoToR *)action)->getDest())) {
+ if (dest->isPageRef()) {
+ return false;
+ }
+ targetPage = dest->getPageNum();
+ targetDest = "";
+ } else if ((namedDest = ((LinkGoToR *)action)->getNamedDest())) {
+ targetDest = namedDest->getCString();
+ targetPage = 1;
+ }
+ return true;
+ case actionLaunch:
+ fileName = ((LinkLaunch *)action)->getFileName();
+ s = fileName->getCString();
+ if (!(fileName->getLength() >= 4 &&
+ (!strcmp(s + fileName->getLength() - 4, ".pdf") ||
+ !strcmp(s + fileName->getLength() - 4, ".PDF")))) {
+ return false;
+ }
+ if (isAbsolutePath(s)) {
+ targetFileName = s;
+ } else {
+ if (!core->getDoc()->getFileName()) {
+ return false;
+ }
+ path = appendToPath(
+ grabPath(core->getDoc()->getFileName()->getCString()), s);
+ targetFileName = path->getCString();
+ delete path;
+ }
+ targetPage = 1;
+ targetDest = "";
+ return true;
+ default:
+ return false;
+ }
+ } catch (GMemException e) {
+ return false;
+ }
+}
+
+XpdfAnnotHandle XpdfWidget::onAnnot(int page, double xx, double yy) {
+ try {
+ if (!core->getDoc()) {
+ return NULL;
+ }
+ return (XpdfAnnotHandle)core->findAnnot(page, xx, yy);
+ } catch (GMemException e) {
+ return NULL;
+ }
+}
+
+QString XpdfWidget::getAnnotType(XpdfAnnotHandle annot) {
+ try {
+ return ((Annot *)annot)->getType()->getCString();
+ } catch (GMemException e) {
+ return QString();
+ }
+}
+
+QString XpdfWidget::getAnnotContent(XpdfAnnotHandle annot) {
+ QString s;
+ Object annotObj, contentsObj;
+ TextString *ts;
+ Unicode *u;
+ int i;
+
+ try {
+ if (((Annot *)annot)->getObject(&annotObj)->isDict()) {
+ if (annotObj.dictLookup("Contents", &contentsObj)->isString()) {
+ ts = new TextString(contentsObj.getString());
+ u = ts->getUnicode();
+ for (i = 0; i < ts->getLength(); ++i) {
+ s.append((QChar)u[i]);
+ }
+ }
+ contentsObj.free();
+ }
+ annotObj.free();
+ return s;
+ } catch (GMemException e) {
+ return QString();
+ }
+}
+
+XpdfFormFieldHandle XpdfWidget::onFormField(int page, double xx, double yy) {
+ try {
+ if (!core->getDoc()) {
+ return NULL;
+ }
+ return (XpdfFormFieldHandle)core->findFormField(page, xx, yy);
+ } catch (GMemException e) {
+ return NULL;
+ }
+}
+
+QString XpdfWidget::getFormFieldType(XpdfFormFieldHandle field) {
+ try {
+ return ((AcroFormField *)field)->getType();
+ } catch (GMemException e) {
+ return QString();
+ }
+}
+
+QString XpdfWidget::getFormFieldName(XpdfFormFieldHandle field) {
+ Unicode *u;
+ QString s;
+ int length, i;
+
+ try {
+ u = ((AcroFormField *)field)->getName(&length);
+ for (i = 0; i < length; ++i) {
+ s.append((QChar)u[i]);
+ }
+ gfree(u);
+ return s;
+ } catch (GMemException e) {
+ return QString();
+ }
+}
+
+QString XpdfWidget::getFormFieldValue(XpdfFormFieldHandle field) {
+ Unicode *u;
+ QString s;
+ int length, i;
+
+ try {
+ u = ((AcroFormField *)field)->getValue(&length);
+ for (i = 0; i < length; ++i) {
+ s.append((QChar)u[i]);
+ }
+ gfree(u);
+ return s;
+ } catch (GMemException e) {
+ return QString();
+ }
+}
+
+void XpdfWidget::getFormFieldBBox(XpdfFormFieldHandle field, int *pageNum,
+ double *xMin, double *yMin,
+ double *xMax, double *yMax) {
+ try {
+ *pageNum = ((AcroFormField *)field)->getPageNum();
+ ((AcroFormField *)field)->getBBox(xMin, yMin, xMax, yMax);
+ } catch (GMemException e) {
+ }
+}
+
+bool XpdfWidget::convertWindowToPDFCoords(int winX, int winY,
+ int *page,
+ double *pdfX, double *pdfY) {
+ try {
+ return core->cvtWindowToUser(winX, winY, page, pdfX, pdfY);
+ } catch (GMemException e) {
+ return false;
+ }
+}
+
+void XpdfWidget::convertPDFToWindowCoords(int page, double pdfX, double pdfY,
+ int *winX, int *winY) {
+ try {
+ core->cvtUserToWindow(page, pdfX, pdfY, winX, winY);
+ } catch (GMemException e) {
+ }
+}
+
+void XpdfWidget::enableRedraw(bool enable) {
+ setUpdatesEnabled(enable);
+}
+
+void XpdfWidget::getPageBox(int page, const QString &box,
+ double *xMin, double *yMin,
+ double *xMax, double *yMax) const {
+ PDFRectangle *r;
+
+ *xMin = *yMin = *xMax = *yMax = 0;
+ try {
+ if (!core->getDoc()) {
+ return;
+ }
+ if (page < 1 || page > core->getDoc()->getNumPages()) {
+ return;
+ }
+ if (!box.compare("media", Qt::CaseInsensitive)) {
+ r = core->getDoc()->getCatalog()->getPage(page)->getMediaBox();
+ } else if (!box.compare("crop", Qt::CaseInsensitive)) {
+ r = core->getDoc()->getCatalog()->getPage(page)->getCropBox();
+ } else if (!box.compare("bleed", Qt::CaseInsensitive)) {
+ r = core->getDoc()->getCatalog()->getPage(page)->getBleedBox();
+ } else if (!box.compare("trim", Qt::CaseInsensitive)) {
+ r = core->getDoc()->getCatalog()->getPage(page)->getTrimBox();
+ } else if (!box.compare("art", Qt::CaseInsensitive)) {
+ r = core->getDoc()->getCatalog()->getPage(page)->getArtBox();
+ } else {
+ return;
+ }
+ *xMin = r->x1;
+ *yMin = r->y1;
+ *xMax = r->x2;
+ *yMax = r->y2;
+ } catch (GMemException e) {
+ }
+}
+
+double XpdfWidget::getPageWidth(int page) const {
+ try {
+ if (!core->getDoc()) {
+ return 0;
+ }
+ if (page < 1 || page > core->getDoc()->getNumPages()) {
+ return 0;
+ }
+ return core->getDoc()->getPageCropWidth(page);
+ } catch (GMemException e) {
+ return 0;
+ }
+}
+
+double XpdfWidget::getPageHeight(int page) const {
+ try {
+ if (!core->getDoc()) {
+ return 0;
+ }
+ if (page < 1 || page > core->getDoc()->getNumPages()) {
+ return 0;
+ }
+ return core->getDoc()->getPageCropHeight(page);
+ } catch (GMemException e) {
+ return 0;
+ }
+}
+
+int XpdfWidget::getPageRotation(int page) const {
+ try {
+ if (!core->getDoc()) {
+ return 0;
+ }
+ if (page < 1 || page > core->getDoc()->getNumPages()) {
+ return 0;
+ }
+ return core->getDoc()->getCatalog()->getPage(page)->getRotate();
+ } catch (GMemException e) {
+ return 0;
+ }
+}
+
+bool XpdfWidget::hasSelection() {
+ try {
+ return (bool)core->hasSelection();
+ } catch (GMemException e) {
+ return false;
+ }
+}
+
+bool XpdfWidget::getCurrentSelection(int *page, double *x0, double *y0,
+ double *x1, double *y1) const {
+ try {
+ return (bool)core->getSelection(page, x0, y0, x1, y1);
+ } catch (GMemException e) {
+ return false;
+ }
+}
+
+void XpdfWidget::setCurrentSelection(int page, double x0, double y0,
+ double x1, double y1) {
+ int ulx, uly, lrx, lry, t;
+
+ try {
+ core->cvtUserToDev(page, x0, y0, &ulx, &uly);
+ core->cvtUserToDev(page, x1, y1, &lrx, &lry);
+ if (ulx > lrx) {
+ t = ulx; ulx = lrx; lrx = t;
+ }
+ if (uly > lry) {
+ t = uly; uly = lry; lry = t;
+ }
+ core->setSelection(page, ulx, uly, lrx, lry);
+ } catch (GMemException e) {
+ }
+}
+
+void XpdfWidget::clearSelection() {
+ try {
+ core->clearSelection();
+ } catch (GMemException e) {
+ }
+}
+
+bool XpdfWidget::isBlockSelectMode() {
+ try {
+ return core->getSelectMode() == selectModeBlock;
+ } catch (GMemException e) {
+ return false;
+ }
+}
+
+bool XpdfWidget::isLinearSelectMode() {
+ try {
+ return core->getSelectMode() == selectModeLinear;
+ } catch (GMemException e) {
+ return false;
+ }
+}
+
+void XpdfWidget::setBlockSelectMode() {
+ try {
+ core->setSelectMode(selectModeBlock);
+ } catch (GMemException e) {
+ }
+}
+
+void XpdfWidget::setLinearSelectMode() {
+ try {
+ core->setSelectMode(selectModeLinear);
+ } catch (GMemException e) {
+ }
+}
+
+void XpdfWidget::setSelectionColor(const QColor &selectionColor) {
+ SplashColor col;
+
+ try {
+ col[0] = (Guchar)selectionColor.red();
+ col[1] = (Guchar)selectionColor.green();
+ col[2] = (Guchar)selectionColor.blue();
+ core->setSelectionColor(col);
+ } catch (GMemException e) {
+ }
+}
+
+
+void XpdfWidget::forceRedraw() {
+ try {
+ core->forceRedraw();
+ } catch (GMemException e) {
+ }
+}
+
+#if XPDFWIDGET_PRINTING
+
+bool XpdfWidget::okToPrint() const {
+ try {
+ if (!core->getDoc()) {
+ return false;
+ }
+ return (bool)core->getDoc()->okToPrint();
+ } catch (GMemException e) {
+ return false;
+ }
+}
+
+XpdfWidget::ErrorCode XpdfWidget::print(bool showDialog) {
+ GString *defaultPrinter;
+ ErrorCode err;
+
+ try {
+ if (!core->getDoc()) {
+ return pdfErrNoHandle;
+ }
+ if (!printerForDialog) {
+ printerForDialog = new QPrinter(QPrinter::HighResolution);
+ if ((defaultPrinter = globalParams->getDefaultPrinter())) {
+ printerForDialog->setPrinterName(
+ QString::fromUtf8(defaultPrinter->getCString()));
+ delete defaultPrinter;
+ }
+ }
+ printerForDialog->setFromTo(1, core->getDoc()->getNumPages());
+ if (showDialog) {
+ if (!printDialog) {
+ printDialog = new QPrintDialog(printerForDialog, this);
+ }
+ if (printDialog->exec() != QDialog::Accepted) {
+ return pdfErrPrinting;
+ }
+ }
+ printCanceled = false;
+ err = printPDF(core->getDoc(), printerForDialog,
+ printHDPI, printVDPI, this);
+ return err;
+ } catch (GMemException e) {
+ return pdfErrOutOfMemory;
+ }
+}
+
+XpdfWidget::ErrorCode XpdfWidget::print(QPrinter *prt) {
+ try {
+ if (!core->getDoc()) {
+ return pdfErrNoHandle;
+ }
+ printCanceled = false;
+ return printPDF(core->getDoc(), prt, printHDPI, printVDPI, this);
+ } catch (GMemException e) {
+ return pdfErrOutOfMemory;
+ }
+}
+
+void XpdfWidget::updatePrintStatus(int nextPage, int firstPage, int lastPage) {
+ emit printStatus(nextPage, firstPage, lastPage);
+}
+
+void XpdfWidget::setPrintDPI(int hDPI, int vDPI) {
+ printHDPI = hDPI;
+ printVDPI = vDPI;
+}
+
+#endif // XPDFWIDGET_PRINTING
+
+QImage XpdfWidget::convertPageToImage(int page, double dpi, bool transparent) {
+ try {
+ PDFDoc *doc = core->getDoc();
+ if (!doc) {
+ return QImage();
+ }
+ if (page < 1 || page > doc->getNumPages()) {
+ return QImage();
+ }
+ if (transparent) {
+ SplashColor paperColor;
+ paperColor[0] = paperColor[1] = paperColor[2] = 0xff; // unused
+ SplashOutputDev *out = new SplashOutputDev(splashModeRGB8, 1, gFalse,
+ paperColor);
+ out->setNoComposite(gTrue);
+ out->startDoc(doc->getXRef());
+ doc->displayPage(out, page, dpi, dpi, core->getRotate(),
+ gFalse, gTrue, gFalse);
+ SplashBitmap *bitmap = out->getBitmap();
+ QImage img(bitmap->getWidth(), bitmap->getHeight(),
+ QImage::Format_ARGB32);
+ Guchar *pix = bitmap->getDataPtr();
+ Guchar *alpha = bitmap->getAlphaPtr();
+ Guint *argb = (Guint *)img.bits();
+ for (int y = 0; y < bitmap->getHeight(); ++y) {
+ for (int x = 0; x < bitmap->getWidth(); ++x) {
+ *argb = (*alpha << 24) | (pix[0] << 16) | (pix[1] << 8) | pix[2];
+ pix += 3;
+ ++alpha;
+ ++argb;
+ }
+ }
+ delete out;
+ return img;
+ } else {
+ SplashColor paperColor;
+ paperColor[0] = paperColor[1] = paperColor[2] = 0xff;
+ SplashOutputDev *out = new SplashOutputDev(splashModeRGB8, 4, gFalse,
+ paperColor);
+ out->startDoc(doc->getXRef());
+ doc->displayPage(out, page, dpi, dpi, core->getRotate(),
+ gFalse, gTrue, gFalse);
+ SplashBitmap *bitmap = out->getBitmap();
+ QImage *img = new QImage((const uchar *)bitmap->getDataPtr(),
+ bitmap->getWidth(), bitmap->getHeight(),
+ QImage::Format_RGB888);
+ // force a copy
+ QImage img2(img->copy());
+ delete img;
+ delete out;
+ return img2;
+ }
+ } catch (GMemException e) {
+ return QImage();
+ }
+}
+
+QImage XpdfWidget::convertRegionToImage(int page, double x0, double y0,
+ double x1, double y1, double dpi,
+ bool transparent) {
+ try {
+ PDFDoc *doc = core->getDoc();
+ if (!doc) {
+ return QImage();
+ }
+ if (page < 1 || page > doc->getNumPages()) {
+ return QImage();
+ }
+
+ if (x0 > x1) {
+ double t = x0; x0 = x1; x1 = t;
+ }
+ if (y0 > y1) {
+ double t = y0; y0 = y1; y1 = t;
+ }
+ PDFRectangle *box = doc->getCatalog()->getPage(page)->getCropBox();
+ int rot = doc->getPageRotate(page);
+ double k = dpi / 72.0;
+ int sliceX, sliceY, sliceW, sliceH;
+ if (rot == 90) {
+ sliceX = (int)(k * (y0 - box->y1));
+ sliceY = (int)(k * (x0 - box->x1));
+ sliceW = (int)(k * (y1 - y0));
+ sliceH = (int)(k * (x1 - x0));
+ } else if (rot == 180) {
+ sliceX = (int)(k * (box->x2 - x1));
+ sliceY = (int)(k * (y0 - box->y1));
+ sliceW = (int)(k * (x1 - x0));
+ sliceH = (int)(k * (y1 - y0));
+ } else if (rot == 270) {
+ sliceX = (int)(k * (box->y2 - y1));
+ sliceY = (int)(k * (box->x2 - x1));
+ sliceW = (int)(k * (y1 - y0));
+ sliceH = (int)(k * (x1 - x0));
+ } else {
+ sliceX = (int)(k * (x0 - box->x1));
+ sliceY = (int)(k * (box->y2 - y1));
+ sliceW = (int)(k * (x1 - x0));
+ sliceH = (int)(k * (y1 - y0));
+ }
+
+ if (transparent) {
+ SplashColor paperColor;
+ paperColor[0] = paperColor[1] = paperColor[2] = 0xff; // unused
+ SplashOutputDev *out = new SplashOutputDev(splashModeRGB8, 1, gFalse,
+ paperColor);
+ out->setNoComposite(gTrue);
+ out->startDoc(doc->getXRef());
+ doc->displayPageSlice(out, page, dpi, dpi, core->getRotate(),
+ gFalse, gTrue, gFalse,
+ sliceX, sliceY, sliceW, sliceH);
+ SplashBitmap *bitmap = out->getBitmap();
+ QImage img(bitmap->getWidth(), bitmap->getHeight(),
+ QImage::Format_ARGB32);
+ Guchar *pix = bitmap->getDataPtr();
+ Guchar *alpha = bitmap->getAlphaPtr();
+ Guint *argb = (Guint *)img.bits();
+ for (int y = 0; y < bitmap->getHeight(); ++y) {
+ for (int x = 0; x < bitmap->getWidth(); ++x) {
+ *argb = (*alpha << 24) | (pix[0] << 16) | (pix[1] << 8) | pix[2];
+ pix += 3;
+ ++alpha;
+ ++argb;
+ }
+ }
+ delete out;
+ return img;
+ } else {
+ SplashColor paperColor;
+ paperColor[0] = paperColor[1] = paperColor[2] = 0xff;
+ SplashOutputDev *out = new SplashOutputDev(splashModeRGB8, 4, gFalse,
+ paperColor);
+ out->startDoc(doc->getXRef());
+ doc->displayPageSlice(out, page, dpi, dpi, core->getRotate(),
+ gFalse, gTrue, gFalse,
+ sliceX, sliceY, sliceW, sliceH);
+ SplashBitmap *bitmap = out->getBitmap();
+ QImage *img = new QImage((const uchar *)bitmap->getDataPtr(),
+ bitmap->getWidth(), bitmap->getHeight(),
+ QImage::Format_RGB888);
+ // force a copy
+ QImage img2(img->copy());
+ delete img;
+ delete out;
+ return img2;
+ }
+ } catch (GMemException e) {
+ return QImage();
+ }
+}
+
+QImage XpdfWidget::getThumbnail(int page) {
+ Object thumbObj, decodeObj, colorSpaceObj, obj;
+ Dict *thumbDict;
+ GfxColorSpace *colorSpace;
+ GfxImageColorMap *colorMap;
+ ImageStream *imgStream;
+ Guchar *line, *rgb;
+ int w, h, bpc, yy;
+
+ try {
+ if (!core->getDoc()) {
+ return QImage();
+ }
+ if (page < 1 || page > core->getDoc()->getNumPages()) {
+ return QImage();
+ }
+
+ // get the thumbnail image object
+ if (!core->getDoc()->getCatalog()->getPage(page)
+ ->getThumbnail(&thumbObj)->isStream()) {
+ thumbObj.free();
+ return QImage();
+ }
+
+ // get the image parameters
+ thumbDict = thumbObj.streamGetDict();
+ if (!thumbDict->lookup("Width", &obj)->isInt()) {
+ obj.free();
+ thumbObj.free();
+ return QImage();
+ }
+ w = obj.getInt();
+ obj.free();
+ if (!thumbDict->lookup("Height", &obj)->isInt()) {
+ obj.free();
+ thumbObj.free();
+ return QImage();
+ }
+ h = obj.getInt();
+ obj.free();
+ if (!thumbDict->lookup("BitsPerComponent", &obj)->isInt()) {
+ obj.free();
+ thumbObj.free();
+ return QImage();
+ }
+ bpc = obj.getInt();
+ obj.free();
+
+ // create the color space and color map
+ thumbDict->lookup("Decode", &decodeObj);
+ thumbDict->lookup("ColorSpace", &colorSpaceObj);
+ colorSpace = GfxColorSpace::parse(&colorSpaceObj
+ );
+ colorMap = new GfxImageColorMap(bpc, &decodeObj, colorSpace);
+ colorSpaceObj.free();
+ decodeObj.free();
+ imgStream = new ImageStream(thumbObj.getStream(),
+ w, colorSpace->getNComps(), bpc);
+
+ // create the QImage, and read the image data
+ QImage img(w, h, QImage::Format_RGB888);
+ rgb = (Guchar *)gmallocn(w, 3);
+ imgStream->reset();
+ for (yy = 0; yy < h; ++yy) {
+ line = imgStream->getLine();
+ colorMap->getRGBByteLine(line, rgb, w, gfxRenderingIntentPerceptual);
+ memcpy(img.scanLine(yy), rgb, 3 * w);
+ }
+ gfree(rgb);
+
+ delete colorMap;
+ delete imgStream;
+ thumbObj.free();
+
+ return img;
+ } catch (GMemException e) {
+ return QImage();
+ }
+}
+
+bool XpdfWidget::okToExtractText() const {
+ try {
+ if (!core->getDoc()) {
+ return false;
+ }
+ return (bool)core->getDoc()->okToCopy();
+ } catch (GMemException e) {
+ return false;
+ }
+}
+
+void XpdfWidget::setTextEncoding(const QString &encodingName) {
+ init();
+ try {
+ globalParams->setTextEncoding((char *)encodingName.toLatin1().constData());
+ } catch (GMemException e) {
+ }
+}
+
+QString XpdfWidget::extractText(int page, double x0, double y0,
+ double x1, double y1) {
+ GString *s, *enc;
+ GBool twoByte;
+ QString ret;
+ int i;
+
+ try {
+ if (!core->getDoc()) {
+ return QString();
+ }
+ if (!(s = core->extractText(page, x0, y0, x1, y1))) {
+ return QString();
+ }
+ enc = globalParams->getTextEncodingName();
+ twoByte = !enc->cmp("UCS-2");
+ delete enc;
+ if (twoByte) {
+ for (i = 0; i+1 < s->getLength(); i += 2) {
+ ret.append((QChar)(((s->getChar(i) & 0xff) << 8) +
+ (s->getChar(i+1) & 0xff)));
+ }
+ } else {
+ ret.append(s->getCString());
+ }
+ delete s;
+ return ret;
+ } catch (GMemException e) {
+ return QString();
+ }
+}
+
+QString XpdfWidget::getSelectedText() {
+ try {
+ return core->getSelectedTextQString();
+ } catch (GMemException e) {
+ return "";
+ }
+}
+
+void XpdfWidget::copySelection() {
+ try {
+ core->copySelection(gTrue);
+ } catch (GMemException e) {
+ }
+}
+
+bool XpdfWidget::find(const QString &text, int flags) {
+ Unicode *u;
+ bool ret;
+ int len, i;
+
+ try {
+ if (!core->getDoc()) {
+ return false;
+ }
+ len = text.length();
+ u = (Unicode *)gmallocn(len, sizeof(Unicode));
+ for (i = 0; i < len; ++i) {
+ u[i] = (Unicode)text[i].unicode();
+ }
+ ret = (bool)core->findU(u, len,
+ (flags & findCaseSensitive) ? gTrue : gFalse,
+ (flags & findNext) ? gTrue : gFalse,
+ (flags & findBackward) ? gTrue : gFalse,
+ (flags & findWholeWord) ? gTrue : gFalse,
+ (flags & findOnePageOnly) ? gTrue : gFalse);
+ gfree(u);
+ return ret;
+ } catch (GMemException e) {
+ return false;
+ }
+}
+
+QVector<XpdfFindResult> XpdfWidget::findAll(const QString &text, int firstPage,
+ int lastPage, int flags) {
+ QVector<XpdfFindResult> v;
+ try {
+ if (!core->getDoc()) {
+ return v;
+ }
+ int len = text.length();
+ Unicode *u = (Unicode *)gmallocn(len, sizeof(Unicode));
+ for (int i = 0; i < len; ++i) {
+ u[i] = (Unicode)text[i].unicode();
+ }
+ GList *results = core->findAll(u, len,
+ (flags & findCaseSensitive) ? gTrue : gFalse,
+ (flags & findWholeWord) ? gTrue : gFalse,
+ firstPage, lastPage);
+ gfree(u);
+ for (int i = 0; i < results->getLength(); ++i) {
+ FindResult *result = (FindResult *)results->get(i);
+ v.append(XpdfFindResult(result->page, result->xMin, result->yMin,
+ result->xMax, result->yMax));
+ }
+ deleteGList(results, FindResult);
+ return v;
+ } catch (GMemException e) {
+ return v;
+ }
+}
+
+bool XpdfWidget::hasPageLabels() {
+ try {
+ if (!core->getDoc()) {
+ return false;
+ }
+ return core->getDoc()->getCatalog()->hasPageLabels();
+ } catch (GMemException e) {
+ return false;
+ }
+}
+
+QString XpdfWidget::getPageLabelFromPageNum(int pageNum) {
+ try {
+ if (!core->getDoc()) {
+ return QString();
+ }
+ TextString *ts = core->getDoc()->getCatalog()->getPageLabel(pageNum);
+ if (!ts) {
+ return QString();
+ }
+ QString qs;
+ Unicode *u = ts->getUnicode();
+ for (int i = 0; i < ts->getLength(); ++i) {
+ qs.append((QChar)u[i]);
+ }
+ delete ts;
+ return qs;
+ } catch (GMemException e) {
+ return QString();
+ }
+}
+
+int XpdfWidget::getPageNumFromPageLabel(QString pageLabel) {
+ try {
+ if (!core->getDoc()) {
+ return -1;
+ }
+ TextString *ts = new TextString();
+ for (int i = 0; i < pageLabel.size(); ++i) {
+ ts->append((Unicode)pageLabel.at(i).unicode());
+ }
+ int pg = core->getDoc()->getCatalog()->getPageNumFromPageLabel(ts);
+ delete ts;
+ return pg;
+ } catch (GMemException e) {
+ return -1;
+ }
+}
+
+int XpdfWidget::getOutlineNumChildren(XpdfOutlineHandle outline) {
+ GList *items;
+
+ try {
+ if (!core->getDoc()) {
+ return 0;
+ }
+ if (outline) {
+ ((OutlineItem *)outline)->open();
+ items = ((OutlineItem *)outline)->getKids();
+ } else {
+ items = core->getDoc()->getOutline()->getItems();
+ }
+ if (!items) {
+ return 0;
+ }
+ return items->getLength();
+ } catch (GMemException e) {
+ return 0;
+ }
+}
+
+XpdfOutlineHandle XpdfWidget::getOutlineChild(XpdfOutlineHandle outline,
+ int idx) {
+ GList *items;
+
+ try {
+ if (!core->getDoc()) {
+ return NULL;
+ }
+ if (outline) {
+ ((OutlineItem *)outline)->open();
+ items = ((OutlineItem *)outline)->getKids();
+ } else {
+ items = core->getDoc()->getOutline()->getItems();
+ }
+ if (!items) {
+ return NULL;
+ }
+ if (idx < 0 || idx >= items->getLength()) {
+ return NULL;
+ }
+ return (XpdfOutlineHandle)items->get(idx);
+ } catch (GMemException e) {
+ return NULL;
+ }
+}
+
+XpdfOutlineHandle XpdfWidget::getOutlineParent(XpdfOutlineHandle outline) {
+ if (!outline) {
+ return NULL;
+ }
+ return (XpdfOutlineHandle)((OutlineItem *)outline)->getParent();
+}
+
+QString XpdfWidget::getOutlineTitle(XpdfOutlineHandle outline) {
+ Unicode *title;
+ QString s;
+ int titleLen, i;
+
+ if (!outline) {
+ return QString();
+ }
+ try {
+ title = ((OutlineItem *)outline)->getTitle();
+ titleLen = ((OutlineItem *)outline)->getTitleLength();
+ for (i = 0; i < titleLen; ++i) {
+ s.append((QChar)title[i]);
+ }
+ return s;
+ } catch (GMemException e) {
+ return QString();
+ }
+}
+
+bool XpdfWidget::getOutlineStartsOpen(XpdfOutlineHandle outline) {
+ if (!outline) {
+ return false;
+ }
+ try {
+ return (bool)((OutlineItem *)outline)->isOpen();
+ } catch (GMemException e) {
+ return false;
+ }
+}
+
+int XpdfWidget::getOutlineTargetPage(XpdfOutlineHandle outline) {
+ try {
+ if (!outline || !core->getDoc()) {
+ return 0;
+ }
+ return core->getDoc()->getOutlineTargetPage((OutlineItem *)outline);
+ } catch (GMemException e) {
+ return 0;
+ }
+}
+
+void XpdfWidget::gotoOutlineTarget(XpdfOutlineHandle outline) {
+ if (!outline) {
+ return;
+ }
+ try {
+ if (((OutlineItem *)outline)->getAction()) {
+ core->doAction(((OutlineItem *)outline)->getAction());
+ }
+ } catch (GMemException e) {
+ }
+}
+
+int XpdfWidget::getNumLayers() const {
+ try {
+ if (!core->getDoc()) {
+ return 0;
+ }
+ return core->getDoc()->getOptionalContent()->getNumOCGs();
+ } catch (GMemException e) {
+ return 0;
+ }
+}
+
+XpdfLayerHandle XpdfWidget::getLayer(int idx) const {
+ try {
+ if (!core->getDoc() ||
+ idx < 0 ||
+ idx >= core->getDoc()->getOptionalContent()->getNumOCGs()) {
+ return NULL;
+ }
+ return (XpdfLayerHandle)core->getDoc()->getOptionalContent()->getOCG(idx);
+ } catch (GMemException e) {
+ return NULL;
+ }
+}
+
+QString XpdfWidget::getLayerName(XpdfLayerHandle layer) const {
+ Unicode *name;
+ QString s;
+ int nameLen, i;
+
+ if (!layer) {
+ return QString();
+ }
+ try {
+ name = ((OptionalContentGroup *)layer)->getName();
+ nameLen = ((OptionalContentGroup *)layer)->getNameLength();
+ for (i = 0; i < nameLen; ++i) {
+ s.append((QChar)name[i]);
+ }
+ return s;
+ } catch (GMemException e) {
+ return QString();
+ }
+}
+
+bool XpdfWidget::getLayerVisibility(XpdfLayerHandle layer) const {
+ if (!layer) {
+ return false;
+ }
+ try {
+ return (bool)((OptionalContentGroup *)layer)->getState();
+ } catch (GMemException e) {
+ return false;
+ }
+}
+
+void XpdfWidget::setLayerVisibility(XpdfLayerHandle layer, bool visibility) {
+ try {
+ if (!core->getDoc() || !layer) {
+ return;
+ }
+ core->setOCGState(((OptionalContentGroup *)layer), (GBool)visibility);
+ } catch (GMemException e) {
+ return;
+ }
+}
+
+int XpdfWidget::getLayerViewState(XpdfLayerHandle layer) const {
+ int s;
+
+ if (!layer) {
+ return 0;
+ }
+ try {
+ s = ((OptionalContentGroup *)layer)->getViewState();
+ return (s == ocUsageOn) ? 1 : (s == ocUsageOff) ? 0 : -1;
+ } catch (GMemException e) {
+ return 0;
+ }
+}
+
+int XpdfWidget::getLayerPrintState(XpdfLayerHandle layer) const {
+ int s;
+
+ if (!layer) {
+ return 0;
+ }
+ try {
+ s = ((OptionalContentGroup *)layer)->getPrintState();
+ return (s == ocUsageOn) ? 1 : (s == ocUsageOff) ? 0 : -1;
+ } catch (GMemException e) {
+ return 0;
+ }
+}
+
+XpdfLayerOrderHandle XpdfWidget::getLayerOrderRoot() const {
+ try {
+ if (!core->getDoc()) {
+ return NULL;
+ }
+ return (XpdfLayerOrderHandle)
+ core->getDoc()->getOptionalContent()->getDisplayRoot();
+ } catch (GMemException e) {
+ return NULL;
+ }
+}
+
+bool XpdfWidget::getLayerOrderIsName(XpdfLayerOrderHandle order) const {
+ if (!order) {
+ return false;
+ }
+ try {
+ return ((OCDisplayNode *)order)->getOCG() == NULL;
+ } catch (GMemException e) {
+ return false;
+ }
+}
+
+QString XpdfWidget::getLayerOrderName(XpdfLayerOrderHandle order) const {
+ Unicode *name;
+ QString s;
+ int nameLen, i;
+
+ if (!order) {
+ return QString();
+ }
+ try {
+ name = ((OCDisplayNode *)order)->getName();
+ nameLen = ((OCDisplayNode *)order)->getNameLength();
+ for (i = 0; i < nameLen; ++i) {
+ s.append((QChar)name[i]);
+ }
+ return s;
+ } catch (GMemException e) {
+ return QString();
+ }
+}
+
+XpdfLayerHandle XpdfWidget::getLayerOrderLayer(XpdfLayerOrderHandle order) {
+ if (!order) {
+ return NULL;
+ }
+ try {
+ return (XpdfLayerHandle)((OCDisplayNode *)order)->getOCG();
+ } catch (GMemException e) {
+ return NULL;
+ }
+}
+
+int XpdfWidget::getLayerOrderNumChildren(XpdfLayerOrderHandle order) {
+ if (!order) {
+ return 0;
+ }
+ try {
+ return ((OCDisplayNode *)order)->getNumChildren();
+ } catch (GMemException e) {
+ return 0;
+ }
+}
+
+XpdfLayerOrderHandle XpdfWidget::getLayerOrderChild(XpdfLayerOrderHandle order,
+ int idx) {
+ if (!order) {
+ return NULL;
+ }
+ try {
+ if (idx < 0 || idx >= ((OCDisplayNode *)order)->getNumChildren()) {
+ return NULL;
+ }
+ return (XpdfLayerOrderHandle)((OCDisplayNode *)order)->getChild(idx);
+ } catch (GMemException e) {
+ return NULL;
+ }
+}
+
+XpdfLayerOrderHandle XpdfWidget::getLayerOrderParent(
+ XpdfLayerOrderHandle order) {
+ if (!order) {
+ return NULL;
+ }
+ try {
+ return (XpdfLayerOrderHandle)((OCDisplayNode *)order)->getParent();
+ } catch (GMemException e) {
+ return NULL;
+ }
+}
+
+int XpdfWidget::getNumEmbeddedFiles() {
+ try {
+ if (!core->getDoc()) {
+ return 0;
+ }
+ return core->getDoc()->getNumEmbeddedFiles();
+ } catch (GMemException e) {
+ return 0;
+ }
+}
+
+QString XpdfWidget::getEmbeddedFileName(int idx) {
+ Unicode *name;
+ QString s;
+ int nameLen, i;
+
+ try {
+ if (!core->getDoc() ||
+ idx < 0 ||
+ idx >= core->getDoc()->getNumEmbeddedFiles()) {
+ return "";
+ }
+ name = core->getDoc()->getEmbeddedFileName(idx);
+ nameLen = core->getDoc()->getEmbeddedFileNameLength(idx);
+ for (i = 0; i < nameLen; ++i) {
+ s.append((QChar)name[i]);
+ }
+ return s;
+ } catch (GMemException e) {
+ return 0;
+ }
+}
+
+bool XpdfWidget::saveEmbeddedFile(int idx, QString fileName) {
+ try {
+ if (!core->getDoc() ||
+ idx < 0 ||
+ idx >= core->getDoc()->getNumEmbeddedFiles()) {
+ return false;
+ }
+ return core->getDoc()->saveEmbeddedFile(
+ idx, fileName.toLocal8Bit().constData());
+ } catch (GMemException e) {
+ return false;
+ }
+}
+
+QSize XpdfWidget::sizeHint() const {
+ try {
+ return core->getBestSize();
+ } catch (GMemException e) {
+ }
+ return QSize(612, 792);
+}
+
+//------------------------------------------------------------------------
+// callbacks from QtPDFCore
+//------------------------------------------------------------------------
+
+void XpdfWidget::updateCbk(void *data, GString *fileName,
+ int pageNum, int numPages,
+ const char *linkLabel) {
+ XpdfWidget *xpdf = (XpdfWidget *)data;
+
+ if (fileName) {
+ if (pageNum >= 0) {
+ emit xpdf->pageChange(pageNum);
+ }
+ }
+}
+
+void XpdfWidget::midPageChangedCbk(void *data, int pageNum) {
+ XpdfWidget *xpdf = (XpdfWidget *)data;
+
+ emit xpdf->midPageChange(pageNum);
+}
+
+void XpdfWidget::preLoadCbk(void *data) {
+ XpdfWidget *xpdf = (XpdfWidget *)data;
+
+ emit xpdf->preLoad();
+}
+
+void XpdfWidget::postLoadCbk(void *data) {
+ XpdfWidget *xpdf = (XpdfWidget *)data;
+
+ emit xpdf->postLoad();
+}
+
+void XpdfWidget::linkCbk(void *data, const char *type,
+ const char *dest, int page) {
+ XpdfWidget *xpdf = (XpdfWidget *)data;
+
+ emit xpdf->linkClick(type, dest, page);
+}
+
+void XpdfWidget::selectDoneCbk(void *data) {
+ XpdfWidget *xpdf = (XpdfWidget *)data;
+
+ emit xpdf->selectDone();
+}
+
+void XpdfWidget::paintDoneCbk(void *data, bool finished) {
+ XpdfWidget *xpdf = (XpdfWidget *)data;
+
+ emit xpdf->paintDone(finished);
+}
+
+// NB: this function is called on a worker thread.
+void XpdfWidget::tileDoneCbk(void *data) {
+ XpdfWidget *xpdf = (XpdfWidget *)data;
+
+ emit xpdf->tileDone();
+}
+
+
+//------------------------------------------------------------------------
+// events from the QAbstractScrollArea
+//------------------------------------------------------------------------
+
+void XpdfWidget::paintEvent(QPaintEvent *eventA) {
+ core->paintEvent(eventA->rect().left(),
+ eventA->rect().top(),
+ eventA->rect().width(),
+ eventA->rect().height());
+}
+
+void XpdfWidget::resizeEvent(QResizeEvent *eventA) {
+ core->resizeEvent();
+ emit resized();
+}
+
+void XpdfWidget::scrollContentsBy(int dx, int dy) {
+ core->scrollEvent();
+}
+
+void XpdfWidget::keyPressEvent(QKeyEvent *e) {
+ int key;
+
+ if (!keyPassthrough) {
+ key = e->key();
+ if (key == Qt::Key_Left) {
+ core->scrollLeft();
+ return;
+ } else if (key == Qt::Key_Right) {
+ core->scrollRight();
+ return;
+ } else if (key == Qt::Key_Up) {
+ core->scrollUp();
+ return;
+ } else if (key == Qt::Key_Down) {
+ core->scrollDown();
+ return;
+ } else if (key == Qt::Key_PageUp) {
+ core->scrollPageUp();
+ return;
+ } else if (key == Qt::Key_PageDown ||
+ key == Qt::Key_Space) {
+ core->scrollPageDown();
+ return;
+ }
+ }
+ emit keyPress(e);
+}
+
+void XpdfWidget::mousePressEvent(QMouseEvent *e) {
+ int x, y;
+
+ lastMousePressX[0] = lastMousePressX[1];
+ lastMousePressY[0] = lastMousePressY[1];
+ lastMousePressTime[0] = lastMousePressTime[1];
+ lastMousePressX[1] = lastMousePressX[2];
+ lastMousePressY[1] = lastMousePressY[2];
+ lastMousePressTime[1] = lastMousePressTime[2];
+ lastMousePressX[2] = e->pos().x();
+ lastMousePressY[2] = e->pos().y();
+ lastMousePressTime[2] = e->timestamp();
+ lastMouseEventWasPress = true;
+ if (!mousePassthrough) {
+ x = (int)(e->pos().x() * scaleFactor);
+ y = (int)(e->pos().y() * scaleFactor);
+ if (e->button() == Qt::LeftButton) {
+ core->startSelection(x, y, e->modifiers() & Qt::ShiftModifier);
+ } else if (e->button() == Qt::MiddleButton) {
+ core->startPan(x, y);
+ }
+ }
+ emit mousePress(e);
+}
+
+void XpdfWidget::mouseReleaseEvent(QMouseEvent *e) {
+ int x, y;
+
+ // some versions of Qt drop mouse press events in double-clicks (?)
+ if (!lastMouseEventWasPress) {
+ mousePressEvent(e);
+ }
+ lastMouseEventWasPress = false;
+
+ x = y = 0;
+ if (!mousePassthrough) {
+ x = (int)(e->pos().x() * scaleFactor);
+ y = (int)(e->pos().y() * scaleFactor);
+ if (e->button() == Qt::LeftButton) {
+ core->endSelection(x, y);
+ } else if (e->button() == Qt::MiddleButton) {
+ core->endPan(x, y);
+ }
+ }
+ emit mouseRelease(e);
+
+ // double and triple clicks have to be "quick" and "nearby";
+ // single clicks just have to be "nearby"
+ ulong maxTime = (ulong)QApplication::doubleClickInterval();
+ int maxDistance = QApplication::startDragDistance();
+ if (e->timestamp() - lastMousePressTime[0] < 2 * maxTime &&
+ abs(e->pos().x() - lastMousePressX[0])
+ + abs(e->pos().y() - lastMousePressY[0]) <= maxDistance) {
+ if (!mousePassthrough && e->button() == Qt::LeftButton) {
+ core->selectLine(x, y);
+ }
+ emit mouseTripleClick(e);
+ } else if (e->timestamp() - lastMousePressTime[1] < maxTime &&
+ abs(e->pos().x() - lastMousePressX[1])
+ + abs(e->pos().y() - lastMousePressY[1]) <= maxDistance) {
+ if (!mousePassthrough && e->button() == Qt::LeftButton) {
+ core->selectWord(x, y);
+ }
+ emit mouseDoubleClick(e);
+ } else if (abs(e->pos().x() - lastMousePressX[2])
+ + abs(e->pos().y() - lastMousePressY[2]) <= maxDistance) {
+ emit mouseClick(e);
+ }
+}
+
+void XpdfWidget::mouseMoveEvent(QMouseEvent *e) {
+ int x, y;
+
+ x = (int)(e->pos().x() * scaleFactor);
+ y = (int)(e->pos().y() * scaleFactor);
+ core->mouseMove(x, y);
+ emit mouseMove(e);
+}
+
+void XpdfWidget::wheelEvent(QWheelEvent *e) {
+ if (!mousePassthrough) {
+ QAbstractScrollArea::wheelEvent(e);
+ }
+ emit mouseWheel(e);
+}
+
+bool XpdfWidget::eventFilter(QObject *obj, QEvent *event) {
+ QGestureEvent *gestureEvent;
+ QPanGesture *panGesture;
+ QPinchGesture *pinchGesture;
+ double z;
+
+ if (obj == viewport() && event->type() == QEvent::Gesture) {
+ gestureEvent = (QGestureEvent *)event;
+ if (touchPanEnabled &&
+ (panGesture = (QPanGesture *)gestureEvent->gesture(Qt::PanGesture))) {
+ core->scrollTo(core->getScrollX() - (int)panGesture->delta().x(),
+ core->getScrollY() - (int)panGesture->delta().y());
+ gestureEvent->accept();
+ return true;
+ } else if (touchZoomEnabled &&
+ (pinchGesture =
+ (QPinchGesture *)gestureEvent->gesture(Qt::PinchGesture))) {
+ if (pinchGesture->changeFlags() & QPinchGesture::ScaleFactorChanged) {
+ if (pinchGesture->state() == Qt::GestureStarted) {
+ pinchZoomStart = getZoomPercent(core->getMidPageNum());
+ } else {
+ z = pinchZoomStart * pinchGesture->totalScaleFactor();
+ if (z < 10) {
+ z = 10;
+ } else if (z > 800) {
+ z = 800;
+ }
+ core->zoomCentered(z);
+ }
+ }
+ gestureEvent->accept();
+ return true;
+ }
+ }
+ return QAbstractScrollArea::eventFilter(obj, event);
+}
+
+void XpdfWidget::tick() {
+ core->tick();
+}
diff --git a/xpdf-qt/XpdfWidget.h b/xpdf-qt/XpdfWidget.h
new file mode 100644
index 0000000..0e33d0d
--- /dev/null
+++ b/xpdf-qt/XpdfWidget.h
@@ -0,0 +1,1029 @@
+//========================================================================
+//
+// XpdfWidget.h
+//
+// Copyright 2009-2021 Glyph & Cog, LLC
+//
+//========================================================================
+
+//! \mainpage
+//!
+//! XpdfWidget is a PDF viewer widget class for Qt.
+//! <br><br>
+//! <a href="changes.html">Change history</a>
+//! <br><br>
+//! Copyright 2009-2022 Glyph & Cog, LLC
+
+//! \file
+
+#ifndef XPDFWIDGET_H
+#define XPDFWIDGET_H
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include <QAbstractScrollArea>
+
+class QMutex;
+class QTimer;
+#if XPDFWIDGET_PRINTING
+class QPrinter;
+class QPrintDialog;
+#endif
+
+class GString;
+class PDFDoc;
+class QtPDFCore;
+
+//------------------------------------------------------------------------
+
+
+/*! Opaque handle used to represent an outline node. */
+typedef void *XpdfOutlineHandle;
+
+/*! Opaque handle used to represent a layer. */
+typedef void *XpdfLayerHandle;
+
+/*! Opaque handle used to represent a layer display order tree node. */
+typedef void *XpdfLayerOrderHandle;
+
+/*! Opaque handle used to represent an annotation. */
+typedef void *XpdfAnnotHandle;
+
+/*! Opaque handle used to represent a form field. */
+typedef void *XpdfFormFieldHandle;
+
+/*! Opaque handle used to represent a PDF document. */
+typedef void *XpdfDocHandle;
+
+//------------------------------------------------------------------------
+
+/*! Text search result, returned by XpdfWidget::findAll(). */
+struct XpdfFindResult {
+
+ //! \cond PROTECTED
+ XpdfFindResult(int pageA, double xMinA, double yMinA,
+ double xMaxA, double yMaxA)
+ : page(pageA), xMin(xMinA), yMin(yMinA), xMax(xMaxA), yMax(yMaxA) {}
+ XpdfFindResult(): page(0), xMin(0), yMin(0), xMax(0), yMax(0) {}
+ //! \endcond
+
+ /*! Page number. */
+ int page;
+
+ /*! \name Bounding box. */
+ ///@{
+ double xMin, yMin, xMax, yMax;
+ ///@}
+};
+
+//------------------------------------------------------------------------
+
+//! A PDF viewer widget class for Qt.
+class XpdfWidget: public QAbstractScrollArea {
+ Q_OBJECT
+
+public:
+
+ //! Error codes returned by certain XpdfViewer functions.
+ enum ErrorCode {
+ pdfOk = 0, //!< no error
+ pdfErrOpenFile = 1, //!< couldn't open the PDF file
+ pdfErrBadCatalog = 2, //!< couldn't read the page catalog
+ pdfErrDamaged = 3, //!< PDF file was damaged and couldn't be
+ //!< repaired
+ pdfErrEncrypted = 4, //!< file was encrypted and password was
+ //!< incorrect or not supplied
+ pdfErrHighlightFile = 5, //!< nonexistent or invalid highlight file
+ pdfErrBadPrinter = 6, //!< invalid printer
+ pdfErrPrinting = 7, //!< error during printing
+ pdfErrPermission = 8, //!< PDF file doesn't allow that operation
+ pdfErrBadPageNum = 9, //!< invalid page number
+ pdfErrFileIO = 10, //!< file I/O error
+ pdfErrNoHandle = 1001, //!< NULL object handle
+ pdfErrOutOfMemory = 1002, //!< out of memory
+ pdfErrBusy = 1003, //!< PDF component is busy
+ pdfErrBadArg = 1004 //!< invalid argument
+ };
+
+ //! Display modes, to be passed to XpdfWidget::setDisplayMode().
+ enum DisplayMode {
+ pdfDisplaySingle, //!< single page
+ pdfDisplayContinuous, //!< pages stacked vertically
+ pdfDisplaySideBySideSingle, //!< two facing pages
+ pdfDisplaySideBySideContinuous, //!< facing pages, stacked vertically
+ pdfDisplayHorizontalContinuous //!< pages stacked horizontally
+ };
+
+ //! \name Zoom values
+ //! Special values for XpdfWidget::setZoom() / XpdfWidget::getZoom()
+ //@{
+ static const int zoomToPage = -1; //!< zoom to fit whole page
+ static const int zoomToWidth = -2; //!< zoom to fit page width
+ static const int zoomToHeight = -3; //!< zoom to fit page height
+ //@}
+
+ //! \name Find flags
+ //! Flags to be passed to XpdfWidget::find()
+ //@{
+ //! search backward from the starting point
+ static const int findBackward = 0x00000001;
+ //! perform a case-sensitive search (default is case-insensitive)
+ static const int findCaseSensitive = 0x00000002;
+ //! start searching from the previous search result
+ static const int findNext = 0x00000004;
+ //! limit the search to the current page
+ static const int findOnePageOnly = 0x00000008;
+ //! limit the search to whole words
+ static const int findWholeWord = 0x00000010;
+ //@}
+
+ //! Initialize the XpdfWidget class, reading a configuration file.
+ //! If \a configFileName is non-empty, the specified file is
+ //! tried first. If \a configFileName is empty, or the file
+ //! doesn't exist, the default location is tried (\c <exe-dir>/xpdfrc
+ //! on Windows; \c ~/\c .xpdfrc on Unix).
+ //!
+ //! This function must be called before any other XpdfWidget functions
+ //! (including the constructor). It will be called automatically
+ //! (with a NULL \a configFileName) if it hasn't already been
+ //! called when the first XpdfWidget function is used.
+ static void init(const QString &configFileName = QString());
+
+ //! Process a configuration command, i.e., one line of an xpdfrc file.
+ //! Note that this applies globally to all XpdfWidget instances.
+ static void setConfig(const QString &command);
+
+ //! The XpdfWidget constructor.
+ //! \param paperColor the paper background color (which should generally
+ //! be left as white)
+ //! \param matteColor the matte color displayed between pages, and around
+ //! pages that are smaller than the window
+ //! \param reverseVideo sets reverse video at startup
+ //! \param parentA the parent QWidget
+ XpdfWidget(const QColor &paperColor = QColor(0xff, 0xff, 0xff),
+ const QColor &matteColor = QColor(0x80, 0x80, 0x80),
+ bool reverseVideo = false, QWidget *parentA = 0);
+
+ //! The XpdfWidget constructor.
+ //! \param paperColor the paper background color (which should generally
+ //! be left as white)
+ //! \param matteColor the matte color displayed between pages, and around
+ //! pages that are smaller than the window
+ //! \param reverseVideo sets reverse video at startup
+ //! \param parentA the parent QWidget
+ //! This version has the \a parent argument first so it works correctly
+ //! with Qt Designer.
+ XpdfWidget(QWidget *parentA,
+ const QColor &paperColor = QColor(0xff, 0xff, 0xff),
+ const QColor &matteColor = QColor(0x80, 0x80, 0x80),
+ bool reverseVideo = false);
+
+ //! Destroys the XpdfWidget.
+ virtual ~XpdfWidget();
+
+ //! Control handling of hyperlinks.
+ //! If enabled, the viewer will follow hyperlinks when clicked with the
+ //! left mouse button. If disabled, the viewer will ignore left mouse
+ //! button clicks on hyperlinks. The default is enabled.
+ void enableHyperlinks(bool on);
+
+ //! Control handling of external hyperlinks.
+ //! This setting allows disabling external hyperlinks (links that
+ //! open another PDF file, or that involve a URL), independent of
+ //! internal hyperlinks (links to locations within the same PDF
+ //! file). This setting is ignored if all hyperlinks are disabled
+ //! (enableHyperlinks(false)). The default is enabled.
+ void enableExternalHyperlinks(bool on);
+
+ //! Control handling of text selection.
+ //! If enabled, the viewer will allow the user to select rectangular
+ //! regions of text when the user drags with the left mouse button. If
+ //! disabled, dragging with the left mouse button is ignored. The
+ //! default is enabled.
+ void enableSelect(bool on);
+
+ //! Control mouse panning.
+ //! If enabled, dragging with the middle mouse button pressed will pan
+ //! the page. If disabled, the middle button is ignored. The default
+ //! is enabled.
+ void enablePan(bool on);
+
+ //! Control touchscreen panning.
+ //! If enabled, QPanGestures are recognized and used to pan the PDF
+ //! view.
+ void enableTouchPan(bool on);
+
+ //! Control touchscreen zooming.
+ //! If enabled QPinchGestures are recognized and used to pinch-zoom
+ //! the PDF view.
+ void enableTouchZoom(bool on);
+
+ //! Control keypress passthrough.
+ //! If enabled, XpdfWidget will pass keypress events through to the
+ //! keyPress signal, with no other processing. If disabled, XpdfWidget
+ //! will implement some built-in key bindings. The default is disabled.
+ void setKeyPassthrough(bool on) { keyPassthrough = on; }
+
+ //! Control mouse event passthrough.
+ //! If enabled, XpdfWidget will pass mouse events through to the
+ //! mousePress/mouseRelease signals, with no other processing. If
+ //! disabled, XpdfWidget will implement some built-in mouse handling
+ //! (in addition to sending the signals). The default is disabled.
+ void setMousePassthrough(bool on) { mousePassthrough = on; }
+
+ //! Control the password dialog.
+ //! If enabled, the viewer will show a password dialog for encrypted
+ //! files; if disabled, it will simply return \c pdfErrEncrypted unless
+ //! the correct password is passed to \c pdfLoadFileWithPassword. The
+ //! default is enabled.
+ void showPasswordDialog(bool showDlg);
+
+ //! Set the matte color, i.e., the color used for background outside
+ //! the actual page area. The default is a medium gray.
+ void setMatteColor(const QColor &matteColor);
+
+ //! Turn reverse video mode on/off. The default is off.
+ void setReverseVideo(bool reverse);
+
+ //! Set the cursor. The requested cursor will only be displayed in
+ //! the viewport (not in the scrollbars).
+ void setCursor(const QCursor &cursor);
+
+ //! Reset to the default cursor.
+ void unsetCursor();
+
+ //! Load a PDF file and display its first page.
+ //! \param fileName the PDF file to load
+ //! \param password a string to be tried first as the owner password
+ //! and then as the user password
+ //! \return \c pdfOk if successful; an error code, otherwise
+ ErrorCode loadFile(const QString &fileName,
+ const QString &password = "");
+
+ //! Load a PDF file from a memory buffer and display its first page.
+ //! \param buffer the PDF file in memory
+ //! \param bufferLength length of \a buffer
+ //! \param password a string to be tried first as the owner password
+ //! and then as the user password
+ //! \return \c pdfOk if successful; an error code otherwise
+ ErrorCode loadMem(const char *buffer, unsigned int bufferLength,
+ const QString &password = "");
+
+ //! Load a PDF file and return a handle.
+
+ //! This function can be safely called from a non-GUI thread. Use
+ //! XpdfWidget::loadDoc (on the GUI thread) to load the document
+ //! handle into the viewer. The handle returned in *\c docPtr
+ //! should be passed to either XpdfWidget::loadDoc or
+ //! XpdfWidget::freeDoc.
+ //!
+ //! Calling XpdfWidget::readDoc + XpdfWidget::loadDoc is equivalent
+ //! to calling XpdfWidget::loadFile. The difference is that readDoc
+ //! can be called on a background thread to avoid stalling the user
+ //! interface.
+ //! \param docPtr the PDF document handle will be returned her
+ //! \param fileName the PDF file to load
+ //! \param password a string to be tried first as the owner password
+ //! and then as the user password
+ //! \return \c pdfOk if successful; an error code, otherwise
+ ErrorCode readDoc(XpdfDocHandle *docPtr,
+ const QString &fileName,
+ const QString &password = "");
+
+ //! Load a PDF document and display its first page.
+ //! This function displays a PDF document handle created by
+ //! XpdfWidget::readDoc. The document handle should not be used for
+ //! anything else after calling this function.
+ //! \return \c pdfOk if successful; an error code, otherwise
+ ErrorCode loadDoc(XpdfDocHandle doc);
+
+ //! Free a PDF document.
+ //! This function frees a PDF document handle created by
+ //! XpdfWidget::readDoc. It should only be called if the document
+ //! is not going to be displayed. That is: after calling
+ //! XpdfWidget::readDoc, you should call either XpdfWidget::loadDoc
+ //! or XpdfWidget::freeDoc. The document handle should not be used
+ //! for anything else after calling this function.
+ void freeDoc(XpdfDocHandle doc);
+
+ //! Reload the current PDF file.
+ //! This reloads the current PDF file, maintaining the zoom and
+ //! scroll position (if possible). This only works if the PDF file
+ //! was loaded from a file (i.e., with XpdfWidget::loadFile, not
+ //! with XpdfWidget::loadMem).
+ //! \return \c pdfOk if successful; an error code otherwise
+ ErrorCode reload();
+
+ //! Close the currently open PDF file (if any).
+ //! Calling this function is optional - the current PDF file will be
+ //! automatically closed if XpdfWidget::loadFile or XpdfWidget::loadMem
+ //! is called.
+ void closeFile();
+
+ //! Save the PDF file with another name.
+ //! \param fileName the file to be written
+ //! \return \c pdfOk if successful; an error code otherwise
+ ErrorCode saveAs(const QString &fileName);
+
+ //! Get the file name of the currently open PDF file.
+ QString getFileName() const;
+
+ //! Returns true if there is currently a PDF file open.
+ bool hasOpenDocument() const;
+
+ //! Return the number of pages in the currently open PDF file.
+ //! Returns -1 if no file is open.
+ int getNumPages() const;
+
+ //! Return the currently displayed page number.
+ //! Returns -1 if no file is open.
+ int getCurrentPage() const;
+
+ //! Return the page number corresponding to the middle of the
+ //! window.
+ int getMidPage() const;
+
+ //! Display the specified page.
+ void gotoPage(int pageNum);
+
+ //! Display the first page.
+ //! This is equivalent to \code
+ //! gotoPage(1)
+ //! \endcode
+ void gotoFirstPage();
+
+ //! Display the last page.
+ //! This is equivalent to \code
+ //! gotoPage(getNumPages())
+ //! \endcode
+ void gotoLastPage();
+
+ //! Display the next page.
+ void gotoNextPage(bool scrollToTop = true);
+
+ //! Display the previous page.
+ void gotoPreviousPage(bool scrollToTop = true);
+
+ //! Go to a named destination.
+ bool gotoNamedDestination(const QString &dest);
+
+ //! Go forward along the history list.
+ void goForward();
+
+ //! Go backward along the history list.
+ void goBackward();
+
+ //! Scroll one screen up.
+ void scrollPageUp();
+
+ //! Scroll one screen down.
+ void scrollPageDown();
+
+ //! Scroll the page so that the top-left corner of the window is
+ //! (\a xx,\a yy) pixels from the top-left corner of the PDF page.
+ void scrollTo(int xx, int yy);
+
+ //! Scroll the page by (\a dx,\a dy) pixels. If \a dx is positive,
+ //! scrolls right; if \a dx is negative, scrolls left. Similarly,
+ //! positive and negative values of \a dy scroll down and up,
+ //! respectively.
+ void scrollBy(int dx, int dy);
+
+ //! Return the current scroll position x coordinate.
+ int getScrollX() const;
+
+ //! Return the current scroll position y coordinate.
+ int getScrollY() const;
+
+ //! Change the zoom factor.
+ //! This can be a percentage factor (where 100 means 72 dpi) or one of
+ //! the special values, XpdfWidget::zoomToPage or XpdfWidget::zoomToWidth.
+ void setZoom(double zoom);
+
+ //! Return the current zoom factor.
+ //! This can be a percentage factor or one of the special values,
+ //! XpdfWidget::zoomToPage or XpdfWidget::zoomToWidth.
+ double getZoom() const;
+
+ //! Return the current zoom factor as a percentage.
+ //! If the zoom is set to XpdfWidget::zoomToPage or
+ //! XpdfWidget::zoomToWidth, returns the computed zoom percentage
+ //! for the specified page, based on the current window size.
+ double getZoomPercent(int page = 1) const;
+
+ //! Zoom in to the specified rectangle.
+ //! The coordinate system is the same one used by
+ //! XpdfWidget::getCurrentSelection. This function will set the zoom
+ //! factor and scroll position so that the specified rectangle just fits
+ //! in the window.
+ void zoomToRect(int page, double xMin, double yMin,
+ double xMax, double yMax);
+
+ //! Set the zoom factor, while maintaining the current center.
+ //! Accepts the same zoom values as XpdfWidget::setZoom.
+ void zoomCentered(double zoom);
+
+ //! Zoom so that the current page(s) fill the window width.
+ //! Maintains the vertical center.
+ void zoomToCurrentWidth();
+
+ //! Change the page rotation.
+ //! \param rotate rotation angle in degrees - must be 0, 90, 180, or 270
+ void setRotate(int rotate);
+
+ //! Return the current page rotation.
+ //! The angle can be 0, 90, 180, or 270.
+ int getRotate() const;
+
+ //! Set continuous or single-page view mode.
+ //! Deprecated: this is equivalent to calling setDisplayMode() with
+ //! pdfDisplaySingle or pdfDisplayContinuous.
+ //! \param continuous true for continous view mode, false for single-page
+ //! view mode
+ void setContinuousMode(bool continuous);
+
+ //! Return true if the viewer is in continuous view mode, or false
+ //! if it is in any other mode. Deprecated: see getDisplayMode().
+ bool getContinuousMode() const;
+
+ //! Set the display mode.
+ void setDisplayMode(DisplayMode mode);
+
+ //! Return the current display mode.
+ DisplayMode getDisplayMode();
+
+ //! Returns true if the mouse is currently over a hyperlink.
+ bool mouseOverLink();
+
+ //! Returns true if the specified coordinates are inside a
+ //! hyperlink. Note: This function expects PDF coordinates, not window
+ //! coordinates.
+ bool onLink(int page, double xx, double yy);
+
+ //! Get destination information for the hyperlink at the specified
+ //! page and coordinates. If there is a link at the specified
+ //! point, returns a string suitable for displaying to a user;
+ //! otherwise returns an empty string. Note: This function expects
+ //! PDF coordinates, not window coordinates.
+ QString getLinkInfo(int page, double xx, double yy);
+
+ //! Get destination information for the hyperlink under the mouse.
+ //! If the mouse is currently over a hyperlink, return an info
+ //! string (same as with getLinkInfo()); otherwise return an empty
+ //! string.
+ QString getMouseLinkInfo();
+
+ //! Activate the link (if any) at the specified page and coordinates.
+ //! Returns true if successful. Note: This function expects PDF
+ //! coordinates, not window coordinates.
+ bool gotoLinkAt(int page, double xx, double yy);
+
+ //! Check for an annotation containing the specified point.
+ //! Returns NULL if there is no annotation at this point. Note:
+ //! This function expects PDF coordinates, not window coordinates.
+ XpdfAnnotHandle onAnnot(int page, double xx, double yy);
+
+ //! Get the annotation type.
+ QString getAnnotType(XpdfAnnotHandle annot);
+
+ //! Get the annotation's content.
+ //! Usage of this depends on the annotation type.
+ QString getAnnotContent(XpdfAnnotHandle annot);
+
+ //! Check for a form field containing the specified point.
+ //! Returns NULL if there is no annotation at this point. Note:
+ //! This function expects PDF coordinates, not window coordinates.
+ XpdfFormFieldHandle onFormField(int page, double xx, double yy);
+
+ //! Get the form field's type.
+ QString getFormFieldType(XpdfFormFieldHandle field);
+
+ //! Get the form field's name.
+ QString getFormFieldName(XpdfFormFieldHandle field);
+
+ //! Get the form field's content.
+ //! Usage of this depends on the field type.
+ QString getFormFieldValue(XpdfFormFieldHandle field);
+
+ //! Get the form field's bounding box.
+ void getFormFieldBBox(XpdfFormFieldHandle field, int *pageNum,
+ double *xMin, double *yMin,
+ double *xMax, double *yMax);
+
+ //! Convert window coordinates to PDF coordinates. Returns true if
+ //! successful, i.e., if the specified point falls on a PDF page.
+ bool convertWindowToPDFCoords(int winX, int winY,
+ int *page, double *pdfX, double *pdfY);
+
+ //! Convert PDF coordinates to window coordinates.
+ void convertPDFToWindowCoords(int page, double pdfX, double pdfY,
+ int *winX, int *winY);
+
+ //! Enable or disable window redraws.
+ //! This is useful, e.g., for avoiding extra redraws during window
+ //! resizing. Deprecated -- this just calls setUpdatesEnabled().
+ void enableRedraw(bool enable);
+
+ //! Return the coordinates of the specified page box.
+ //! \param page the page number
+ //! \param box the requested page box - one of "media", "crop",
+ //! "bleed", "trim", or "art" (\a box is not case-sensitive)
+ //! \param *xMin returns the minimum x coordinate of the box
+ //! \param *yMin returns the minimum y coordinate of the box
+ //! \param *xMax returns the maximum x coordinate of the box
+ //! \param *yMax returns the maximum y coordinate of the box
+ //!
+ //! All coordinates are in points (1 point = 1/72 inch).
+ void getPageBox(int page, const QString &box,
+ double *xMin, double *yMin, double *xMax, double *yMax) const;
+
+ //! Return the width of the specified page.
+ //! This function returns the crop box width, measured in points
+ //! (1 point = 1/72 inch).
+ double getPageWidth(int page) const;
+
+ //! Return the height of the specified page.
+ //! This function returns the crop box height, measured in points
+ //! (1 point = 1/72 inch).
+ double getPageHeight(int page) const;
+
+ //! Get the default rotation for the specified page.
+ //! This is the default viewing rotation specified in the PDF file -
+ //! it will be one of 0, 90, 180, or 270.
+ int getPageRotation(int page) const;
+
+ //! Check to see if there is a selection.
+ //! Returns true if there is a currently active selection.
+ bool hasSelection();
+
+ //! Returns the current selection.
+ //! If there is a currently active selection, sets *\a page, (*\a x0,*\a y0),
+ //! and (*\a x1,*\a y1) to the page number and upper-left and lower-right
+ //! coordinates, respectively, and returns true. If there is no selection,
+ //! returns false.
+ bool getCurrentSelection(int *page, double *x0, double *y0,
+ double *x1, double *y1) const;
+
+ //! Set the selection.
+ //! Sets the current selection to the rectangle with upper-left corner
+ //! (\a x0,\a y0) and lower-right corner (\a x1,\a y1) on \a page.
+ void setCurrentSelection(int page, double x0, double y0,
+ double x1, double y1);
+
+ //! Clear the selection.
+ void clearSelection();
+
+ //! Check for block selection mode.
+ //! Returns true if the current selection mode is block.
+ bool isBlockSelectMode();
+
+ //! Check for linear selection mode.
+ //! Returns true if the current selection mode is linear.
+ bool isLinearSelectMode();
+
+ //! Set block selection mode.
+ //! In this mode, the selection is a simple rectangle. Any part of
+ //! the page can be selected, regardless of the content on the page.
+ void setBlockSelectMode();
+
+ //! Set linear selection mode.
+ //! In this mode, the selection follows text. Non-text regions
+ //! cannot be selected.
+ void setLinearSelectMode();
+
+ //! Set the selection color.
+ void setSelectionColor(const QColor &selectionColor);
+
+
+ //! Force a complete redraw.
+ void forceRedraw();
+
+#if XPDFWIDGET_PRINTING
+ //! Checks to see if printing is allowed.
+ //! This function returns false if the currently displayed PDF file
+ //! is encrypted and does not allow printing (or if no PDF file is
+ //! currently open). The owner password can be used to circumvent
+ //! this: if a valid owner password was supplied to
+ //! XpdfWidget::loadFile, this function will always return true. If
+ //! this function returns false, the printing functions will return
+ //! an error.
+ bool okToPrint() const;
+
+ //! Print the currently displayed PDF file.
+ //! Prints the currently displayed PDF file. If \a showDialog is
+ //! true, displays the Qt print dialog, and uses the printer
+ //! selected by the user. If \a showDialog is false, prints to the
+ //! default printer without showing any dialogs.
+ ErrorCode print(bool showDialog);
+
+ //! Print the currently displayed PDF file.
+ //! Prints the currently displayed PDF file to \a prt.
+ ErrorCode print(QPrinter *prt);
+
+ //! Cancel an in-progress print job. This should be called in
+ //! response to a printStatus signal.
+ void cancelPrint() { printCanceled = true; }
+
+ void updatePrintStatus(int nextPage, int firstPage, int lastPage);
+ bool isPrintCanceled() { return printCanceled; }
+
+ //! Set the horizontal and vertical print resolution, in dots per
+ //! inch (DPI). The horizontal and vertical resolutions are
+ //! typically the same. (There are exceptions, such as some chart
+ //! printers.)
+ void setPrintDPI(int hDPI, int vDPI);
+#endif // XPDFWIDGET_PRINTING
+
+ //! Convert a page to a color image.
+ //! This function converts the page number \a page to a 24-bit RGB
+ //! bitmap, at a resolution of \a dpi dots per inch. If \a
+ //! transparent is true, the returned image will be 32-bit ARGB
+ //! instead, and will include an alpha channel.
+ QImage convertPageToImage(int page, double dpi, bool transparent = false);
+
+ //! Convert a rectangular region of a page to a color image.
+ //! This function converts a rectangular region, defined by corners
+ //! (\a x0,\a y0) and (\a x1,\a y1), of page number \a page to a
+ //! 24-bit RGB bitmap, at a resolution of \a dpi dots per inch. If
+ //! \a transparent is true, the returned image will be 32-bit ARGB
+ //! instead, and will include an alpha channel.
+ QImage convertRegionToImage(int page, double x0, double y0,
+ double x1, double y1, double dpi,
+ bool transparent = false);
+
+ //! Retrieve an embedded thumbnail image.
+ //! This function returns the embedded thumbnail image for the
+ //! specified page, or a null image if there is no embedded
+ //! thumbnail. This function does not do any rasterization -- it
+ //! only returns a non-null image if there is an embedded thumbnail
+ //! in the PDF file.
+ QImage getThumbnail(int page);
+
+ //! Checks to see if text extraction is allowed.
+ //! This function returns false if the currently displayed PDF file
+ //! is encrypted and does not allow extraction of text (or if no PDF
+ //! file is currently open). The owner password can be used to
+ //! circumvent this: if a valid owner password was supplied to
+ //! XpdfWidget::loadFile, this function will always return true.
+ //! If this function returns false, the text extraction functions will
+ //! not return any text.
+ bool okToExtractText() const;
+
+ //! Set the encoding to use for text extraction.
+ //! The following encodings are predefined:
+ //! - \c "Latin1": ISO-8859-1 (this is the default value)
+ //! - \c "ASCII7": 7-bit ASCII
+ //! - \c "UTF-8": Unicode in UTF-8 format
+ //! - \c "UCS-2": Unicode in UCS-2 format
+ //!
+ //! Additional encodings can be defined via the xpdfrc config file.
+ void setTextEncoding(const QString &encodingName);
+
+ //! Extract text from a region of a page.
+ //! This function extracts and returns text from the rectangular
+ //! region, defined by corners (\a x0,\a y0) and (\a x1,\a y1), of
+ //! page number \a page. The coordinates returned by
+ //! XpdfWidget::getCurrentSelection may be passed directly to this
+ //! function. Returns an empty string if no file is open or if
+ //! text extraction is not allowed.
+ QString extractText(int page, double x0, double y0,
+ double x1, double y1);
+
+ //! Get the currently selected text.
+ //! Returns an empty string if there is no selection (or if there is
+ //! no text in the selected region).
+ QString getSelectedText();
+
+ //! Copy the current selection to the clipboard.
+ void copySelection();
+
+ //! Find a text string.
+ //! This function searches for a Unicode text string. Starts
+ //! searching after (before, if searching backward) the current
+ //! selection (if there is a selection), or at the top (bottom,
+ //! if searching backward) of the current page (if there is no
+ //! selection). The \a flags argument consists of zero or more
+ //! of the following, or-ed together:
+ //! - \c findBackward - search backward from the starting point
+ //! - \c findCaseSensitive - perform a case-sensitive search
+ //! (default is case-insensitive)
+ //! - \c findNext - start searching from the previous search result
+ //! - \c findOnePageOnly - limit the search to the current page
+ //! - \c findWholeWord - limit the search to whole words
+ bool find(const QString &text, int flags = 0);
+
+ //! Find all occurrences of a text string.
+ //! This function searches for a Unicode text string, in pages
+ //! \a firstPage .. \a lastPage. The \a flags argument consists of
+ //! zero or more of the following, or-ed together:
+ //! - \c findCaseSensitive - perform a case-sensitive search
+ //! (default is case-insensitive)
+ //! - \c findWholeWord - limit the search to whole words
+ //! Returns a list of search results.
+ QVector<XpdfFindResult> findAll(const QString &text, int firstPage,
+ int lastPage, int flags = 0);
+
+ //! Check if the PDF file has page labels.
+ //! Return true if the currently open PDF file has page labels.
+ bool hasPageLabels();
+
+ //! Convert a page number to a page label.
+ //! Return the page label for page number \a pageNum. Returns an
+ //! empty string if the page number is invalid or if the PDF file
+ //! doesn't have page labels.
+ QString getPageLabelFromPageNum(int pageNum);
+
+ //! Convert a page label to a page number.
+ //! Return the page number for \a pageLabel. Returns -1 if there is
+ //! no matching page label or if the PDF file doesn't have page
+ //! labels.
+ int getPageNumFromPageLabel(QString pageLabel);
+
+ //! Return the number of children of an outline tree node.
+ //! This function returns the number of children of node \a outline,
+ //! or the number of root outline entries if \a outline is \c NULL.
+ int getOutlineNumChildren(XpdfOutlineHandle outline);
+
+ //! Return a child of an outline tree node.
+ //! This function returns the \a idx 'th child of node \a outline,
+ //! or the \a idx 'th root entry if \a outline is \c NULL.
+ XpdfOutlineHandle getOutlineChild(XpdfOutlineHandle outline, int idx);
+
+ //! Return the parent of an outline tree node.
+ //! This function returns the parent of node \a outline, or NULL if
+ //! \a outline is a root item.
+ XpdfOutlineHandle getOutlineParent(XpdfOutlineHandle outline);
+
+ //! Get the title of an outline tree node.
+ //! This function returns the title of node \a outline.
+ QString getOutlineTitle(XpdfOutlineHandle outline);
+
+ //! Return true if the specified outline entry starts open.
+ bool getOutlineStartsOpen(XpdfOutlineHandle outline);
+
+ //! Return the target page number for the specified outline entry.
+ int getOutlineTargetPage(XpdfOutlineHandle outline);
+
+ //! Jump to the target of the specified outline entry.
+ void gotoOutlineTarget(XpdfOutlineHandle outline);
+
+ //! Return the number of layers in the PDF file.
+ //! Note that a PDF file can have zero or more layers.
+ int getNumLayers() const;
+
+ //! Get a layer handle.
+ //! This function returns a handle for the \a idx 'th layer.
+ XpdfLayerHandle getLayer(int idx) const;
+
+ //! Get the name of a layer.
+ //! This function returns the title of \a layer.
+ QString getLayerName(XpdfLayerHandle layer) const;
+
+ //! Get the visibility state of a layer.
+ //! Returns true if the layer is currently visible, false if not.
+ bool getLayerVisibility(XpdfLayerHandle layer) const;
+
+ //! Set the visibility state of a layer.
+ //! \param layer the layer handle
+ //! \param visibility the new state - true for visible, false for not
+ //! visible
+ void setLayerVisibility(XpdfLayerHandle layer, bool visibility);
+
+ //! Get the suggested state for this layer in viewing mode.
+ //! This function returns one of:
+ //! - 1: on
+ //! - 0: off
+ //! - -1: unset
+ int getLayerViewState(XpdfLayerHandle layer) const;
+
+ //! Get the suggested state for this layer in printing mode.
+ //! This function returns one of:
+ //! - 1: on
+ //! - 0: off
+ //! - -1: unset
+ int getLayerPrintState(XpdfLayerHandle layer) const;
+
+ //! Get the root of the layer display order tree.
+ XpdfLayerOrderHandle getLayerOrderRoot() const;
+
+ //! Check the type of a layer display order tree node.
+ //! Returns true if the specified node of the layer display order
+ //! tree is a name; false if the node is a layer.
+ bool getLayerOrderIsName(XpdfLayerOrderHandle order) const;
+
+ //! Get the name of a layer display order tree node.
+ //! This should only be called if getLayerOrderIsName returns true.
+ QString getLayerOrderName(XpdfLayerOrderHandle order) const;
+
+ //! Get the layer associated with a layer display order tree node.
+ XpdfLayerHandle getLayerOrderLayer(XpdfLayerOrderHandle order);
+
+ //! Returns the number of children attached to a layer display order
+ //! tree node.
+ int getLayerOrderNumChildren(XpdfLayerOrderHandle order);
+
+ //! Returns the \a idx 'th child of a layer display order tree node.
+ XpdfLayerOrderHandle getLayerOrderChild(XpdfLayerOrderHandle order, int idx);
+
+ //! Return the parent of a layer display order tree node.
+ //! This function returns the parent of node \a order, or NULL if \a
+ //! order is the root node.
+ XpdfLayerOrderHandle getLayerOrderParent(XpdfLayerOrderHandle order);
+
+ //! Return the number of embedded files in the current PDF file.
+ int getNumEmbeddedFiles();
+
+ //! Return the name of the \a idx 'th embedded file.
+ QString getEmbeddedFileName(int idx);
+
+ //! Save the \a idx 'th embedded file with the specified file name.
+ //! Returns true if successful.
+ bool saveEmbeddedFile(int idx, QString fileName);
+
+ //--- for internal use
+
+ //! \cond
+
+ virtual QSize sizeHint() const;
+ QtPDFCore *getCore() { return core; }
+
+ //! \endcond
+
+signals:
+
+ //! This signal is emitted whenever the viewer displays a new page.
+ //! It can be triggered by user actions (e.g., the PageDown button),
+ //! or program control (e.g., the gotoNextPage function).
+ //! \param pageNum - the new page number
+ void pageChange(int pageNum);
+
+ //! This signal is emitted whenever the page shown at the middle of
+ //! the window changes.
+ //! It is similar to XpdfWidget::pageChange, except that it reflects
+ //! the page shown at the middle of the window (instead of the page
+ //! at the top of the window).
+ void midPageChange(int pageNum);
+
+ //! This signal is emitted just before a PDF file is loaded.
+ void preLoad();
+
+ //! This signal is emitted just after a PDF file is loaded.
+ void postLoad();
+
+ //! This signal is emitted whenever a key is pressed.
+ void keyPress(QKeyEvent *e);
+
+ //! This signal is emitted whenever a mouse button is pressed.
+ void mousePress(QMouseEvent *e);
+
+ //! This signal is emitted whenever a mouse button is released.
+ void mouseRelease(QMouseEvent *e);
+
+ //! This signal is emitted whenever a mouse button is clicked.
+ //! A click is defined as a button press and release within a short
+ //! distance of each other (a few pixels). The sequence of signals
+ //! is: mousePress, possibly a few mouseMoves, mouseRelease, and
+ //! then mouseClick.
+ void mouseClick(QMouseEvent *e);
+
+ //! This signal is emitted whenever a mouse button is double-clicked.
+ //! Double clicks are two clicks within a few pixels of each other,
+ //! and within a certain time of each other. The sequence of
+ //! signals is: mousePress, mouseRelease, mouseClick, mousePress,
+ //! mouseRelease, mouseDoubleClick. There may also be mouseMoves
+ //! between the presses and releases.
+ void mouseDoubleClick(QMouseEvent *e);
+
+ //! This signal is emitted whenever a mouse button is triple-clicked.
+ //! Triple clicks are three clicks within a few pixels of each
+ //! other, and within a certain time of each other. The sequence of
+ //! signals is: mousePress, mouseRelease, mouseClick, mousePress,
+ //! mouseRelease, mouseDoubleClick, mousePress, mouseRelease,
+ //! mouseTripleClick. There may also be mouseMoves between the
+ //! presses and releases.
+ void mouseTripleClick(QMouseEvent *e);
+
+ //! This signal is emitted whenever the mouse pointer is moved.
+ void mouseMove(QMouseEvent *e);
+
+ //! This signal is emitted whenever a mouse wheel is clicked.
+ void mouseWheel(QWheelEvent *e);
+
+ //! This signal is emitted whenever the user clicks on a hyperlink.
+ //! \param linkType the type of link - one of:
+ //! - \c "goto": a link to another page in the same PDF
+ //! file - \a dest is empty; \a page is the destination
+ //! page number
+ //! - \c "pdf": a link to another PDF file - \a dest is the
+ //! target PDF file; \a page is 0
+ //! - \c "launch": an arbitrary command to be run - \a dest
+ //! is the command; \a page is 0
+ //! - \c "url": a URL link - \a dest is the URL; \a page is 0
+ //! - \c "named": a "named action" link - \a dest is the
+ //! action (see the PDF spec for details); \a page is 0
+ //! - \c "unknown": an unknown link type - \a dest is empty;
+ //! \a page is 0
+ //! \param dest destination string
+ //! \param page destination page number
+ void linkClick(const QString &linkType, const QString &dest, int page);
+
+ //! This signal is emitted when the user selects an area.
+ //! Use XpdfWidget::getCurrentSelection to retrieve the selection.
+ void selectDone();
+
+ //! This signal is emitted whenever the widget is repainted. \a
+ //! finished is true if the painted view is complete, or false if
+ //! this was an incremental update, i.e., if the view is still being
+ //! rendered.
+ void paintDone(bool finished);
+
+ //! This signal is emitted when the widget is resized.
+ void resized();
+
+
+#if XPDFWIDGET_PRINTING
+ //! This signal is called before each page is spooled, and after the
+ //! last page is spooled. It is typically used to update a print
+ //! status dialog. \a nextPage is the next page to be printed.
+ //! \a firstPage and \a lastPage specify the range of pages being
+ //! printed.
+ void printStatus(int nextPage, int firstPage, int lastPage);
+#endif
+
+ //! \cond PROTECTED
+
+ void tileDone();
+
+ //! \endcond
+
+protected:
+
+ //! \cond PROTECTED
+
+ virtual void paintEvent(QPaintEvent *eventA);
+ virtual void resizeEvent(QResizeEvent *eventA);
+ virtual void scrollContentsBy(int dx, int dy);
+ virtual void keyPressEvent(QKeyEvent *e);
+ virtual void mousePressEvent(QMouseEvent *e);
+ virtual void mouseReleaseEvent(QMouseEvent *e);
+ virtual void mouseMoveEvent(QMouseEvent *e);
+ virtual void wheelEvent(QWheelEvent *e);
+ virtual bool eventFilter(QObject *obj, QEvent *event);
+
+ //! \endcond
+
+private slots:
+
+ void tick();
+
+private:
+
+ void setup(const QColor &paperColor, const QColor &matteColor,
+ bool reverseVideo);
+ static void updateCbk(void *data, GString *fileName,
+ int pageNum, int numPages,
+ const char *linkLabel);
+ static void midPageChangedCbk(void *data, int pageNum);
+ static void preLoadCbk(void *data);
+ static void postLoadCbk(void *data);
+ static void linkCbk(void *data, const char *type,
+ const char *dest, int page);
+ static void selectDoneCbk(void *data);
+ static void paintDoneCbk(void *data, bool finished);
+ static void tileDoneCbk(void *data);
+
+ friend class XpdfViewer;
+ bool getLinkTarget(int page, double xx, double yy,
+ QString &targetFileName, int &targetPage,
+ QString &targetDest);
+
+#if XPDFWIDGET_PRINTING
+ QPrinter *printerForDialog;
+ QPrintDialog *printDialog;
+ int printHDPI, printVDPI;
+ bool printCanceled;
+#endif
+
+ static QMutex initMutex;
+
+ QtPDFCore *core;
+ double scaleFactor;
+
+ bool keyPassthrough;
+ bool mousePassthrough;
+ int lastMousePressX[3], lastMousePressY[3];
+ ulong lastMousePressTime[3];
+ bool lastMouseEventWasPress;
+
+ bool touchPanEnabled;
+ bool touchZoomEnabled;
+ double pinchZoomStart;
+
+ QTimer *tickTimer;
+};
+
+#endif
diff --git a/xpdf-qt/XpdfWidgetPrint.cc b/xpdf-qt/XpdfWidgetPrint.cc
new file mode 100644
index 0000000..e57ae10
--- /dev/null
+++ b/xpdf-qt/XpdfWidgetPrint.cc
@@ -0,0 +1,500 @@
+//========================================================================
+//
+// XpdfWidgetPrint.cc
+//
+// Copyright 2012 Glyph & Cog, LLC
+//
+//========================================================================
+
+#if XPDFWIDGET_PRINTING
+
+#include <aconf.h>
+
+#include <stdlib.h>
+#include <QPrinter>
+#include "gfile.h"
+#include "PDFDoc.h"
+#include "ErrorCodes.h"
+#include "XpdfWidget.h"
+
+#if defined(_WIN32)
+#elif defined(__APPLE__)
+# include <CoreFoundation/CoreFoundation.h>
+# include <ApplicationServices/ApplicationServices.h>
+#elif defined(__linux__)
+# include "PSOutputDev.h"
+# include <cups/cups.h>
+#endif
+
+#include "gmempp.h"
+
+//------------------------------------------------------------------------
+// Windows
+//------------------------------------------------------------------------
+
+#if defined(_WIN32)
+
+//------------------------------------------------------------------------
+// Mac OS X
+//------------------------------------------------------------------------
+
+#elif defined(__APPLE__)
+
+XpdfWidget::ErrorCode printPDF(PDFDoc *doc, QPrinter *prt,
+ int hDPI, int vDPI,
+ XpdfWidget *widget) {
+ GString *pdfFileName;
+ CFStringRef s;
+ CFURLRef url;
+ CGPDFDocumentRef pdfDoc;
+ CGPDFPageRef pdfPage;
+ GString *printerName;
+ CFArrayRef printerList, pageFormatList;
+ char prtName[512];
+ PMPrinter printer;
+ PMPrintSession session;
+ PMPageFormat pageFormat;
+ PMPrintSettings printSettings;
+ PMRect paperRect;
+ CGRect paperRect2;
+ CGContextRef ctx;
+ CGAffineTransform pageTransform;
+ QPrinter::ColorMode colorMode;
+ QSizeF paperSize;
+ QPrinter::PaperSource paperSource;
+ QPageLayout::Orientation pageOrientation;
+ FILE *f;
+ GBool deletePDFFile;
+ int startPage, endPage, pg, i;
+
+ //--- get PDF file name
+
+ deletePDFFile = gFalse;
+ if (doc->getFileName()) {
+ pdfFileName = doc->getFileName()->copy();
+ } else {
+ if (!openTempFile(&pdfFileName, &f, "wb", ".pdf")) {
+ goto err0;
+ }
+ fclose(f);
+ deletePDFFile = gTrue;
+ if (!doc->saveAs(pdfFileName)) {
+ goto err1;
+ }
+ }
+
+ //--- load the PDF file
+
+ s = CFStringCreateWithCString(NULL, pdfFileName->getCString(),
+ kCFStringEncodingUTF8);
+ url = CFURLCreateWithFileSystemPath(NULL, s, kCFURLPOSIXPathStyle, false);
+ CFRelease(s);
+ pdfDoc = CGPDFDocumentCreateWithURL(url);
+ CFRelease(url);
+ if (!pdfDoc) {
+ goto err1;
+ }
+
+ //--- get page range
+
+ startPage = prt->fromPage();
+ endPage = prt->toPage();
+ if (startPage == 0) {
+ startPage = 1;
+ }
+ if (endPage == 0) {
+ endPage = doc->getNumPages();
+ }
+ if (startPage > endPage) {
+ CFRelease(pdfDoc);
+ if (deletePDFFile) {
+ unlink(pdfFileName->getCString());
+ }
+ delete pdfFileName;
+ return XpdfWidget::pdfErrBadPageNum;
+ }
+
+ //--- get other parameters
+
+ colorMode = prt->colorMode();
+ paperSize = prt->paperSize(QPrinter::Point);
+ paperSource = prt->paperSource();
+ pageOrientation = prt->pageLayout().orientation();
+
+ //--- create the Session and PrintSettings
+
+ if (PMCreateSession(&session)) {
+ goto err2;
+ }
+ if (PMCreatePrintSettings(&printSettings)) {
+ goto err3;
+ }
+ if (PMSessionDefaultPrintSettings(session, printSettings)) {
+ goto err4;
+ }
+ s = CFStringCreateWithCString(NULL, pdfFileName->getCString(),
+ kCFStringEncodingUTF8);
+ PMPrintSettingsSetJobName(printSettings, s);
+ CFRelease(s);
+
+ //--- set up for print-to-file
+
+ if (!prt->outputFileName().isEmpty()) {
+
+ s = CFStringCreateWithCString(NULL,
+ prt->outputFileName().toUtf8().constData(),
+ kCFStringEncodingUTF8);
+ url = CFURLCreateWithFileSystemPath(NULL, s, kCFURLPOSIXPathStyle, false);
+ CFRelease(s);
+ if (PMSessionSetDestination(session, printSettings, kPMDestinationFile,
+ kPMDocumentFormatPDF, url)) {
+ CFRelease(url);
+ goto err4;
+ }
+ CFRelease(url);
+
+ //--- set the printer
+
+ } else {
+
+ if (PMServerCreatePrinterList(kPMServerLocal, &printerList)) {
+ goto err4;
+ }
+ printer = NULL;
+ printerName = new GString(prt->printerName().toUtf8().constData());
+ for (i = 0; i < CFArrayGetCount(printerList); ++i) {
+ printer = (PMPrinter)CFArrayGetValueAtIndex(printerList, i);
+#if QT_VERSION >= 0x050000
+ s = PMPrinterGetID(printer);
+#else
+ s = PMPrinterGetName(printer);
+#endif
+ if (CFStringGetCString(s, prtName, sizeof(prtName),
+ kCFStringEncodingUTF8)) {
+ if (!strcmp(prtName, printerName->getCString())) {
+ break;
+ }
+ }
+ }
+ delete printerName;
+ if (i >= CFArrayGetCount(printerList)) {
+ CFRelease(printerList);
+ PMRelease(printSettings);
+ PMRelease(session);
+ CFRelease(pdfDoc);
+ return XpdfWidget::pdfErrBadPrinter;
+ }
+ if (PMSessionSetCurrentPMPrinter(session, printer)) {
+ CFRelease(printerList);
+ goto err4;
+ }
+ CFRelease(printerList);
+ }
+
+ //--- set color mode
+
+#if 0
+ if (colorMode == QPrinter::GrayScale) {
+ // this is deprecated, with no replacement
+ PMSetColorMode(printSettings, kPMGray);
+ }
+#endif
+
+ //--- set paper size
+
+ if (PMSessionGetCurrentPrinter(session, &printer)) {
+ goto err4;
+ }
+ if (PMSessionCreatePageFormatList(session, printer, &pageFormatList)) {
+ goto err4;
+ }
+ pageFormat = NULL;
+ for (i = 0; i < CFArrayGetCount(pageFormatList); ++i) {
+ pageFormat = (PMPageFormat)CFArrayGetValueAtIndex(pageFormatList, i);
+ PMGetUnadjustedPaperRect(pageFormat, &paperRect);
+ if (fabs((paperRect.right - paperRect.left) - paperSize.width()) < 2 &&
+ fabs((paperRect.bottom - paperRect.top) - paperSize.height()) < 2) {
+ PMRetain(pageFormat);
+ break;
+ }
+ pageFormat = NULL;
+ }
+ CFRelease(pageFormatList);
+ if (!pageFormat) {
+ if (PMCreatePageFormat(&pageFormat)) {
+ goto err4;
+ }
+ if (PMSessionDefaultPageFormat(session, pageFormat)) {
+ goto err5;
+ }
+ }
+
+ //--- set page orientation
+
+ PMGetAdjustedPaperRect(pageFormat, &paperRect);
+ if (pageOrientation == QPageLayout::Landscape) {
+ PMSetOrientation(pageFormat, kPMLandscape, kPMUnlocked);
+ paperRect2 = CGRectMake(paperRect.top,
+ paperRect.left,
+ paperRect.bottom - paperRect.top,
+ paperRect.right - paperRect.left);
+ } else {
+ PMSetOrientation(pageFormat, kPMPortrait, kPMUnlocked);
+ paperRect2 = CGRectMake(paperRect.left,
+ paperRect.top,
+ paperRect.right - paperRect.left,
+ paperRect.bottom - paperRect.top);
+ }
+
+ //--- print
+
+ if (PMSetPageRange(printSettings, startPage, endPage)) {
+ goto err5;
+ }
+ if (PMSessionBeginCGDocumentNoDialog(session, printSettings, pageFormat)) {
+ goto err5;
+ }
+ for (pg = startPage; pg <= endPage; ++pg) {
+ widget->updatePrintStatus(pg, startPage, endPage);
+ if (widget->isPrintCanceled()) {
+ goto err6;
+ }
+ if (PMSessionBeginPageNoDialog(session, pageFormat, NULL)) {
+ goto err6;
+ }
+ if (PMSessionGetCGGraphicsContext(session, &ctx)) {
+ goto err6;
+ }
+ if (!(pdfPage = CGPDFDocumentGetPage(pdfDoc, pg))) {
+ goto err6;
+ }
+ pageTransform = CGPDFPageGetDrawingTransform(pdfPage, kCGPDFMediaBox,
+ paperRect2, 0, true);
+ CGContextSaveGState(ctx);
+ CGContextConcatCTM(ctx, pageTransform);
+ CGContextDrawPDFPage(ctx, pdfPage);
+ CGContextRestoreGState(ctx);
+ if (PMSessionEndPageNoDialog(session)) {
+ goto err6;
+ }
+ }
+ widget->updatePrintStatus(endPage + 1, startPage, endPage);
+ PMSessionEndDocumentNoDialog(session);
+ PMRelease(pageFormat);
+ PMRelease(printSettings);
+ PMRelease(session);
+
+ CFRelease(pdfDoc);
+ if (deletePDFFile) {
+ unlink(pdfFileName->getCString());
+ }
+ delete pdfFileName;
+
+ return XpdfWidget::pdfOk;
+
+ err6:
+ PMSessionEndDocumentNoDialog(session);
+ err5:
+ PMRelease(pageFormat);
+ err4:
+ PMRelease(printSettings);
+ err3:
+ PMRelease(session);
+ err2:
+ CFRelease(pdfDoc);
+ err1:
+ if (deletePDFFile) {
+ unlink(pdfFileName->getCString());
+ }
+ delete pdfFileName;
+ err0:
+ return XpdfWidget::pdfErrPrinting;
+}
+
+//------------------------------------------------------------------------
+// Linux
+//------------------------------------------------------------------------
+
+#elif defined(__linux__)
+
+static void fileOut(void *stream, const char *data, int len) {
+ fwrite(data, 1, len, (FILE *)stream);
+}
+
+XpdfWidget::ErrorCode printPDF(PDFDoc *doc, QPrinter *prt,
+ int hDPI, int vDPI,
+ XpdfWidget *widget) {
+ int startPage, endPage;
+ QPrinter::PaperSize paperSize;
+ QSizeF paperSizePts;
+ QPrinter::PaperSource paperSource;
+ QPrinter::DuplexMode duplex;
+ GString *psFileName;
+ FILE *psFile;
+ PSOutputDev *psOut;
+ GString *printerName;
+ cups_dest_t *dests, *dest;
+ cups_option_t *options;
+ const char *paperSizeStr, *paperSourceStr;
+ GString *s;
+ int nDests, nOptions;
+ int pg;
+
+ //--- get page range
+
+ startPage = prt->fromPage();
+ endPage = prt->toPage();
+ if (startPage == 0) {
+ startPage = 1;
+ }
+ if (endPage == 0) {
+ endPage = doc->getNumPages();
+ }
+ if (startPage > endPage) {
+ return XpdfWidget::pdfErrBadPageNum;
+ }
+
+ //--- get other parameters
+
+ paperSize = prt->paperSize();
+ paperSizePts = prt->paperSize(QPrinter::Point);
+ paperSource = prt->paperSource();
+ duplex = prt->duplex();
+
+ //--- print to file
+
+ if (!prt->outputFileName().isEmpty()) {
+ psFileName = NULL; // don't delete the PS file
+ if (!(psFile = fopen(prt->outputFileName().toUtf8().constData(), "wb"))) {
+ goto err0;
+ }
+
+ //--- open temporary PS file
+
+ } else {
+ if (!openTempFile(&psFileName, &psFile, "wb", ".ps")) {
+ goto err0;
+ }
+ }
+
+ //--- generate the PS file
+
+ globalParams->setPSPaperWidth((int)(paperSizePts.width() + 0.5));
+ globalParams->setPSPaperHeight((int)(paperSizePts.height() + 0.5));
+
+ widget->updatePrintStatus(startPage, startPage, endPage);
+ psOut = new PSOutputDev(fileOut, psFile, doc, startPage, endPage,
+ psModePS);
+ if (!psOut->isOk()) {
+ delete psOut;
+ goto err1;
+ }
+ for (pg = startPage; pg <= endPage; ++pg) {
+ if (widget->isPrintCanceled()) {
+ delete psOut;
+ fclose(psFile);
+ goto err1;
+ }
+ doc->displayPage(psOut, pg, 72, 72, 0,
+ !globalParams->getPSUseCropBoxAsPage(),
+ gTrue, gTrue);
+ widget->updatePrintStatus(pg + 1, startPage, endPage);
+ }
+ delete psOut;
+ fclose(psFile);
+
+ //--- print the PS file
+
+ if (psFileName) {
+
+ if (!prt->printerName().isEmpty()) {
+ printerName = new GString(prt->printerName().toLocal8Bit().constData());
+ } else {
+ nDests = cupsGetDests(&dests);
+ if (!(dest = cupsGetDest(NULL, NULL, nDests, dests))) {
+ unlink(psFileName->getCString());
+ delete psFileName;
+ cupsFreeDests(nDests, dests);
+ return XpdfWidget::pdfErrBadPrinter;
+ }
+ printerName = new GString(dest->name);
+ cupsFreeDests(nDests, dests);
+ }
+
+ options = NULL;
+ nOptions = 0;
+
+ switch (paperSize) {
+ case QPrinter::A4: paperSizeStr = "A4"; break;
+ case QPrinter::Comm10E: paperSizeStr = "COM10"; break;
+ case QPrinter::DLE: paperSizeStr = "DL"; break;
+ case QPrinter::Legal: paperSizeStr = "Legal"; break;
+ case QPrinter::Letter: paperSizeStr = "Letter"; break;
+ default: paperSizeStr = NULL; break;
+ }
+ switch (paperSource) {
+ case QPrinter::LargeCapacity: paperSourceStr = "LargeCapacity"; break;
+ case QPrinter::Lower: paperSourceStr = "Lower"; break;
+ default: paperSourceStr = NULL; break;
+ }
+ if (paperSizeStr && paperSourceStr) {
+ s = GString::format("{0:s},{1:s}", paperSizeStr, paperSourceStr);
+ cupsAddOption("media", s->getCString(), nOptions, &options);
+ delete s;
+ ++nOptions;
+ } else if (paperSizeStr) {
+ cupsAddOption("media", paperSizeStr, nOptions, &options);
+ ++nOptions;
+ } else if (paperSourceStr) {
+ cupsAddOption("media", paperSourceStr, nOptions, &options);
+ ++nOptions;
+ }
+
+ switch (duplex) {
+ case QPrinter::DuplexNone:
+ cupsAddOption("sides", "one-sided", nOptions, &options);
+ ++nOptions;
+ break;
+ case QPrinter::DuplexAuto:
+ break;
+ case QPrinter::DuplexLongSide:
+ cupsAddOption("sides", "two-sided-long-edge", nOptions, &options);
+ ++nOptions;
+ break;
+ case QPrinter::DuplexShortSide:
+ cupsAddOption("sides", "two-sided-short-edge", nOptions, &options);
+ ++nOptions;
+ break;
+ }
+
+ if (!cupsPrintFile(printerName->getCString(),
+ psFileName->getCString(),
+ doc->getFileName() ? doc->getFileName()->getCString()
+ : "Xpdf printing",
+ nOptions, options)) {
+ cupsFreeOptions(nOptions, options);
+ delete printerName;
+ goto err1;
+ }
+ cupsFreeOptions(nOptions, options);
+
+ delete printerName;
+
+ unlink(psFileName->getCString());
+ delete psFileName;
+ }
+
+ return XpdfWidget::pdfOk;
+
+ err1:
+ if (psFileName) {
+ unlink(psFileName->getCString());
+ delete psFileName;
+ }
+ err0:
+ return XpdfWidget::pdfErrPrinting;
+}
+
+#endif
+
+#endif // XPDFWIDGET_PRINTING
diff --git a/xpdf-qt/XpdfWidgetPrint.h b/xpdf-qt/XpdfWidgetPrint.h
new file mode 100644
index 0000000..b48cd8f
--- /dev/null
+++ b/xpdf-qt/XpdfWidgetPrint.h
@@ -0,0 +1,24 @@
+//========================================================================
+//
+// XpdfWidgetPrint.h
+//
+// Copyright 2012 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef XPDFWIDGETPRINT_H
+#define XPDFWIDGETPRINT_H
+
+#if XPDFWIDGET_PRINTING
+
+#include <aconf.h>
+
+class XpdfWidget;
+
+extern XpdfWidget::ErrorCode printPDF(PDFDoc *doc, QPrinter *prt,
+ int hDPI, int vDPI,
+ XpdfWidget *widget);
+
+#endif // XPDFWIDGET_PRINTING
+
+#endif // XPDFWIDGETPRINT_H
diff --git a/xpdf-qt/back.svg b/xpdf-qt/back.svg
new file mode 100644
index 0000000..69a37b8
--- /dev/null
+++ b/xpdf-qt/back.svg
@@ -0,0 +1,10 @@
+<?xml version="1.0"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg width="80" height="80" version="1.1"
+ xmlns="http://www.w3.org/2000/svg">
+ <polyline stroke="#555555" stroke-width="8" fill="none"
+ points="16,40 68,40"/>
+ <polyline stroke="#555555" stroke-width="8" fill="none"
+ points="36,20 12,40 36,60"/>
+</svg>
diff --git a/xpdf-qt/cmake_install.cmake b/xpdf-qt/cmake_install.cmake
new file mode 100644
index 0000000..58e79c3
--- /dev/null
+++ b/xpdf-qt/cmake_install.cmake
@@ -0,0 +1,64 @@
+# Install script for directory: /home/calvin/src/xpdf-4.04/xpdf-qt
+
+# 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/xpdf" AND
+ NOT IS_SYMLINK "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/xpdf")
+ file(RPATH_CHECK
+ FILE "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/xpdf"
+ RPATH "")
+ endif()
+ file(INSTALL DESTINATION "${CMAKE_INSTALL_PREFIX}/bin" TYPE EXECUTABLE FILES "/home/calvin/src/xpdf-4.04/xpdf-qt/xpdf")
+ if(EXISTS "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/xpdf" AND
+ NOT IS_SYMLINK "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/xpdf")
+ if(CMAKE_INSTALL_DO_STRIP)
+ execute_process(COMMAND "/usr/bin/strip" "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/xpdf")
+ 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/xpdf.1")
+endif()
+
diff --git a/xpdf-qt/findNext.svg b/xpdf-qt/findNext.svg
new file mode 100644
index 0000000..fa6a4ef
--- /dev/null
+++ b/xpdf-qt/findNext.svg
@@ -0,0 +1,8 @@
+<?xml version="1.0"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg width="60" height="80" version="1.1"
+ xmlns="http://www.w3.org/2000/svg">
+ <polyline stroke="#555555" stroke-width="8" fill="none"
+ points="12,32 30,48 48,32"/>
+</svg>
diff --git a/xpdf-qt/findPrevious.svg b/xpdf-qt/findPrevious.svg
new file mode 100644
index 0000000..2088342
--- /dev/null
+++ b/xpdf-qt/findPrevious.svg
@@ -0,0 +1,8 @@
+<?xml version="1.0"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg width="60" height="80" version="1.1"
+ xmlns="http://www.w3.org/2000/svg">
+ <polyline stroke="#555555" stroke-width="8" fill="none"
+ points="12,48 30,32 48,48"/>
+</svg>
diff --git a/xpdf-qt/findSettings.svg b/xpdf-qt/findSettings.svg
new file mode 100644
index 0000000..97aefdf
--- /dev/null
+++ b/xpdf-qt/findSettings.svg
@@ -0,0 +1,9 @@
+<?xml version="1.0"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg width="60" height="80" version="1.1"
+ xmlns="http://www.w3.org/2000/svg">
+ <circle fill="#555555" cx="14" cy="40" r="5"/>
+ <circle fill="#555555" cx="30" cy="40" r="5"/>
+ <circle fill="#555555" cx="46" cy="40" r="5"/>
+</svg>
diff --git a/xpdf-qt/fitPage.svg b/xpdf-qt/fitPage.svg
new file mode 100644
index 0000000..6922ace
--- /dev/null
+++ b/xpdf-qt/fitPage.svg
@@ -0,0 +1,20 @@
+<?xml version="1.0"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg width="80" height="80" version="1.1"
+ xmlns="http://www.w3.org/2000/svg">
+ <rect fill="none" stroke="#555555" stroke-width="4"
+ x="14" y="6" width="56" height="72"/>
+ <polyline stroke="#555555" stroke-width="4" fill="none"
+ points="22,42 62,42"/>
+ <polyline stroke="#555555" stroke-width="4" fill="none"
+ points="32,32 22,42 32,52"/>
+ <polyline stroke="#555555" stroke-width="4" fill="none"
+ points="52,32 62,42 52,52"/>
+ <polyline stroke="#555555" stroke-width="4" fill="none"
+ points="42,14 42,70"/>
+ <polyline stroke="#555555" stroke-width="4" fill="none"
+ points="32,24 42,14 52,24"/>
+ <polyline stroke="#555555" stroke-width="4" fill="none"
+ points="32,60 42,70 52,60"/>
+</svg>
diff --git a/xpdf-qt/fitPageOn.svg b/xpdf-qt/fitPageOn.svg
new file mode 100644
index 0000000..170644f
--- /dev/null
+++ b/xpdf-qt/fitPageOn.svg
@@ -0,0 +1,20 @@
+<?xml version="1.0"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg width="80" height="80" version="1.1"
+ xmlns="http://www.w3.org/2000/svg">
+ <rect fill="#ddddff" stroke="#555555" stroke-width="4"
+ x="14" y="6" width="56" height="72"/>
+ <polyline stroke="#555555" stroke-width="4" fill="none"
+ points="22,42 62,42"/>
+ <polyline stroke="#555555" stroke-width="4" fill="none"
+ points="32,32 22,42 32,52"/>
+ <polyline stroke="#555555" stroke-width="4" fill="none"
+ points="52,32 62,42 52,52"/>
+ <polyline stroke="#555555" stroke-width="4" fill="none"
+ points="42,14 42,70"/>
+ <polyline stroke="#555555" stroke-width="4" fill="none"
+ points="32,24 42,14 52,24"/>
+ <polyline stroke="#555555" stroke-width="4" fill="none"
+ points="32,60 42,70 52,60"/>
+</svg>
diff --git a/xpdf-qt/fitWidth.svg b/xpdf-qt/fitWidth.svg
new file mode 100644
index 0000000..622eb9e
--- /dev/null
+++ b/xpdf-qt/fitWidth.svg
@@ -0,0 +1,14 @@
+<?xml version="1.0"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg width="80" height="80" version="1.1"
+ xmlns="http://www.w3.org/2000/svg">
+ <rect fill="none" stroke="#555555" stroke-width="4"
+ x="14" y="6" width="56" height="72"/>
+ <polyline stroke="#555555" stroke-width="4" fill="none"
+ points="22,42 62,42"/>
+ <polyline stroke="#555555" stroke-width="4" fill="none"
+ points="32,32 22,42 32,52"/>
+ <polyline stroke="#555555" stroke-width="4" fill="none"
+ points="52,32 62,42 52,52"/>
+</svg>
diff --git a/xpdf-qt/fitWidthOn.svg b/xpdf-qt/fitWidthOn.svg
new file mode 100644
index 0000000..06f0990
--- /dev/null
+++ b/xpdf-qt/fitWidthOn.svg
@@ -0,0 +1,14 @@
+<?xml version="1.0"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg width="80" height="80" version="1.1"
+ xmlns="http://www.w3.org/2000/svg">
+ <rect fill="#ddddff" stroke="#555555" stroke-width="4"
+ x="14" y="6" width="56" height="72"/>
+ <polyline stroke="#555555" stroke-width="4" fill="none"
+ points="22,42 62,42"/>
+ <polyline stroke="#555555" stroke-width="4" fill="none"
+ points="32,32 22,42 32,52"/>
+ <polyline stroke="#555555" stroke-width="4" fill="none"
+ points="52,32 62,42 52,52"/>
+</svg>
diff --git a/xpdf-qt/forward.svg b/xpdf-qt/forward.svg
new file mode 100644
index 0000000..e408ff7
--- /dev/null
+++ b/xpdf-qt/forward.svg
@@ -0,0 +1,10 @@
+<?xml version="1.0"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg width="80" height="80" version="1.1"
+ xmlns="http://www.w3.org/2000/svg">
+ <polyline stroke="#555555" stroke-width="8" fill="none"
+ points="12,40 64,40"/>
+ <polyline stroke="#555555" stroke-width="8" fill="none"
+ points="44,20 68,40 44,60"/>
+</svg>
diff --git a/xpdf-qt/icons.qrc b/xpdf-qt/icons.qrc
new file mode 100644
index 0000000..07566f3
--- /dev/null
+++ b/xpdf-qt/icons.qrc
@@ -0,0 +1,35 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file alias="back-button">back.svg</file>
+ <file alias="forward-button">forward.svg</file>
+ <file alias="findNext-button">findNext.svg</file>
+ <file alias="findPrevious-button">findPrevious.svg</file>
+ <file alias="findSettings-button">findSettings.svg</file>
+ <file alias="fitPage-button">fitPage.svg</file>
+ <file alias="fitPageOn-button">fitPageOn.svg</file>
+ <file alias="fitWidth-button">fitWidth.svg</file>
+ <file alias="fitWidthOn-button">fitWidthOn.svg</file>
+ <file alias="toggleSidebar-button">toggleSidebar.svg</file>
+ <file alias="zoomIn-button">zoomIn.svg</file>
+ <file alias="zoomOut-button">zoomOut.svg</file>
+ <file alias="indicator-icon0">indicator-icon0.svg</file>
+ <file alias="indicator-icon1">indicator-icon1.svg</file>
+ <file alias="indicator-icon2">indicator-icon2.svg</file>
+ <file alias="indicator-icon3">indicator-icon3.svg</file>
+ <file alias="indicator-icon4">indicator-icon4.svg</file>
+ <file alias="indicator-icon5">indicator-icon5.svg</file>
+ <file alias="indicator-icon6">indicator-icon6.svg</file>
+ <file alias="indicator-icon7">indicator-icon7.svg</file>
+ <file alias="indicator-icon-err0">indicator-icon-err0.svg</file>
+ <file alias="indicator-icon-err1">indicator-icon-err1.svg</file>
+ <file alias="indicator-icon-err2">indicator-icon-err2.svg</file>
+ <file alias="indicator-icon-err3">indicator-icon-err3.svg</file>
+ <file alias="indicator-icon-err4">indicator-icon-err4.svg</file>
+ <file alias="indicator-icon-err5">indicator-icon-err5.svg</file>
+ <file alias="indicator-icon-err6">indicator-icon-err6.svg</file>
+ <file alias="indicator-icon-err7">indicator-icon-err7.svg</file>
+ <file alias="selectModeLinear-button">selectModeLinear.svg</file>
+ <file alias="selectModeBlock-button">selectModeBlock.svg</file>
+ <file alias="xpdf-icon">xpdf-icon.svg</file>
+</qresource>
+</RCC>
diff --git a/xpdf-qt/icons.qrc.depends b/xpdf-qt/icons.qrc.depends
new file mode 100644
index 0000000..07566f3
--- /dev/null
+++ b/xpdf-qt/icons.qrc.depends
@@ -0,0 +1,35 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file alias="back-button">back.svg</file>
+ <file alias="forward-button">forward.svg</file>
+ <file alias="findNext-button">findNext.svg</file>
+ <file alias="findPrevious-button">findPrevious.svg</file>
+ <file alias="findSettings-button">findSettings.svg</file>
+ <file alias="fitPage-button">fitPage.svg</file>
+ <file alias="fitPageOn-button">fitPageOn.svg</file>
+ <file alias="fitWidth-button">fitWidth.svg</file>
+ <file alias="fitWidthOn-button">fitWidthOn.svg</file>
+ <file alias="toggleSidebar-button">toggleSidebar.svg</file>
+ <file alias="zoomIn-button">zoomIn.svg</file>
+ <file alias="zoomOut-button">zoomOut.svg</file>
+ <file alias="indicator-icon0">indicator-icon0.svg</file>
+ <file alias="indicator-icon1">indicator-icon1.svg</file>
+ <file alias="indicator-icon2">indicator-icon2.svg</file>
+ <file alias="indicator-icon3">indicator-icon3.svg</file>
+ <file alias="indicator-icon4">indicator-icon4.svg</file>
+ <file alias="indicator-icon5">indicator-icon5.svg</file>
+ <file alias="indicator-icon6">indicator-icon6.svg</file>
+ <file alias="indicator-icon7">indicator-icon7.svg</file>
+ <file alias="indicator-icon-err0">indicator-icon-err0.svg</file>
+ <file alias="indicator-icon-err1">indicator-icon-err1.svg</file>
+ <file alias="indicator-icon-err2">indicator-icon-err2.svg</file>
+ <file alias="indicator-icon-err3">indicator-icon-err3.svg</file>
+ <file alias="indicator-icon-err4">indicator-icon-err4.svg</file>
+ <file alias="indicator-icon-err5">indicator-icon-err5.svg</file>
+ <file alias="indicator-icon-err6">indicator-icon-err6.svg</file>
+ <file alias="indicator-icon-err7">indicator-icon-err7.svg</file>
+ <file alias="selectModeLinear-button">selectModeLinear.svg</file>
+ <file alias="selectModeBlock-button">selectModeBlock.svg</file>
+ <file alias="xpdf-icon">xpdf-icon.svg</file>
+</qresource>
+</RCC>
diff --git a/xpdf-qt/indicator-icon-err0.svg b/xpdf-qt/indicator-icon-err0.svg
new file mode 100644
index 0000000..3cc00d1
--- /dev/null
+++ b/xpdf-qt/indicator-icon-err0.svg
@@ -0,0 +1,12 @@
+<?xml version="1.0"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg width="80" height="80" version="1.1"
+ xmlns="http://www.w3.org/2000/svg">
+ <circle fill="#ff4444" stroke="none"
+ cx="40" cy="40" r="33"/>
+ <circle stroke="#555555" stroke-width="6" fill="none"
+ cx="40" cy="40" r="30"/>
+ <circle fill="#555555" stroke="none"
+ cx="40" cy="24" r="8"/>
+</svg>
diff --git a/xpdf-qt/indicator-icon-err1.svg b/xpdf-qt/indicator-icon-err1.svg
new file mode 100644
index 0000000..ce1c5a4
--- /dev/null
+++ b/xpdf-qt/indicator-icon-err1.svg
@@ -0,0 +1,12 @@
+<?xml version="1.0"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg width="80" height="80" version="1.1"
+ xmlns="http://www.w3.org/2000/svg">
+ <circle fill="#ff4444" stroke="none"
+ cx="40" cy="40" r="33"/>
+ <circle stroke="#555555" stroke-width="6" fill="none"
+ cx="40" cy="40" r="30"/>
+ <circle fill="#555555" stroke="none"
+ cx="51" cy="29" r="8"/>
+</svg>
diff --git a/xpdf-qt/indicator-icon-err2.svg b/xpdf-qt/indicator-icon-err2.svg
new file mode 100644
index 0000000..d5143eb
--- /dev/null
+++ b/xpdf-qt/indicator-icon-err2.svg
@@ -0,0 +1,12 @@
+<?xml version="1.0"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg width="80" height="80" version="1.1"
+ xmlns="http://www.w3.org/2000/svg">
+ <circle fill="#ff4444" stroke="none"
+ cx="40" cy="40" r="33"/>
+ <circle stroke="#555555" stroke-width="6" fill="none"
+ cx="40" cy="40" r="30"/>
+ <circle fill="#555555" stroke="none"
+ cx="56" cy="40" r="8"/>
+</svg>
diff --git a/xpdf-qt/indicator-icon-err3.svg b/xpdf-qt/indicator-icon-err3.svg
new file mode 100644
index 0000000..76fdf1e
--- /dev/null
+++ b/xpdf-qt/indicator-icon-err3.svg
@@ -0,0 +1,12 @@
+<?xml version="1.0"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg width="80" height="80" version="1.1"
+ xmlns="http://www.w3.org/2000/svg">
+ <circle fill="#ff4444" stroke="none"
+ cx="40" cy="40" r="33"/>
+ <circle stroke="#555555" stroke-width="6" fill="none"
+ cx="40" cy="40" r="30"/>
+ <circle fill="#555555" stroke="none"
+ cx="51" cy="51" r="8"/>
+</svg>
diff --git a/xpdf-qt/indicator-icon-err4.svg b/xpdf-qt/indicator-icon-err4.svg
new file mode 100644
index 0000000..ebca839
--- /dev/null
+++ b/xpdf-qt/indicator-icon-err4.svg
@@ -0,0 +1,12 @@
+<?xml version="1.0"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg width="80" height="80" version="1.1"
+ xmlns="http://www.w3.org/2000/svg">
+ <circle fill="#ff4444" stroke="none"
+ cx="40" cy="40" r="33"/>
+ <circle stroke="#555555" stroke-width="6" fill="none"
+ cx="40" cy="40" r="30"/>
+ <circle fill="#555555" stroke="none"
+ cx="40" cy="56" r="8"/>
+</svg>
diff --git a/xpdf-qt/indicator-icon-err5.svg b/xpdf-qt/indicator-icon-err5.svg
new file mode 100644
index 0000000..6c0de7c
--- /dev/null
+++ b/xpdf-qt/indicator-icon-err5.svg
@@ -0,0 +1,12 @@
+<?xml version="1.0"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg width="80" height="80" version="1.1"
+ xmlns="http://www.w3.org/2000/svg">
+ <circle fill="#ff4444" stroke="none"
+ cx="40" cy="40" r="33"/>
+ <circle stroke="#555555" stroke-width="6" fill="none"
+ cx="40" cy="40" r="30"/>
+ <circle fill="#555555" stroke="none"
+ cx="29" cy="51" r="8"/>
+</svg>
diff --git a/xpdf-qt/indicator-icon-err6.svg b/xpdf-qt/indicator-icon-err6.svg
new file mode 100644
index 0000000..f46b797
--- /dev/null
+++ b/xpdf-qt/indicator-icon-err6.svg
@@ -0,0 +1,12 @@
+<?xml version="1.0"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg width="80" height="80" version="1.1"
+ xmlns="http://www.w3.org/2000/svg">
+ <circle fill="#ff4444" stroke="none"
+ cx="40" cy="40" r="33"/>
+ <circle stroke="#555555" stroke-width="6" fill="none"
+ cx="40" cy="40" r="30"/>
+ <circle fill="#555555" stroke="none"
+ cx="24" cy="40" r="8"/>
+</svg>
diff --git a/xpdf-qt/indicator-icon-err7.svg b/xpdf-qt/indicator-icon-err7.svg
new file mode 100644
index 0000000..75266a4
--- /dev/null
+++ b/xpdf-qt/indicator-icon-err7.svg
@@ -0,0 +1,12 @@
+<?xml version="1.0"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg width="80" height="80" version="1.1"
+ xmlns="http://www.w3.org/2000/svg">
+ <circle fill="#ff4444" stroke="none"
+ cx="40" cy="40" r="33"/>
+ <circle stroke="#555555" stroke-width="6" fill="none"
+ cx="40" cy="40" r="30"/>
+ <circle fill="#555555" stroke="none"
+ cx="29" cy="29" r="8"/>
+</svg>
diff --git a/xpdf-qt/indicator-icon0.svg b/xpdf-qt/indicator-icon0.svg
new file mode 100644
index 0000000..eacb3ab
--- /dev/null
+++ b/xpdf-qt/indicator-icon0.svg
@@ -0,0 +1,10 @@
+<?xml version="1.0"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg width="80" height="80" version="1.1"
+ xmlns="http://www.w3.org/2000/svg">
+ <circle stroke="#555555" stroke-width="6" fill="none"
+ cx="40" cy="40" r="30"/>
+ <circle fill="#555555" stroke="none"
+ cx="40" cy="24" r="8"/>
+</svg>
diff --git a/xpdf-qt/indicator-icon1.svg b/xpdf-qt/indicator-icon1.svg
new file mode 100644
index 0000000..c1aec28
--- /dev/null
+++ b/xpdf-qt/indicator-icon1.svg
@@ -0,0 +1,10 @@
+<?xml version="1.0"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg width="80" height="80" version="1.1"
+ xmlns="http://www.w3.org/2000/svg">
+ <circle stroke="#555555" stroke-width="6" fill="none"
+ cx="40" cy="40" r="30"/>
+ <circle fill="#555555" stroke="none"
+ cx="51" cy="29" r="8"/>
+</svg>
diff --git a/xpdf-qt/indicator-icon2.svg b/xpdf-qt/indicator-icon2.svg
new file mode 100644
index 0000000..9a4a4d5
--- /dev/null
+++ b/xpdf-qt/indicator-icon2.svg
@@ -0,0 +1,10 @@
+<?xml version="1.0"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg width="80" height="80" version="1.1"
+ xmlns="http://www.w3.org/2000/svg">
+ <circle stroke="#555555" stroke-width="6" fill="none"
+ cx="40" cy="40" r="30"/>
+ <circle fill="#555555" stroke="none"
+ cx="56" cy="40" r="8"/>
+</svg>
diff --git a/xpdf-qt/indicator-icon3.svg b/xpdf-qt/indicator-icon3.svg
new file mode 100644
index 0000000..1f8d941
--- /dev/null
+++ b/xpdf-qt/indicator-icon3.svg
@@ -0,0 +1,10 @@
+<?xml version="1.0"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg width="80" height="80" version="1.1"
+ xmlns="http://www.w3.org/2000/svg">
+ <circle stroke="#555555" stroke-width="6" fill="none"
+ cx="40" cy="40" r="30"/>
+ <circle fill="#555555" stroke="none"
+ cx="51" cy="51" r="8"/>
+</svg>
diff --git a/xpdf-qt/indicator-icon4.svg b/xpdf-qt/indicator-icon4.svg
new file mode 100644
index 0000000..bc3dc40
--- /dev/null
+++ b/xpdf-qt/indicator-icon4.svg
@@ -0,0 +1,10 @@
+<?xml version="1.0"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg width="80" height="80" version="1.1"
+ xmlns="http://www.w3.org/2000/svg">
+ <circle stroke="#555555" stroke-width="6" fill="none"
+ cx="40" cy="40" r="30"/>
+ <circle fill="#555555" stroke="none"
+ cx="40" cy="56" r="8"/>
+</svg>
diff --git a/xpdf-qt/indicator-icon5.svg b/xpdf-qt/indicator-icon5.svg
new file mode 100644
index 0000000..42a51d9
--- /dev/null
+++ b/xpdf-qt/indicator-icon5.svg
@@ -0,0 +1,10 @@
+<?xml version="1.0"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg width="80" height="80" version="1.1"
+ xmlns="http://www.w3.org/2000/svg">
+ <circle stroke="#555555" stroke-width="6" fill="none"
+ cx="40" cy="40" r="30"/>
+ <circle fill="#555555" stroke="none"
+ cx="29" cy="51" r="8"/>
+</svg>
diff --git a/xpdf-qt/indicator-icon6.svg b/xpdf-qt/indicator-icon6.svg
new file mode 100644
index 0000000..0f5798f
--- /dev/null
+++ b/xpdf-qt/indicator-icon6.svg
@@ -0,0 +1,10 @@
+<?xml version="1.0"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg width="80" height="80" version="1.1"
+ xmlns="http://www.w3.org/2000/svg">
+ <circle stroke="#555555" stroke-width="6" fill="none"
+ cx="40" cy="40" r="30"/>
+ <circle fill="#555555" stroke="none"
+ cx="24" cy="40" r="8"/>
+</svg>
diff --git a/xpdf-qt/indicator-icon7.svg b/xpdf-qt/indicator-icon7.svg
new file mode 100644
index 0000000..ce2a819
--- /dev/null
+++ b/xpdf-qt/indicator-icon7.svg
@@ -0,0 +1,10 @@
+<?xml version="1.0"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg width="80" height="80" version="1.1"
+ xmlns="http://www.w3.org/2000/svg">
+ <circle stroke="#555555" stroke-width="6" fill="none"
+ cx="40" cy="40" r="30"/>
+ <circle fill="#555555" stroke="none"
+ cx="29" cy="29" r="8"/>
+</svg>
diff --git a/xpdf-qt/moc_XpdfApp.cpp b/xpdf-qt/moc_XpdfApp.cpp
new file mode 100644
index 0000000..9a4e4cb
--- /dev/null
+++ b/xpdf-qt/moc_XpdfApp.cpp
@@ -0,0 +1,95 @@
+/****************************************************************************
+** Meta object code from reading C++ file 'XpdfApp.h'
+**
+** Created by: The Qt Meta Object Compiler version 67 (Qt 5.15.2)
+**
+** WARNING! All changes made in this file will be lost!
+*****************************************************************************/
+
+#include <memory>
+#include "XpdfApp.h"
+#include <QtCore/qbytearray.h>
+#include <QtCore/qmetatype.h>
+#if !defined(Q_MOC_OUTPUT_REVISION)
+#error "The header file 'XpdfApp.h' doesn't include <QObject>."
+#elif Q_MOC_OUTPUT_REVISION != 67
+#error "This file was generated using the moc from 5.15.2. It"
+#error "cannot be used with the include files from this version of Qt."
+#error "(The moc has changed too much.)"
+#endif
+
+QT_BEGIN_MOC_NAMESPACE
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
+struct qt_meta_stringdata_XpdfApp_t {
+ QByteArrayData data[1];
+ char stringdata0[8];
+};
+#define QT_MOC_LITERAL(idx, ofs, len) \
+ Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \
+ qptrdiff(offsetof(qt_meta_stringdata_XpdfApp_t, stringdata0) + ofs \
+ - idx * sizeof(QByteArrayData)) \
+ )
+static const qt_meta_stringdata_XpdfApp_t qt_meta_stringdata_XpdfApp = {
+ {
+QT_MOC_LITERAL(0, 0, 7) // "XpdfApp"
+
+ },
+ "XpdfApp"
+};
+#undef QT_MOC_LITERAL
+
+static const uint qt_meta_data_XpdfApp[] = {
+
+ // content:
+ 8, // revision
+ 0, // classname
+ 0, 0, // classinfo
+ 0, 0, // methods
+ 0, 0, // properties
+ 0, 0, // enums/sets
+ 0, 0, // constructors
+ 0, // flags
+ 0, // signalCount
+
+ 0 // eod
+};
+
+void XpdfApp::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
+{
+ Q_UNUSED(_o);
+ Q_UNUSED(_id);
+ Q_UNUSED(_c);
+ Q_UNUSED(_a);
+}
+
+QT_INIT_METAOBJECT const QMetaObject XpdfApp::staticMetaObject = { {
+ QMetaObject::SuperData::link<QApplication::staticMetaObject>(),
+ qt_meta_stringdata_XpdfApp.data,
+ qt_meta_data_XpdfApp,
+ qt_static_metacall,
+ nullptr,
+ nullptr
+} };
+
+
+const QMetaObject *XpdfApp::metaObject() const
+{
+ return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject;
+}
+
+void *XpdfApp::qt_metacast(const char *_clname)
+{
+ if (!_clname) return nullptr;
+ if (!strcmp(_clname, qt_meta_stringdata_XpdfApp.stringdata0))
+ return static_cast<void*>(this);
+ return QApplication::qt_metacast(_clname);
+}
+
+int XpdfApp::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
+{
+ _id = QApplication::qt_metacall(_c, _id, _a);
+ return _id;
+}
+QT_WARNING_POP
+QT_END_MOC_NAMESPACE
diff --git a/xpdf-qt/moc_XpdfApp.cpp_parameters b/xpdf-qt/moc_XpdfApp.cpp_parameters
new file mode 100644
index 0000000..77077d6
--- /dev/null
+++ b/xpdf-qt/moc_XpdfApp.cpp_parameters
@@ -0,0 +1,28 @@
+-I/home/calvin/src/xpdf-4.04
+-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
+-I/home/calvin/src/xpdf-4.04/xpdf
+-I/usr/include/x86_64-linux-gnu/qt5/
+-I/usr/include/x86_64-linux-gnu/qt5/QtWidgets
+-I/usr/include/x86_64-linux-gnu/qt5/QtGui
+-I/usr/include/x86_64-linux-gnu/qt5/QtCore
+-I/usr/lib/x86_64-linux-gnu/qt5/mkspecs/linux-g++ /usr/include/x86_64-linux-gnu/qt5/
+-I/usr/include/x86_64-linux-gnu/qt5/QtNetwork
+-I/usr/include/x86_64-linux-gnu/qt5/QtCore
+-I/usr/lib/x86_64-linux-gnu/qt5/mkspecs/linux-g++ /usr/include/x86_64-linux-gnu/qt5/
+-I/usr/include/x86_64-linux-gnu/qt5/QtPrintSupport
+-I/usr/include/x86_64-linux-gnu/qt5/QtWidgets
+-I/usr/include/x86_64-linux-gnu/qt5/QtGui
+-I/usr/include/x86_64-linux-gnu/qt5/QtCore
+-I/usr/lib/x86_64-linux-gnu/qt5/mkspecs/linux-g++
+-DQT_WIDGETS_LIB
+-DQT_GUI_LIB
+-DQT_WIDGETS_LIB
+-DQT_GUI_LIB
+-DQT_CORE_LIB
+-DXPDFWIDGET_PRINTING=1
+-o
+/home/calvin/src/xpdf-4.04/xpdf-qt/moc_XpdfApp.cpp
+/home/calvin/src/xpdf-4.04/xpdf-qt/XpdfApp.h
diff --git a/xpdf-qt/moc_XpdfViewer.cpp b/xpdf-qt/moc_XpdfViewer.cpp
new file mode 100644
index 0000000..c004cc2
--- /dev/null
+++ b/xpdf-qt/moc_XpdfViewer.cpp
@@ -0,0 +1,654 @@
+/****************************************************************************
+** Meta object code from reading C++ file 'XpdfViewer.h'
+**
+** Created by: The Qt Meta Object Compiler version 67 (Qt 5.15.2)
+**
+** WARNING! All changes made in this file will be lost!
+*****************************************************************************/
+
+#include <memory>
+#include "XpdfViewer.h"
+#include <QtCore/qbytearray.h>
+#include <QtCore/qmetatype.h>
+#if !defined(Q_MOC_OUTPUT_REVISION)
+#error "The header file 'XpdfViewer.h' doesn't include <QObject>."
+#elif Q_MOC_OUTPUT_REVISION != 67
+#error "This file was generated using the moc from 5.15.2. It"
+#error "cannot be used with the include files from this version of Qt."
+#error "(The moc has changed too much.)"
+#endif
+
+QT_BEGIN_MOC_NAMESPACE
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
+struct qt_meta_stringdata_XpdfMenuButton_t {
+ QByteArrayData data[3];
+ char stringdata0[27];
+};
+#define QT_MOC_LITERAL(idx, ofs, len) \
+ Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \
+ qptrdiff(offsetof(qt_meta_stringdata_XpdfMenuButton_t, stringdata0) + ofs \
+ - idx * sizeof(QByteArrayData)) \
+ )
+static const qt_meta_stringdata_XpdfMenuButton_t qt_meta_stringdata_XpdfMenuButton = {
+ {
+QT_MOC_LITERAL(0, 0, 14), // "XpdfMenuButton"
+QT_MOC_LITERAL(1, 15, 10), // "btnPressed"
+QT_MOC_LITERAL(2, 26, 0) // ""
+
+ },
+ "XpdfMenuButton\0btnPressed\0"
+};
+#undef QT_MOC_LITERAL
+
+static const uint qt_meta_data_XpdfMenuButton[] = {
+
+ // content:
+ 8, // revision
+ 0, // classname
+ 0, 0, // classinfo
+ 1, 14, // methods
+ 0, 0, // properties
+ 0, 0, // enums/sets
+ 0, 0, // constructors
+ 0, // flags
+ 0, // signalCount
+
+ // slots: name, argc, parameters, tag, flags
+ 1, 0, 19, 2, 0x08 /* Private */,
+
+ // slots: parameters
+ QMetaType::Void,
+
+ 0 // eod
+};
+
+void XpdfMenuButton::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
+{
+ if (_c == QMetaObject::InvokeMetaMethod) {
+ auto *_t = static_cast<XpdfMenuButton *>(_o);
+ Q_UNUSED(_t)
+ switch (_id) {
+ case 0: _t->btnPressed(); break;
+ default: ;
+ }
+ }
+ Q_UNUSED(_a);
+}
+
+QT_INIT_METAOBJECT const QMetaObject XpdfMenuButton::staticMetaObject = { {
+ QMetaObject::SuperData::link<QToolButton::staticMetaObject>(),
+ qt_meta_stringdata_XpdfMenuButton.data,
+ qt_meta_data_XpdfMenuButton,
+ qt_static_metacall,
+ nullptr,
+ nullptr
+} };
+
+
+const QMetaObject *XpdfMenuButton::metaObject() const
+{
+ return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject;
+}
+
+void *XpdfMenuButton::qt_metacast(const char *_clname)
+{
+ if (!_clname) return nullptr;
+ if (!strcmp(_clname, qt_meta_stringdata_XpdfMenuButton.stringdata0))
+ return static_cast<void*>(this);
+ return QToolButton::qt_metacast(_clname);
+}
+
+int XpdfMenuButton::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
+{
+ _id = QToolButton::qt_metacall(_c, _id, _a);
+ if (_id < 0)
+ return _id;
+ if (_c == QMetaObject::InvokeMetaMethod) {
+ if (_id < 1)
+ qt_static_metacall(this, _c, _id, _a);
+ _id -= 1;
+ } else if (_c == QMetaObject::RegisterMethodArgumentMetaType) {
+ if (_id < 1)
+ *reinterpret_cast<int*>(_a[0]) = -1;
+ _id -= 1;
+ }
+ return _id;
+}
+struct qt_meta_stringdata_XpdfErrorWindow_t {
+ QByteArrayData data[3];
+ char stringdata0[33];
+};
+#define QT_MOC_LITERAL(idx, ofs, len) \
+ Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \
+ qptrdiff(offsetof(qt_meta_stringdata_XpdfErrorWindow_t, stringdata0) + ofs \
+ - idx * sizeof(QByteArrayData)) \
+ )
+static const qt_meta_stringdata_XpdfErrorWindow_t qt_meta_stringdata_XpdfErrorWindow = {
+ {
+QT_MOC_LITERAL(0, 0, 15), // "XpdfErrorWindow"
+QT_MOC_LITERAL(1, 16, 15), // "clearBtnPressed"
+QT_MOC_LITERAL(2, 32, 0) // ""
+
+ },
+ "XpdfErrorWindow\0clearBtnPressed\0"
+};
+#undef QT_MOC_LITERAL
+
+static const uint qt_meta_data_XpdfErrorWindow[] = {
+
+ // content:
+ 8, // revision
+ 0, // classname
+ 0, 0, // classinfo
+ 1, 14, // methods
+ 0, 0, // properties
+ 0, 0, // enums/sets
+ 0, 0, // constructors
+ 0, // flags
+ 0, // signalCount
+
+ // slots: name, argc, parameters, tag, flags
+ 1, 0, 19, 2, 0x08 /* Private */,
+
+ // slots: parameters
+ QMetaType::Void,
+
+ 0 // eod
+};
+
+void XpdfErrorWindow::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
+{
+ if (_c == QMetaObject::InvokeMetaMethod) {
+ auto *_t = static_cast<XpdfErrorWindow *>(_o);
+ Q_UNUSED(_t)
+ switch (_id) {
+ case 0: _t->clearBtnPressed(); break;
+ default: ;
+ }
+ }
+ Q_UNUSED(_a);
+}
+
+QT_INIT_METAOBJECT const QMetaObject XpdfErrorWindow::staticMetaObject = { {
+ QMetaObject::SuperData::link<QWidget::staticMetaObject>(),
+ qt_meta_stringdata_XpdfErrorWindow.data,
+ qt_meta_data_XpdfErrorWindow,
+ qt_static_metacall,
+ nullptr,
+ nullptr
+} };
+
+
+const QMetaObject *XpdfErrorWindow::metaObject() const
+{
+ return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject;
+}
+
+void *XpdfErrorWindow::qt_metacast(const char *_clname)
+{
+ if (!_clname) return nullptr;
+ if (!strcmp(_clname, qt_meta_stringdata_XpdfErrorWindow.stringdata0))
+ return static_cast<void*>(this);
+ return QWidget::qt_metacast(_clname);
+}
+
+int XpdfErrorWindow::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
+{
+ _id = QWidget::qt_metacall(_c, _id, _a);
+ if (_id < 0)
+ return _id;
+ if (_c == QMetaObject::InvokeMetaMethod) {
+ if (_id < 1)
+ qt_static_metacall(this, _c, _id, _a);
+ _id -= 1;
+ } else if (_c == QMetaObject::RegisterMethodArgumentMetaType) {
+ if (_id < 1)
+ *reinterpret_cast<int*>(_a[0]) = -1;
+ _id -= 1;
+ }
+ return _id;
+}
+struct qt_meta_stringdata_XpdfViewer_t {
+ QByteArrayData data[96];
+ char stringdata0[1559];
+};
+#define QT_MOC_LITERAL(idx, ofs, len) \
+ Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \
+ qptrdiff(offsetof(qt_meta_stringdata_XpdfViewer_t, stringdata0) + ofs \
+ - idx * sizeof(QByteArrayData)) \
+ )
+static const qt_meta_stringdata_XpdfViewer_t qt_meta_stringdata_XpdfViewer = {
+ {
+QT_MOC_LITERAL(0, 0, 10), // "XpdfViewer"
+QT_MOC_LITERAL(1, 11, 5), // "close"
+QT_MOC_LITERAL(2, 17, 0), // ""
+QT_MOC_LITERAL(3, 18, 22), // "remoteServerConnection"
+QT_MOC_LITERAL(4, 41, 16), // "remoteServerRead"
+QT_MOC_LITERAL(5, 58, 10), // "pdfResized"
+QT_MOC_LITERAL(6, 69, 12), // "pdfPaintDone"
+QT_MOC_LITERAL(7, 82, 8), // "finished"
+QT_MOC_LITERAL(8, 91, 7), // "preLoad"
+QT_MOC_LITERAL(9, 99, 8), // "postLoad"
+QT_MOC_LITERAL(10, 108, 8), // "keyPress"
+QT_MOC_LITERAL(11, 117, 10), // "QKeyEvent*"
+QT_MOC_LITERAL(12, 128, 1), // "e"
+QT_MOC_LITERAL(13, 130, 10), // "mousePress"
+QT_MOC_LITERAL(14, 141, 12), // "QMouseEvent*"
+QT_MOC_LITERAL(15, 154, 12), // "mouseRelease"
+QT_MOC_LITERAL(16, 167, 10), // "mouseClick"
+QT_MOC_LITERAL(17, 178, 16), // "mouseDoubleClick"
+QT_MOC_LITERAL(18, 195, 16), // "mouseTripleClick"
+QT_MOC_LITERAL(19, 212, 10), // "mouseWheel"
+QT_MOC_LITERAL(20, 223, 12), // "QWheelEvent*"
+QT_MOC_LITERAL(21, 236, 9), // "mouseMove"
+QT_MOC_LITERAL(22, 246, 10), // "pageChange"
+QT_MOC_LITERAL(23, 257, 2), // "pg"
+QT_MOC_LITERAL(24, 260, 20), // "sidebarSplitterMoved"
+QT_MOC_LITERAL(25, 281, 3), // "pos"
+QT_MOC_LITERAL(26, 285, 5), // "index"
+QT_MOC_LITERAL(27, 291, 11), // "printStatus"
+QT_MOC_LITERAL(28, 303, 8), // "nextPage"
+QT_MOC_LITERAL(29, 312, 9), // "firstPage"
+QT_MOC_LITERAL(30, 322, 8), // "lastPage"
+QT_MOC_LITERAL(31, 331, 11), // "cancelPrint"
+QT_MOC_LITERAL(32, 343, 14), // "openMenuAction"
+QT_MOC_LITERAL(33, 358, 22), // "openInNewWinMenuAction"
+QT_MOC_LITERAL(34, 381, 16), // "reloadMenuAction"
+QT_MOC_LITERAL(35, 398, 16), // "saveAsMenuAction"
+QT_MOC_LITERAL(36, 415, 19), // "saveImageMenuAction"
+QT_MOC_LITERAL(37, 435, 15), // "printMenuAction"
+QT_MOC_LITERAL(38, 451, 14), // "quitMenuAction"
+QT_MOC_LITERAL(39, 466, 14), // "copyMenuAction"
+QT_MOC_LITERAL(40, 481, 24), // "singlePageModeMenuAction"
+QT_MOC_LITERAL(41, 506, 24), // "continuousModeMenuAction"
+QT_MOC_LITERAL(42, 531, 30), // "sideBySideSingleModeMenuAction"
+QT_MOC_LITERAL(43, 562, 34), // "sideBySideContinuousModeMenuA..."
+QT_MOC_LITERAL(44, 597, 34), // "horizontalContinuousModeMenuA..."
+QT_MOC_LITERAL(45, 632, 20), // "fullScreenMenuAction"
+QT_MOC_LITERAL(46, 653, 7), // "checked"
+QT_MOC_LITERAL(47, 661, 25), // "rotateClockwiseMenuAction"
+QT_MOC_LITERAL(48, 687, 32), // "rotateCounterclockwiseMenuAction"
+QT_MOC_LITERAL(49, 720, 25), // "zoomToSelectionMenuAction"
+QT_MOC_LITERAL(50, 746, 23), // "toggleToolbarMenuAction"
+QT_MOC_LITERAL(51, 770, 23), // "toggleSidebarMenuAction"
+QT_MOC_LITERAL(52, 794, 24), // "viewPageLabelsMenuAction"
+QT_MOC_LITERAL(53, 819, 22), // "documentInfoMenuAction"
+QT_MOC_LITERAL(54, 842, 16), // "newTabMenuAction"
+QT_MOC_LITERAL(55, 859, 19), // "newWindowMenuAction"
+QT_MOC_LITERAL(56, 879, 18), // "closeTabMenuAction"
+QT_MOC_LITERAL(57, 898, 21), // "closeWindowMenuAction"
+QT_MOC_LITERAL(58, 920, 25), // "openErrorWindowMenuAction"
+QT_MOC_LITERAL(59, 946, 14), // "helpMenuAction"
+QT_MOC_LITERAL(60, 961, 21), // "keyBindingsMenuAction"
+QT_MOC_LITERAL(61, 983, 15), // "aboutMenuAction"
+QT_MOC_LITERAL(62, 999, 15), // "popupMenuAction"
+QT_MOC_LITERAL(63, 1015, 3), // "idx"
+QT_MOC_LITERAL(64, 1019, 26), // "toggleSidebarButtonPressed"
+QT_MOC_LITERAL(65, 1046, 17), // "pageNumberChanged"
+QT_MOC_LITERAL(66, 1064, 17), // "backButtonPressed"
+QT_MOC_LITERAL(67, 1082, 20), // "forwardButtonPressed"
+QT_MOC_LITERAL(68, 1103, 20), // "zoomOutButtonPressed"
+QT_MOC_LITERAL(69, 1124, 19), // "zoomInButtonPressed"
+QT_MOC_LITERAL(70, 1144, 16), // "zoomIndexChanged"
+QT_MOC_LITERAL(71, 1161, 19), // "zoomEditingFinished"
+QT_MOC_LITERAL(72, 1181, 21), // "fitWidthButtonPressed"
+QT_MOC_LITERAL(73, 1203, 20), // "fitPageButtonPressed"
+QT_MOC_LITERAL(74, 1224, 23), // "selectModeButtonPressed"
+QT_MOC_LITERAL(75, 1248, 22), // "statusIndicatorPressed"
+QT_MOC_LITERAL(76, 1271, 15), // "findTextChanged"
+QT_MOC_LITERAL(77, 1287, 21), // "findNextButtonPressed"
+QT_MOC_LITERAL(78, 1309, 21), // "findPrevButtonPressed"
+QT_MOC_LITERAL(79, 1331, 19), // "newTabButtonPressed"
+QT_MOC_LITERAL(80, 1351, 9), // "switchTab"
+QT_MOC_LITERAL(81, 1361, 16), // "QListWidgetItem*"
+QT_MOC_LITERAL(82, 1378, 7), // "current"
+QT_MOC_LITERAL(83, 1386, 8), // "previous"
+QT_MOC_LITERAL(84, 1395, 13), // "tabsReordered"
+QT_MOC_LITERAL(85, 1409, 11), // "QModelIndex"
+QT_MOC_LITERAL(86, 1421, 9), // "srcParent"
+QT_MOC_LITERAL(87, 1431, 8), // "srcStart"
+QT_MOC_LITERAL(88, 1440, 6), // "srcEnd"
+QT_MOC_LITERAL(89, 1447, 10), // "destParent"
+QT_MOC_LITERAL(90, 1458, 7), // "destRow"
+QT_MOC_LITERAL(91, 1466, 19), // "infoComboBoxChanged"
+QT_MOC_LITERAL(92, 1486, 18), // "outlineItemClicked"
+QT_MOC_LITERAL(93, 1505, 16), // "layerItemClicked"
+QT_MOC_LITERAL(94, 1522, 21), // "attachmentSaveClicked"
+QT_MOC_LITERAL(95, 1544, 14) // "clearFindError"
+
+ },
+ "XpdfViewer\0close\0\0remoteServerConnection\0"
+ "remoteServerRead\0pdfResized\0pdfPaintDone\0"
+ "finished\0preLoad\0postLoad\0keyPress\0"
+ "QKeyEvent*\0e\0mousePress\0QMouseEvent*\0"
+ "mouseRelease\0mouseClick\0mouseDoubleClick\0"
+ "mouseTripleClick\0mouseWheel\0QWheelEvent*\0"
+ "mouseMove\0pageChange\0pg\0sidebarSplitterMoved\0"
+ "pos\0index\0printStatus\0nextPage\0firstPage\0"
+ "lastPage\0cancelPrint\0openMenuAction\0"
+ "openInNewWinMenuAction\0reloadMenuAction\0"
+ "saveAsMenuAction\0saveImageMenuAction\0"
+ "printMenuAction\0quitMenuAction\0"
+ "copyMenuAction\0singlePageModeMenuAction\0"
+ "continuousModeMenuAction\0"
+ "sideBySideSingleModeMenuAction\0"
+ "sideBySideContinuousModeMenuAction\0"
+ "horizontalContinuousModeMenuAction\0"
+ "fullScreenMenuAction\0checked\0"
+ "rotateClockwiseMenuAction\0"
+ "rotateCounterclockwiseMenuAction\0"
+ "zoomToSelectionMenuAction\0"
+ "toggleToolbarMenuAction\0toggleSidebarMenuAction\0"
+ "viewPageLabelsMenuAction\0"
+ "documentInfoMenuAction\0newTabMenuAction\0"
+ "newWindowMenuAction\0closeTabMenuAction\0"
+ "closeWindowMenuAction\0openErrorWindowMenuAction\0"
+ "helpMenuAction\0keyBindingsMenuAction\0"
+ "aboutMenuAction\0popupMenuAction\0idx\0"
+ "toggleSidebarButtonPressed\0pageNumberChanged\0"
+ "backButtonPressed\0forwardButtonPressed\0"
+ "zoomOutButtonPressed\0zoomInButtonPressed\0"
+ "zoomIndexChanged\0zoomEditingFinished\0"
+ "fitWidthButtonPressed\0fitPageButtonPressed\0"
+ "selectModeButtonPressed\0statusIndicatorPressed\0"
+ "findTextChanged\0findNextButtonPressed\0"
+ "findPrevButtonPressed\0newTabButtonPressed\0"
+ "switchTab\0QListWidgetItem*\0current\0"
+ "previous\0tabsReordered\0QModelIndex\0"
+ "srcParent\0srcStart\0srcEnd\0destParent\0"
+ "destRow\0infoComboBoxChanged\0"
+ "outlineItemClicked\0layerItemClicked\0"
+ "attachmentSaveClicked\0clearFindError"
+};
+#undef QT_MOC_LITERAL
+
+static const uint qt_meta_data_XpdfViewer[] = {
+
+ // content:
+ 8, // revision
+ 0, // classname
+ 0, 0, // classinfo
+ 72, 14, // methods
+ 0, 0, // properties
+ 0, 0, // enums/sets
+ 0, 0, // constructors
+ 0, // flags
+ 0, // signalCount
+
+ // slots: name, argc, parameters, tag, flags
+ 1, 0, 374, 2, 0x0a /* Public */,
+ 3, 0, 375, 2, 0x08 /* Private */,
+ 4, 0, 376, 2, 0x08 /* Private */,
+ 5, 0, 377, 2, 0x08 /* Private */,
+ 6, 1, 378, 2, 0x08 /* Private */,
+ 8, 0, 381, 2, 0x08 /* Private */,
+ 9, 0, 382, 2, 0x08 /* Private */,
+ 10, 1, 383, 2, 0x08 /* Private */,
+ 13, 1, 386, 2, 0x08 /* Private */,
+ 15, 1, 389, 2, 0x08 /* Private */,
+ 16, 1, 392, 2, 0x08 /* Private */,
+ 17, 1, 395, 2, 0x08 /* Private */,
+ 18, 1, 398, 2, 0x08 /* Private */,
+ 19, 1, 401, 2, 0x08 /* Private */,
+ 21, 1, 404, 2, 0x08 /* Private */,
+ 22, 1, 407, 2, 0x08 /* Private */,
+ 24, 2, 410, 2, 0x08 /* Private */,
+ 27, 3, 415, 2, 0x08 /* Private */,
+ 31, 0, 422, 2, 0x08 /* Private */,
+ 32, 0, 423, 2, 0x08 /* Private */,
+ 33, 0, 424, 2, 0x08 /* Private */,
+ 34, 0, 425, 2, 0x08 /* Private */,
+ 35, 0, 426, 2, 0x08 /* Private */,
+ 36, 0, 427, 2, 0x08 /* Private */,
+ 37, 0, 428, 2, 0x08 /* Private */,
+ 38, 0, 429, 2, 0x08 /* Private */,
+ 39, 0, 430, 2, 0x08 /* Private */,
+ 40, 0, 431, 2, 0x08 /* Private */,
+ 41, 0, 432, 2, 0x08 /* Private */,
+ 42, 0, 433, 2, 0x08 /* Private */,
+ 43, 0, 434, 2, 0x08 /* Private */,
+ 44, 0, 435, 2, 0x08 /* Private */,
+ 45, 1, 436, 2, 0x08 /* Private */,
+ 47, 0, 439, 2, 0x08 /* Private */,
+ 48, 0, 440, 2, 0x08 /* Private */,
+ 49, 0, 441, 2, 0x08 /* Private */,
+ 50, 1, 442, 2, 0x08 /* Private */,
+ 51, 1, 445, 2, 0x08 /* Private */,
+ 52, 1, 448, 2, 0x08 /* Private */,
+ 53, 0, 451, 2, 0x08 /* Private */,
+ 54, 0, 452, 2, 0x08 /* Private */,
+ 55, 0, 453, 2, 0x08 /* Private */,
+ 56, 0, 454, 2, 0x08 /* Private */,
+ 57, 0, 455, 2, 0x08 /* Private */,
+ 58, 0, 456, 2, 0x08 /* Private */,
+ 59, 0, 457, 2, 0x08 /* Private */,
+ 60, 0, 458, 2, 0x08 /* Private */,
+ 61, 0, 459, 2, 0x08 /* Private */,
+ 62, 1, 460, 2, 0x08 /* Private */,
+ 64, 0, 463, 2, 0x08 /* Private */,
+ 65, 0, 464, 2, 0x08 /* Private */,
+ 66, 0, 465, 2, 0x08 /* Private */,
+ 67, 0, 466, 2, 0x08 /* Private */,
+ 68, 0, 467, 2, 0x08 /* Private */,
+ 69, 0, 468, 2, 0x08 /* Private */,
+ 70, 1, 469, 2, 0x08 /* Private */,
+ 71, 0, 472, 2, 0x08 /* Private */,
+ 72, 0, 473, 2, 0x08 /* Private */,
+ 73, 0, 474, 2, 0x08 /* Private */,
+ 74, 0, 475, 2, 0x08 /* Private */,
+ 75, 0, 476, 2, 0x08 /* Private */,
+ 76, 0, 477, 2, 0x08 /* Private */,
+ 77, 0, 478, 2, 0x08 /* Private */,
+ 78, 0, 479, 2, 0x08 /* Private */,
+ 79, 0, 480, 2, 0x08 /* Private */,
+ 80, 2, 481, 2, 0x08 /* Private */,
+ 84, 5, 486, 2, 0x08 /* Private */,
+ 91, 1, 497, 2, 0x08 /* Private */,
+ 92, 1, 500, 2, 0x08 /* Private */,
+ 93, 1, 503, 2, 0x08 /* Private */,
+ 94, 1, 506, 2, 0x08 /* Private */,
+ 95, 0, 509, 2, 0x08 /* Private */,
+
+ // slots: parameters
+ QMetaType::Bool,
+ QMetaType::Void,
+ QMetaType::Void,
+ QMetaType::Void,
+ QMetaType::Void, QMetaType::Bool, 7,
+ QMetaType::Void,
+ QMetaType::Void,
+ QMetaType::Void, 0x80000000 | 11, 12,
+ QMetaType::Void, 0x80000000 | 14, 12,
+ QMetaType::Void, 0x80000000 | 14, 12,
+ QMetaType::Void, 0x80000000 | 14, 12,
+ QMetaType::Void, 0x80000000 | 14, 12,
+ QMetaType::Void, 0x80000000 | 14, 12,
+ QMetaType::Void, 0x80000000 | 20, 12,
+ QMetaType::Void, 0x80000000 | 14, 12,
+ QMetaType::Void, QMetaType::Int, 23,
+ QMetaType::Void, QMetaType::Int, QMetaType::Int, 25, 26,
+ QMetaType::Void, QMetaType::Int, QMetaType::Int, QMetaType::Int, 28, 29, 30,
+ QMetaType::Void,
+ QMetaType::Void,
+ QMetaType::Void,
+ QMetaType::Void,
+ QMetaType::Void,
+ QMetaType::Void,
+ QMetaType::Void,
+ QMetaType::Void,
+ QMetaType::Void,
+ QMetaType::Void,
+ QMetaType::Void,
+ QMetaType::Void,
+ QMetaType::Void,
+ QMetaType::Void,
+ QMetaType::Void, QMetaType::Bool, 46,
+ QMetaType::Void,
+ QMetaType::Void,
+ QMetaType::Void,
+ QMetaType::Void, QMetaType::Bool, 46,
+ QMetaType::Void, QMetaType::Bool, 46,
+ QMetaType::Void, QMetaType::Bool, 46,
+ QMetaType::Void,
+ QMetaType::Void,
+ QMetaType::Void,
+ QMetaType::Void,
+ QMetaType::Void,
+ QMetaType::Void,
+ QMetaType::Void,
+ QMetaType::Void,
+ QMetaType::Void,
+ QMetaType::Void, QMetaType::Int, 63,
+ QMetaType::Void,
+ QMetaType::Void,
+ QMetaType::Void,
+ QMetaType::Void,
+ QMetaType::Void,
+ QMetaType::Void,
+ QMetaType::Void, QMetaType::Int, 63,
+ QMetaType::Void,
+ QMetaType::Void,
+ QMetaType::Void,
+ QMetaType::Void,
+ QMetaType::Void,
+ QMetaType::Void,
+ QMetaType::Void,
+ QMetaType::Void,
+ QMetaType::Void,
+ QMetaType::Void, 0x80000000 | 81, 0x80000000 | 81, 82, 83,
+ QMetaType::Void, 0x80000000 | 85, QMetaType::Int, QMetaType::Int, 0x80000000 | 85, QMetaType::Int, 86, 87, 88, 89, 90,
+ QMetaType::Void, QMetaType::Int, 63,
+ QMetaType::Void, 0x80000000 | 85, 63,
+ QMetaType::Void, 0x80000000 | 85, 63,
+ QMetaType::Void, QMetaType::Int, 63,
+ QMetaType::Void,
+
+ 0 // eod
+};
+
+void XpdfViewer::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
+{
+ if (_c == QMetaObject::InvokeMetaMethod) {
+ auto *_t = static_cast<XpdfViewer *>(_o);
+ Q_UNUSED(_t)
+ switch (_id) {
+ case 0: { bool _r = _t->close();
+ if (_a[0]) *reinterpret_cast< bool*>(_a[0]) = std::move(_r); } break;
+ case 1: _t->remoteServerConnection(); break;
+ case 2: _t->remoteServerRead(); break;
+ case 3: _t->pdfResized(); break;
+ case 4: _t->pdfPaintDone((*reinterpret_cast< bool(*)>(_a[1]))); break;
+ case 5: _t->preLoad(); break;
+ case 6: _t->postLoad(); break;
+ case 7: _t->keyPress((*reinterpret_cast< QKeyEvent*(*)>(_a[1]))); break;
+ case 8: _t->mousePress((*reinterpret_cast< QMouseEvent*(*)>(_a[1]))); break;
+ case 9: _t->mouseRelease((*reinterpret_cast< QMouseEvent*(*)>(_a[1]))); break;
+ case 10: _t->mouseClick((*reinterpret_cast< QMouseEvent*(*)>(_a[1]))); break;
+ case 11: _t->mouseDoubleClick((*reinterpret_cast< QMouseEvent*(*)>(_a[1]))); break;
+ case 12: _t->mouseTripleClick((*reinterpret_cast< QMouseEvent*(*)>(_a[1]))); break;
+ case 13: _t->mouseWheel((*reinterpret_cast< QWheelEvent*(*)>(_a[1]))); break;
+ case 14: _t->mouseMove((*reinterpret_cast< QMouseEvent*(*)>(_a[1]))); break;
+ case 15: _t->pageChange((*reinterpret_cast< int(*)>(_a[1]))); break;
+ case 16: _t->sidebarSplitterMoved((*reinterpret_cast< int(*)>(_a[1])),(*reinterpret_cast< int(*)>(_a[2]))); break;
+ case 17: _t->printStatus((*reinterpret_cast< int(*)>(_a[1])),(*reinterpret_cast< int(*)>(_a[2])),(*reinterpret_cast< int(*)>(_a[3]))); break;
+ case 18: _t->cancelPrint(); break;
+ case 19: _t->openMenuAction(); break;
+ case 20: _t->openInNewWinMenuAction(); break;
+ case 21: _t->reloadMenuAction(); break;
+ case 22: _t->saveAsMenuAction(); break;
+ case 23: _t->saveImageMenuAction(); break;
+ case 24: _t->printMenuAction(); break;
+ case 25: _t->quitMenuAction(); break;
+ case 26: _t->copyMenuAction(); break;
+ case 27: _t->singlePageModeMenuAction(); break;
+ case 28: _t->continuousModeMenuAction(); break;
+ case 29: _t->sideBySideSingleModeMenuAction(); break;
+ case 30: _t->sideBySideContinuousModeMenuAction(); break;
+ case 31: _t->horizontalContinuousModeMenuAction(); break;
+ case 32: _t->fullScreenMenuAction((*reinterpret_cast< bool(*)>(_a[1]))); break;
+ case 33: _t->rotateClockwiseMenuAction(); break;
+ case 34: _t->rotateCounterclockwiseMenuAction(); break;
+ case 35: _t->zoomToSelectionMenuAction(); break;
+ case 36: _t->toggleToolbarMenuAction((*reinterpret_cast< bool(*)>(_a[1]))); break;
+ case 37: _t->toggleSidebarMenuAction((*reinterpret_cast< bool(*)>(_a[1]))); break;
+ case 38: _t->viewPageLabelsMenuAction((*reinterpret_cast< bool(*)>(_a[1]))); break;
+ case 39: _t->documentInfoMenuAction(); break;
+ case 40: _t->newTabMenuAction(); break;
+ case 41: _t->newWindowMenuAction(); break;
+ case 42: _t->closeTabMenuAction(); break;
+ case 43: _t->closeWindowMenuAction(); break;
+ case 44: _t->openErrorWindowMenuAction(); break;
+ case 45: _t->helpMenuAction(); break;
+ case 46: _t->keyBindingsMenuAction(); break;
+ case 47: _t->aboutMenuAction(); break;
+ case 48: _t->popupMenuAction((*reinterpret_cast< int(*)>(_a[1]))); break;
+ case 49: _t->toggleSidebarButtonPressed(); break;
+ case 50: _t->pageNumberChanged(); break;
+ case 51: _t->backButtonPressed(); break;
+ case 52: _t->forwardButtonPressed(); break;
+ case 53: _t->zoomOutButtonPressed(); break;
+ case 54: _t->zoomInButtonPressed(); break;
+ case 55: _t->zoomIndexChanged((*reinterpret_cast< int(*)>(_a[1]))); break;
+ case 56: _t->zoomEditingFinished(); break;
+ case 57: _t->fitWidthButtonPressed(); break;
+ case 58: _t->fitPageButtonPressed(); break;
+ case 59: _t->selectModeButtonPressed(); break;
+ case 60: _t->statusIndicatorPressed(); break;
+ case 61: _t->findTextChanged(); break;
+ case 62: _t->findNextButtonPressed(); break;
+ case 63: _t->findPrevButtonPressed(); break;
+ case 64: _t->newTabButtonPressed(); break;
+ case 65: _t->switchTab((*reinterpret_cast< QListWidgetItem*(*)>(_a[1])),(*reinterpret_cast< QListWidgetItem*(*)>(_a[2]))); break;
+ case 66: _t->tabsReordered((*reinterpret_cast< const QModelIndex(*)>(_a[1])),(*reinterpret_cast< int(*)>(_a[2])),(*reinterpret_cast< int(*)>(_a[3])),(*reinterpret_cast< const QModelIndex(*)>(_a[4])),(*reinterpret_cast< int(*)>(_a[5]))); break;
+ case 67: _t->infoComboBoxChanged((*reinterpret_cast< int(*)>(_a[1]))); break;
+ case 68: _t->outlineItemClicked((*reinterpret_cast< const QModelIndex(*)>(_a[1]))); break;
+ case 69: _t->layerItemClicked((*reinterpret_cast< const QModelIndex(*)>(_a[1]))); break;
+ case 70: _t->attachmentSaveClicked((*reinterpret_cast< int(*)>(_a[1]))); break;
+ case 71: _t->clearFindError(); break;
+ default: ;
+ }
+ }
+}
+
+QT_INIT_METAOBJECT const QMetaObject XpdfViewer::staticMetaObject = { {
+ QMetaObject::SuperData::link<QMainWindow::staticMetaObject>(),
+ qt_meta_stringdata_XpdfViewer.data,
+ qt_meta_data_XpdfViewer,
+ qt_static_metacall,
+ nullptr,
+ nullptr
+} };
+
+
+const QMetaObject *XpdfViewer::metaObject() const
+{
+ return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject;
+}
+
+void *XpdfViewer::qt_metacast(const char *_clname)
+{
+ if (!_clname) return nullptr;
+ if (!strcmp(_clname, qt_meta_stringdata_XpdfViewer.stringdata0))
+ return static_cast<void*>(this);
+ return QMainWindow::qt_metacast(_clname);
+}
+
+int XpdfViewer::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
+{
+ _id = QMainWindow::qt_metacall(_c, _id, _a);
+ if (_id < 0)
+ return _id;
+ if (_c == QMetaObject::InvokeMetaMethod) {
+ if (_id < 72)
+ qt_static_metacall(this, _c, _id, _a);
+ _id -= 72;
+ } else if (_c == QMetaObject::RegisterMethodArgumentMetaType) {
+ if (_id < 72)
+ *reinterpret_cast<int*>(_a[0]) = -1;
+ _id -= 72;
+ }
+ return _id;
+}
+QT_WARNING_POP
+QT_END_MOC_NAMESPACE
diff --git a/xpdf-qt/moc_XpdfViewer.cpp_parameters b/xpdf-qt/moc_XpdfViewer.cpp_parameters
new file mode 100644
index 0000000..0bd1c12
--- /dev/null
+++ b/xpdf-qt/moc_XpdfViewer.cpp_parameters
@@ -0,0 +1,28 @@
+-I/home/calvin/src/xpdf-4.04
+-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
+-I/home/calvin/src/xpdf-4.04/xpdf
+-I/usr/include/x86_64-linux-gnu/qt5/
+-I/usr/include/x86_64-linux-gnu/qt5/QtWidgets
+-I/usr/include/x86_64-linux-gnu/qt5/QtGui
+-I/usr/include/x86_64-linux-gnu/qt5/QtCore
+-I/usr/lib/x86_64-linux-gnu/qt5/mkspecs/linux-g++ /usr/include/x86_64-linux-gnu/qt5/
+-I/usr/include/x86_64-linux-gnu/qt5/QtNetwork
+-I/usr/include/x86_64-linux-gnu/qt5/QtCore
+-I/usr/lib/x86_64-linux-gnu/qt5/mkspecs/linux-g++ /usr/include/x86_64-linux-gnu/qt5/
+-I/usr/include/x86_64-linux-gnu/qt5/QtPrintSupport
+-I/usr/include/x86_64-linux-gnu/qt5/QtWidgets
+-I/usr/include/x86_64-linux-gnu/qt5/QtGui
+-I/usr/include/x86_64-linux-gnu/qt5/QtCore
+-I/usr/lib/x86_64-linux-gnu/qt5/mkspecs/linux-g++
+-DQT_WIDGETS_LIB
+-DQT_GUI_LIB
+-DQT_WIDGETS_LIB
+-DQT_GUI_LIB
+-DQT_CORE_LIB
+-DXPDFWIDGET_PRINTING=1
+-o
+/home/calvin/src/xpdf-4.04/xpdf-qt/moc_XpdfViewer.cpp
+/home/calvin/src/xpdf-4.04/xpdf-qt/XpdfViewer.h
diff --git a/xpdf-qt/moc_XpdfWidget.cpp b/xpdf-qt/moc_XpdfWidget.cpp
new file mode 100644
index 0000000..b0b2ea7
--- /dev/null
+++ b/xpdf-qt/moc_XpdfWidget.cpp
@@ -0,0 +1,463 @@
+/****************************************************************************
+** Meta object code from reading C++ file 'XpdfWidget.h'
+**
+** Created by: The Qt Meta Object Compiler version 67 (Qt 5.15.2)
+**
+** WARNING! All changes made in this file will be lost!
+*****************************************************************************/
+
+#include <memory>
+#include "XpdfWidget.h"
+#include <QtCore/qbytearray.h>
+#include <QtCore/qmetatype.h>
+#if !defined(Q_MOC_OUTPUT_REVISION)
+#error "The header file 'XpdfWidget.h' doesn't include <QObject>."
+#elif Q_MOC_OUTPUT_REVISION != 67
+#error "This file was generated using the moc from 5.15.2. It"
+#error "cannot be used with the include files from this version of Qt."
+#error "(The moc has changed too much.)"
+#endif
+
+QT_BEGIN_MOC_NAMESPACE
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
+struct qt_meta_stringdata_XpdfWidget_t {
+ QByteArrayData data[33];
+ char stringdata0[321];
+};
+#define QT_MOC_LITERAL(idx, ofs, len) \
+ Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \
+ qptrdiff(offsetof(qt_meta_stringdata_XpdfWidget_t, stringdata0) + ofs \
+ - idx * sizeof(QByteArrayData)) \
+ )
+static const qt_meta_stringdata_XpdfWidget_t qt_meta_stringdata_XpdfWidget = {
+ {
+QT_MOC_LITERAL(0, 0, 10), // "XpdfWidget"
+QT_MOC_LITERAL(1, 11, 10), // "pageChange"
+QT_MOC_LITERAL(2, 22, 0), // ""
+QT_MOC_LITERAL(3, 23, 7), // "pageNum"
+QT_MOC_LITERAL(4, 31, 13), // "midPageChange"
+QT_MOC_LITERAL(5, 45, 7), // "preLoad"
+QT_MOC_LITERAL(6, 53, 8), // "postLoad"
+QT_MOC_LITERAL(7, 62, 8), // "keyPress"
+QT_MOC_LITERAL(8, 71, 10), // "QKeyEvent*"
+QT_MOC_LITERAL(9, 82, 1), // "e"
+QT_MOC_LITERAL(10, 84, 10), // "mousePress"
+QT_MOC_LITERAL(11, 95, 12), // "QMouseEvent*"
+QT_MOC_LITERAL(12, 108, 12), // "mouseRelease"
+QT_MOC_LITERAL(13, 121, 10), // "mouseClick"
+QT_MOC_LITERAL(14, 132, 16), // "mouseDoubleClick"
+QT_MOC_LITERAL(15, 149, 16), // "mouseTripleClick"
+QT_MOC_LITERAL(16, 166, 9), // "mouseMove"
+QT_MOC_LITERAL(17, 176, 10), // "mouseWheel"
+QT_MOC_LITERAL(18, 187, 12), // "QWheelEvent*"
+QT_MOC_LITERAL(19, 200, 9), // "linkClick"
+QT_MOC_LITERAL(20, 210, 8), // "linkType"
+QT_MOC_LITERAL(21, 219, 4), // "dest"
+QT_MOC_LITERAL(22, 224, 4), // "page"
+QT_MOC_LITERAL(23, 229, 10), // "selectDone"
+QT_MOC_LITERAL(24, 240, 9), // "paintDone"
+QT_MOC_LITERAL(25, 250, 8), // "finished"
+QT_MOC_LITERAL(26, 259, 7), // "resized"
+QT_MOC_LITERAL(27, 267, 11), // "printStatus"
+QT_MOC_LITERAL(28, 279, 8), // "nextPage"
+QT_MOC_LITERAL(29, 288, 9), // "firstPage"
+QT_MOC_LITERAL(30, 298, 8), // "lastPage"
+QT_MOC_LITERAL(31, 307, 8), // "tileDone"
+QT_MOC_LITERAL(32, 316, 4) // "tick"
+
+ },
+ "XpdfWidget\0pageChange\0\0pageNum\0"
+ "midPageChange\0preLoad\0postLoad\0keyPress\0"
+ "QKeyEvent*\0e\0mousePress\0QMouseEvent*\0"
+ "mouseRelease\0mouseClick\0mouseDoubleClick\0"
+ "mouseTripleClick\0mouseMove\0mouseWheel\0"
+ "QWheelEvent*\0linkClick\0linkType\0dest\0"
+ "page\0selectDone\0paintDone\0finished\0"
+ "resized\0printStatus\0nextPage\0firstPage\0"
+ "lastPage\0tileDone\0tick"
+};
+#undef QT_MOC_LITERAL
+
+static const uint qt_meta_data_XpdfWidget[] = {
+
+ // content:
+ 8, // revision
+ 0, // classname
+ 0, 0, // classinfo
+ 19, 14, // methods
+ 0, 0, // properties
+ 0, 0, // enums/sets
+ 0, 0, // constructors
+ 0, // flags
+ 18, // signalCount
+
+ // signals: name, argc, parameters, tag, flags
+ 1, 1, 109, 2, 0x06 /* Public */,
+ 4, 1, 112, 2, 0x06 /* Public */,
+ 5, 0, 115, 2, 0x06 /* Public */,
+ 6, 0, 116, 2, 0x06 /* Public */,
+ 7, 1, 117, 2, 0x06 /* Public */,
+ 10, 1, 120, 2, 0x06 /* Public */,
+ 12, 1, 123, 2, 0x06 /* Public */,
+ 13, 1, 126, 2, 0x06 /* Public */,
+ 14, 1, 129, 2, 0x06 /* Public */,
+ 15, 1, 132, 2, 0x06 /* Public */,
+ 16, 1, 135, 2, 0x06 /* Public */,
+ 17, 1, 138, 2, 0x06 /* Public */,
+ 19, 3, 141, 2, 0x06 /* Public */,
+ 23, 0, 148, 2, 0x06 /* Public */,
+ 24, 1, 149, 2, 0x06 /* Public */,
+ 26, 0, 152, 2, 0x06 /* Public */,
+ 27, 3, 153, 2, 0x06 /* Public */,
+ 31, 0, 160, 2, 0x06 /* Public */,
+
+ // slots: name, argc, parameters, tag, flags
+ 32, 0, 161, 2, 0x08 /* Private */,
+
+ // signals: parameters
+ QMetaType::Void, QMetaType::Int, 3,
+ QMetaType::Void, QMetaType::Int, 3,
+ QMetaType::Void,
+ QMetaType::Void,
+ QMetaType::Void, 0x80000000 | 8, 9,
+ QMetaType::Void, 0x80000000 | 11, 9,
+ QMetaType::Void, 0x80000000 | 11, 9,
+ QMetaType::Void, 0x80000000 | 11, 9,
+ QMetaType::Void, 0x80000000 | 11, 9,
+ QMetaType::Void, 0x80000000 | 11, 9,
+ QMetaType::Void, 0x80000000 | 11, 9,
+ QMetaType::Void, 0x80000000 | 18, 9,
+ QMetaType::Void, QMetaType::QString, QMetaType::QString, QMetaType::Int, 20, 21, 22,
+ QMetaType::Void,
+ QMetaType::Void, QMetaType::Bool, 25,
+ QMetaType::Void,
+ QMetaType::Void, QMetaType::Int, QMetaType::Int, QMetaType::Int, 28, 29, 30,
+ QMetaType::Void,
+
+ // slots: parameters
+ QMetaType::Void,
+
+ 0 // eod
+};
+
+void XpdfWidget::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
+{
+ if (_c == QMetaObject::InvokeMetaMethod) {
+ auto *_t = static_cast<XpdfWidget *>(_o);
+ Q_UNUSED(_t)
+ switch (_id) {
+ case 0: _t->pageChange((*reinterpret_cast< int(*)>(_a[1]))); break;
+ case 1: _t->midPageChange((*reinterpret_cast< int(*)>(_a[1]))); break;
+ case 2: _t->preLoad(); break;
+ case 3: _t->postLoad(); break;
+ case 4: _t->keyPress((*reinterpret_cast< QKeyEvent*(*)>(_a[1]))); break;
+ case 5: _t->mousePress((*reinterpret_cast< QMouseEvent*(*)>(_a[1]))); break;
+ case 6: _t->mouseRelease((*reinterpret_cast< QMouseEvent*(*)>(_a[1]))); break;
+ case 7: _t->mouseClick((*reinterpret_cast< QMouseEvent*(*)>(_a[1]))); break;
+ case 8: _t->mouseDoubleClick((*reinterpret_cast< QMouseEvent*(*)>(_a[1]))); break;
+ case 9: _t->mouseTripleClick((*reinterpret_cast< QMouseEvent*(*)>(_a[1]))); break;
+ case 10: _t->mouseMove((*reinterpret_cast< QMouseEvent*(*)>(_a[1]))); break;
+ case 11: _t->mouseWheel((*reinterpret_cast< QWheelEvent*(*)>(_a[1]))); break;
+ case 12: _t->linkClick((*reinterpret_cast< const QString(*)>(_a[1])),(*reinterpret_cast< const QString(*)>(_a[2])),(*reinterpret_cast< int(*)>(_a[3]))); break;
+ case 13: _t->selectDone(); break;
+ case 14: _t->paintDone((*reinterpret_cast< bool(*)>(_a[1]))); break;
+ case 15: _t->resized(); break;
+ case 16: _t->printStatus((*reinterpret_cast< int(*)>(_a[1])),(*reinterpret_cast< int(*)>(_a[2])),(*reinterpret_cast< int(*)>(_a[3]))); break;
+ case 17: _t->tileDone(); break;
+ case 18: _t->tick(); break;
+ default: ;
+ }
+ } else if (_c == QMetaObject::IndexOfMethod) {
+ int *result = reinterpret_cast<int *>(_a[0]);
+ {
+ using _t = void (XpdfWidget::*)(int );
+ if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&XpdfWidget::pageChange)) {
+ *result = 0;
+ return;
+ }
+ }
+ {
+ using _t = void (XpdfWidget::*)(int );
+ if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&XpdfWidget::midPageChange)) {
+ *result = 1;
+ return;
+ }
+ }
+ {
+ using _t = void (XpdfWidget::*)();
+ if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&XpdfWidget::preLoad)) {
+ *result = 2;
+ return;
+ }
+ }
+ {
+ using _t = void (XpdfWidget::*)();
+ if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&XpdfWidget::postLoad)) {
+ *result = 3;
+ return;
+ }
+ }
+ {
+ using _t = void (XpdfWidget::*)(QKeyEvent * );
+ if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&XpdfWidget::keyPress)) {
+ *result = 4;
+ return;
+ }
+ }
+ {
+ using _t = void (XpdfWidget::*)(QMouseEvent * );
+ if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&XpdfWidget::mousePress)) {
+ *result = 5;
+ return;
+ }
+ }
+ {
+ using _t = void (XpdfWidget::*)(QMouseEvent * );
+ if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&XpdfWidget::mouseRelease)) {
+ *result = 6;
+ return;
+ }
+ }
+ {
+ using _t = void (XpdfWidget::*)(QMouseEvent * );
+ if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&XpdfWidget::mouseClick)) {
+ *result = 7;
+ return;
+ }
+ }
+ {
+ using _t = void (XpdfWidget::*)(QMouseEvent * );
+ if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&XpdfWidget::mouseDoubleClick)) {
+ *result = 8;
+ return;
+ }
+ }
+ {
+ using _t = void (XpdfWidget::*)(QMouseEvent * );
+ if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&XpdfWidget::mouseTripleClick)) {
+ *result = 9;
+ return;
+ }
+ }
+ {
+ using _t = void (XpdfWidget::*)(QMouseEvent * );
+ if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&XpdfWidget::mouseMove)) {
+ *result = 10;
+ return;
+ }
+ }
+ {
+ using _t = void (XpdfWidget::*)(QWheelEvent * );
+ if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&XpdfWidget::mouseWheel)) {
+ *result = 11;
+ return;
+ }
+ }
+ {
+ using _t = void (XpdfWidget::*)(const QString & , const QString & , int );
+ if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&XpdfWidget::linkClick)) {
+ *result = 12;
+ return;
+ }
+ }
+ {
+ using _t = void (XpdfWidget::*)();
+ if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&XpdfWidget::selectDone)) {
+ *result = 13;
+ return;
+ }
+ }
+ {
+ using _t = void (XpdfWidget::*)(bool );
+ if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&XpdfWidget::paintDone)) {
+ *result = 14;
+ return;
+ }
+ }
+ {
+ using _t = void (XpdfWidget::*)();
+ if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&XpdfWidget::resized)) {
+ *result = 15;
+ return;
+ }
+ }
+ {
+ using _t = void (XpdfWidget::*)(int , int , int );
+ if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&XpdfWidget::printStatus)) {
+ *result = 16;
+ return;
+ }
+ }
+ {
+ using _t = void (XpdfWidget::*)();
+ if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&XpdfWidget::tileDone)) {
+ *result = 17;
+ return;
+ }
+ }
+ }
+}
+
+QT_INIT_METAOBJECT const QMetaObject XpdfWidget::staticMetaObject = { {
+ QMetaObject::SuperData::link<QAbstractScrollArea::staticMetaObject>(),
+ qt_meta_stringdata_XpdfWidget.data,
+ qt_meta_data_XpdfWidget,
+ qt_static_metacall,
+ nullptr,
+ nullptr
+} };
+
+
+const QMetaObject *XpdfWidget::metaObject() const
+{
+ return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject;
+}
+
+void *XpdfWidget::qt_metacast(const char *_clname)
+{
+ if (!_clname) return nullptr;
+ if (!strcmp(_clname, qt_meta_stringdata_XpdfWidget.stringdata0))
+ return static_cast<void*>(this);
+ return QAbstractScrollArea::qt_metacast(_clname);
+}
+
+int XpdfWidget::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
+{
+ _id = QAbstractScrollArea::qt_metacall(_c, _id, _a);
+ if (_id < 0)
+ return _id;
+ if (_c == QMetaObject::InvokeMetaMethod) {
+ if (_id < 19)
+ qt_static_metacall(this, _c, _id, _a);
+ _id -= 19;
+ } else if (_c == QMetaObject::RegisterMethodArgumentMetaType) {
+ if (_id < 19)
+ *reinterpret_cast<int*>(_a[0]) = -1;
+ _id -= 19;
+ }
+ return _id;
+}
+
+// SIGNAL 0
+void XpdfWidget::pageChange(int _t1)
+{
+ void *_a[] = { nullptr, const_cast<void*>(reinterpret_cast<const void*>(std::addressof(_t1))) };
+ QMetaObject::activate(this, &staticMetaObject, 0, _a);
+}
+
+// SIGNAL 1
+void XpdfWidget::midPageChange(int _t1)
+{
+ void *_a[] = { nullptr, const_cast<void*>(reinterpret_cast<const void*>(std::addressof(_t1))) };
+ QMetaObject::activate(this, &staticMetaObject, 1, _a);
+}
+
+// SIGNAL 2
+void XpdfWidget::preLoad()
+{
+ QMetaObject::activate(this, &staticMetaObject, 2, nullptr);
+}
+
+// SIGNAL 3
+void XpdfWidget::postLoad()
+{
+ QMetaObject::activate(this, &staticMetaObject, 3, nullptr);
+}
+
+// SIGNAL 4
+void XpdfWidget::keyPress(QKeyEvent * _t1)
+{
+ void *_a[] = { nullptr, const_cast<void*>(reinterpret_cast<const void*>(std::addressof(_t1))) };
+ QMetaObject::activate(this, &staticMetaObject, 4, _a);
+}
+
+// SIGNAL 5
+void XpdfWidget::mousePress(QMouseEvent * _t1)
+{
+ void *_a[] = { nullptr, const_cast<void*>(reinterpret_cast<const void*>(std::addressof(_t1))) };
+ QMetaObject::activate(this, &staticMetaObject, 5, _a);
+}
+
+// SIGNAL 6
+void XpdfWidget::mouseRelease(QMouseEvent * _t1)
+{
+ void *_a[] = { nullptr, const_cast<void*>(reinterpret_cast<const void*>(std::addressof(_t1))) };
+ QMetaObject::activate(this, &staticMetaObject, 6, _a);
+}
+
+// SIGNAL 7
+void XpdfWidget::mouseClick(QMouseEvent * _t1)
+{
+ void *_a[] = { nullptr, const_cast<void*>(reinterpret_cast<const void*>(std::addressof(_t1))) };
+ QMetaObject::activate(this, &staticMetaObject, 7, _a);
+}
+
+// SIGNAL 8
+void XpdfWidget::mouseDoubleClick(QMouseEvent * _t1)
+{
+ void *_a[] = { nullptr, const_cast<void*>(reinterpret_cast<const void*>(std::addressof(_t1))) };
+ QMetaObject::activate(this, &staticMetaObject, 8, _a);
+}
+
+// SIGNAL 9
+void XpdfWidget::mouseTripleClick(QMouseEvent * _t1)
+{
+ void *_a[] = { nullptr, const_cast<void*>(reinterpret_cast<const void*>(std::addressof(_t1))) };
+ QMetaObject::activate(this, &staticMetaObject, 9, _a);
+}
+
+// SIGNAL 10
+void XpdfWidget::mouseMove(QMouseEvent * _t1)
+{
+ void *_a[] = { nullptr, const_cast<void*>(reinterpret_cast<const void*>(std::addressof(_t1))) };
+ QMetaObject::activate(this, &staticMetaObject, 10, _a);
+}
+
+// SIGNAL 11
+void XpdfWidget::mouseWheel(QWheelEvent * _t1)
+{
+ void *_a[] = { nullptr, const_cast<void*>(reinterpret_cast<const void*>(std::addressof(_t1))) };
+ QMetaObject::activate(this, &staticMetaObject, 11, _a);
+}
+
+// SIGNAL 12
+void XpdfWidget::linkClick(const QString & _t1, const QString & _t2, int _t3)
+{
+ void *_a[] = { nullptr, const_cast<void*>(reinterpret_cast<const void*>(std::addressof(_t1))), const_cast<void*>(reinterpret_cast<const void*>(std::addressof(_t2))), const_cast<void*>(reinterpret_cast<const void*>(std::addressof(_t3))) };
+ QMetaObject::activate(this, &staticMetaObject, 12, _a);
+}
+
+// SIGNAL 13
+void XpdfWidget::selectDone()
+{
+ QMetaObject::activate(this, &staticMetaObject, 13, nullptr);
+}
+
+// SIGNAL 14
+void XpdfWidget::paintDone(bool _t1)
+{
+ void *_a[] = { nullptr, const_cast<void*>(reinterpret_cast<const void*>(std::addressof(_t1))) };
+ QMetaObject::activate(this, &staticMetaObject, 14, _a);
+}
+
+// SIGNAL 15
+void XpdfWidget::resized()
+{
+ QMetaObject::activate(this, &staticMetaObject, 15, nullptr);
+}
+
+// SIGNAL 16
+void XpdfWidget::printStatus(int _t1, int _t2, int _t3)
+{
+ void *_a[] = { nullptr, const_cast<void*>(reinterpret_cast<const void*>(std::addressof(_t1))), const_cast<void*>(reinterpret_cast<const void*>(std::addressof(_t2))), const_cast<void*>(reinterpret_cast<const void*>(std::addressof(_t3))) };
+ QMetaObject::activate(this, &staticMetaObject, 16, _a);
+}
+
+// SIGNAL 17
+void XpdfWidget::tileDone()
+{
+ QMetaObject::activate(this, &staticMetaObject, 17, nullptr);
+}
+QT_WARNING_POP
+QT_END_MOC_NAMESPACE
diff --git a/xpdf-qt/moc_XpdfWidget.cpp_parameters b/xpdf-qt/moc_XpdfWidget.cpp_parameters
new file mode 100644
index 0000000..524da2a
--- /dev/null
+++ b/xpdf-qt/moc_XpdfWidget.cpp_parameters
@@ -0,0 +1,28 @@
+-I/home/calvin/src/xpdf-4.04
+-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
+-I/home/calvin/src/xpdf-4.04/xpdf
+-I/usr/include/x86_64-linux-gnu/qt5/
+-I/usr/include/x86_64-linux-gnu/qt5/QtWidgets
+-I/usr/include/x86_64-linux-gnu/qt5/QtGui
+-I/usr/include/x86_64-linux-gnu/qt5/QtCore
+-I/usr/lib/x86_64-linux-gnu/qt5/mkspecs/linux-g++ /usr/include/x86_64-linux-gnu/qt5/
+-I/usr/include/x86_64-linux-gnu/qt5/QtNetwork
+-I/usr/include/x86_64-linux-gnu/qt5/QtCore
+-I/usr/lib/x86_64-linux-gnu/qt5/mkspecs/linux-g++ /usr/include/x86_64-linux-gnu/qt5/
+-I/usr/include/x86_64-linux-gnu/qt5/QtPrintSupport
+-I/usr/include/x86_64-linux-gnu/qt5/QtWidgets
+-I/usr/include/x86_64-linux-gnu/qt5/QtGui
+-I/usr/include/x86_64-linux-gnu/qt5/QtCore
+-I/usr/lib/x86_64-linux-gnu/qt5/mkspecs/linux-g++
+-DQT_WIDGETS_LIB
+-DQT_GUI_LIB
+-DQT_WIDGETS_LIB
+-DQT_GUI_LIB
+-DQT_CORE_LIB
+-DXPDFWIDGET_PRINTING=1
+-o
+/home/calvin/src/xpdf-4.04/xpdf-qt/moc_XpdfWidget.cpp
+/home/calvin/src/xpdf-4.04/xpdf-qt/XpdfWidget.h
diff --git a/xpdf-qt/qrc_icons.cpp b/xpdf-qt/qrc_icons.cpp
new file mode 100644
index 0000000..0bdcd27
--- /dev/null
+++ b/xpdf-qt/qrc_icons.cpp
@@ -0,0 +1,1325 @@
+/****************************************************************************
+** Resource object code
+**
+** Created by: The Resource Compiler for Qt version 5.15.2
+**
+** WARNING! All changes made in this file will be lost!
+*****************************************************************************/
+
+static const unsigned char qt_resource_data[] = {
+ // /home/calvin/src/xpdf-4.04/xpdf-qt/fitPage.svg
+ 0x0,0x0,0x3,0x4b,
+ 0x3c,
+ 0x3f,0x78,0x6d,0x6c,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x3d,0x22,0x31,0x2e,
+ 0x30,0x22,0x3f,0x3e,0xa,0x3c,0x21,0x44,0x4f,0x43,0x54,0x59,0x50,0x45,0x20,0x73,
+ 0x76,0x67,0x20,0x50,0x55,0x42,0x4c,0x49,0x43,0x20,0x22,0x2d,0x2f,0x2f,0x57,0x33,
+ 0x43,0x2f,0x2f,0x44,0x54,0x44,0x20,0x53,0x56,0x47,0x20,0x31,0x2e,0x31,0x2f,0x2f,
+ 0x45,0x4e,0x22,0x20,0xa,0x20,0x20,0x22,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,
+ 0x77,0x77,0x2e,0x77,0x33,0x2e,0x6f,0x72,0x67,0x2f,0x47,0x72,0x61,0x70,0x68,0x69,
+ 0x63,0x73,0x2f,0x53,0x56,0x47,0x2f,0x31,0x2e,0x31,0x2f,0x44,0x54,0x44,0x2f,0x73,
+ 0x76,0x67,0x31,0x31,0x2e,0x64,0x74,0x64,0x22,0x3e,0xa,0x3c,0x73,0x76,0x67,0x20,
+ 0x77,0x69,0x64,0x74,0x68,0x3d,0x22,0x38,0x30,0x22,0x20,0x68,0x65,0x69,0x67,0x68,
+ 0x74,0x3d,0x22,0x38,0x30,0x22,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x3d,0x22,
+ 0x31,0x2e,0x31,0x22,0xa,0x20,0x78,0x6d,0x6c,0x6e,0x73,0x3d,0x22,0x68,0x74,0x74,
+ 0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x77,0x33,0x2e,0x6f,0x72,0x67,0x2f,0x32,
+ 0x30,0x30,0x30,0x2f,0x73,0x76,0x67,0x22,0x3e,0xa,0x20,0x20,0x3c,0x72,0x65,0x63,
+ 0x74,0x20,0x66,0x69,0x6c,0x6c,0x3d,0x22,0x6e,0x6f,0x6e,0x65,0x22,0x20,0x73,0x74,
+ 0x72,0x6f,0x6b,0x65,0x3d,0x22,0x23,0x35,0x35,0x35,0x35,0x35,0x35,0x22,0x20,0x73,
+ 0x74,0x72,0x6f,0x6b,0x65,0x2d,0x77,0x69,0x64,0x74,0x68,0x3d,0x22,0x34,0x22,0xa,
+ 0x20,0x20,0x20,0x78,0x3d,0x22,0x31,0x34,0x22,0x20,0x79,0x3d,0x22,0x36,0x22,0x20,
+ 0x77,0x69,0x64,0x74,0x68,0x3d,0x22,0x35,0x36,0x22,0x20,0x68,0x65,0x69,0x67,0x68,
+ 0x74,0x3d,0x22,0x37,0x32,0x22,0x2f,0x3e,0xa,0x20,0x20,0x3c,0x70,0x6f,0x6c,0x79,
+ 0x6c,0x69,0x6e,0x65,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x3d,0x22,0x23,0x35,0x35,
+ 0x35,0x35,0x35,0x35,0x22,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x2d,0x77,0x69,0x64,
+ 0x74,0x68,0x3d,0x22,0x34,0x22,0x20,0x66,0x69,0x6c,0x6c,0x3d,0x22,0x6e,0x6f,0x6e,
+ 0x65,0x22,0xa,0x20,0x20,0x20,0x70,0x6f,0x69,0x6e,0x74,0x73,0x3d,0x22,0x32,0x32,
+ 0x2c,0x34,0x32,0x20,0x20,0x36,0x32,0x2c,0x34,0x32,0x22,0x2f,0x3e,0xa,0x20,0x20,
+ 0x3c,0x70,0x6f,0x6c,0x79,0x6c,0x69,0x6e,0x65,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,
+ 0x3d,0x22,0x23,0x35,0x35,0x35,0x35,0x35,0x35,0x22,0x20,0x73,0x74,0x72,0x6f,0x6b,
+ 0x65,0x2d,0x77,0x69,0x64,0x74,0x68,0x3d,0x22,0x34,0x22,0x20,0x66,0x69,0x6c,0x6c,
+ 0x3d,0x22,0x6e,0x6f,0x6e,0x65,0x22,0xa,0x20,0x20,0x20,0x70,0x6f,0x69,0x6e,0x74,
+ 0x73,0x3d,0x22,0x33,0x32,0x2c,0x33,0x32,0x20,0x20,0x32,0x32,0x2c,0x34,0x32,0x20,
+ 0x20,0x33,0x32,0x2c,0x35,0x32,0x22,0x2f,0x3e,0xa,0x20,0x20,0x3c,0x70,0x6f,0x6c,
+ 0x79,0x6c,0x69,0x6e,0x65,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x3d,0x22,0x23,0x35,
+ 0x35,0x35,0x35,0x35,0x35,0x22,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x2d,0x77,0x69,
+ 0x64,0x74,0x68,0x3d,0x22,0x34,0x22,0x20,0x66,0x69,0x6c,0x6c,0x3d,0x22,0x6e,0x6f,
+ 0x6e,0x65,0x22,0xa,0x20,0x20,0x20,0x70,0x6f,0x69,0x6e,0x74,0x73,0x3d,0x22,0x35,
+ 0x32,0x2c,0x33,0x32,0x20,0x20,0x36,0x32,0x2c,0x34,0x32,0x20,0x20,0x35,0x32,0x2c,
+ 0x35,0x32,0x22,0x2f,0x3e,0xa,0x20,0x20,0x3c,0x70,0x6f,0x6c,0x79,0x6c,0x69,0x6e,
+ 0x65,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x3d,0x22,0x23,0x35,0x35,0x35,0x35,0x35,
+ 0x35,0x22,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x2d,0x77,0x69,0x64,0x74,0x68,0x3d,
+ 0x22,0x34,0x22,0x20,0x66,0x69,0x6c,0x6c,0x3d,0x22,0x6e,0x6f,0x6e,0x65,0x22,0xa,
+ 0x20,0x20,0x20,0x70,0x6f,0x69,0x6e,0x74,0x73,0x3d,0x22,0x34,0x32,0x2c,0x31,0x34,
+ 0x20,0x20,0x34,0x32,0x2c,0x37,0x30,0x22,0x2f,0x3e,0xa,0x20,0x20,0x3c,0x70,0x6f,
+ 0x6c,0x79,0x6c,0x69,0x6e,0x65,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x3d,0x22,0x23,
+ 0x35,0x35,0x35,0x35,0x35,0x35,0x22,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x2d,0x77,
+ 0x69,0x64,0x74,0x68,0x3d,0x22,0x34,0x22,0x20,0x66,0x69,0x6c,0x6c,0x3d,0x22,0x6e,
+ 0x6f,0x6e,0x65,0x22,0xa,0x20,0x20,0x20,0x70,0x6f,0x69,0x6e,0x74,0x73,0x3d,0x22,
+ 0x33,0x32,0x2c,0x32,0x34,0x20,0x20,0x34,0x32,0x2c,0x31,0x34,0x20,0x20,0x35,0x32,
+ 0x2c,0x32,0x34,0x22,0x2f,0x3e,0xa,0x20,0x20,0x3c,0x70,0x6f,0x6c,0x79,0x6c,0x69,
+ 0x6e,0x65,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x3d,0x22,0x23,0x35,0x35,0x35,0x35,
+ 0x35,0x35,0x22,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x2d,0x77,0x69,0x64,0x74,0x68,
+ 0x3d,0x22,0x34,0x22,0x20,0x66,0x69,0x6c,0x6c,0x3d,0x22,0x6e,0x6f,0x6e,0x65,0x22,
+ 0xa,0x20,0x20,0x20,0x70,0x6f,0x69,0x6e,0x74,0x73,0x3d,0x22,0x33,0x32,0x2c,0x36,
+ 0x30,0x20,0x20,0x34,0x32,0x2c,0x37,0x30,0x20,0x20,0x35,0x32,0x2c,0x36,0x30,0x22,
+ 0x2f,0x3e,0xa,0x3c,0x2f,0x73,0x76,0x67,0x3e,0xa,
+ // /home/calvin/src/xpdf-4.04/xpdf-qt/back.svg
+ 0x0,0x0,0x1,0x83,
+ 0x3c,
+ 0x3f,0x78,0x6d,0x6c,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x3d,0x22,0x31,0x2e,
+ 0x30,0x22,0x3f,0x3e,0xa,0x3c,0x21,0x44,0x4f,0x43,0x54,0x59,0x50,0x45,0x20,0x73,
+ 0x76,0x67,0x20,0x50,0x55,0x42,0x4c,0x49,0x43,0x20,0x22,0x2d,0x2f,0x2f,0x57,0x33,
+ 0x43,0x2f,0x2f,0x44,0x54,0x44,0x20,0x53,0x56,0x47,0x20,0x31,0x2e,0x31,0x2f,0x2f,
+ 0x45,0x4e,0x22,0x20,0xa,0x20,0x20,0x22,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,
+ 0x77,0x77,0x2e,0x77,0x33,0x2e,0x6f,0x72,0x67,0x2f,0x47,0x72,0x61,0x70,0x68,0x69,
+ 0x63,0x73,0x2f,0x53,0x56,0x47,0x2f,0x31,0x2e,0x31,0x2f,0x44,0x54,0x44,0x2f,0x73,
+ 0x76,0x67,0x31,0x31,0x2e,0x64,0x74,0x64,0x22,0x3e,0xa,0x3c,0x73,0x76,0x67,0x20,
+ 0x77,0x69,0x64,0x74,0x68,0x3d,0x22,0x38,0x30,0x22,0x20,0x68,0x65,0x69,0x67,0x68,
+ 0x74,0x3d,0x22,0x38,0x30,0x22,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x3d,0x22,
+ 0x31,0x2e,0x31,0x22,0xa,0x20,0x78,0x6d,0x6c,0x6e,0x73,0x3d,0x22,0x68,0x74,0x74,
+ 0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x77,0x33,0x2e,0x6f,0x72,0x67,0x2f,0x32,
+ 0x30,0x30,0x30,0x2f,0x73,0x76,0x67,0x22,0x3e,0xa,0x20,0x20,0x3c,0x70,0x6f,0x6c,
+ 0x79,0x6c,0x69,0x6e,0x65,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x3d,0x22,0x23,0x35,
+ 0x35,0x35,0x35,0x35,0x35,0x22,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x2d,0x77,0x69,
+ 0x64,0x74,0x68,0x3d,0x22,0x38,0x22,0x20,0x66,0x69,0x6c,0x6c,0x3d,0x22,0x6e,0x6f,
+ 0x6e,0x65,0x22,0xa,0x20,0x20,0x20,0x70,0x6f,0x69,0x6e,0x74,0x73,0x3d,0x22,0x31,
+ 0x36,0x2c,0x34,0x30,0x20,0x20,0x36,0x38,0x2c,0x34,0x30,0x22,0x2f,0x3e,0xa,0x20,
+ 0x20,0x3c,0x70,0x6f,0x6c,0x79,0x6c,0x69,0x6e,0x65,0x20,0x73,0x74,0x72,0x6f,0x6b,
+ 0x65,0x3d,0x22,0x23,0x35,0x35,0x35,0x35,0x35,0x35,0x22,0x20,0x73,0x74,0x72,0x6f,
+ 0x6b,0x65,0x2d,0x77,0x69,0x64,0x74,0x68,0x3d,0x22,0x38,0x22,0x20,0x66,0x69,0x6c,
+ 0x6c,0x3d,0x22,0x6e,0x6f,0x6e,0x65,0x22,0xa,0x20,0x20,0x20,0x70,0x6f,0x69,0x6e,
+ 0x74,0x73,0x3d,0x22,0x33,0x36,0x2c,0x32,0x30,0x20,0x20,0x31,0x32,0x2c,0x34,0x30,
+ 0x20,0x20,0x33,0x36,0x2c,0x36,0x30,0x22,0x2f,0x3e,0xa,0x3c,0x2f,0x73,0x76,0x67,
+ 0x3e,0xa,
+ // /home/calvin/src/xpdf-4.04/xpdf-qt/selectModeLinear.svg
+ 0x0,0x0,0x3,0xa0,
+ 0x3c,
+ 0x3f,0x78,0x6d,0x6c,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x3d,0x22,0x31,0x2e,
+ 0x30,0x22,0x3f,0x3e,0xa,0x3c,0x21,0x44,0x4f,0x43,0x54,0x59,0x50,0x45,0x20,0x73,
+ 0x76,0x67,0x20,0x50,0x55,0x42,0x4c,0x49,0x43,0x20,0x22,0x2d,0x2f,0x2f,0x57,0x33,
+ 0x43,0x2f,0x2f,0x44,0x54,0x44,0x20,0x53,0x56,0x47,0x20,0x31,0x2e,0x31,0x2f,0x2f,
+ 0x45,0x4e,0x22,0x20,0xa,0x20,0x20,0x22,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,
+ 0x77,0x77,0x2e,0x77,0x33,0x2e,0x6f,0x72,0x67,0x2f,0x47,0x72,0x61,0x70,0x68,0x69,
+ 0x63,0x73,0x2f,0x53,0x56,0x47,0x2f,0x31,0x2e,0x31,0x2f,0x44,0x54,0x44,0x2f,0x73,
+ 0x76,0x67,0x31,0x31,0x2e,0x64,0x74,0x64,0x22,0x3e,0xa,0x3c,0x73,0x76,0x67,0x20,
+ 0x77,0x69,0x64,0x74,0x68,0x3d,0x22,0x38,0x30,0x22,0x20,0x68,0x65,0x69,0x67,0x68,
+ 0x74,0x3d,0x22,0x38,0x30,0x22,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x3d,0x22,
+ 0x31,0x2e,0x31,0x22,0xa,0x20,0x78,0x6d,0x6c,0x6e,0x73,0x3d,0x22,0x68,0x74,0x74,
+ 0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x77,0x33,0x2e,0x6f,0x72,0x67,0x2f,0x32,
+ 0x30,0x30,0x30,0x2f,0x73,0x76,0x67,0x22,0x3e,0xa,0x20,0x20,0x3c,0x70,0x6f,0x6c,
+ 0x79,0x6c,0x69,0x6e,0x65,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x3d,0x22,0x23,0x35,
+ 0x35,0x35,0x35,0x35,0x35,0x22,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x2d,0x77,0x69,
+ 0x64,0x74,0x68,0x3d,0x22,0x34,0x22,0x20,0x66,0x69,0x6c,0x6c,0x3d,0x22,0x6e,0x6f,
+ 0x6e,0x65,0x22,0xa,0x20,0x20,0x20,0x70,0x6f,0x69,0x6e,0x74,0x73,0x3d,0x22,0x32,
+ 0x36,0x2c,0x31,0x38,0x20,0x33,0x34,0x2c,0x31,0x38,0x20,0x33,0x38,0x2c,0x32,0x32,
+ 0x20,0x34,0x32,0x2c,0x31,0x38,0x20,0x35,0x30,0x2c,0x31,0x38,0x22,0x2f,0x3e,0xa,
+ 0x20,0x20,0x3c,0x70,0x6f,0x6c,0x79,0x6c,0x69,0x6e,0x65,0x20,0x73,0x74,0x72,0x6f,
+ 0x6b,0x65,0x3d,0x22,0x23,0x35,0x35,0x35,0x35,0x35,0x35,0x22,0x20,0x73,0x74,0x72,
+ 0x6f,0x6b,0x65,0x2d,0x77,0x69,0x64,0x74,0x68,0x3d,0x22,0x34,0x22,0x20,0x66,0x69,
+ 0x6c,0x6c,0x3d,0x22,0x6e,0x6f,0x6e,0x65,0x22,0xa,0x20,0x20,0x20,0x70,0x6f,0x69,
+ 0x6e,0x74,0x73,0x3d,0x22,0x33,0x38,0x2c,0x32,0x32,0x20,0x33,0x38,0x2c,0x36,0x32,
+ 0x22,0x2f,0x3e,0xa,0x20,0x20,0x3c,0x70,0x6f,0x6c,0x79,0x6c,0x69,0x6e,0x65,0x20,
+ 0x73,0x74,0x72,0x6f,0x6b,0x65,0x3d,0x22,0x23,0x35,0x35,0x35,0x35,0x35,0x35,0x22,
+ 0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x2d,0x77,0x69,0x64,0x74,0x68,0x3d,0x22,0x34,
+ 0x22,0x20,0x66,0x69,0x6c,0x6c,0x3d,0x22,0x6e,0x6f,0x6e,0x65,0x22,0xa,0x20,0x20,
+ 0x20,0x70,0x6f,0x69,0x6e,0x74,0x73,0x3d,0x22,0x32,0x36,0x2c,0x36,0x36,0x20,0x33,
+ 0x34,0x2c,0x36,0x36,0x20,0x33,0x38,0x2c,0x36,0x32,0x20,0x34,0x32,0x2c,0x36,0x36,
+ 0x20,0x35,0x30,0x2c,0x36,0x36,0x22,0x2f,0x3e,0xa,0xa,0x3c,0x21,0x2d,0x2d,0xa,
+ 0x20,0x20,0x3c,0x70,0x6f,0x6c,0x79,0x6c,0x69,0x6e,0x65,0x20,0x73,0x74,0x72,0x6f,
+ 0x6b,0x65,0x3d,0x22,0x23,0x35,0x35,0x35,0x35,0x35,0x35,0x22,0x20,0x73,0x74,0x72,
+ 0x6f,0x6b,0x65,0x2d,0x77,0x69,0x64,0x74,0x68,0x3d,0x22,0x38,0x22,0x20,0x66,0x69,
+ 0x6c,0x6c,0x3d,0x22,0x6e,0x6f,0x6e,0x65,0x22,0xa,0x20,0x20,0x20,0x70,0x6f,0x69,
+ 0x6e,0x74,0x73,0x3d,0x22,0x34,0x30,0x2c,0x32,0x30,0x20,0x34,0x30,0x2c,0x36,0x30,
+ 0x22,0x2f,0x3e,0xa,0x20,0x20,0x3c,0x70,0x6f,0x6c,0x79,0x6c,0x69,0x6e,0x65,0x20,
+ 0x73,0x74,0x72,0x6f,0x6b,0x65,0x3d,0x22,0x23,0x35,0x35,0x35,0x35,0x35,0x35,0x22,
+ 0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x2d,0x77,0x69,0x64,0x74,0x68,0x3d,0x22,0x38,
+ 0x22,0x20,0x66,0x69,0x6c,0x6c,0x3d,0x22,0x6e,0x6f,0x6e,0x65,0x22,0xa,0x20,0x20,
+ 0x20,0x70,0x6f,0x69,0x6e,0x74,0x73,0x3d,0x22,0x32,0x34,0x2c,0x31,0x36,0x20,0x33,
+ 0x36,0x2c,0x31,0x36,0x22,0x2f,0x3e,0xa,0x20,0x20,0x3c,0x70,0x6f,0x6c,0x79,0x6c,
+ 0x69,0x6e,0x65,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x3d,0x22,0x23,0x35,0x35,0x35,
+ 0x35,0x35,0x35,0x22,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x2d,0x77,0x69,0x64,0x74,
+ 0x68,0x3d,0x22,0x38,0x22,0x20,0x66,0x69,0x6c,0x6c,0x3d,0x22,0x6e,0x6f,0x6e,0x65,
+ 0x22,0xa,0x20,0x20,0x20,0x70,0x6f,0x69,0x6e,0x74,0x73,0x3d,0x22,0x34,0x34,0x2c,
+ 0x31,0x36,0x20,0x35,0x36,0x2c,0x31,0x36,0x22,0x2f,0x3e,0xa,0x20,0x20,0x3c,0x70,
+ 0x6f,0x6c,0x79,0x6c,0x69,0x6e,0x65,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x3d,0x22,
+ 0x23,0x35,0x35,0x35,0x35,0x35,0x35,0x22,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x2d,
+ 0x77,0x69,0x64,0x74,0x68,0x3d,0x22,0x38,0x22,0x20,0x66,0x69,0x6c,0x6c,0x3d,0x22,
+ 0x6e,0x6f,0x6e,0x65,0x22,0xa,0x20,0x20,0x20,0x70,0x6f,0x69,0x6e,0x74,0x73,0x3d,
+ 0x22,0x32,0x34,0x2c,0x36,0x34,0x20,0x33,0x36,0x2c,0x36,0x34,0x22,0x2f,0x3e,0xa,
+ 0x20,0x20,0x3c,0x70,0x6f,0x6c,0x79,0x6c,0x69,0x6e,0x65,0x20,0x73,0x74,0x72,0x6f,
+ 0x6b,0x65,0x3d,0x22,0x23,0x35,0x35,0x35,0x35,0x35,0x35,0x22,0x20,0x73,0x74,0x72,
+ 0x6f,0x6b,0x65,0x2d,0x77,0x69,0x64,0x74,0x68,0x3d,0x22,0x38,0x22,0x20,0x66,0x69,
+ 0x6c,0x6c,0x3d,0x22,0x6e,0x6f,0x6e,0x65,0x22,0xa,0x20,0x20,0x20,0x70,0x6f,0x69,
+ 0x6e,0x74,0x73,0x3d,0x22,0x34,0x34,0x2c,0x36,0x34,0x20,0x35,0x36,0x2c,0x36,0x34,
+ 0x22,0x2f,0x3e,0xa,0x2d,0x2d,0x3e,0xa,0x3c,0x2f,0x73,0x76,0x67,0x3e,0xa,
+ // /home/calvin/src/xpdf-4.04/xpdf-qt/findPrevious.svg
+ 0x0,0x0,0x1,0x2e,
+ 0x3c,
+ 0x3f,0x78,0x6d,0x6c,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x3d,0x22,0x31,0x2e,
+ 0x30,0x22,0x3f,0x3e,0xa,0x3c,0x21,0x44,0x4f,0x43,0x54,0x59,0x50,0x45,0x20,0x73,
+ 0x76,0x67,0x20,0x50,0x55,0x42,0x4c,0x49,0x43,0x20,0x22,0x2d,0x2f,0x2f,0x57,0x33,
+ 0x43,0x2f,0x2f,0x44,0x54,0x44,0x20,0x53,0x56,0x47,0x20,0x31,0x2e,0x31,0x2f,0x2f,
+ 0x45,0x4e,0x22,0x20,0xa,0x20,0x20,0x22,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,
+ 0x77,0x77,0x2e,0x77,0x33,0x2e,0x6f,0x72,0x67,0x2f,0x47,0x72,0x61,0x70,0x68,0x69,
+ 0x63,0x73,0x2f,0x53,0x56,0x47,0x2f,0x31,0x2e,0x31,0x2f,0x44,0x54,0x44,0x2f,0x73,
+ 0x76,0x67,0x31,0x31,0x2e,0x64,0x74,0x64,0x22,0x3e,0xa,0x3c,0x73,0x76,0x67,0x20,
+ 0x77,0x69,0x64,0x74,0x68,0x3d,0x22,0x36,0x30,0x22,0x20,0x68,0x65,0x69,0x67,0x68,
+ 0x74,0x3d,0x22,0x38,0x30,0x22,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x3d,0x22,
+ 0x31,0x2e,0x31,0x22,0xa,0x20,0x78,0x6d,0x6c,0x6e,0x73,0x3d,0x22,0x68,0x74,0x74,
+ 0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x77,0x33,0x2e,0x6f,0x72,0x67,0x2f,0x32,
+ 0x30,0x30,0x30,0x2f,0x73,0x76,0x67,0x22,0x3e,0xa,0x20,0x20,0x3c,0x70,0x6f,0x6c,
+ 0x79,0x6c,0x69,0x6e,0x65,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x3d,0x22,0x23,0x35,
+ 0x35,0x35,0x35,0x35,0x35,0x22,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x2d,0x77,0x69,
+ 0x64,0x74,0x68,0x3d,0x22,0x38,0x22,0x20,0x66,0x69,0x6c,0x6c,0x3d,0x22,0x6e,0x6f,
+ 0x6e,0x65,0x22,0xa,0x20,0x20,0x20,0x70,0x6f,0x69,0x6e,0x74,0x73,0x3d,0x22,0x31,
+ 0x32,0x2c,0x34,0x38,0x20,0x20,0x33,0x30,0x2c,0x33,0x32,0x20,0x20,0x34,0x38,0x2c,
+ 0x34,0x38,0x22,0x2f,0x3e,0xa,0x3c,0x2f,0x73,0x76,0x67,0x3e,0xa,
+ // /home/calvin/src/xpdf-4.04/xpdf-qt/zoomIn.svg
+ 0x0,0x0,0x1,0x7c,
+ 0x3c,
+ 0x3f,0x78,0x6d,0x6c,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x3d,0x22,0x31,0x2e,
+ 0x30,0x22,0x3f,0x3e,0xa,0x3c,0x21,0x44,0x4f,0x43,0x54,0x59,0x50,0x45,0x20,0x73,
+ 0x76,0x67,0x20,0x50,0x55,0x42,0x4c,0x49,0x43,0x20,0x22,0x2d,0x2f,0x2f,0x57,0x33,
+ 0x43,0x2f,0x2f,0x44,0x54,0x44,0x20,0x53,0x56,0x47,0x20,0x31,0x2e,0x31,0x2f,0x2f,
+ 0x45,0x4e,0x22,0x20,0xa,0x20,0x20,0x22,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,
+ 0x77,0x77,0x2e,0x77,0x33,0x2e,0x6f,0x72,0x67,0x2f,0x47,0x72,0x61,0x70,0x68,0x69,
+ 0x63,0x73,0x2f,0x53,0x56,0x47,0x2f,0x31,0x2e,0x31,0x2f,0x44,0x54,0x44,0x2f,0x73,
+ 0x76,0x67,0x31,0x31,0x2e,0x64,0x74,0x64,0x22,0x3e,0xa,0x3c,0x73,0x76,0x67,0x20,
+ 0x77,0x69,0x64,0x74,0x68,0x3d,0x22,0x38,0x30,0x22,0x20,0x68,0x65,0x69,0x67,0x68,
+ 0x74,0x3d,0x22,0x38,0x30,0x22,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x3d,0x22,
+ 0x31,0x2e,0x31,0x22,0xa,0x20,0x78,0x6d,0x6c,0x6e,0x73,0x3d,0x22,0x68,0x74,0x74,
+ 0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x77,0x33,0x2e,0x6f,0x72,0x67,0x2f,0x32,
+ 0x30,0x30,0x30,0x2f,0x73,0x76,0x67,0x22,0x3e,0xa,0x20,0x20,0x3c,0x70,0x6f,0x6c,
+ 0x79,0x6c,0x69,0x6e,0x65,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x3d,0x22,0x23,0x35,
+ 0x35,0x35,0x35,0x35,0x35,0x22,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x2d,0x77,0x69,
+ 0x64,0x74,0x68,0x3d,0x22,0x38,0x22,0x20,0x66,0x69,0x6c,0x6c,0x3d,0x22,0x6e,0x6f,
+ 0x6e,0x65,0x22,0xa,0x20,0x20,0x20,0x70,0x6f,0x69,0x6e,0x74,0x73,0x3d,0x22,0x31,
+ 0x36,0x2c,0x34,0x30,0x20,0x20,0x36,0x34,0x2c,0x34,0x30,0x22,0x2f,0x3e,0xa,0x20,
+ 0x20,0x3c,0x70,0x6f,0x6c,0x79,0x6c,0x69,0x6e,0x65,0x20,0x73,0x74,0x72,0x6f,0x6b,
+ 0x65,0x3d,0x22,0x23,0x35,0x35,0x35,0x35,0x35,0x35,0x22,0x20,0x73,0x74,0x72,0x6f,
+ 0x6b,0x65,0x2d,0x77,0x69,0x64,0x74,0x68,0x3d,0x22,0x38,0x22,0x20,0x66,0x69,0x6c,
+ 0x6c,0x3d,0x22,0x6e,0x6f,0x6e,0x65,0x22,0xa,0x20,0x20,0x20,0x70,0x6f,0x69,0x6e,
+ 0x74,0x73,0x3d,0x22,0x34,0x30,0x2c,0x31,0x36,0x20,0x20,0x34,0x30,0x2c,0x36,0x34,
+ 0x22,0x2f,0x3e,0xa,0x3c,0x2f,0x73,0x76,0x67,0x3e,0xa,
+ // /home/calvin/src/xpdf-4.04/xpdf-qt/forward.svg
+ 0x0,0x0,0x1,0x83,
+ 0x3c,
+ 0x3f,0x78,0x6d,0x6c,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x3d,0x22,0x31,0x2e,
+ 0x30,0x22,0x3f,0x3e,0xa,0x3c,0x21,0x44,0x4f,0x43,0x54,0x59,0x50,0x45,0x20,0x73,
+ 0x76,0x67,0x20,0x50,0x55,0x42,0x4c,0x49,0x43,0x20,0x22,0x2d,0x2f,0x2f,0x57,0x33,
+ 0x43,0x2f,0x2f,0x44,0x54,0x44,0x20,0x53,0x56,0x47,0x20,0x31,0x2e,0x31,0x2f,0x2f,
+ 0x45,0x4e,0x22,0x20,0xa,0x20,0x20,0x22,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,
+ 0x77,0x77,0x2e,0x77,0x33,0x2e,0x6f,0x72,0x67,0x2f,0x47,0x72,0x61,0x70,0x68,0x69,
+ 0x63,0x73,0x2f,0x53,0x56,0x47,0x2f,0x31,0x2e,0x31,0x2f,0x44,0x54,0x44,0x2f,0x73,
+ 0x76,0x67,0x31,0x31,0x2e,0x64,0x74,0x64,0x22,0x3e,0xa,0x3c,0x73,0x76,0x67,0x20,
+ 0x77,0x69,0x64,0x74,0x68,0x3d,0x22,0x38,0x30,0x22,0x20,0x68,0x65,0x69,0x67,0x68,
+ 0x74,0x3d,0x22,0x38,0x30,0x22,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x3d,0x22,
+ 0x31,0x2e,0x31,0x22,0xa,0x20,0x78,0x6d,0x6c,0x6e,0x73,0x3d,0x22,0x68,0x74,0x74,
+ 0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x77,0x33,0x2e,0x6f,0x72,0x67,0x2f,0x32,
+ 0x30,0x30,0x30,0x2f,0x73,0x76,0x67,0x22,0x3e,0xa,0x20,0x20,0x3c,0x70,0x6f,0x6c,
+ 0x79,0x6c,0x69,0x6e,0x65,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x3d,0x22,0x23,0x35,
+ 0x35,0x35,0x35,0x35,0x35,0x22,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x2d,0x77,0x69,
+ 0x64,0x74,0x68,0x3d,0x22,0x38,0x22,0x20,0x66,0x69,0x6c,0x6c,0x3d,0x22,0x6e,0x6f,
+ 0x6e,0x65,0x22,0xa,0x20,0x20,0x20,0x70,0x6f,0x69,0x6e,0x74,0x73,0x3d,0x22,0x31,
+ 0x32,0x2c,0x34,0x30,0x20,0x20,0x36,0x34,0x2c,0x34,0x30,0x22,0x2f,0x3e,0xa,0x20,
+ 0x20,0x3c,0x70,0x6f,0x6c,0x79,0x6c,0x69,0x6e,0x65,0x20,0x73,0x74,0x72,0x6f,0x6b,
+ 0x65,0x3d,0x22,0x23,0x35,0x35,0x35,0x35,0x35,0x35,0x22,0x20,0x73,0x74,0x72,0x6f,
+ 0x6b,0x65,0x2d,0x77,0x69,0x64,0x74,0x68,0x3d,0x22,0x38,0x22,0x20,0x66,0x69,0x6c,
+ 0x6c,0x3d,0x22,0x6e,0x6f,0x6e,0x65,0x22,0xa,0x20,0x20,0x20,0x70,0x6f,0x69,0x6e,
+ 0x74,0x73,0x3d,0x22,0x34,0x34,0x2c,0x32,0x30,0x20,0x20,0x36,0x38,0x2c,0x34,0x30,
+ 0x20,0x20,0x34,0x34,0x2c,0x36,0x30,0x22,0x2f,0x3e,0xa,0x3c,0x2f,0x73,0x76,0x67,
+ 0x3e,0xa,
+ // /home/calvin/src/xpdf-4.04/xpdf-qt/fitWidth.svg
+ 0x0,0x0,0x2,0x3e,
+ 0x3c,
+ 0x3f,0x78,0x6d,0x6c,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x3d,0x22,0x31,0x2e,
+ 0x30,0x22,0x3f,0x3e,0xa,0x3c,0x21,0x44,0x4f,0x43,0x54,0x59,0x50,0x45,0x20,0x73,
+ 0x76,0x67,0x20,0x50,0x55,0x42,0x4c,0x49,0x43,0x20,0x22,0x2d,0x2f,0x2f,0x57,0x33,
+ 0x43,0x2f,0x2f,0x44,0x54,0x44,0x20,0x53,0x56,0x47,0x20,0x31,0x2e,0x31,0x2f,0x2f,
+ 0x45,0x4e,0x22,0x20,0xa,0x20,0x20,0x22,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,
+ 0x77,0x77,0x2e,0x77,0x33,0x2e,0x6f,0x72,0x67,0x2f,0x47,0x72,0x61,0x70,0x68,0x69,
+ 0x63,0x73,0x2f,0x53,0x56,0x47,0x2f,0x31,0x2e,0x31,0x2f,0x44,0x54,0x44,0x2f,0x73,
+ 0x76,0x67,0x31,0x31,0x2e,0x64,0x74,0x64,0x22,0x3e,0xa,0x3c,0x73,0x76,0x67,0x20,
+ 0x77,0x69,0x64,0x74,0x68,0x3d,0x22,0x38,0x30,0x22,0x20,0x68,0x65,0x69,0x67,0x68,
+ 0x74,0x3d,0x22,0x38,0x30,0x22,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x3d,0x22,
+ 0x31,0x2e,0x31,0x22,0xa,0x20,0x78,0x6d,0x6c,0x6e,0x73,0x3d,0x22,0x68,0x74,0x74,
+ 0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x77,0x33,0x2e,0x6f,0x72,0x67,0x2f,0x32,
+ 0x30,0x30,0x30,0x2f,0x73,0x76,0x67,0x22,0x3e,0xa,0x20,0x20,0x3c,0x72,0x65,0x63,
+ 0x74,0x20,0x66,0x69,0x6c,0x6c,0x3d,0x22,0x6e,0x6f,0x6e,0x65,0x22,0x20,0x73,0x74,
+ 0x72,0x6f,0x6b,0x65,0x3d,0x22,0x23,0x35,0x35,0x35,0x35,0x35,0x35,0x22,0x20,0x73,
+ 0x74,0x72,0x6f,0x6b,0x65,0x2d,0x77,0x69,0x64,0x74,0x68,0x3d,0x22,0x34,0x22,0xa,
+ 0x20,0x20,0x20,0x78,0x3d,0x22,0x31,0x34,0x22,0x20,0x79,0x3d,0x22,0x36,0x22,0x20,
+ 0x77,0x69,0x64,0x74,0x68,0x3d,0x22,0x35,0x36,0x22,0x20,0x68,0x65,0x69,0x67,0x68,
+ 0x74,0x3d,0x22,0x37,0x32,0x22,0x2f,0x3e,0xa,0x20,0x20,0x3c,0x70,0x6f,0x6c,0x79,
+ 0x6c,0x69,0x6e,0x65,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x3d,0x22,0x23,0x35,0x35,
+ 0x35,0x35,0x35,0x35,0x22,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x2d,0x77,0x69,0x64,
+ 0x74,0x68,0x3d,0x22,0x34,0x22,0x20,0x66,0x69,0x6c,0x6c,0x3d,0x22,0x6e,0x6f,0x6e,
+ 0x65,0x22,0xa,0x20,0x20,0x20,0x70,0x6f,0x69,0x6e,0x74,0x73,0x3d,0x22,0x32,0x32,
+ 0x2c,0x34,0x32,0x20,0x20,0x36,0x32,0x2c,0x34,0x32,0x22,0x2f,0x3e,0xa,0x20,0x20,
+ 0x3c,0x70,0x6f,0x6c,0x79,0x6c,0x69,0x6e,0x65,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,
+ 0x3d,0x22,0x23,0x35,0x35,0x35,0x35,0x35,0x35,0x22,0x20,0x73,0x74,0x72,0x6f,0x6b,
+ 0x65,0x2d,0x77,0x69,0x64,0x74,0x68,0x3d,0x22,0x34,0x22,0x20,0x66,0x69,0x6c,0x6c,
+ 0x3d,0x22,0x6e,0x6f,0x6e,0x65,0x22,0xa,0x20,0x20,0x20,0x70,0x6f,0x69,0x6e,0x74,
+ 0x73,0x3d,0x22,0x33,0x32,0x2c,0x33,0x32,0x20,0x20,0x32,0x32,0x2c,0x34,0x32,0x20,
+ 0x20,0x33,0x32,0x2c,0x35,0x32,0x22,0x2f,0x3e,0xa,0x20,0x20,0x3c,0x70,0x6f,0x6c,
+ 0x79,0x6c,0x69,0x6e,0x65,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x3d,0x22,0x23,0x35,
+ 0x35,0x35,0x35,0x35,0x35,0x22,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x2d,0x77,0x69,
+ 0x64,0x74,0x68,0x3d,0x22,0x34,0x22,0x20,0x66,0x69,0x6c,0x6c,0x3d,0x22,0x6e,0x6f,
+ 0x6e,0x65,0x22,0xa,0x20,0x20,0x20,0x70,0x6f,0x69,0x6e,0x74,0x73,0x3d,0x22,0x35,
+ 0x32,0x2c,0x33,0x32,0x20,0x20,0x36,0x32,0x2c,0x34,0x32,0x20,0x20,0x35,0x32,0x2c,
+ 0x35,0x32,0x22,0x2f,0x3e,0xa,0x3c,0x2f,0x73,0x76,0x67,0x3e,0xa,
+ // /home/calvin/src/xpdf-4.04/xpdf-qt/indicator-icon-err0.svg
+ 0x0,0x0,0x1,0xa9,
+ 0x3c,
+ 0x3f,0x78,0x6d,0x6c,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x3d,0x22,0x31,0x2e,
+ 0x30,0x22,0x3f,0x3e,0xa,0x3c,0x21,0x44,0x4f,0x43,0x54,0x59,0x50,0x45,0x20,0x73,
+ 0x76,0x67,0x20,0x50,0x55,0x42,0x4c,0x49,0x43,0x20,0x22,0x2d,0x2f,0x2f,0x57,0x33,
+ 0x43,0x2f,0x2f,0x44,0x54,0x44,0x20,0x53,0x56,0x47,0x20,0x31,0x2e,0x31,0x2f,0x2f,
+ 0x45,0x4e,0x22,0xa,0x20,0x22,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,
+ 0x2e,0x77,0x33,0x2e,0x6f,0x72,0x67,0x2f,0x47,0x72,0x61,0x70,0x68,0x69,0x63,0x73,
+ 0x2f,0x53,0x56,0x47,0x2f,0x31,0x2e,0x31,0x2f,0x44,0x54,0x44,0x2f,0x73,0x76,0x67,
+ 0x31,0x31,0x2e,0x64,0x74,0x64,0x22,0x3e,0xa,0x3c,0x73,0x76,0x67,0x20,0x77,0x69,
+ 0x64,0x74,0x68,0x3d,0x22,0x38,0x30,0x22,0x20,0x68,0x65,0x69,0x67,0x68,0x74,0x3d,
+ 0x22,0x38,0x30,0x22,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x3d,0x22,0x31,0x2e,
+ 0x31,0x22,0xa,0x20,0x78,0x6d,0x6c,0x6e,0x73,0x3d,0x22,0x68,0x74,0x74,0x70,0x3a,
+ 0x2f,0x2f,0x77,0x77,0x77,0x2e,0x77,0x33,0x2e,0x6f,0x72,0x67,0x2f,0x32,0x30,0x30,
+ 0x30,0x2f,0x73,0x76,0x67,0x22,0x3e,0xa,0x20,0x20,0x3c,0x63,0x69,0x72,0x63,0x6c,
+ 0x65,0x20,0x66,0x69,0x6c,0x6c,0x3d,0x22,0x23,0x66,0x66,0x34,0x34,0x34,0x34,0x22,
+ 0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x3d,0x22,0x6e,0x6f,0x6e,0x65,0x22,0xa,0x20,
+ 0x20,0x20,0x63,0x78,0x3d,0x22,0x34,0x30,0x22,0x20,0x63,0x79,0x3d,0x22,0x34,0x30,
+ 0x22,0x20,0x72,0x3d,0x22,0x33,0x33,0x22,0x2f,0x3e,0xa,0x20,0x20,0x3c,0x63,0x69,
+ 0x72,0x63,0x6c,0x65,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x3d,0x22,0x23,0x35,0x35,
+ 0x35,0x35,0x35,0x35,0x22,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x2d,0x77,0x69,0x64,
+ 0x74,0x68,0x3d,0x22,0x36,0x22,0x20,0x66,0x69,0x6c,0x6c,0x3d,0x22,0x6e,0x6f,0x6e,
+ 0x65,0x22,0xa,0x20,0x20,0x20,0x63,0x78,0x3d,0x22,0x34,0x30,0x22,0x20,0x63,0x79,
+ 0x3d,0x22,0x34,0x30,0x22,0x20,0x72,0x3d,0x22,0x33,0x30,0x22,0x2f,0x3e,0xa,0x20,
+ 0x20,0x3c,0x63,0x69,0x72,0x63,0x6c,0x65,0x20,0x66,0x69,0x6c,0x6c,0x3d,0x22,0x23,
+ 0x35,0x35,0x35,0x35,0x35,0x35,0x22,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x3d,0x22,
+ 0x6e,0x6f,0x6e,0x65,0x22,0xa,0x20,0x20,0x20,0x63,0x78,0x3d,0x22,0x34,0x30,0x22,
+ 0x20,0x63,0x79,0x3d,0x22,0x32,0x34,0x22,0x20,0x72,0x3d,0x22,0x38,0x22,0x2f,0x3e,
+ 0xa,0x3c,0x2f,0x73,0x76,0x67,0x3e,0xa,
+ // /home/calvin/src/xpdf-4.04/xpdf-qt/indicator-icon-err1.svg
+ 0x0,0x0,0x1,0xa9,
+ 0x3c,
+ 0x3f,0x78,0x6d,0x6c,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x3d,0x22,0x31,0x2e,
+ 0x30,0x22,0x3f,0x3e,0xa,0x3c,0x21,0x44,0x4f,0x43,0x54,0x59,0x50,0x45,0x20,0x73,
+ 0x76,0x67,0x20,0x50,0x55,0x42,0x4c,0x49,0x43,0x20,0x22,0x2d,0x2f,0x2f,0x57,0x33,
+ 0x43,0x2f,0x2f,0x44,0x54,0x44,0x20,0x53,0x56,0x47,0x20,0x31,0x2e,0x31,0x2f,0x2f,
+ 0x45,0x4e,0x22,0xa,0x20,0x22,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,
+ 0x2e,0x77,0x33,0x2e,0x6f,0x72,0x67,0x2f,0x47,0x72,0x61,0x70,0x68,0x69,0x63,0x73,
+ 0x2f,0x53,0x56,0x47,0x2f,0x31,0x2e,0x31,0x2f,0x44,0x54,0x44,0x2f,0x73,0x76,0x67,
+ 0x31,0x31,0x2e,0x64,0x74,0x64,0x22,0x3e,0xa,0x3c,0x73,0x76,0x67,0x20,0x77,0x69,
+ 0x64,0x74,0x68,0x3d,0x22,0x38,0x30,0x22,0x20,0x68,0x65,0x69,0x67,0x68,0x74,0x3d,
+ 0x22,0x38,0x30,0x22,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x3d,0x22,0x31,0x2e,
+ 0x31,0x22,0xa,0x20,0x78,0x6d,0x6c,0x6e,0x73,0x3d,0x22,0x68,0x74,0x74,0x70,0x3a,
+ 0x2f,0x2f,0x77,0x77,0x77,0x2e,0x77,0x33,0x2e,0x6f,0x72,0x67,0x2f,0x32,0x30,0x30,
+ 0x30,0x2f,0x73,0x76,0x67,0x22,0x3e,0xa,0x20,0x20,0x3c,0x63,0x69,0x72,0x63,0x6c,
+ 0x65,0x20,0x66,0x69,0x6c,0x6c,0x3d,0x22,0x23,0x66,0x66,0x34,0x34,0x34,0x34,0x22,
+ 0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x3d,0x22,0x6e,0x6f,0x6e,0x65,0x22,0xa,0x20,
+ 0x20,0x20,0x63,0x78,0x3d,0x22,0x34,0x30,0x22,0x20,0x63,0x79,0x3d,0x22,0x34,0x30,
+ 0x22,0x20,0x72,0x3d,0x22,0x33,0x33,0x22,0x2f,0x3e,0xa,0x20,0x20,0x3c,0x63,0x69,
+ 0x72,0x63,0x6c,0x65,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x3d,0x22,0x23,0x35,0x35,
+ 0x35,0x35,0x35,0x35,0x22,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x2d,0x77,0x69,0x64,
+ 0x74,0x68,0x3d,0x22,0x36,0x22,0x20,0x66,0x69,0x6c,0x6c,0x3d,0x22,0x6e,0x6f,0x6e,
+ 0x65,0x22,0xa,0x20,0x20,0x20,0x63,0x78,0x3d,0x22,0x34,0x30,0x22,0x20,0x63,0x79,
+ 0x3d,0x22,0x34,0x30,0x22,0x20,0x72,0x3d,0x22,0x33,0x30,0x22,0x2f,0x3e,0xa,0x20,
+ 0x20,0x3c,0x63,0x69,0x72,0x63,0x6c,0x65,0x20,0x66,0x69,0x6c,0x6c,0x3d,0x22,0x23,
+ 0x35,0x35,0x35,0x35,0x35,0x35,0x22,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x3d,0x22,
+ 0x6e,0x6f,0x6e,0x65,0x22,0xa,0x20,0x20,0x20,0x63,0x78,0x3d,0x22,0x35,0x31,0x22,
+ 0x20,0x63,0x79,0x3d,0x22,0x32,0x39,0x22,0x20,0x72,0x3d,0x22,0x38,0x22,0x2f,0x3e,
+ 0xa,0x3c,0x2f,0x73,0x76,0x67,0x3e,0xa,
+ // /home/calvin/src/xpdf-4.04/xpdf-qt/indicator-icon-err2.svg
+ 0x0,0x0,0x1,0xa9,
+ 0x3c,
+ 0x3f,0x78,0x6d,0x6c,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x3d,0x22,0x31,0x2e,
+ 0x30,0x22,0x3f,0x3e,0xa,0x3c,0x21,0x44,0x4f,0x43,0x54,0x59,0x50,0x45,0x20,0x73,
+ 0x76,0x67,0x20,0x50,0x55,0x42,0x4c,0x49,0x43,0x20,0x22,0x2d,0x2f,0x2f,0x57,0x33,
+ 0x43,0x2f,0x2f,0x44,0x54,0x44,0x20,0x53,0x56,0x47,0x20,0x31,0x2e,0x31,0x2f,0x2f,
+ 0x45,0x4e,0x22,0xa,0x20,0x22,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,
+ 0x2e,0x77,0x33,0x2e,0x6f,0x72,0x67,0x2f,0x47,0x72,0x61,0x70,0x68,0x69,0x63,0x73,
+ 0x2f,0x53,0x56,0x47,0x2f,0x31,0x2e,0x31,0x2f,0x44,0x54,0x44,0x2f,0x73,0x76,0x67,
+ 0x31,0x31,0x2e,0x64,0x74,0x64,0x22,0x3e,0xa,0x3c,0x73,0x76,0x67,0x20,0x77,0x69,
+ 0x64,0x74,0x68,0x3d,0x22,0x38,0x30,0x22,0x20,0x68,0x65,0x69,0x67,0x68,0x74,0x3d,
+ 0x22,0x38,0x30,0x22,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x3d,0x22,0x31,0x2e,
+ 0x31,0x22,0xa,0x20,0x78,0x6d,0x6c,0x6e,0x73,0x3d,0x22,0x68,0x74,0x74,0x70,0x3a,
+ 0x2f,0x2f,0x77,0x77,0x77,0x2e,0x77,0x33,0x2e,0x6f,0x72,0x67,0x2f,0x32,0x30,0x30,
+ 0x30,0x2f,0x73,0x76,0x67,0x22,0x3e,0xa,0x20,0x20,0x3c,0x63,0x69,0x72,0x63,0x6c,
+ 0x65,0x20,0x66,0x69,0x6c,0x6c,0x3d,0x22,0x23,0x66,0x66,0x34,0x34,0x34,0x34,0x22,
+ 0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x3d,0x22,0x6e,0x6f,0x6e,0x65,0x22,0xa,0x20,
+ 0x20,0x20,0x63,0x78,0x3d,0x22,0x34,0x30,0x22,0x20,0x63,0x79,0x3d,0x22,0x34,0x30,
+ 0x22,0x20,0x72,0x3d,0x22,0x33,0x33,0x22,0x2f,0x3e,0xa,0x20,0x20,0x3c,0x63,0x69,
+ 0x72,0x63,0x6c,0x65,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x3d,0x22,0x23,0x35,0x35,
+ 0x35,0x35,0x35,0x35,0x22,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x2d,0x77,0x69,0x64,
+ 0x74,0x68,0x3d,0x22,0x36,0x22,0x20,0x66,0x69,0x6c,0x6c,0x3d,0x22,0x6e,0x6f,0x6e,
+ 0x65,0x22,0xa,0x20,0x20,0x20,0x63,0x78,0x3d,0x22,0x34,0x30,0x22,0x20,0x63,0x79,
+ 0x3d,0x22,0x34,0x30,0x22,0x20,0x72,0x3d,0x22,0x33,0x30,0x22,0x2f,0x3e,0xa,0x20,
+ 0x20,0x3c,0x63,0x69,0x72,0x63,0x6c,0x65,0x20,0x66,0x69,0x6c,0x6c,0x3d,0x22,0x23,
+ 0x35,0x35,0x35,0x35,0x35,0x35,0x22,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x3d,0x22,
+ 0x6e,0x6f,0x6e,0x65,0x22,0xa,0x20,0x20,0x20,0x63,0x78,0x3d,0x22,0x35,0x36,0x22,
+ 0x20,0x63,0x79,0x3d,0x22,0x34,0x30,0x22,0x20,0x72,0x3d,0x22,0x38,0x22,0x2f,0x3e,
+ 0xa,0x3c,0x2f,0x73,0x76,0x67,0x3e,0xa,
+ // /home/calvin/src/xpdf-4.04/xpdf-qt/indicator-icon-err3.svg
+ 0x0,0x0,0x1,0xa9,
+ 0x3c,
+ 0x3f,0x78,0x6d,0x6c,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x3d,0x22,0x31,0x2e,
+ 0x30,0x22,0x3f,0x3e,0xa,0x3c,0x21,0x44,0x4f,0x43,0x54,0x59,0x50,0x45,0x20,0x73,
+ 0x76,0x67,0x20,0x50,0x55,0x42,0x4c,0x49,0x43,0x20,0x22,0x2d,0x2f,0x2f,0x57,0x33,
+ 0x43,0x2f,0x2f,0x44,0x54,0x44,0x20,0x53,0x56,0x47,0x20,0x31,0x2e,0x31,0x2f,0x2f,
+ 0x45,0x4e,0x22,0xa,0x20,0x22,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,
+ 0x2e,0x77,0x33,0x2e,0x6f,0x72,0x67,0x2f,0x47,0x72,0x61,0x70,0x68,0x69,0x63,0x73,
+ 0x2f,0x53,0x56,0x47,0x2f,0x31,0x2e,0x31,0x2f,0x44,0x54,0x44,0x2f,0x73,0x76,0x67,
+ 0x31,0x31,0x2e,0x64,0x74,0x64,0x22,0x3e,0xa,0x3c,0x73,0x76,0x67,0x20,0x77,0x69,
+ 0x64,0x74,0x68,0x3d,0x22,0x38,0x30,0x22,0x20,0x68,0x65,0x69,0x67,0x68,0x74,0x3d,
+ 0x22,0x38,0x30,0x22,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x3d,0x22,0x31,0x2e,
+ 0x31,0x22,0xa,0x20,0x78,0x6d,0x6c,0x6e,0x73,0x3d,0x22,0x68,0x74,0x74,0x70,0x3a,
+ 0x2f,0x2f,0x77,0x77,0x77,0x2e,0x77,0x33,0x2e,0x6f,0x72,0x67,0x2f,0x32,0x30,0x30,
+ 0x30,0x2f,0x73,0x76,0x67,0x22,0x3e,0xa,0x20,0x20,0x3c,0x63,0x69,0x72,0x63,0x6c,
+ 0x65,0x20,0x66,0x69,0x6c,0x6c,0x3d,0x22,0x23,0x66,0x66,0x34,0x34,0x34,0x34,0x22,
+ 0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x3d,0x22,0x6e,0x6f,0x6e,0x65,0x22,0xa,0x20,
+ 0x20,0x20,0x63,0x78,0x3d,0x22,0x34,0x30,0x22,0x20,0x63,0x79,0x3d,0x22,0x34,0x30,
+ 0x22,0x20,0x72,0x3d,0x22,0x33,0x33,0x22,0x2f,0x3e,0xa,0x20,0x20,0x3c,0x63,0x69,
+ 0x72,0x63,0x6c,0x65,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x3d,0x22,0x23,0x35,0x35,
+ 0x35,0x35,0x35,0x35,0x22,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x2d,0x77,0x69,0x64,
+ 0x74,0x68,0x3d,0x22,0x36,0x22,0x20,0x66,0x69,0x6c,0x6c,0x3d,0x22,0x6e,0x6f,0x6e,
+ 0x65,0x22,0xa,0x20,0x20,0x20,0x63,0x78,0x3d,0x22,0x34,0x30,0x22,0x20,0x63,0x79,
+ 0x3d,0x22,0x34,0x30,0x22,0x20,0x72,0x3d,0x22,0x33,0x30,0x22,0x2f,0x3e,0xa,0x20,
+ 0x20,0x3c,0x63,0x69,0x72,0x63,0x6c,0x65,0x20,0x66,0x69,0x6c,0x6c,0x3d,0x22,0x23,
+ 0x35,0x35,0x35,0x35,0x35,0x35,0x22,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x3d,0x22,
+ 0x6e,0x6f,0x6e,0x65,0x22,0xa,0x20,0x20,0x20,0x63,0x78,0x3d,0x22,0x35,0x31,0x22,
+ 0x20,0x63,0x79,0x3d,0x22,0x35,0x31,0x22,0x20,0x72,0x3d,0x22,0x38,0x22,0x2f,0x3e,
+ 0xa,0x3c,0x2f,0x73,0x76,0x67,0x3e,0xa,
+ // /home/calvin/src/xpdf-4.04/xpdf-qt/indicator-icon-err4.svg
+ 0x0,0x0,0x1,0xa9,
+ 0x3c,
+ 0x3f,0x78,0x6d,0x6c,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x3d,0x22,0x31,0x2e,
+ 0x30,0x22,0x3f,0x3e,0xa,0x3c,0x21,0x44,0x4f,0x43,0x54,0x59,0x50,0x45,0x20,0x73,
+ 0x76,0x67,0x20,0x50,0x55,0x42,0x4c,0x49,0x43,0x20,0x22,0x2d,0x2f,0x2f,0x57,0x33,
+ 0x43,0x2f,0x2f,0x44,0x54,0x44,0x20,0x53,0x56,0x47,0x20,0x31,0x2e,0x31,0x2f,0x2f,
+ 0x45,0x4e,0x22,0xa,0x20,0x22,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,
+ 0x2e,0x77,0x33,0x2e,0x6f,0x72,0x67,0x2f,0x47,0x72,0x61,0x70,0x68,0x69,0x63,0x73,
+ 0x2f,0x53,0x56,0x47,0x2f,0x31,0x2e,0x31,0x2f,0x44,0x54,0x44,0x2f,0x73,0x76,0x67,
+ 0x31,0x31,0x2e,0x64,0x74,0x64,0x22,0x3e,0xa,0x3c,0x73,0x76,0x67,0x20,0x77,0x69,
+ 0x64,0x74,0x68,0x3d,0x22,0x38,0x30,0x22,0x20,0x68,0x65,0x69,0x67,0x68,0x74,0x3d,
+ 0x22,0x38,0x30,0x22,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x3d,0x22,0x31,0x2e,
+ 0x31,0x22,0xa,0x20,0x78,0x6d,0x6c,0x6e,0x73,0x3d,0x22,0x68,0x74,0x74,0x70,0x3a,
+ 0x2f,0x2f,0x77,0x77,0x77,0x2e,0x77,0x33,0x2e,0x6f,0x72,0x67,0x2f,0x32,0x30,0x30,
+ 0x30,0x2f,0x73,0x76,0x67,0x22,0x3e,0xa,0x20,0x20,0x3c,0x63,0x69,0x72,0x63,0x6c,
+ 0x65,0x20,0x66,0x69,0x6c,0x6c,0x3d,0x22,0x23,0x66,0x66,0x34,0x34,0x34,0x34,0x22,
+ 0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x3d,0x22,0x6e,0x6f,0x6e,0x65,0x22,0xa,0x20,
+ 0x20,0x20,0x63,0x78,0x3d,0x22,0x34,0x30,0x22,0x20,0x63,0x79,0x3d,0x22,0x34,0x30,
+ 0x22,0x20,0x72,0x3d,0x22,0x33,0x33,0x22,0x2f,0x3e,0xa,0x20,0x20,0x3c,0x63,0x69,
+ 0x72,0x63,0x6c,0x65,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x3d,0x22,0x23,0x35,0x35,
+ 0x35,0x35,0x35,0x35,0x22,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x2d,0x77,0x69,0x64,
+ 0x74,0x68,0x3d,0x22,0x36,0x22,0x20,0x66,0x69,0x6c,0x6c,0x3d,0x22,0x6e,0x6f,0x6e,
+ 0x65,0x22,0xa,0x20,0x20,0x20,0x63,0x78,0x3d,0x22,0x34,0x30,0x22,0x20,0x63,0x79,
+ 0x3d,0x22,0x34,0x30,0x22,0x20,0x72,0x3d,0x22,0x33,0x30,0x22,0x2f,0x3e,0xa,0x20,
+ 0x20,0x3c,0x63,0x69,0x72,0x63,0x6c,0x65,0x20,0x66,0x69,0x6c,0x6c,0x3d,0x22,0x23,
+ 0x35,0x35,0x35,0x35,0x35,0x35,0x22,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x3d,0x22,
+ 0x6e,0x6f,0x6e,0x65,0x22,0xa,0x20,0x20,0x20,0x63,0x78,0x3d,0x22,0x34,0x30,0x22,
+ 0x20,0x63,0x79,0x3d,0x22,0x35,0x36,0x22,0x20,0x72,0x3d,0x22,0x38,0x22,0x2f,0x3e,
+ 0xa,0x3c,0x2f,0x73,0x76,0x67,0x3e,0xa,
+ // /home/calvin/src/xpdf-4.04/xpdf-qt/indicator-icon-err5.svg
+ 0x0,0x0,0x1,0xa9,
+ 0x3c,
+ 0x3f,0x78,0x6d,0x6c,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x3d,0x22,0x31,0x2e,
+ 0x30,0x22,0x3f,0x3e,0xa,0x3c,0x21,0x44,0x4f,0x43,0x54,0x59,0x50,0x45,0x20,0x73,
+ 0x76,0x67,0x20,0x50,0x55,0x42,0x4c,0x49,0x43,0x20,0x22,0x2d,0x2f,0x2f,0x57,0x33,
+ 0x43,0x2f,0x2f,0x44,0x54,0x44,0x20,0x53,0x56,0x47,0x20,0x31,0x2e,0x31,0x2f,0x2f,
+ 0x45,0x4e,0x22,0xa,0x20,0x22,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,
+ 0x2e,0x77,0x33,0x2e,0x6f,0x72,0x67,0x2f,0x47,0x72,0x61,0x70,0x68,0x69,0x63,0x73,
+ 0x2f,0x53,0x56,0x47,0x2f,0x31,0x2e,0x31,0x2f,0x44,0x54,0x44,0x2f,0x73,0x76,0x67,
+ 0x31,0x31,0x2e,0x64,0x74,0x64,0x22,0x3e,0xa,0x3c,0x73,0x76,0x67,0x20,0x77,0x69,
+ 0x64,0x74,0x68,0x3d,0x22,0x38,0x30,0x22,0x20,0x68,0x65,0x69,0x67,0x68,0x74,0x3d,
+ 0x22,0x38,0x30,0x22,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x3d,0x22,0x31,0x2e,
+ 0x31,0x22,0xa,0x20,0x78,0x6d,0x6c,0x6e,0x73,0x3d,0x22,0x68,0x74,0x74,0x70,0x3a,
+ 0x2f,0x2f,0x77,0x77,0x77,0x2e,0x77,0x33,0x2e,0x6f,0x72,0x67,0x2f,0x32,0x30,0x30,
+ 0x30,0x2f,0x73,0x76,0x67,0x22,0x3e,0xa,0x20,0x20,0x3c,0x63,0x69,0x72,0x63,0x6c,
+ 0x65,0x20,0x66,0x69,0x6c,0x6c,0x3d,0x22,0x23,0x66,0x66,0x34,0x34,0x34,0x34,0x22,
+ 0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x3d,0x22,0x6e,0x6f,0x6e,0x65,0x22,0xa,0x20,
+ 0x20,0x20,0x63,0x78,0x3d,0x22,0x34,0x30,0x22,0x20,0x63,0x79,0x3d,0x22,0x34,0x30,
+ 0x22,0x20,0x72,0x3d,0x22,0x33,0x33,0x22,0x2f,0x3e,0xa,0x20,0x20,0x3c,0x63,0x69,
+ 0x72,0x63,0x6c,0x65,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x3d,0x22,0x23,0x35,0x35,
+ 0x35,0x35,0x35,0x35,0x22,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x2d,0x77,0x69,0x64,
+ 0x74,0x68,0x3d,0x22,0x36,0x22,0x20,0x66,0x69,0x6c,0x6c,0x3d,0x22,0x6e,0x6f,0x6e,
+ 0x65,0x22,0xa,0x20,0x20,0x20,0x63,0x78,0x3d,0x22,0x34,0x30,0x22,0x20,0x63,0x79,
+ 0x3d,0x22,0x34,0x30,0x22,0x20,0x72,0x3d,0x22,0x33,0x30,0x22,0x2f,0x3e,0xa,0x20,
+ 0x20,0x3c,0x63,0x69,0x72,0x63,0x6c,0x65,0x20,0x66,0x69,0x6c,0x6c,0x3d,0x22,0x23,
+ 0x35,0x35,0x35,0x35,0x35,0x35,0x22,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x3d,0x22,
+ 0x6e,0x6f,0x6e,0x65,0x22,0xa,0x20,0x20,0x20,0x63,0x78,0x3d,0x22,0x32,0x39,0x22,
+ 0x20,0x63,0x79,0x3d,0x22,0x35,0x31,0x22,0x20,0x72,0x3d,0x22,0x38,0x22,0x2f,0x3e,
+ 0xa,0x3c,0x2f,0x73,0x76,0x67,0x3e,0xa,
+ // /home/calvin/src/xpdf-4.04/xpdf-qt/indicator-icon-err6.svg
+ 0x0,0x0,0x1,0xa9,
+ 0x3c,
+ 0x3f,0x78,0x6d,0x6c,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x3d,0x22,0x31,0x2e,
+ 0x30,0x22,0x3f,0x3e,0xa,0x3c,0x21,0x44,0x4f,0x43,0x54,0x59,0x50,0x45,0x20,0x73,
+ 0x76,0x67,0x20,0x50,0x55,0x42,0x4c,0x49,0x43,0x20,0x22,0x2d,0x2f,0x2f,0x57,0x33,
+ 0x43,0x2f,0x2f,0x44,0x54,0x44,0x20,0x53,0x56,0x47,0x20,0x31,0x2e,0x31,0x2f,0x2f,
+ 0x45,0x4e,0x22,0xa,0x20,0x22,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,
+ 0x2e,0x77,0x33,0x2e,0x6f,0x72,0x67,0x2f,0x47,0x72,0x61,0x70,0x68,0x69,0x63,0x73,
+ 0x2f,0x53,0x56,0x47,0x2f,0x31,0x2e,0x31,0x2f,0x44,0x54,0x44,0x2f,0x73,0x76,0x67,
+ 0x31,0x31,0x2e,0x64,0x74,0x64,0x22,0x3e,0xa,0x3c,0x73,0x76,0x67,0x20,0x77,0x69,
+ 0x64,0x74,0x68,0x3d,0x22,0x38,0x30,0x22,0x20,0x68,0x65,0x69,0x67,0x68,0x74,0x3d,
+ 0x22,0x38,0x30,0x22,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x3d,0x22,0x31,0x2e,
+ 0x31,0x22,0xa,0x20,0x78,0x6d,0x6c,0x6e,0x73,0x3d,0x22,0x68,0x74,0x74,0x70,0x3a,
+ 0x2f,0x2f,0x77,0x77,0x77,0x2e,0x77,0x33,0x2e,0x6f,0x72,0x67,0x2f,0x32,0x30,0x30,
+ 0x30,0x2f,0x73,0x76,0x67,0x22,0x3e,0xa,0x20,0x20,0x3c,0x63,0x69,0x72,0x63,0x6c,
+ 0x65,0x20,0x66,0x69,0x6c,0x6c,0x3d,0x22,0x23,0x66,0x66,0x34,0x34,0x34,0x34,0x22,
+ 0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x3d,0x22,0x6e,0x6f,0x6e,0x65,0x22,0xa,0x20,
+ 0x20,0x20,0x63,0x78,0x3d,0x22,0x34,0x30,0x22,0x20,0x63,0x79,0x3d,0x22,0x34,0x30,
+ 0x22,0x20,0x72,0x3d,0x22,0x33,0x33,0x22,0x2f,0x3e,0xa,0x20,0x20,0x3c,0x63,0x69,
+ 0x72,0x63,0x6c,0x65,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x3d,0x22,0x23,0x35,0x35,
+ 0x35,0x35,0x35,0x35,0x22,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x2d,0x77,0x69,0x64,
+ 0x74,0x68,0x3d,0x22,0x36,0x22,0x20,0x66,0x69,0x6c,0x6c,0x3d,0x22,0x6e,0x6f,0x6e,
+ 0x65,0x22,0xa,0x20,0x20,0x20,0x63,0x78,0x3d,0x22,0x34,0x30,0x22,0x20,0x63,0x79,
+ 0x3d,0x22,0x34,0x30,0x22,0x20,0x72,0x3d,0x22,0x33,0x30,0x22,0x2f,0x3e,0xa,0x20,
+ 0x20,0x3c,0x63,0x69,0x72,0x63,0x6c,0x65,0x20,0x66,0x69,0x6c,0x6c,0x3d,0x22,0x23,
+ 0x35,0x35,0x35,0x35,0x35,0x35,0x22,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x3d,0x22,
+ 0x6e,0x6f,0x6e,0x65,0x22,0xa,0x20,0x20,0x20,0x63,0x78,0x3d,0x22,0x32,0x34,0x22,
+ 0x20,0x63,0x79,0x3d,0x22,0x34,0x30,0x22,0x20,0x72,0x3d,0x22,0x38,0x22,0x2f,0x3e,
+ 0xa,0x3c,0x2f,0x73,0x76,0x67,0x3e,0xa,
+ // /home/calvin/src/xpdf-4.04/xpdf-qt/indicator-icon0.svg
+ 0x0,0x0,0x1,0x66,
+ 0x3c,
+ 0x3f,0x78,0x6d,0x6c,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x3d,0x22,0x31,0x2e,
+ 0x30,0x22,0x3f,0x3e,0xa,0x3c,0x21,0x44,0x4f,0x43,0x54,0x59,0x50,0x45,0x20,0x73,
+ 0x76,0x67,0x20,0x50,0x55,0x42,0x4c,0x49,0x43,0x20,0x22,0x2d,0x2f,0x2f,0x57,0x33,
+ 0x43,0x2f,0x2f,0x44,0x54,0x44,0x20,0x53,0x56,0x47,0x20,0x31,0x2e,0x31,0x2f,0x2f,
+ 0x45,0x4e,0x22,0xa,0x20,0x22,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,
+ 0x2e,0x77,0x33,0x2e,0x6f,0x72,0x67,0x2f,0x47,0x72,0x61,0x70,0x68,0x69,0x63,0x73,
+ 0x2f,0x53,0x56,0x47,0x2f,0x31,0x2e,0x31,0x2f,0x44,0x54,0x44,0x2f,0x73,0x76,0x67,
+ 0x31,0x31,0x2e,0x64,0x74,0x64,0x22,0x3e,0xa,0x3c,0x73,0x76,0x67,0x20,0x77,0x69,
+ 0x64,0x74,0x68,0x3d,0x22,0x38,0x30,0x22,0x20,0x68,0x65,0x69,0x67,0x68,0x74,0x3d,
+ 0x22,0x38,0x30,0x22,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x3d,0x22,0x31,0x2e,
+ 0x31,0x22,0xa,0x20,0x78,0x6d,0x6c,0x6e,0x73,0x3d,0x22,0x68,0x74,0x74,0x70,0x3a,
+ 0x2f,0x2f,0x77,0x77,0x77,0x2e,0x77,0x33,0x2e,0x6f,0x72,0x67,0x2f,0x32,0x30,0x30,
+ 0x30,0x2f,0x73,0x76,0x67,0x22,0x3e,0xa,0x20,0x20,0x3c,0x63,0x69,0x72,0x63,0x6c,
+ 0x65,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x3d,0x22,0x23,0x35,0x35,0x35,0x35,0x35,
+ 0x35,0x22,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x2d,0x77,0x69,0x64,0x74,0x68,0x3d,
+ 0x22,0x36,0x22,0x20,0x66,0x69,0x6c,0x6c,0x3d,0x22,0x6e,0x6f,0x6e,0x65,0x22,0xa,
+ 0x20,0x20,0x20,0x63,0x78,0x3d,0x22,0x34,0x30,0x22,0x20,0x63,0x79,0x3d,0x22,0x34,
+ 0x30,0x22,0x20,0x72,0x3d,0x22,0x33,0x30,0x22,0x2f,0x3e,0xa,0x20,0x20,0x3c,0x63,
+ 0x69,0x72,0x63,0x6c,0x65,0x20,0x66,0x69,0x6c,0x6c,0x3d,0x22,0x23,0x35,0x35,0x35,
+ 0x35,0x35,0x35,0x22,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x3d,0x22,0x6e,0x6f,0x6e,
+ 0x65,0x22,0xa,0x20,0x20,0x20,0x63,0x78,0x3d,0x22,0x34,0x30,0x22,0x20,0x63,0x79,
+ 0x3d,0x22,0x32,0x34,0x22,0x20,0x72,0x3d,0x22,0x38,0x22,0x2f,0x3e,0xa,0x3c,0x2f,
+ 0x73,0x76,0x67,0x3e,0xa,
+ // /home/calvin/src/xpdf-4.04/xpdf-qt/indicator-icon-err7.svg
+ 0x0,0x0,0x1,0xa9,
+ 0x3c,
+ 0x3f,0x78,0x6d,0x6c,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x3d,0x22,0x31,0x2e,
+ 0x30,0x22,0x3f,0x3e,0xa,0x3c,0x21,0x44,0x4f,0x43,0x54,0x59,0x50,0x45,0x20,0x73,
+ 0x76,0x67,0x20,0x50,0x55,0x42,0x4c,0x49,0x43,0x20,0x22,0x2d,0x2f,0x2f,0x57,0x33,
+ 0x43,0x2f,0x2f,0x44,0x54,0x44,0x20,0x53,0x56,0x47,0x20,0x31,0x2e,0x31,0x2f,0x2f,
+ 0x45,0x4e,0x22,0xa,0x20,0x22,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,
+ 0x2e,0x77,0x33,0x2e,0x6f,0x72,0x67,0x2f,0x47,0x72,0x61,0x70,0x68,0x69,0x63,0x73,
+ 0x2f,0x53,0x56,0x47,0x2f,0x31,0x2e,0x31,0x2f,0x44,0x54,0x44,0x2f,0x73,0x76,0x67,
+ 0x31,0x31,0x2e,0x64,0x74,0x64,0x22,0x3e,0xa,0x3c,0x73,0x76,0x67,0x20,0x77,0x69,
+ 0x64,0x74,0x68,0x3d,0x22,0x38,0x30,0x22,0x20,0x68,0x65,0x69,0x67,0x68,0x74,0x3d,
+ 0x22,0x38,0x30,0x22,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x3d,0x22,0x31,0x2e,
+ 0x31,0x22,0xa,0x20,0x78,0x6d,0x6c,0x6e,0x73,0x3d,0x22,0x68,0x74,0x74,0x70,0x3a,
+ 0x2f,0x2f,0x77,0x77,0x77,0x2e,0x77,0x33,0x2e,0x6f,0x72,0x67,0x2f,0x32,0x30,0x30,
+ 0x30,0x2f,0x73,0x76,0x67,0x22,0x3e,0xa,0x20,0x20,0x3c,0x63,0x69,0x72,0x63,0x6c,
+ 0x65,0x20,0x66,0x69,0x6c,0x6c,0x3d,0x22,0x23,0x66,0x66,0x34,0x34,0x34,0x34,0x22,
+ 0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x3d,0x22,0x6e,0x6f,0x6e,0x65,0x22,0xa,0x20,
+ 0x20,0x20,0x63,0x78,0x3d,0x22,0x34,0x30,0x22,0x20,0x63,0x79,0x3d,0x22,0x34,0x30,
+ 0x22,0x20,0x72,0x3d,0x22,0x33,0x33,0x22,0x2f,0x3e,0xa,0x20,0x20,0x3c,0x63,0x69,
+ 0x72,0x63,0x6c,0x65,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x3d,0x22,0x23,0x35,0x35,
+ 0x35,0x35,0x35,0x35,0x22,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x2d,0x77,0x69,0x64,
+ 0x74,0x68,0x3d,0x22,0x36,0x22,0x20,0x66,0x69,0x6c,0x6c,0x3d,0x22,0x6e,0x6f,0x6e,
+ 0x65,0x22,0xa,0x20,0x20,0x20,0x63,0x78,0x3d,0x22,0x34,0x30,0x22,0x20,0x63,0x79,
+ 0x3d,0x22,0x34,0x30,0x22,0x20,0x72,0x3d,0x22,0x33,0x30,0x22,0x2f,0x3e,0xa,0x20,
+ 0x20,0x3c,0x63,0x69,0x72,0x63,0x6c,0x65,0x20,0x66,0x69,0x6c,0x6c,0x3d,0x22,0x23,
+ 0x35,0x35,0x35,0x35,0x35,0x35,0x22,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x3d,0x22,
+ 0x6e,0x6f,0x6e,0x65,0x22,0xa,0x20,0x20,0x20,0x63,0x78,0x3d,0x22,0x32,0x39,0x22,
+ 0x20,0x63,0x79,0x3d,0x22,0x32,0x39,0x22,0x20,0x72,0x3d,0x22,0x38,0x22,0x2f,0x3e,
+ 0xa,0x3c,0x2f,0x73,0x76,0x67,0x3e,0xa,
+ // /home/calvin/src/xpdf-4.04/xpdf-qt/findSettings.svg
+ 0x0,0x0,0x1,0x65,
+ 0x3c,
+ 0x3f,0x78,0x6d,0x6c,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x3d,0x22,0x31,0x2e,
+ 0x30,0x22,0x3f,0x3e,0xa,0x3c,0x21,0x44,0x4f,0x43,0x54,0x59,0x50,0x45,0x20,0x73,
+ 0x76,0x67,0x20,0x50,0x55,0x42,0x4c,0x49,0x43,0x20,0x22,0x2d,0x2f,0x2f,0x57,0x33,
+ 0x43,0x2f,0x2f,0x44,0x54,0x44,0x20,0x53,0x56,0x47,0x20,0x31,0x2e,0x31,0x2f,0x2f,
+ 0x45,0x4e,0x22,0x20,0xa,0x20,0x20,0x22,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,
+ 0x77,0x77,0x2e,0x77,0x33,0x2e,0x6f,0x72,0x67,0x2f,0x47,0x72,0x61,0x70,0x68,0x69,
+ 0x63,0x73,0x2f,0x53,0x56,0x47,0x2f,0x31,0x2e,0x31,0x2f,0x44,0x54,0x44,0x2f,0x73,
+ 0x76,0x67,0x31,0x31,0x2e,0x64,0x74,0x64,0x22,0x3e,0xa,0x3c,0x73,0x76,0x67,0x20,
+ 0x77,0x69,0x64,0x74,0x68,0x3d,0x22,0x36,0x30,0x22,0x20,0x68,0x65,0x69,0x67,0x68,
+ 0x74,0x3d,0x22,0x38,0x30,0x22,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x3d,0x22,
+ 0x31,0x2e,0x31,0x22,0xa,0x20,0x78,0x6d,0x6c,0x6e,0x73,0x3d,0x22,0x68,0x74,0x74,
+ 0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x77,0x33,0x2e,0x6f,0x72,0x67,0x2f,0x32,
+ 0x30,0x30,0x30,0x2f,0x73,0x76,0x67,0x22,0x3e,0xa,0x20,0x20,0x3c,0x63,0x69,0x72,
+ 0x63,0x6c,0x65,0x20,0x66,0x69,0x6c,0x6c,0x3d,0x22,0x23,0x35,0x35,0x35,0x35,0x35,
+ 0x35,0x22,0x20,0x63,0x78,0x3d,0x22,0x31,0x34,0x22,0x20,0x63,0x79,0x3d,0x22,0x34,
+ 0x30,0x22,0x20,0x72,0x3d,0x22,0x35,0x22,0x2f,0x3e,0xa,0x20,0x20,0x3c,0x63,0x69,
+ 0x72,0x63,0x6c,0x65,0x20,0x66,0x69,0x6c,0x6c,0x3d,0x22,0x23,0x35,0x35,0x35,0x35,
+ 0x35,0x35,0x22,0x20,0x63,0x78,0x3d,0x22,0x33,0x30,0x22,0x20,0x63,0x79,0x3d,0x22,
+ 0x34,0x30,0x22,0x20,0x72,0x3d,0x22,0x35,0x22,0x2f,0x3e,0xa,0x20,0x20,0x3c,0x63,
+ 0x69,0x72,0x63,0x6c,0x65,0x20,0x66,0x69,0x6c,0x6c,0x3d,0x22,0x23,0x35,0x35,0x35,
+ 0x35,0x35,0x35,0x22,0x20,0x63,0x78,0x3d,0x22,0x34,0x36,0x22,0x20,0x63,0x79,0x3d,
+ 0x22,0x34,0x30,0x22,0x20,0x72,0x3d,0x22,0x35,0x22,0x2f,0x3e,0xa,0x3c,0x2f,0x73,
+ 0x76,0x67,0x3e,0xa,
+ // /home/calvin/src/xpdf-4.04/xpdf-qt/indicator-icon1.svg
+ 0x0,0x0,0x1,0x66,
+ 0x3c,
+ 0x3f,0x78,0x6d,0x6c,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x3d,0x22,0x31,0x2e,
+ 0x30,0x22,0x3f,0x3e,0xa,0x3c,0x21,0x44,0x4f,0x43,0x54,0x59,0x50,0x45,0x20,0x73,
+ 0x76,0x67,0x20,0x50,0x55,0x42,0x4c,0x49,0x43,0x20,0x22,0x2d,0x2f,0x2f,0x57,0x33,
+ 0x43,0x2f,0x2f,0x44,0x54,0x44,0x20,0x53,0x56,0x47,0x20,0x31,0x2e,0x31,0x2f,0x2f,
+ 0x45,0x4e,0x22,0xa,0x20,0x22,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,
+ 0x2e,0x77,0x33,0x2e,0x6f,0x72,0x67,0x2f,0x47,0x72,0x61,0x70,0x68,0x69,0x63,0x73,
+ 0x2f,0x53,0x56,0x47,0x2f,0x31,0x2e,0x31,0x2f,0x44,0x54,0x44,0x2f,0x73,0x76,0x67,
+ 0x31,0x31,0x2e,0x64,0x74,0x64,0x22,0x3e,0xa,0x3c,0x73,0x76,0x67,0x20,0x77,0x69,
+ 0x64,0x74,0x68,0x3d,0x22,0x38,0x30,0x22,0x20,0x68,0x65,0x69,0x67,0x68,0x74,0x3d,
+ 0x22,0x38,0x30,0x22,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x3d,0x22,0x31,0x2e,
+ 0x31,0x22,0xa,0x20,0x78,0x6d,0x6c,0x6e,0x73,0x3d,0x22,0x68,0x74,0x74,0x70,0x3a,
+ 0x2f,0x2f,0x77,0x77,0x77,0x2e,0x77,0x33,0x2e,0x6f,0x72,0x67,0x2f,0x32,0x30,0x30,
+ 0x30,0x2f,0x73,0x76,0x67,0x22,0x3e,0xa,0x20,0x20,0x3c,0x63,0x69,0x72,0x63,0x6c,
+ 0x65,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x3d,0x22,0x23,0x35,0x35,0x35,0x35,0x35,
+ 0x35,0x22,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x2d,0x77,0x69,0x64,0x74,0x68,0x3d,
+ 0x22,0x36,0x22,0x20,0x66,0x69,0x6c,0x6c,0x3d,0x22,0x6e,0x6f,0x6e,0x65,0x22,0xa,
+ 0x20,0x20,0x20,0x63,0x78,0x3d,0x22,0x34,0x30,0x22,0x20,0x63,0x79,0x3d,0x22,0x34,
+ 0x30,0x22,0x20,0x72,0x3d,0x22,0x33,0x30,0x22,0x2f,0x3e,0xa,0x20,0x20,0x3c,0x63,
+ 0x69,0x72,0x63,0x6c,0x65,0x20,0x66,0x69,0x6c,0x6c,0x3d,0x22,0x23,0x35,0x35,0x35,
+ 0x35,0x35,0x35,0x22,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x3d,0x22,0x6e,0x6f,0x6e,
+ 0x65,0x22,0xa,0x20,0x20,0x20,0x63,0x78,0x3d,0x22,0x35,0x31,0x22,0x20,0x63,0x79,
+ 0x3d,0x22,0x32,0x39,0x22,0x20,0x72,0x3d,0x22,0x38,0x22,0x2f,0x3e,0xa,0x3c,0x2f,
+ 0x73,0x76,0x67,0x3e,0xa,
+ // /home/calvin/src/xpdf-4.04/xpdf-qt/zoomOut.svg
+ 0x0,0x0,0x1,0x27,
+ 0x3c,
+ 0x3f,0x78,0x6d,0x6c,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x3d,0x22,0x31,0x2e,
+ 0x30,0x22,0x3f,0x3e,0xa,0x3c,0x21,0x44,0x4f,0x43,0x54,0x59,0x50,0x45,0x20,0x73,
+ 0x76,0x67,0x20,0x50,0x55,0x42,0x4c,0x49,0x43,0x20,0x22,0x2d,0x2f,0x2f,0x57,0x33,
+ 0x43,0x2f,0x2f,0x44,0x54,0x44,0x20,0x53,0x56,0x47,0x20,0x31,0x2e,0x31,0x2f,0x2f,
+ 0x45,0x4e,0x22,0x20,0xa,0x20,0x20,0x22,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,
+ 0x77,0x77,0x2e,0x77,0x33,0x2e,0x6f,0x72,0x67,0x2f,0x47,0x72,0x61,0x70,0x68,0x69,
+ 0x63,0x73,0x2f,0x53,0x56,0x47,0x2f,0x31,0x2e,0x31,0x2f,0x44,0x54,0x44,0x2f,0x73,
+ 0x76,0x67,0x31,0x31,0x2e,0x64,0x74,0x64,0x22,0x3e,0xa,0x3c,0x73,0x76,0x67,0x20,
+ 0x77,0x69,0x64,0x74,0x68,0x3d,0x22,0x38,0x30,0x22,0x20,0x68,0x65,0x69,0x67,0x68,
+ 0x74,0x3d,0x22,0x38,0x30,0x22,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x3d,0x22,
+ 0x31,0x2e,0x31,0x22,0xa,0x20,0x78,0x6d,0x6c,0x6e,0x73,0x3d,0x22,0x68,0x74,0x74,
+ 0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x77,0x33,0x2e,0x6f,0x72,0x67,0x2f,0x32,
+ 0x30,0x30,0x30,0x2f,0x73,0x76,0x67,0x22,0x3e,0xa,0x20,0x20,0x3c,0x70,0x6f,0x6c,
+ 0x79,0x6c,0x69,0x6e,0x65,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x3d,0x22,0x23,0x35,
+ 0x35,0x35,0x35,0x35,0x35,0x22,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x2d,0x77,0x69,
+ 0x64,0x74,0x68,0x3d,0x22,0x38,0x22,0x20,0x66,0x69,0x6c,0x6c,0x3d,0x22,0x6e,0x6f,
+ 0x6e,0x65,0x22,0xa,0x20,0x20,0x20,0x70,0x6f,0x69,0x6e,0x74,0x73,0x3d,0x22,0x31,
+ 0x36,0x2c,0x34,0x30,0x20,0x20,0x36,0x34,0x2c,0x34,0x30,0x22,0x2f,0x3e,0xa,0x3c,
+ 0x2f,0x73,0x76,0x67,0x3e,0xa,
+ // /home/calvin/src/xpdf-4.04/xpdf-qt/indicator-icon2.svg
+ 0x0,0x0,0x1,0x66,
+ 0x3c,
+ 0x3f,0x78,0x6d,0x6c,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x3d,0x22,0x31,0x2e,
+ 0x30,0x22,0x3f,0x3e,0xa,0x3c,0x21,0x44,0x4f,0x43,0x54,0x59,0x50,0x45,0x20,0x73,
+ 0x76,0x67,0x20,0x50,0x55,0x42,0x4c,0x49,0x43,0x20,0x22,0x2d,0x2f,0x2f,0x57,0x33,
+ 0x43,0x2f,0x2f,0x44,0x54,0x44,0x20,0x53,0x56,0x47,0x20,0x31,0x2e,0x31,0x2f,0x2f,
+ 0x45,0x4e,0x22,0xa,0x20,0x22,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,
+ 0x2e,0x77,0x33,0x2e,0x6f,0x72,0x67,0x2f,0x47,0x72,0x61,0x70,0x68,0x69,0x63,0x73,
+ 0x2f,0x53,0x56,0x47,0x2f,0x31,0x2e,0x31,0x2f,0x44,0x54,0x44,0x2f,0x73,0x76,0x67,
+ 0x31,0x31,0x2e,0x64,0x74,0x64,0x22,0x3e,0xa,0x3c,0x73,0x76,0x67,0x20,0x77,0x69,
+ 0x64,0x74,0x68,0x3d,0x22,0x38,0x30,0x22,0x20,0x68,0x65,0x69,0x67,0x68,0x74,0x3d,
+ 0x22,0x38,0x30,0x22,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x3d,0x22,0x31,0x2e,
+ 0x31,0x22,0xa,0x20,0x78,0x6d,0x6c,0x6e,0x73,0x3d,0x22,0x68,0x74,0x74,0x70,0x3a,
+ 0x2f,0x2f,0x77,0x77,0x77,0x2e,0x77,0x33,0x2e,0x6f,0x72,0x67,0x2f,0x32,0x30,0x30,
+ 0x30,0x2f,0x73,0x76,0x67,0x22,0x3e,0xa,0x20,0x20,0x3c,0x63,0x69,0x72,0x63,0x6c,
+ 0x65,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x3d,0x22,0x23,0x35,0x35,0x35,0x35,0x35,
+ 0x35,0x22,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x2d,0x77,0x69,0x64,0x74,0x68,0x3d,
+ 0x22,0x36,0x22,0x20,0x66,0x69,0x6c,0x6c,0x3d,0x22,0x6e,0x6f,0x6e,0x65,0x22,0xa,
+ 0x20,0x20,0x20,0x63,0x78,0x3d,0x22,0x34,0x30,0x22,0x20,0x63,0x79,0x3d,0x22,0x34,
+ 0x30,0x22,0x20,0x72,0x3d,0x22,0x33,0x30,0x22,0x2f,0x3e,0xa,0x20,0x20,0x3c,0x63,
+ 0x69,0x72,0x63,0x6c,0x65,0x20,0x66,0x69,0x6c,0x6c,0x3d,0x22,0x23,0x35,0x35,0x35,
+ 0x35,0x35,0x35,0x22,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x3d,0x22,0x6e,0x6f,0x6e,
+ 0x65,0x22,0xa,0x20,0x20,0x20,0x63,0x78,0x3d,0x22,0x35,0x36,0x22,0x20,0x63,0x79,
+ 0x3d,0x22,0x34,0x30,0x22,0x20,0x72,0x3d,0x22,0x38,0x22,0x2f,0x3e,0xa,0x3c,0x2f,
+ 0x73,0x76,0x67,0x3e,0xa,
+ // /home/calvin/src/xpdf-4.04/xpdf-qt/indicator-icon3.svg
+ 0x0,0x0,0x1,0x66,
+ 0x3c,
+ 0x3f,0x78,0x6d,0x6c,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x3d,0x22,0x31,0x2e,
+ 0x30,0x22,0x3f,0x3e,0xa,0x3c,0x21,0x44,0x4f,0x43,0x54,0x59,0x50,0x45,0x20,0x73,
+ 0x76,0x67,0x20,0x50,0x55,0x42,0x4c,0x49,0x43,0x20,0x22,0x2d,0x2f,0x2f,0x57,0x33,
+ 0x43,0x2f,0x2f,0x44,0x54,0x44,0x20,0x53,0x56,0x47,0x20,0x31,0x2e,0x31,0x2f,0x2f,
+ 0x45,0x4e,0x22,0xa,0x20,0x22,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,
+ 0x2e,0x77,0x33,0x2e,0x6f,0x72,0x67,0x2f,0x47,0x72,0x61,0x70,0x68,0x69,0x63,0x73,
+ 0x2f,0x53,0x56,0x47,0x2f,0x31,0x2e,0x31,0x2f,0x44,0x54,0x44,0x2f,0x73,0x76,0x67,
+ 0x31,0x31,0x2e,0x64,0x74,0x64,0x22,0x3e,0xa,0x3c,0x73,0x76,0x67,0x20,0x77,0x69,
+ 0x64,0x74,0x68,0x3d,0x22,0x38,0x30,0x22,0x20,0x68,0x65,0x69,0x67,0x68,0x74,0x3d,
+ 0x22,0x38,0x30,0x22,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x3d,0x22,0x31,0x2e,
+ 0x31,0x22,0xa,0x20,0x78,0x6d,0x6c,0x6e,0x73,0x3d,0x22,0x68,0x74,0x74,0x70,0x3a,
+ 0x2f,0x2f,0x77,0x77,0x77,0x2e,0x77,0x33,0x2e,0x6f,0x72,0x67,0x2f,0x32,0x30,0x30,
+ 0x30,0x2f,0x73,0x76,0x67,0x22,0x3e,0xa,0x20,0x20,0x3c,0x63,0x69,0x72,0x63,0x6c,
+ 0x65,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x3d,0x22,0x23,0x35,0x35,0x35,0x35,0x35,
+ 0x35,0x22,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x2d,0x77,0x69,0x64,0x74,0x68,0x3d,
+ 0x22,0x36,0x22,0x20,0x66,0x69,0x6c,0x6c,0x3d,0x22,0x6e,0x6f,0x6e,0x65,0x22,0xa,
+ 0x20,0x20,0x20,0x63,0x78,0x3d,0x22,0x34,0x30,0x22,0x20,0x63,0x79,0x3d,0x22,0x34,
+ 0x30,0x22,0x20,0x72,0x3d,0x22,0x33,0x30,0x22,0x2f,0x3e,0xa,0x20,0x20,0x3c,0x63,
+ 0x69,0x72,0x63,0x6c,0x65,0x20,0x66,0x69,0x6c,0x6c,0x3d,0x22,0x23,0x35,0x35,0x35,
+ 0x35,0x35,0x35,0x22,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x3d,0x22,0x6e,0x6f,0x6e,
+ 0x65,0x22,0xa,0x20,0x20,0x20,0x63,0x78,0x3d,0x22,0x35,0x31,0x22,0x20,0x63,0x79,
+ 0x3d,0x22,0x35,0x31,0x22,0x20,0x72,0x3d,0x22,0x38,0x22,0x2f,0x3e,0xa,0x3c,0x2f,
+ 0x73,0x76,0x67,0x3e,0xa,
+ // /home/calvin/src/xpdf-4.04/xpdf-qt/indicator-icon4.svg
+ 0x0,0x0,0x1,0x66,
+ 0x3c,
+ 0x3f,0x78,0x6d,0x6c,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x3d,0x22,0x31,0x2e,
+ 0x30,0x22,0x3f,0x3e,0xa,0x3c,0x21,0x44,0x4f,0x43,0x54,0x59,0x50,0x45,0x20,0x73,
+ 0x76,0x67,0x20,0x50,0x55,0x42,0x4c,0x49,0x43,0x20,0x22,0x2d,0x2f,0x2f,0x57,0x33,
+ 0x43,0x2f,0x2f,0x44,0x54,0x44,0x20,0x53,0x56,0x47,0x20,0x31,0x2e,0x31,0x2f,0x2f,
+ 0x45,0x4e,0x22,0xa,0x20,0x22,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,
+ 0x2e,0x77,0x33,0x2e,0x6f,0x72,0x67,0x2f,0x47,0x72,0x61,0x70,0x68,0x69,0x63,0x73,
+ 0x2f,0x53,0x56,0x47,0x2f,0x31,0x2e,0x31,0x2f,0x44,0x54,0x44,0x2f,0x73,0x76,0x67,
+ 0x31,0x31,0x2e,0x64,0x74,0x64,0x22,0x3e,0xa,0x3c,0x73,0x76,0x67,0x20,0x77,0x69,
+ 0x64,0x74,0x68,0x3d,0x22,0x38,0x30,0x22,0x20,0x68,0x65,0x69,0x67,0x68,0x74,0x3d,
+ 0x22,0x38,0x30,0x22,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x3d,0x22,0x31,0x2e,
+ 0x31,0x22,0xa,0x20,0x78,0x6d,0x6c,0x6e,0x73,0x3d,0x22,0x68,0x74,0x74,0x70,0x3a,
+ 0x2f,0x2f,0x77,0x77,0x77,0x2e,0x77,0x33,0x2e,0x6f,0x72,0x67,0x2f,0x32,0x30,0x30,
+ 0x30,0x2f,0x73,0x76,0x67,0x22,0x3e,0xa,0x20,0x20,0x3c,0x63,0x69,0x72,0x63,0x6c,
+ 0x65,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x3d,0x22,0x23,0x35,0x35,0x35,0x35,0x35,
+ 0x35,0x22,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x2d,0x77,0x69,0x64,0x74,0x68,0x3d,
+ 0x22,0x36,0x22,0x20,0x66,0x69,0x6c,0x6c,0x3d,0x22,0x6e,0x6f,0x6e,0x65,0x22,0xa,
+ 0x20,0x20,0x20,0x63,0x78,0x3d,0x22,0x34,0x30,0x22,0x20,0x63,0x79,0x3d,0x22,0x34,
+ 0x30,0x22,0x20,0x72,0x3d,0x22,0x33,0x30,0x22,0x2f,0x3e,0xa,0x20,0x20,0x3c,0x63,
+ 0x69,0x72,0x63,0x6c,0x65,0x20,0x66,0x69,0x6c,0x6c,0x3d,0x22,0x23,0x35,0x35,0x35,
+ 0x35,0x35,0x35,0x22,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x3d,0x22,0x6e,0x6f,0x6e,
+ 0x65,0x22,0xa,0x20,0x20,0x20,0x63,0x78,0x3d,0x22,0x34,0x30,0x22,0x20,0x63,0x79,
+ 0x3d,0x22,0x35,0x36,0x22,0x20,0x72,0x3d,0x22,0x38,0x22,0x2f,0x3e,0xa,0x3c,0x2f,
+ 0x73,0x76,0x67,0x3e,0xa,
+ // /home/calvin/src/xpdf-4.04/xpdf-qt/findNext.svg
+ 0x0,0x0,0x1,0x2e,
+ 0x3c,
+ 0x3f,0x78,0x6d,0x6c,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x3d,0x22,0x31,0x2e,
+ 0x30,0x22,0x3f,0x3e,0xa,0x3c,0x21,0x44,0x4f,0x43,0x54,0x59,0x50,0x45,0x20,0x73,
+ 0x76,0x67,0x20,0x50,0x55,0x42,0x4c,0x49,0x43,0x20,0x22,0x2d,0x2f,0x2f,0x57,0x33,
+ 0x43,0x2f,0x2f,0x44,0x54,0x44,0x20,0x53,0x56,0x47,0x20,0x31,0x2e,0x31,0x2f,0x2f,
+ 0x45,0x4e,0x22,0x20,0xa,0x20,0x20,0x22,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,
+ 0x77,0x77,0x2e,0x77,0x33,0x2e,0x6f,0x72,0x67,0x2f,0x47,0x72,0x61,0x70,0x68,0x69,
+ 0x63,0x73,0x2f,0x53,0x56,0x47,0x2f,0x31,0x2e,0x31,0x2f,0x44,0x54,0x44,0x2f,0x73,
+ 0x76,0x67,0x31,0x31,0x2e,0x64,0x74,0x64,0x22,0x3e,0xa,0x3c,0x73,0x76,0x67,0x20,
+ 0x77,0x69,0x64,0x74,0x68,0x3d,0x22,0x36,0x30,0x22,0x20,0x68,0x65,0x69,0x67,0x68,
+ 0x74,0x3d,0x22,0x38,0x30,0x22,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x3d,0x22,
+ 0x31,0x2e,0x31,0x22,0xa,0x20,0x78,0x6d,0x6c,0x6e,0x73,0x3d,0x22,0x68,0x74,0x74,
+ 0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x77,0x33,0x2e,0x6f,0x72,0x67,0x2f,0x32,
+ 0x30,0x30,0x30,0x2f,0x73,0x76,0x67,0x22,0x3e,0xa,0x20,0x20,0x3c,0x70,0x6f,0x6c,
+ 0x79,0x6c,0x69,0x6e,0x65,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x3d,0x22,0x23,0x35,
+ 0x35,0x35,0x35,0x35,0x35,0x22,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x2d,0x77,0x69,
+ 0x64,0x74,0x68,0x3d,0x22,0x38,0x22,0x20,0x66,0x69,0x6c,0x6c,0x3d,0x22,0x6e,0x6f,
+ 0x6e,0x65,0x22,0xa,0x20,0x20,0x20,0x70,0x6f,0x69,0x6e,0x74,0x73,0x3d,0x22,0x31,
+ 0x32,0x2c,0x33,0x32,0x20,0x20,0x33,0x30,0x2c,0x34,0x38,0x20,0x20,0x34,0x38,0x2c,
+ 0x33,0x32,0x22,0x2f,0x3e,0xa,0x3c,0x2f,0x73,0x76,0x67,0x3e,0xa,
+ // /home/calvin/src/xpdf-4.04/xpdf-qt/xpdf-icon.svg
+ 0x0,0x0,0x3,0x47,
+ 0x3c,
+ 0x3f,0x78,0x6d,0x6c,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x3d,0x22,0x31,0x2e,
+ 0x30,0x22,0x3f,0x3e,0xa,0x3c,0x21,0x44,0x4f,0x43,0x54,0x59,0x50,0x45,0x20,0x73,
+ 0x76,0x67,0x20,0x50,0x55,0x42,0x4c,0x49,0x43,0x20,0x22,0x2d,0x2f,0x2f,0x57,0x33,
+ 0x43,0x2f,0x2f,0x44,0x54,0x44,0x20,0x53,0x56,0x47,0x20,0x31,0x2e,0x31,0x2f,0x2f,
+ 0x45,0x4e,0x22,0xa,0x20,0x22,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,
+ 0x2e,0x77,0x33,0x2e,0x6f,0x72,0x67,0x2f,0x47,0x72,0x61,0x70,0x68,0x69,0x63,0x73,
+ 0x2f,0x53,0x56,0x47,0x2f,0x31,0x2e,0x31,0x2f,0x44,0x54,0x44,0x2f,0x73,0x76,0x67,
+ 0x31,0x31,0x2e,0x64,0x74,0x64,0x22,0x3e,0xa,0x3c,0x73,0x76,0x67,0x20,0x77,0x69,
+ 0x64,0x74,0x68,0x3d,0x22,0x36,0x34,0x22,0x20,0x68,0x65,0x69,0x67,0x68,0x74,0x3d,
+ 0x22,0x36,0x34,0x22,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x3d,0x22,0x31,0x2e,
+ 0x31,0x22,0xa,0x20,0x78,0x6d,0x6c,0x6e,0x73,0x3d,0x22,0x68,0x74,0x74,0x70,0x3a,
+ 0x2f,0x2f,0x77,0x77,0x77,0x2e,0x77,0x33,0x2e,0x6f,0x72,0x67,0x2f,0x32,0x30,0x30,
+ 0x30,0x2f,0x73,0x76,0x67,0x22,0x3e,0xa,0x20,0x20,0x3c,0x70,0x61,0x74,0x68,0x20,
+ 0x66,0x69,0x6c,0x6c,0x3d,0x22,0x23,0x30,0x30,0x34,0x34,0x36,0x36,0x22,0x20,0x73,
+ 0x74,0x72,0x6f,0x6b,0x65,0x3d,0x22,0x6e,0x6f,0x6e,0x65,0x22,0xa,0x20,0x20,0x20,
+ 0x64,0x3d,0x22,0x4d,0x20,0x38,0x2c,0x34,0x20,0x4c,0x20,0x32,0x30,0x2c,0x34,0x20,
+ 0x41,0x20,0x31,0x32,0x2c,0x31,0x32,0x2c,0x30,0x2c,0x30,0x2c,0x31,0x2c,0x33,0x32,
+ 0x2c,0x31,0x36,0x20,0x41,0x20,0x31,0x32,0x2c,0x31,0x32,0x2c,0x30,0x2c,0x30,0x2c,
+ 0x31,0x2c,0x34,0x34,0x2c,0x34,0x20,0x4c,0x20,0x35,0x36,0x2c,0x34,0xa,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x4c,0x20,0x35,0x36,0x2c,0x36,0x30,0xa,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x4c,0x20,0x34,0x34,0x2c,0x36,0x30,0x20,0x41,0x20,0x31,0x32,0x2c,0x31,
+ 0x32,0x2c,0x30,0x2c,0x30,0x2c,0x31,0x2c,0x33,0x32,0x2c,0x34,0x38,0x20,0x41,0x20,
+ 0x31,0x32,0x2c,0x31,0x32,0x2c,0x30,0x2c,0x30,0x2c,0x31,0x2c,0x32,0x30,0x2c,0x36,
+ 0x30,0x20,0x4c,0x20,0x38,0x2c,0x36,0x30,0xa,0x20,0x20,0x20,0x20,0x20,0x20,0x4c,
+ 0x20,0x38,0x2c,0x34,0x34,0x20,0x4c,0x20,0x31,0x32,0x2c,0x34,0x34,0x20,0x41,0x20,
+ 0x34,0x2c,0x34,0x2c,0x30,0x2c,0x30,0x2c,0x30,0x2c,0x31,0x36,0x2c,0x34,0x30,0x20,
+ 0x4c,0x20,0x31,0x36,0x2c,0x32,0x34,0x20,0x41,0x20,0x34,0x2c,0x34,0x2c,0x30,0x2c,
+ 0x30,0x2c,0x30,0x2c,0x31,0x32,0x2c,0x32,0x30,0x20,0x4c,0x20,0x38,0x2c,0x32,0x30,
+ 0x22,0x2f,0x3e,0xa,0x20,0x20,0x3c,0x70,0x61,0x74,0x68,0x20,0x73,0x74,0x72,0x6f,
+ 0x6b,0x65,0x3d,0x22,0x23,0x66,0x66,0x66,0x66,0x66,0x66,0x22,0x20,0x73,0x74,0x72,
+ 0x6f,0x6b,0x65,0x2d,0x77,0x69,0x64,0x74,0x68,0x3d,0x22,0x36,0x22,0x20,0x66,0x69,
+ 0x6c,0x6c,0x3d,0x22,0x6e,0x6f,0x6e,0x65,0x22,0xa,0x20,0x20,0x20,0x64,0x3d,0x22,
+ 0x4d,0x20,0x31,0x32,0x2c,0x31,0x32,0x20,0x4c,0x20,0x31,0x36,0x2c,0x31,0x32,0x20,
+ 0x41,0x20,0x38,0x2c,0x38,0x2c,0x30,0x2c,0x30,0x2c,0x31,0x2c,0x32,0x34,0x2c,0x32,
+ 0x30,0x20,0x4c,0x20,0x32,0x34,0x2c,0x32,0x34,0x20,0x41,0x20,0x38,0x2c,0x38,0x2c,
+ 0x30,0x2c,0x30,0x2c,0x30,0x2c,0x33,0x32,0x2c,0x33,0x32,0xa,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x41,0x20,0x38,0x2c,0x38,0x2c,0x30,0x2c,0x30,0x2c,0x30,0x2c,0x32,0x34,
+ 0x2c,0x34,0x30,0x20,0x4c,0x20,0x32,0x34,0x2c,0x34,0x34,0x20,0x41,0x20,0x38,0x2c,
+ 0x38,0x2c,0x30,0x2c,0x30,0x2c,0x31,0x2c,0x31,0x36,0x2c,0x35,0x32,0x20,0x4c,0x20,
+ 0x31,0x32,0x2c,0x35,0x32,0x22,0x2f,0x3e,0xa,0x20,0x20,0x3c,0x63,0x69,0x72,0x63,
+ 0x6c,0x65,0x20,0x66,0x69,0x6c,0x6c,0x3d,0x22,0x23,0x66,0x66,0x66,0x66,0x66,0x66,
+ 0x22,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x3d,0x22,0x6e,0x6f,0x6e,0x65,0x22,0xa,
+ 0x20,0x20,0x20,0x63,0x78,0x3d,0x22,0x34,0x36,0x22,0x20,0x63,0x79,0x3d,0x22,0x31,
+ 0x35,0x22,0x20,0x72,0x3d,0x22,0x36,0x22,0x2f,0x3e,0xa,0x20,0x20,0x3c,0x63,0x69,
+ 0x72,0x63,0x6c,0x65,0x20,0x66,0x69,0x6c,0x6c,0x3d,0x22,0x23,0x30,0x30,0x61,0x61,
+ 0x30,0x30,0x22,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x3d,0x22,0x6e,0x6f,0x6e,0x65,
+ 0x22,0xa,0x20,0x20,0x20,0x63,0x78,0x3d,0x22,0x34,0x36,0x22,0x20,0x63,0x79,0x3d,
+ 0x22,0x33,0x32,0x22,0x20,0x72,0x3d,0x22,0x36,0x22,0x2f,0x3e,0xa,0x20,0x20,0x3c,
+ 0x63,0x69,0x72,0x63,0x6c,0x65,0x20,0x66,0x69,0x6c,0x6c,0x3d,0x22,0x23,0x66,0x66,
+ 0x66,0x66,0x66,0x66,0x22,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x3d,0x22,0x6e,0x6f,
+ 0x6e,0x65,0x22,0xa,0x20,0x20,0x20,0x63,0x78,0x3d,0x22,0x34,0x36,0x22,0x20,0x63,
+ 0x79,0x3d,0x22,0x34,0x39,0x22,0x20,0x72,0x3d,0x22,0x36,0x22,0x2f,0x3e,0xa,0x3c,
+ 0x2f,0x73,0x76,0x67,0x3e,0xa,
+ // /home/calvin/src/xpdf-4.04/xpdf-qt/fitPageOn.svg
+ 0x0,0x0,0x3,0x4e,
+ 0x3c,
+ 0x3f,0x78,0x6d,0x6c,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x3d,0x22,0x31,0x2e,
+ 0x30,0x22,0x3f,0x3e,0xa,0x3c,0x21,0x44,0x4f,0x43,0x54,0x59,0x50,0x45,0x20,0x73,
+ 0x76,0x67,0x20,0x50,0x55,0x42,0x4c,0x49,0x43,0x20,0x22,0x2d,0x2f,0x2f,0x57,0x33,
+ 0x43,0x2f,0x2f,0x44,0x54,0x44,0x20,0x53,0x56,0x47,0x20,0x31,0x2e,0x31,0x2f,0x2f,
+ 0x45,0x4e,0x22,0x20,0xa,0x20,0x20,0x22,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,
+ 0x77,0x77,0x2e,0x77,0x33,0x2e,0x6f,0x72,0x67,0x2f,0x47,0x72,0x61,0x70,0x68,0x69,
+ 0x63,0x73,0x2f,0x53,0x56,0x47,0x2f,0x31,0x2e,0x31,0x2f,0x44,0x54,0x44,0x2f,0x73,
+ 0x76,0x67,0x31,0x31,0x2e,0x64,0x74,0x64,0x22,0x3e,0xa,0x3c,0x73,0x76,0x67,0x20,
+ 0x77,0x69,0x64,0x74,0x68,0x3d,0x22,0x38,0x30,0x22,0x20,0x68,0x65,0x69,0x67,0x68,
+ 0x74,0x3d,0x22,0x38,0x30,0x22,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x3d,0x22,
+ 0x31,0x2e,0x31,0x22,0xa,0x20,0x78,0x6d,0x6c,0x6e,0x73,0x3d,0x22,0x68,0x74,0x74,
+ 0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x77,0x33,0x2e,0x6f,0x72,0x67,0x2f,0x32,
+ 0x30,0x30,0x30,0x2f,0x73,0x76,0x67,0x22,0x3e,0xa,0x20,0x20,0x3c,0x72,0x65,0x63,
+ 0x74,0x20,0x66,0x69,0x6c,0x6c,0x3d,0x22,0x23,0x64,0x64,0x64,0x64,0x66,0x66,0x22,
+ 0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x3d,0x22,0x23,0x35,0x35,0x35,0x35,0x35,0x35,
+ 0x22,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x2d,0x77,0x69,0x64,0x74,0x68,0x3d,0x22,
+ 0x34,0x22,0xa,0x20,0x20,0x20,0x78,0x3d,0x22,0x31,0x34,0x22,0x20,0x79,0x3d,0x22,
+ 0x36,0x22,0x20,0x77,0x69,0x64,0x74,0x68,0x3d,0x22,0x35,0x36,0x22,0x20,0x68,0x65,
+ 0x69,0x67,0x68,0x74,0x3d,0x22,0x37,0x32,0x22,0x2f,0x3e,0xa,0x20,0x20,0x3c,0x70,
+ 0x6f,0x6c,0x79,0x6c,0x69,0x6e,0x65,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x3d,0x22,
+ 0x23,0x35,0x35,0x35,0x35,0x35,0x35,0x22,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x2d,
+ 0x77,0x69,0x64,0x74,0x68,0x3d,0x22,0x34,0x22,0x20,0x66,0x69,0x6c,0x6c,0x3d,0x22,
+ 0x6e,0x6f,0x6e,0x65,0x22,0xa,0x20,0x20,0x20,0x70,0x6f,0x69,0x6e,0x74,0x73,0x3d,
+ 0x22,0x32,0x32,0x2c,0x34,0x32,0x20,0x20,0x36,0x32,0x2c,0x34,0x32,0x22,0x2f,0x3e,
+ 0xa,0x20,0x20,0x3c,0x70,0x6f,0x6c,0x79,0x6c,0x69,0x6e,0x65,0x20,0x73,0x74,0x72,
+ 0x6f,0x6b,0x65,0x3d,0x22,0x23,0x35,0x35,0x35,0x35,0x35,0x35,0x22,0x20,0x73,0x74,
+ 0x72,0x6f,0x6b,0x65,0x2d,0x77,0x69,0x64,0x74,0x68,0x3d,0x22,0x34,0x22,0x20,0x66,
+ 0x69,0x6c,0x6c,0x3d,0x22,0x6e,0x6f,0x6e,0x65,0x22,0xa,0x20,0x20,0x20,0x70,0x6f,
+ 0x69,0x6e,0x74,0x73,0x3d,0x22,0x33,0x32,0x2c,0x33,0x32,0x20,0x20,0x32,0x32,0x2c,
+ 0x34,0x32,0x20,0x20,0x33,0x32,0x2c,0x35,0x32,0x22,0x2f,0x3e,0xa,0x20,0x20,0x3c,
+ 0x70,0x6f,0x6c,0x79,0x6c,0x69,0x6e,0x65,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x3d,
+ 0x22,0x23,0x35,0x35,0x35,0x35,0x35,0x35,0x22,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,
+ 0x2d,0x77,0x69,0x64,0x74,0x68,0x3d,0x22,0x34,0x22,0x20,0x66,0x69,0x6c,0x6c,0x3d,
+ 0x22,0x6e,0x6f,0x6e,0x65,0x22,0xa,0x20,0x20,0x20,0x70,0x6f,0x69,0x6e,0x74,0x73,
+ 0x3d,0x22,0x35,0x32,0x2c,0x33,0x32,0x20,0x20,0x36,0x32,0x2c,0x34,0x32,0x20,0x20,
+ 0x35,0x32,0x2c,0x35,0x32,0x22,0x2f,0x3e,0xa,0x20,0x20,0x3c,0x70,0x6f,0x6c,0x79,
+ 0x6c,0x69,0x6e,0x65,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x3d,0x22,0x23,0x35,0x35,
+ 0x35,0x35,0x35,0x35,0x22,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x2d,0x77,0x69,0x64,
+ 0x74,0x68,0x3d,0x22,0x34,0x22,0x20,0x66,0x69,0x6c,0x6c,0x3d,0x22,0x6e,0x6f,0x6e,
+ 0x65,0x22,0xa,0x20,0x20,0x20,0x70,0x6f,0x69,0x6e,0x74,0x73,0x3d,0x22,0x34,0x32,
+ 0x2c,0x31,0x34,0x20,0x20,0x34,0x32,0x2c,0x37,0x30,0x22,0x2f,0x3e,0xa,0x20,0x20,
+ 0x3c,0x70,0x6f,0x6c,0x79,0x6c,0x69,0x6e,0x65,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,
+ 0x3d,0x22,0x23,0x35,0x35,0x35,0x35,0x35,0x35,0x22,0x20,0x73,0x74,0x72,0x6f,0x6b,
+ 0x65,0x2d,0x77,0x69,0x64,0x74,0x68,0x3d,0x22,0x34,0x22,0x20,0x66,0x69,0x6c,0x6c,
+ 0x3d,0x22,0x6e,0x6f,0x6e,0x65,0x22,0xa,0x20,0x20,0x20,0x70,0x6f,0x69,0x6e,0x74,
+ 0x73,0x3d,0x22,0x33,0x32,0x2c,0x32,0x34,0x20,0x20,0x34,0x32,0x2c,0x31,0x34,0x20,
+ 0x20,0x35,0x32,0x2c,0x32,0x34,0x22,0x2f,0x3e,0xa,0x20,0x20,0x3c,0x70,0x6f,0x6c,
+ 0x79,0x6c,0x69,0x6e,0x65,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x3d,0x22,0x23,0x35,
+ 0x35,0x35,0x35,0x35,0x35,0x22,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x2d,0x77,0x69,
+ 0x64,0x74,0x68,0x3d,0x22,0x34,0x22,0x20,0x66,0x69,0x6c,0x6c,0x3d,0x22,0x6e,0x6f,
+ 0x6e,0x65,0x22,0xa,0x20,0x20,0x20,0x70,0x6f,0x69,0x6e,0x74,0x73,0x3d,0x22,0x33,
+ 0x32,0x2c,0x36,0x30,0x20,0x20,0x34,0x32,0x2c,0x37,0x30,0x20,0x20,0x35,0x32,0x2c,
+ 0x36,0x30,0x22,0x2f,0x3e,0xa,0x3c,0x2f,0x73,0x76,0x67,0x3e,0xa,
+ // /home/calvin/src/xpdf-4.04/xpdf-qt/indicator-icon5.svg
+ 0x0,0x0,0x1,0x66,
+ 0x3c,
+ 0x3f,0x78,0x6d,0x6c,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x3d,0x22,0x31,0x2e,
+ 0x30,0x22,0x3f,0x3e,0xa,0x3c,0x21,0x44,0x4f,0x43,0x54,0x59,0x50,0x45,0x20,0x73,
+ 0x76,0x67,0x20,0x50,0x55,0x42,0x4c,0x49,0x43,0x20,0x22,0x2d,0x2f,0x2f,0x57,0x33,
+ 0x43,0x2f,0x2f,0x44,0x54,0x44,0x20,0x53,0x56,0x47,0x20,0x31,0x2e,0x31,0x2f,0x2f,
+ 0x45,0x4e,0x22,0xa,0x20,0x22,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,
+ 0x2e,0x77,0x33,0x2e,0x6f,0x72,0x67,0x2f,0x47,0x72,0x61,0x70,0x68,0x69,0x63,0x73,
+ 0x2f,0x53,0x56,0x47,0x2f,0x31,0x2e,0x31,0x2f,0x44,0x54,0x44,0x2f,0x73,0x76,0x67,
+ 0x31,0x31,0x2e,0x64,0x74,0x64,0x22,0x3e,0xa,0x3c,0x73,0x76,0x67,0x20,0x77,0x69,
+ 0x64,0x74,0x68,0x3d,0x22,0x38,0x30,0x22,0x20,0x68,0x65,0x69,0x67,0x68,0x74,0x3d,
+ 0x22,0x38,0x30,0x22,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x3d,0x22,0x31,0x2e,
+ 0x31,0x22,0xa,0x20,0x78,0x6d,0x6c,0x6e,0x73,0x3d,0x22,0x68,0x74,0x74,0x70,0x3a,
+ 0x2f,0x2f,0x77,0x77,0x77,0x2e,0x77,0x33,0x2e,0x6f,0x72,0x67,0x2f,0x32,0x30,0x30,
+ 0x30,0x2f,0x73,0x76,0x67,0x22,0x3e,0xa,0x20,0x20,0x3c,0x63,0x69,0x72,0x63,0x6c,
+ 0x65,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x3d,0x22,0x23,0x35,0x35,0x35,0x35,0x35,
+ 0x35,0x22,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x2d,0x77,0x69,0x64,0x74,0x68,0x3d,
+ 0x22,0x36,0x22,0x20,0x66,0x69,0x6c,0x6c,0x3d,0x22,0x6e,0x6f,0x6e,0x65,0x22,0xa,
+ 0x20,0x20,0x20,0x63,0x78,0x3d,0x22,0x34,0x30,0x22,0x20,0x63,0x79,0x3d,0x22,0x34,
+ 0x30,0x22,0x20,0x72,0x3d,0x22,0x33,0x30,0x22,0x2f,0x3e,0xa,0x20,0x20,0x3c,0x63,
+ 0x69,0x72,0x63,0x6c,0x65,0x20,0x66,0x69,0x6c,0x6c,0x3d,0x22,0x23,0x35,0x35,0x35,
+ 0x35,0x35,0x35,0x22,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x3d,0x22,0x6e,0x6f,0x6e,
+ 0x65,0x22,0xa,0x20,0x20,0x20,0x63,0x78,0x3d,0x22,0x32,0x39,0x22,0x20,0x63,0x79,
+ 0x3d,0x22,0x35,0x31,0x22,0x20,0x72,0x3d,0x22,0x38,0x22,0x2f,0x3e,0xa,0x3c,0x2f,
+ 0x73,0x76,0x67,0x3e,0xa,
+ // /home/calvin/src/xpdf-4.04/xpdf-qt/indicator-icon6.svg
+ 0x0,0x0,0x1,0x66,
+ 0x3c,
+ 0x3f,0x78,0x6d,0x6c,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x3d,0x22,0x31,0x2e,
+ 0x30,0x22,0x3f,0x3e,0xa,0x3c,0x21,0x44,0x4f,0x43,0x54,0x59,0x50,0x45,0x20,0x73,
+ 0x76,0x67,0x20,0x50,0x55,0x42,0x4c,0x49,0x43,0x20,0x22,0x2d,0x2f,0x2f,0x57,0x33,
+ 0x43,0x2f,0x2f,0x44,0x54,0x44,0x20,0x53,0x56,0x47,0x20,0x31,0x2e,0x31,0x2f,0x2f,
+ 0x45,0x4e,0x22,0xa,0x20,0x22,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,
+ 0x2e,0x77,0x33,0x2e,0x6f,0x72,0x67,0x2f,0x47,0x72,0x61,0x70,0x68,0x69,0x63,0x73,
+ 0x2f,0x53,0x56,0x47,0x2f,0x31,0x2e,0x31,0x2f,0x44,0x54,0x44,0x2f,0x73,0x76,0x67,
+ 0x31,0x31,0x2e,0x64,0x74,0x64,0x22,0x3e,0xa,0x3c,0x73,0x76,0x67,0x20,0x77,0x69,
+ 0x64,0x74,0x68,0x3d,0x22,0x38,0x30,0x22,0x20,0x68,0x65,0x69,0x67,0x68,0x74,0x3d,
+ 0x22,0x38,0x30,0x22,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x3d,0x22,0x31,0x2e,
+ 0x31,0x22,0xa,0x20,0x78,0x6d,0x6c,0x6e,0x73,0x3d,0x22,0x68,0x74,0x74,0x70,0x3a,
+ 0x2f,0x2f,0x77,0x77,0x77,0x2e,0x77,0x33,0x2e,0x6f,0x72,0x67,0x2f,0x32,0x30,0x30,
+ 0x30,0x2f,0x73,0x76,0x67,0x22,0x3e,0xa,0x20,0x20,0x3c,0x63,0x69,0x72,0x63,0x6c,
+ 0x65,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x3d,0x22,0x23,0x35,0x35,0x35,0x35,0x35,
+ 0x35,0x22,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x2d,0x77,0x69,0x64,0x74,0x68,0x3d,
+ 0x22,0x36,0x22,0x20,0x66,0x69,0x6c,0x6c,0x3d,0x22,0x6e,0x6f,0x6e,0x65,0x22,0xa,
+ 0x20,0x20,0x20,0x63,0x78,0x3d,0x22,0x34,0x30,0x22,0x20,0x63,0x79,0x3d,0x22,0x34,
+ 0x30,0x22,0x20,0x72,0x3d,0x22,0x33,0x30,0x22,0x2f,0x3e,0xa,0x20,0x20,0x3c,0x63,
+ 0x69,0x72,0x63,0x6c,0x65,0x20,0x66,0x69,0x6c,0x6c,0x3d,0x22,0x23,0x35,0x35,0x35,
+ 0x35,0x35,0x35,0x22,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x3d,0x22,0x6e,0x6f,0x6e,
+ 0x65,0x22,0xa,0x20,0x20,0x20,0x63,0x78,0x3d,0x22,0x32,0x34,0x22,0x20,0x63,0x79,
+ 0x3d,0x22,0x34,0x30,0x22,0x20,0x72,0x3d,0x22,0x38,0x22,0x2f,0x3e,0xa,0x3c,0x2f,
+ 0x73,0x76,0x67,0x3e,0xa,
+ // /home/calvin/src/xpdf-4.04/xpdf-qt/indicator-icon7.svg
+ 0x0,0x0,0x1,0x66,
+ 0x3c,
+ 0x3f,0x78,0x6d,0x6c,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x3d,0x22,0x31,0x2e,
+ 0x30,0x22,0x3f,0x3e,0xa,0x3c,0x21,0x44,0x4f,0x43,0x54,0x59,0x50,0x45,0x20,0x73,
+ 0x76,0x67,0x20,0x50,0x55,0x42,0x4c,0x49,0x43,0x20,0x22,0x2d,0x2f,0x2f,0x57,0x33,
+ 0x43,0x2f,0x2f,0x44,0x54,0x44,0x20,0x53,0x56,0x47,0x20,0x31,0x2e,0x31,0x2f,0x2f,
+ 0x45,0x4e,0x22,0xa,0x20,0x22,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,
+ 0x2e,0x77,0x33,0x2e,0x6f,0x72,0x67,0x2f,0x47,0x72,0x61,0x70,0x68,0x69,0x63,0x73,
+ 0x2f,0x53,0x56,0x47,0x2f,0x31,0x2e,0x31,0x2f,0x44,0x54,0x44,0x2f,0x73,0x76,0x67,
+ 0x31,0x31,0x2e,0x64,0x74,0x64,0x22,0x3e,0xa,0x3c,0x73,0x76,0x67,0x20,0x77,0x69,
+ 0x64,0x74,0x68,0x3d,0x22,0x38,0x30,0x22,0x20,0x68,0x65,0x69,0x67,0x68,0x74,0x3d,
+ 0x22,0x38,0x30,0x22,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x3d,0x22,0x31,0x2e,
+ 0x31,0x22,0xa,0x20,0x78,0x6d,0x6c,0x6e,0x73,0x3d,0x22,0x68,0x74,0x74,0x70,0x3a,
+ 0x2f,0x2f,0x77,0x77,0x77,0x2e,0x77,0x33,0x2e,0x6f,0x72,0x67,0x2f,0x32,0x30,0x30,
+ 0x30,0x2f,0x73,0x76,0x67,0x22,0x3e,0xa,0x20,0x20,0x3c,0x63,0x69,0x72,0x63,0x6c,
+ 0x65,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x3d,0x22,0x23,0x35,0x35,0x35,0x35,0x35,
+ 0x35,0x22,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x2d,0x77,0x69,0x64,0x74,0x68,0x3d,
+ 0x22,0x36,0x22,0x20,0x66,0x69,0x6c,0x6c,0x3d,0x22,0x6e,0x6f,0x6e,0x65,0x22,0xa,
+ 0x20,0x20,0x20,0x63,0x78,0x3d,0x22,0x34,0x30,0x22,0x20,0x63,0x79,0x3d,0x22,0x34,
+ 0x30,0x22,0x20,0x72,0x3d,0x22,0x33,0x30,0x22,0x2f,0x3e,0xa,0x20,0x20,0x3c,0x63,
+ 0x69,0x72,0x63,0x6c,0x65,0x20,0x66,0x69,0x6c,0x6c,0x3d,0x22,0x23,0x35,0x35,0x35,
+ 0x35,0x35,0x35,0x22,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x3d,0x22,0x6e,0x6f,0x6e,
+ 0x65,0x22,0xa,0x20,0x20,0x20,0x63,0x78,0x3d,0x22,0x32,0x39,0x22,0x20,0x63,0x79,
+ 0x3d,0x22,0x32,0x39,0x22,0x20,0x72,0x3d,0x22,0x38,0x22,0x2f,0x3e,0xa,0x3c,0x2f,
+ 0x73,0x76,0x67,0x3e,0xa,
+ // /home/calvin/src/xpdf-4.04/xpdf-qt/fitWidthOn.svg
+ 0x0,0x0,0x2,0x41,
+ 0x3c,
+ 0x3f,0x78,0x6d,0x6c,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x3d,0x22,0x31,0x2e,
+ 0x30,0x22,0x3f,0x3e,0xa,0x3c,0x21,0x44,0x4f,0x43,0x54,0x59,0x50,0x45,0x20,0x73,
+ 0x76,0x67,0x20,0x50,0x55,0x42,0x4c,0x49,0x43,0x20,0x22,0x2d,0x2f,0x2f,0x57,0x33,
+ 0x43,0x2f,0x2f,0x44,0x54,0x44,0x20,0x53,0x56,0x47,0x20,0x31,0x2e,0x31,0x2f,0x2f,
+ 0x45,0x4e,0x22,0x20,0xa,0x20,0x20,0x22,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,
+ 0x77,0x77,0x2e,0x77,0x33,0x2e,0x6f,0x72,0x67,0x2f,0x47,0x72,0x61,0x70,0x68,0x69,
+ 0x63,0x73,0x2f,0x53,0x56,0x47,0x2f,0x31,0x2e,0x31,0x2f,0x44,0x54,0x44,0x2f,0x73,
+ 0x76,0x67,0x31,0x31,0x2e,0x64,0x74,0x64,0x22,0x3e,0xa,0x3c,0x73,0x76,0x67,0x20,
+ 0x77,0x69,0x64,0x74,0x68,0x3d,0x22,0x38,0x30,0x22,0x20,0x68,0x65,0x69,0x67,0x68,
+ 0x74,0x3d,0x22,0x38,0x30,0x22,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x3d,0x22,
+ 0x31,0x2e,0x31,0x22,0xa,0x20,0x78,0x6d,0x6c,0x6e,0x73,0x3d,0x22,0x68,0x74,0x74,
+ 0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x77,0x33,0x2e,0x6f,0x72,0x67,0x2f,0x32,
+ 0x30,0x30,0x30,0x2f,0x73,0x76,0x67,0x22,0x3e,0xa,0x20,0x20,0x3c,0x72,0x65,0x63,
+ 0x74,0x20,0x66,0x69,0x6c,0x6c,0x3d,0x22,0x23,0x64,0x64,0x64,0x64,0x66,0x66,0x22,
+ 0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x3d,0x22,0x23,0x35,0x35,0x35,0x35,0x35,0x35,
+ 0x22,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x2d,0x77,0x69,0x64,0x74,0x68,0x3d,0x22,
+ 0x34,0x22,0xa,0x20,0x20,0x20,0x78,0x3d,0x22,0x31,0x34,0x22,0x20,0x79,0x3d,0x22,
+ 0x36,0x22,0x20,0x77,0x69,0x64,0x74,0x68,0x3d,0x22,0x35,0x36,0x22,0x20,0x68,0x65,
+ 0x69,0x67,0x68,0x74,0x3d,0x22,0x37,0x32,0x22,0x2f,0x3e,0xa,0x20,0x20,0x3c,0x70,
+ 0x6f,0x6c,0x79,0x6c,0x69,0x6e,0x65,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x3d,0x22,
+ 0x23,0x35,0x35,0x35,0x35,0x35,0x35,0x22,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x2d,
+ 0x77,0x69,0x64,0x74,0x68,0x3d,0x22,0x34,0x22,0x20,0x66,0x69,0x6c,0x6c,0x3d,0x22,
+ 0x6e,0x6f,0x6e,0x65,0x22,0xa,0x20,0x20,0x20,0x70,0x6f,0x69,0x6e,0x74,0x73,0x3d,
+ 0x22,0x32,0x32,0x2c,0x34,0x32,0x20,0x20,0x36,0x32,0x2c,0x34,0x32,0x22,0x2f,0x3e,
+ 0xa,0x20,0x20,0x3c,0x70,0x6f,0x6c,0x79,0x6c,0x69,0x6e,0x65,0x20,0x73,0x74,0x72,
+ 0x6f,0x6b,0x65,0x3d,0x22,0x23,0x35,0x35,0x35,0x35,0x35,0x35,0x22,0x20,0x73,0x74,
+ 0x72,0x6f,0x6b,0x65,0x2d,0x77,0x69,0x64,0x74,0x68,0x3d,0x22,0x34,0x22,0x20,0x66,
+ 0x69,0x6c,0x6c,0x3d,0x22,0x6e,0x6f,0x6e,0x65,0x22,0xa,0x20,0x20,0x20,0x70,0x6f,
+ 0x69,0x6e,0x74,0x73,0x3d,0x22,0x33,0x32,0x2c,0x33,0x32,0x20,0x20,0x32,0x32,0x2c,
+ 0x34,0x32,0x20,0x20,0x33,0x32,0x2c,0x35,0x32,0x22,0x2f,0x3e,0xa,0x20,0x20,0x3c,
+ 0x70,0x6f,0x6c,0x79,0x6c,0x69,0x6e,0x65,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x3d,
+ 0x22,0x23,0x35,0x35,0x35,0x35,0x35,0x35,0x22,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,
+ 0x2d,0x77,0x69,0x64,0x74,0x68,0x3d,0x22,0x34,0x22,0x20,0x66,0x69,0x6c,0x6c,0x3d,
+ 0x22,0x6e,0x6f,0x6e,0x65,0x22,0xa,0x20,0x20,0x20,0x70,0x6f,0x69,0x6e,0x74,0x73,
+ 0x3d,0x22,0x35,0x32,0x2c,0x33,0x32,0x20,0x20,0x36,0x32,0x2c,0x34,0x32,0x20,0x20,
+ 0x35,0x32,0x2c,0x35,0x32,0x22,0x2f,0x3e,0xa,0x3c,0x2f,0x73,0x76,0x67,0x3e,0xa,
+
+ // /home/calvin/src/xpdf-4.04/xpdf-qt/toggleSidebar.svg
+ 0x0,0x0,0x2,0x39,
+ 0x3c,
+ 0x3f,0x78,0x6d,0x6c,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x3d,0x22,0x31,0x2e,
+ 0x30,0x22,0x3f,0x3e,0xa,0x3c,0x21,0x44,0x4f,0x43,0x54,0x59,0x50,0x45,0x20,0x73,
+ 0x76,0x67,0x20,0x50,0x55,0x42,0x4c,0x49,0x43,0x20,0x22,0x2d,0x2f,0x2f,0x57,0x33,
+ 0x43,0x2f,0x2f,0x44,0x54,0x44,0x20,0x53,0x56,0x47,0x20,0x31,0x2e,0x31,0x2f,0x2f,
+ 0x45,0x4e,0x22,0x20,0xa,0x20,0x20,0x22,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,
+ 0x77,0x77,0x2e,0x77,0x33,0x2e,0x6f,0x72,0x67,0x2f,0x47,0x72,0x61,0x70,0x68,0x69,
+ 0x63,0x73,0x2f,0x53,0x56,0x47,0x2f,0x31,0x2e,0x31,0x2f,0x44,0x54,0x44,0x2f,0x73,
+ 0x76,0x67,0x31,0x31,0x2e,0x64,0x74,0x64,0x22,0x3e,0xa,0x3c,0x73,0x76,0x67,0x20,
+ 0x77,0x69,0x64,0x74,0x68,0x3d,0x22,0x38,0x30,0x22,0x20,0x68,0x65,0x69,0x67,0x68,
+ 0x74,0x3d,0x22,0x38,0x30,0x22,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x3d,0x22,
+ 0x31,0x2e,0x31,0x22,0xa,0x20,0x78,0x6d,0x6c,0x6e,0x73,0x3d,0x22,0x68,0x74,0x74,
+ 0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x77,0x33,0x2e,0x6f,0x72,0x67,0x2f,0x32,
+ 0x30,0x30,0x30,0x2f,0x73,0x76,0x67,0x22,0x3e,0xa,0x20,0x20,0x3c,0x72,0x65,0x63,
+ 0x74,0x20,0x66,0x69,0x6c,0x6c,0x3d,0x22,0x6e,0x6f,0x6e,0x65,0x22,0x20,0x73,0x74,
+ 0x72,0x6f,0x6b,0x65,0x3d,0x22,0x23,0x35,0x35,0x35,0x35,0x35,0x35,0x22,0x20,0x73,
+ 0x74,0x72,0x6f,0x6b,0x65,0x2d,0x77,0x69,0x64,0x74,0x68,0x3d,0x22,0x34,0x22,0xa,
+ 0x20,0x20,0x20,0x78,0x3d,0x22,0x34,0x22,0x20,0x79,0x3d,0x22,0x34,0x22,0x20,0x77,
+ 0x69,0x64,0x74,0x68,0x3d,0x22,0x37,0x32,0x22,0x20,0x68,0x65,0x69,0x67,0x68,0x74,
+ 0x3d,0x22,0x37,0x32,0x22,0x2f,0x3e,0xa,0x20,0x20,0x3c,0x72,0x65,0x63,0x74,0x20,
+ 0x66,0x69,0x6c,0x6c,0x3d,0x22,0x23,0x64,0x64,0x64,0x64,0x66,0x66,0x22,0x20,0x73,
+ 0x74,0x72,0x6f,0x6b,0x65,0x3d,0x22,0x23,0x35,0x35,0x35,0x35,0x35,0x35,0x22,0x20,
+ 0x73,0x74,0x72,0x6f,0x6b,0x65,0x2d,0x77,0x69,0x64,0x74,0x68,0x3d,0x22,0x34,0x22,
+ 0xa,0x20,0x20,0x20,0x78,0x3d,0x22,0x34,0x22,0x20,0x79,0x3d,0x22,0x34,0x22,0x20,
+ 0x77,0x69,0x64,0x74,0x68,0x3d,0x22,0x32,0x30,0x22,0x20,0x68,0x65,0x69,0x67,0x68,
+ 0x74,0x3d,0x22,0x37,0x32,0x22,0x2f,0x3e,0xa,0x3c,0x2f,0x73,0x76,0x67,0x3e,0xa,
+ 0x3c,0x21,0x2d,0x2d,0xa,0x3c,0x73,0x76,0x67,0x20,0x77,0x69,0x64,0x74,0x68,0x3d,
+ 0x22,0x34,0x38,0x22,0x20,0x68,0x65,0x69,0x67,0x68,0x74,0x3d,0x22,0x38,0x30,0x22,
+ 0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x3d,0x22,0x31,0x2e,0x31,0x22,0xa,0x20,
+ 0x78,0x6d,0x6c,0x6e,0x73,0x3d,0x22,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,
+ 0x77,0x2e,0x77,0x33,0x2e,0x6f,0x72,0x67,0x2f,0x32,0x30,0x30,0x30,0x2f,0x73,0x76,
+ 0x67,0x22,0x3e,0xa,0x20,0x20,0x3c,0x70,0x6f,0x6c,0x79,0x6c,0x69,0x6e,0x65,0x20,
+ 0x66,0x69,0x6c,0x6c,0x3d,0x22,0x23,0x35,0x35,0x35,0x35,0x35,0x35,0x22,0x20,0x73,
+ 0x74,0x72,0x6f,0x6b,0x65,0x3d,0x22,0x6e,0x6f,0x6e,0x65,0x22,0xa,0x20,0x20,0x20,
+ 0x70,0x6f,0x69,0x6e,0x74,0x73,0x3d,0x22,0x33,0x32,0x2c,0x31,0x36,0x20,0x31,0x32,
+ 0x2c,0x34,0x30,0x20,0x33,0x32,0x2c,0x36,0x34,0x22,0x2f,0x3e,0xa,0x3c,0x2f,0x73,
+ 0x76,0x67,0x3e,0xa,0x2d,0x2d,0x3e,0xa,
+ // /home/calvin/src/xpdf-4.04/xpdf-qt/selectModeBlock.svg
+ 0x0,0x0,0x1,0x32,
+ 0x3c,
+ 0x3f,0x78,0x6d,0x6c,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x3d,0x22,0x31,0x2e,
+ 0x30,0x22,0x3f,0x3e,0xa,0x3c,0x21,0x44,0x4f,0x43,0x54,0x59,0x50,0x45,0x20,0x73,
+ 0x76,0x67,0x20,0x50,0x55,0x42,0x4c,0x49,0x43,0x20,0x22,0x2d,0x2f,0x2f,0x57,0x33,
+ 0x43,0x2f,0x2f,0x44,0x54,0x44,0x20,0x53,0x56,0x47,0x20,0x31,0x2e,0x31,0x2f,0x2f,
+ 0x45,0x4e,0x22,0x20,0xa,0x20,0x20,0x22,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,
+ 0x77,0x77,0x2e,0x77,0x33,0x2e,0x6f,0x72,0x67,0x2f,0x47,0x72,0x61,0x70,0x68,0x69,
+ 0x63,0x73,0x2f,0x53,0x56,0x47,0x2f,0x31,0x2e,0x31,0x2f,0x44,0x54,0x44,0x2f,0x73,
+ 0x76,0x67,0x31,0x31,0x2e,0x64,0x74,0x64,0x22,0x3e,0xa,0x3c,0x73,0x76,0x67,0x20,
+ 0x77,0x69,0x64,0x74,0x68,0x3d,0x22,0x38,0x30,0x22,0x20,0x68,0x65,0x69,0x67,0x68,
+ 0x74,0x3d,0x22,0x38,0x30,0x22,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x3d,0x22,
+ 0x31,0x2e,0x31,0x22,0xa,0x20,0x78,0x6d,0x6c,0x6e,0x73,0x3d,0x22,0x68,0x74,0x74,
+ 0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x77,0x33,0x2e,0x6f,0x72,0x67,0x2f,0x32,
+ 0x30,0x30,0x30,0x2f,0x73,0x76,0x67,0x22,0x3e,0xa,0x20,0x20,0x3c,0x70,0x6f,0x6c,
+ 0x79,0x6c,0x69,0x6e,0x65,0x20,0x66,0x69,0x6c,0x6c,0x3d,0x22,0x23,0x35,0x35,0x35,
+ 0x35,0x35,0x35,0x22,0x20,0x73,0x74,0x72,0x6f,0x6b,0x65,0x3d,0x22,0x6e,0x6f,0x6e,
+ 0x65,0x22,0xa,0x20,0x20,0x20,0x70,0x6f,0x69,0x6e,0x74,0x73,0x3d,0x22,0x32,0x34,
+ 0x2c,0x34,0x38,0x20,0x32,0x34,0x2c,0x38,0x20,0x35,0x36,0x2c,0x33,0x32,0x20,0x34,
+ 0x34,0x2c,0x33,0x38,0x20,0x35,0x38,0x2c,0x36,0x36,0x20,0x35,0x30,0x2c,0x37,0x30,
+ 0x20,0x33,0x36,0x2c,0x34,0x32,0x22,0x2f,0x3e,0xa,0x3c,0x2f,0x73,0x76,0x67,0x3e,
+ 0xa,
+
+};
+
+static const unsigned char qt_resource_name[] = {
+ // fitPage-button
+ 0x0,0xe,
+ 0x2,0xb0,0x5a,0x9e,
+ 0x0,0x66,
+ 0x0,0x69,0x0,0x74,0x0,0x50,0x0,0x61,0x0,0x67,0x0,0x65,0x0,0x2d,0x0,0x62,0x0,0x75,0x0,0x74,0x0,0x74,0x0,0x6f,0x0,0x6e,
+ // back-button
+ 0x0,0xb,
+ 0x3,0x4c,0x48,0x9e,
+ 0x0,0x62,
+ 0x0,0x61,0x0,0x63,0x0,0x6b,0x0,0x2d,0x0,0x62,0x0,0x75,0x0,0x74,0x0,0x74,0x0,0x6f,0x0,0x6e,
+ // selectModeLinear-button
+ 0x0,0x17,
+ 0xf,0x1a,0x4b,0xbe,
+ 0x0,0x73,
+ 0x0,0x65,0x0,0x6c,0x0,0x65,0x0,0x63,0x0,0x74,0x0,0x4d,0x0,0x6f,0x0,0x64,0x0,0x65,0x0,0x4c,0x0,0x69,0x0,0x6e,0x0,0x65,0x0,0x61,0x0,0x72,0x0,0x2d,
+ 0x0,0x62,0x0,0x75,0x0,0x74,0x0,0x74,0x0,0x6f,0x0,0x6e,
+ // findPrevious-button
+ 0x0,0x13,
+ 0xe,0xe,0x3d,0x5e,
+ 0x0,0x66,
+ 0x0,0x69,0x0,0x6e,0x0,0x64,0x0,0x50,0x0,0x72,0x0,0x65,0x0,0x76,0x0,0x69,0x0,0x6f,0x0,0x75,0x0,0x73,0x0,0x2d,0x0,0x62,0x0,0x75,0x0,0x74,0x0,0x74,
+ 0x0,0x6f,0x0,0x6e,
+ // zoomIn-button
+ 0x0,0xd,
+ 0x1,0x50,0xf9,0x7e,
+ 0x0,0x7a,
+ 0x0,0x6f,0x0,0x6f,0x0,0x6d,0x0,0x49,0x0,0x6e,0x0,0x2d,0x0,0x62,0x0,0x75,0x0,0x74,0x0,0x74,0x0,0x6f,0x0,0x6e,
+ // forward-button
+ 0x0,0xe,
+ 0xe,0xa7,0xb0,0xfe,
+ 0x0,0x66,
+ 0x0,0x6f,0x0,0x72,0x0,0x77,0x0,0x61,0x0,0x72,0x0,0x64,0x0,0x2d,0x0,0x62,0x0,0x75,0x0,0x74,0x0,0x74,0x0,0x6f,0x0,0x6e,
+ // fitWidth-button
+ 0x0,0xf,
+ 0x0,0x22,0x7a,0x1e,
+ 0x0,0x66,
+ 0x0,0x69,0x0,0x74,0x0,0x57,0x0,0x69,0x0,0x64,0x0,0x74,0x0,0x68,0x0,0x2d,0x0,0x62,0x0,0x75,0x0,0x74,0x0,0x74,0x0,0x6f,0x0,0x6e,
+ // indicator-icon-err0
+ 0x0,0x13,
+ 0x5,0xf2,0x53,0xb0,
+ 0x0,0x69,
+ 0x0,0x6e,0x0,0x64,0x0,0x69,0x0,0x63,0x0,0x61,0x0,0x74,0x0,0x6f,0x0,0x72,0x0,0x2d,0x0,0x69,0x0,0x63,0x0,0x6f,0x0,0x6e,0x0,0x2d,0x0,0x65,0x0,0x72,
+ 0x0,0x72,0x0,0x30,
+ // indicator-icon-err1
+ 0x0,0x13,
+ 0x5,0xf2,0x53,0xb1,
+ 0x0,0x69,
+ 0x0,0x6e,0x0,0x64,0x0,0x69,0x0,0x63,0x0,0x61,0x0,0x74,0x0,0x6f,0x0,0x72,0x0,0x2d,0x0,0x69,0x0,0x63,0x0,0x6f,0x0,0x6e,0x0,0x2d,0x0,0x65,0x0,0x72,
+ 0x0,0x72,0x0,0x31,
+ // indicator-icon-err2
+ 0x0,0x13,
+ 0x5,0xf2,0x53,0xb2,
+ 0x0,0x69,
+ 0x0,0x6e,0x0,0x64,0x0,0x69,0x0,0x63,0x0,0x61,0x0,0x74,0x0,0x6f,0x0,0x72,0x0,0x2d,0x0,0x69,0x0,0x63,0x0,0x6f,0x0,0x6e,0x0,0x2d,0x0,0x65,0x0,0x72,
+ 0x0,0x72,0x0,0x32,
+ // indicator-icon-err3
+ 0x0,0x13,
+ 0x5,0xf2,0x53,0xb3,
+ 0x0,0x69,
+ 0x0,0x6e,0x0,0x64,0x0,0x69,0x0,0x63,0x0,0x61,0x0,0x74,0x0,0x6f,0x0,0x72,0x0,0x2d,0x0,0x69,0x0,0x63,0x0,0x6f,0x0,0x6e,0x0,0x2d,0x0,0x65,0x0,0x72,
+ 0x0,0x72,0x0,0x33,
+ // indicator-icon-err4
+ 0x0,0x13,
+ 0x5,0xf2,0x53,0xb4,
+ 0x0,0x69,
+ 0x0,0x6e,0x0,0x64,0x0,0x69,0x0,0x63,0x0,0x61,0x0,0x74,0x0,0x6f,0x0,0x72,0x0,0x2d,0x0,0x69,0x0,0x63,0x0,0x6f,0x0,0x6e,0x0,0x2d,0x0,0x65,0x0,0x72,
+ 0x0,0x72,0x0,0x34,
+ // indicator-icon-err5
+ 0x0,0x13,
+ 0x5,0xf2,0x53,0xb5,
+ 0x0,0x69,
+ 0x0,0x6e,0x0,0x64,0x0,0x69,0x0,0x63,0x0,0x61,0x0,0x74,0x0,0x6f,0x0,0x72,0x0,0x2d,0x0,0x69,0x0,0x63,0x0,0x6f,0x0,0x6e,0x0,0x2d,0x0,0x65,0x0,0x72,
+ 0x0,0x72,0x0,0x35,
+ // indicator-icon-err6
+ 0x0,0x13,
+ 0x5,0xf2,0x53,0xb6,
+ 0x0,0x69,
+ 0x0,0x6e,0x0,0x64,0x0,0x69,0x0,0x63,0x0,0x61,0x0,0x74,0x0,0x6f,0x0,0x72,0x0,0x2d,0x0,0x69,0x0,0x63,0x0,0x6f,0x0,0x6e,0x0,0x2d,0x0,0x65,0x0,0x72,
+ 0x0,0x72,0x0,0x36,
+ // indicator-icon0
+ 0x0,0xf,
+ 0x0,0xcd,0x75,0xf0,
+ 0x0,0x69,
+ 0x0,0x6e,0x0,0x64,0x0,0x69,0x0,0x63,0x0,0x61,0x0,0x74,0x0,0x6f,0x0,0x72,0x0,0x2d,0x0,0x69,0x0,0x63,0x0,0x6f,0x0,0x6e,0x0,0x30,
+ // indicator-icon-err7
+ 0x0,0x13,
+ 0x5,0xf2,0x53,0xb7,
+ 0x0,0x69,
+ 0x0,0x6e,0x0,0x64,0x0,0x69,0x0,0x63,0x0,0x61,0x0,0x74,0x0,0x6f,0x0,0x72,0x0,0x2d,0x0,0x69,0x0,0x63,0x0,0x6f,0x0,0x6e,0x0,0x2d,0x0,0x65,0x0,0x72,
+ 0x0,0x72,0x0,0x37,
+ // findSettings-button
+ 0x0,0x13,
+ 0x0,0xce,0x42,0x5e,
+ 0x0,0x66,
+ 0x0,0x69,0x0,0x6e,0x0,0x64,0x0,0x53,0x0,0x65,0x0,0x74,0x0,0x74,0x0,0x69,0x0,0x6e,0x0,0x67,0x0,0x73,0x0,0x2d,0x0,0x62,0x0,0x75,0x0,0x74,0x0,0x74,
+ 0x0,0x6f,0x0,0x6e,
+ // indicator-icon1
+ 0x0,0xf,
+ 0x0,0xcd,0x75,0xf1,
+ 0x0,0x69,
+ 0x0,0x6e,0x0,0x64,0x0,0x69,0x0,0x63,0x0,0x61,0x0,0x74,0x0,0x6f,0x0,0x72,0x0,0x2d,0x0,0x69,0x0,0x63,0x0,0x6f,0x0,0x6e,0x0,0x31,
+ // zoomOut-button
+ 0x0,0xe,
+ 0xf,0x58,0x43,0xfe,
+ 0x0,0x7a,
+ 0x0,0x6f,0x0,0x6f,0x0,0x6d,0x0,0x4f,0x0,0x75,0x0,0x74,0x0,0x2d,0x0,0x62,0x0,0x75,0x0,0x74,0x0,0x74,0x0,0x6f,0x0,0x6e,
+ // indicator-icon2
+ 0x0,0xf,
+ 0x0,0xcd,0x75,0xf2,
+ 0x0,0x69,
+ 0x0,0x6e,0x0,0x64,0x0,0x69,0x0,0x63,0x0,0x61,0x0,0x74,0x0,0x6f,0x0,0x72,0x0,0x2d,0x0,0x69,0x0,0x63,0x0,0x6f,0x0,0x6e,0x0,0x32,
+ // indicator-icon3
+ 0x0,0xf,
+ 0x0,0xcd,0x75,0xf3,
+ 0x0,0x69,
+ 0x0,0x6e,0x0,0x64,0x0,0x69,0x0,0x63,0x0,0x61,0x0,0x74,0x0,0x6f,0x0,0x72,0x0,0x2d,0x0,0x69,0x0,0x63,0x0,0x6f,0x0,0x6e,0x0,0x33,
+ // indicator-icon4
+ 0x0,0xf,
+ 0x0,0xcd,0x75,0xf4,
+ 0x0,0x69,
+ 0x0,0x6e,0x0,0x64,0x0,0x69,0x0,0x63,0x0,0x61,0x0,0x74,0x0,0x6f,0x0,0x72,0x0,0x2d,0x0,0x69,0x0,0x63,0x0,0x6f,0x0,0x6e,0x0,0x34,
+ // findNext-button
+ 0x0,0xf,
+ 0xa,0xb4,0x91,0xbe,
+ 0x0,0x66,
+ 0x0,0x69,0x0,0x6e,0x0,0x64,0x0,0x4e,0x0,0x65,0x0,0x78,0x0,0x74,0x0,0x2d,0x0,0x62,0x0,0x75,0x0,0x74,0x0,0x74,0x0,0x6f,0x0,0x6e,
+ // xpdf-icon
+ 0x0,0x9,
+ 0xa,0x93,0x8,0x9e,
+ 0x0,0x78,
+ 0x0,0x70,0x0,0x64,0x0,0x66,0x0,0x2d,0x0,0x69,0x0,0x63,0x0,0x6f,0x0,0x6e,
+ // fitPageOn-button
+ 0x0,0x10,
+ 0xf,0x7c,0x35,0x3e,
+ 0x0,0x66,
+ 0x0,0x69,0x0,0x74,0x0,0x50,0x0,0x61,0x0,0x67,0x0,0x65,0x0,0x4f,0x0,0x6e,0x0,0x2d,0x0,0x62,0x0,0x75,0x0,0x74,0x0,0x74,0x0,0x6f,0x0,0x6e,
+ // indicator-icon5
+ 0x0,0xf,
+ 0x0,0xcd,0x75,0xf5,
+ 0x0,0x69,
+ 0x0,0x6e,0x0,0x64,0x0,0x69,0x0,0x63,0x0,0x61,0x0,0x74,0x0,0x6f,0x0,0x72,0x0,0x2d,0x0,0x69,0x0,0x63,0x0,0x6f,0x0,0x6e,0x0,0x35,
+ // indicator-icon6
+ 0x0,0xf,
+ 0x0,0xcd,0x75,0xf6,
+ 0x0,0x69,
+ 0x0,0x6e,0x0,0x64,0x0,0x69,0x0,0x63,0x0,0x61,0x0,0x74,0x0,0x6f,0x0,0x72,0x0,0x2d,0x0,0x69,0x0,0x63,0x0,0x6f,0x0,0x6e,0x0,0x36,
+ // indicator-icon7
+ 0x0,0xf,
+ 0x0,0xcd,0x75,0xf7,
+ 0x0,0x69,
+ 0x0,0x6e,0x0,0x64,0x0,0x69,0x0,0x63,0x0,0x61,0x0,0x74,0x0,0x6f,0x0,0x72,0x0,0x2d,0x0,0x69,0x0,0x63,0x0,0x6f,0x0,0x6e,0x0,0x37,
+ // fitWidthOn-button
+ 0x0,0x11,
+ 0xd,0x5d,0x28,0x1e,
+ 0x0,0x66,
+ 0x0,0x69,0x0,0x74,0x0,0x57,0x0,0x69,0x0,0x64,0x0,0x74,0x0,0x68,0x0,0x4f,0x0,0x6e,0x0,0x2d,0x0,0x62,0x0,0x75,0x0,0x74,0x0,0x74,0x0,0x6f,0x0,0x6e,
+
+ // toggleSidebar-button
+ 0x0,0x14,
+ 0xb,0xb3,0x3c,0x3e,
+ 0x0,0x74,
+ 0x0,0x6f,0x0,0x67,0x0,0x67,0x0,0x6c,0x0,0x65,0x0,0x53,0x0,0x69,0x0,0x64,0x0,0x65,0x0,0x62,0x0,0x61,0x0,0x72,0x0,0x2d,0x0,0x62,0x0,0x75,0x0,0x74,
+ 0x0,0x74,0x0,0x6f,0x0,0x6e,
+ // selectModeBlock-button
+ 0x0,0x16,
+ 0xe,0x22,0xff,0xfe,
+ 0x0,0x73,
+ 0x0,0x65,0x0,0x6c,0x0,0x65,0x0,0x63,0x0,0x74,0x0,0x4d,0x0,0x6f,0x0,0x64,0x0,0x65,0x0,0x42,0x0,0x6c,0x0,0x6f,0x0,0x63,0x0,0x6b,0x0,0x2d,0x0,0x62,
+ 0x0,0x75,0x0,0x74,0x0,0x74,0x0,0x6f,0x0,0x6e,
+
+};
+
+static const unsigned char qt_resource_struct[] = {
+ // :
+ 0x0,0x0,0x0,0x0,0x0,0x2,0x0,0x0,0x0,0x1f,0x0,0x0,0x0,0x1,
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ // :/fitWidth-button
+ 0x0,0x0,0x0,0xe0,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0xc,0xb3,
+0x0,0x0,0x1,0x80,0x3e,0x84,0xc,0x78,
+ // :/indicator-icon0
+ 0x0,0x0,0x2,0x38,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x1a,0xb0,
+0x0,0x0,0x1,0x80,0x3e,0x84,0xc,0x78,
+ // :/indicator-icon1
+ 0x0,0x0,0x2,0xb4,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x1f,0x30,
+0x0,0x0,0x1,0x80,0x3e,0x84,0xc,0x78,
+ // :/indicator-icon2
+ 0x0,0x0,0x2,0xfa,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x21,0xc5,
+0x0,0x0,0x1,0x80,0x3e,0x84,0xc,0x78,
+ // :/indicator-icon3
+ 0x0,0x0,0x3,0x1e,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x23,0x2f,
+0x0,0x0,0x1,0x80,0x3e,0x84,0xc,0x78,
+ // :/indicator-icon4
+ 0x0,0x0,0x3,0x42,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x24,0x99,
+0x0,0x0,0x1,0x80,0x3e,0x84,0xc,0x78,
+ // :/indicator-icon5
+ 0x0,0x0,0x3,0xc8,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x2d,0xd2,
+0x0,0x0,0x1,0x80,0x3e,0x84,0xc,0x78,
+ // :/indicator-icon6
+ 0x0,0x0,0x3,0xec,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x2f,0x3c,
+0x0,0x0,0x1,0x80,0x3e,0x84,0xc,0x78,
+ // :/indicator-icon7
+ 0x0,0x0,0x4,0x10,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x30,0xa6,
+0x0,0x0,0x1,0x80,0x3e,0x84,0xc,0x78,
+ // :/findSettings-button
+ 0x0,0x0,0x2,0x88,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x1d,0xc7,
+0x0,0x0,0x1,0x80,0x3e,0x84,0xc,0x78,
+ // :/zoomIn-button
+ 0x0,0x0,0x0,0x9e,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x9,0xac,
+0x0,0x0,0x1,0x80,0x3e,0x84,0xc,0x78,
+ // :/fitPage-button
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x0,
+0x0,0x0,0x1,0x80,0x3e,0x84,0xc,0x78,
+ // :/back-button
+ 0x0,0x0,0x0,0x22,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x3,0x4f,
+0x0,0x0,0x1,0x80,0x3e,0x84,0xc,0x78,
+ // :/indicator-icon-err0
+ 0x0,0x0,0x1,0x4,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0xe,0xf5,
+0x0,0x0,0x1,0x80,0x3e,0x84,0xc,0x78,
+ // :/indicator-icon-err1
+ 0x0,0x0,0x1,0x30,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x10,0xa2,
+0x0,0x0,0x1,0x80,0x3e,0x84,0xc,0x78,
+ // :/indicator-icon-err2
+ 0x0,0x0,0x1,0x5c,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x12,0x4f,
+0x0,0x0,0x1,0x80,0x3e,0x84,0xc,0x78,
+ // :/indicator-icon-err3
+ 0x0,0x0,0x1,0x88,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x13,0xfc,
+0x0,0x0,0x1,0x80,0x3e,0x84,0xc,0x78,
+ // :/indicator-icon-err4
+ 0x0,0x0,0x1,0xb4,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x15,0xa9,
+0x0,0x0,0x1,0x80,0x3e,0x84,0xc,0x78,
+ // :/indicator-icon-err5
+ 0x0,0x0,0x1,0xe0,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x17,0x56,
+0x0,0x0,0x1,0x80,0x3e,0x84,0xc,0x78,
+ // :/indicator-icon-err6
+ 0x0,0x0,0x2,0xc,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x19,0x3,
+0x0,0x0,0x1,0x80,0x3e,0x84,0xc,0x78,
+ // :/indicator-icon-err7
+ 0x0,0x0,0x2,0x5c,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x1c,0x1a,
+0x0,0x0,0x1,0x80,0x3e,0x84,0xc,0x78,
+ // :/xpdf-icon
+ 0x0,0x0,0x3,0x8a,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x27,0x35,
+0x0,0x0,0x1,0x80,0x3e,0x84,0xc,0x78,
+ // :/findNext-button
+ 0x0,0x0,0x3,0x66,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x26,0x3,
+0x0,0x0,0x1,0x80,0x3e,0x84,0xc,0x78,
+ // :/toggleSidebar-button
+ 0x0,0x0,0x4,0x5c,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x34,0x55,
+0x0,0x0,0x1,0x80,0x3e,0x84,0xc,0x78,
+ // :/fitWidthOn-button
+ 0x0,0x0,0x4,0x34,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x32,0x10,
+0x0,0x0,0x1,0x80,0x3e,0x84,0xc,0x78,
+ // :/findPrevious-button
+ 0x0,0x0,0x0,0x72,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x8,0x7a,
+0x0,0x0,0x1,0x80,0x3e,0x84,0xc,0x78,
+ // :/selectModeBlock-button
+ 0x0,0x0,0x4,0x8a,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x36,0x92,
+0x0,0x0,0x1,0x80,0x3e,0x84,0xc,0x78,
+ // :/forward-button
+ 0x0,0x0,0x0,0xbe,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0xb,0x2c,
+0x0,0x0,0x1,0x80,0x3e,0x84,0xc,0x78,
+ // :/selectModeLinear-button
+ 0x0,0x0,0x0,0x3e,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x4,0xd6,
+0x0,0x0,0x1,0x80,0x3e,0x84,0xc,0x78,
+ // :/zoomOut-button
+ 0x0,0x0,0x2,0xd8,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x20,0x9a,
+0x0,0x0,0x1,0x80,0x3e,0x84,0xc,0x78,
+ // :/fitPageOn-button
+ 0x0,0x0,0x3,0xa2,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x2a,0x80,
+0x0,0x0,0x1,0x80,0x3e,0x84,0xc,0x78,
+
+};
+
+#ifdef QT_NAMESPACE
+# define QT_RCC_PREPEND_NAMESPACE(name) ::QT_NAMESPACE::name
+# define QT_RCC_MANGLE_NAMESPACE0(x) x
+# define QT_RCC_MANGLE_NAMESPACE1(a, b) a##_##b
+# define QT_RCC_MANGLE_NAMESPACE2(a, b) QT_RCC_MANGLE_NAMESPACE1(a,b)
+# define QT_RCC_MANGLE_NAMESPACE(name) QT_RCC_MANGLE_NAMESPACE2( \
+ QT_RCC_MANGLE_NAMESPACE0(name), QT_RCC_MANGLE_NAMESPACE0(QT_NAMESPACE))
+#else
+# define QT_RCC_PREPEND_NAMESPACE(name) name
+# define QT_RCC_MANGLE_NAMESPACE(name) name
+#endif
+
+#ifdef QT_NAMESPACE
+namespace QT_NAMESPACE {
+#endif
+
+bool qRegisterResourceData(int, const unsigned char *, const unsigned char *, const unsigned char *);
+bool qUnregisterResourceData(int, const unsigned char *, const unsigned char *, const unsigned char *);
+
+#ifdef QT_NAMESPACE
+}
+#endif
+
+int QT_RCC_MANGLE_NAMESPACE(qInitResources_icons)();
+int QT_RCC_MANGLE_NAMESPACE(qInitResources_icons)()
+{
+ int version = 3;
+ QT_RCC_PREPEND_NAMESPACE(qRegisterResourceData)
+ (version, qt_resource_struct, qt_resource_name, qt_resource_data);
+ return 1;
+}
+
+int QT_RCC_MANGLE_NAMESPACE(qCleanupResources_icons)();
+int QT_RCC_MANGLE_NAMESPACE(qCleanupResources_icons)()
+{
+ int version = 3;
+ QT_RCC_PREPEND_NAMESPACE(qUnregisterResourceData)
+ (version, qt_resource_struct, qt_resource_name, qt_resource_data);
+ return 1;
+}
+
+namespace {
+ struct initializer {
+ initializer() { QT_RCC_MANGLE_NAMESPACE(qInitResources_icons)(); }
+ ~initializer() { QT_RCC_MANGLE_NAMESPACE(qCleanupResources_icons)(); }
+ } dummy;
+}
diff --git a/xpdf-qt/selectModeBlock.svg b/xpdf-qt/selectModeBlock.svg
new file mode 100644
index 0000000..4918f4e
--- /dev/null
+++ b/xpdf-qt/selectModeBlock.svg
@@ -0,0 +1,8 @@
+<?xml version="1.0"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg width="80" height="80" version="1.1"
+ xmlns="http://www.w3.org/2000/svg">
+ <polyline fill="#555555" stroke="none"
+ points="24,48 24,8 56,32 44,38 58,66 50,70 36,42"/>
+</svg>
diff --git a/xpdf-qt/selectModeLinear.svg b/xpdf-qt/selectModeLinear.svg
new file mode 100644
index 0000000..a463038
--- /dev/null
+++ b/xpdf-qt/selectModeLinear.svg
@@ -0,0 +1,25 @@
+<?xml version="1.0"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg width="80" height="80" version="1.1"
+ xmlns="http://www.w3.org/2000/svg">
+ <polyline stroke="#555555" stroke-width="4" fill="none"
+ points="26,18 34,18 38,22 42,18 50,18"/>
+ <polyline stroke="#555555" stroke-width="4" fill="none"
+ points="38,22 38,62"/>
+ <polyline stroke="#555555" stroke-width="4" fill="none"
+ points="26,66 34,66 38,62 42,66 50,66"/>
+
+<!--
+ <polyline stroke="#555555" stroke-width="8" fill="none"
+ points="40,20 40,60"/>
+ <polyline stroke="#555555" stroke-width="8" fill="none"
+ points="24,16 36,16"/>
+ <polyline stroke="#555555" stroke-width="8" fill="none"
+ points="44,16 56,16"/>
+ <polyline stroke="#555555" stroke-width="8" fill="none"
+ points="24,64 36,64"/>
+ <polyline stroke="#555555" stroke-width="8" fill="none"
+ points="44,64 56,64"/>
+-->
+</svg>
diff --git a/xpdf-qt/toggleSidebar.svg b/xpdf-qt/toggleSidebar.svg
new file mode 100644
index 0000000..99f764e
--- /dev/null
+++ b/xpdf-qt/toggleSidebar.svg
@@ -0,0 +1,17 @@
+<?xml version="1.0"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg width="80" height="80" version="1.1"
+ xmlns="http://www.w3.org/2000/svg">
+ <rect fill="none" stroke="#555555" stroke-width="4"
+ x="4" y="4" width="72" height="72"/>
+ <rect fill="#ddddff" stroke="#555555" stroke-width="4"
+ x="4" y="4" width="20" height="72"/>
+</svg>
+<!--
+<svg width="48" height="80" version="1.1"
+ xmlns="http://www.w3.org/2000/svg">
+ <polyline fill="#555555" stroke="none"
+ points="32,16 12,40 32,64"/>
+</svg>
+-->
diff --git a/xpdf-qt/xpdf b/xpdf-qt/xpdf
new file mode 100755
index 0000000..e283ba8
--- /dev/null
+++ b/xpdf-qt/xpdf
Binary files differ
diff --git a/xpdf-qt/xpdf-icon.ico b/xpdf-qt/xpdf-icon.ico
new file mode 100644
index 0000000..6a4a85c
--- /dev/null
+++ b/xpdf-qt/xpdf-icon.ico
Binary files differ
diff --git a/xpdf-qt/xpdf-icon.svg b/xpdf-qt/xpdf-icon.svg
new file mode 100644
index 0000000..b8e95dc
--- /dev/null
+++ b/xpdf-qt/xpdf-icon.svg
@@ -0,0 +1,20 @@
+<?xml version="1.0"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg width="64" height="64" version="1.1"
+ xmlns="http://www.w3.org/2000/svg">
+ <path fill="#004466" stroke="none"
+ d="M 8,4 L 20,4 A 12,12,0,0,1,32,16 A 12,12,0,0,1,44,4 L 56,4
+ L 56,60
+ L 44,60 A 12,12,0,0,1,32,48 A 12,12,0,0,1,20,60 L 8,60
+ L 8,44 L 12,44 A 4,4,0,0,0,16,40 L 16,24 A 4,4,0,0,0,12,20 L 8,20"/>
+ <path stroke="#ffffff" stroke-width="6" fill="none"
+ d="M 12,12 L 16,12 A 8,8,0,0,1,24,20 L 24,24 A 8,8,0,0,0,32,32
+ A 8,8,0,0,0,24,40 L 24,44 A 8,8,0,0,1,16,52 L 12,52"/>
+ <circle fill="#ffffff" stroke="none"
+ cx="46" cy="15" r="6"/>
+ <circle fill="#00aa00" stroke="none"
+ cx="46" cy="32" r="6"/>
+ <circle fill="#ffffff" stroke="none"
+ cx="46" cy="49" r="6"/>
+</svg>
diff --git a/xpdf-qt/xpdf.cc b/xpdf-qt/xpdf.cc
new file mode 100644
index 0000000..63e52d8
--- /dev/null
+++ b/xpdf-qt/xpdf.cc
@@ -0,0 +1,59 @@
+//========================================================================
+//
+// xpdf.cc
+//
+// Copyright 1996-2105 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <aconf.h>
+
+#include "gmem.h"
+#include "Object.h"
+#include "XpdfApp.h"
+
+int main(int argc, char *argv[]) {
+ int exitCode;
+
+ {
+ // this is inside a block so that the XpdfApp object gets freed
+ XpdfApp app(argc, argv);
+ if (app.getNumViewers() > 0) {
+ exitCode = app.exec();
+ } else {
+ exitCode = 1;
+ }
+ }
+
+ Object::memCheck(stderr);
+ gMemReport(stderr);
+
+ return exitCode;
+}
+
+#ifdef _WIN32
+int CALLBACK WinMain(HINSTANCE hIstance, HINSTANCE hPrevInstance,
+ LPSTR lpCmdLine, int nCmdShow) {
+ wchar_t **args;
+ int argc, i, n, ret;
+
+ if (!(args = CommandLineToArgvW(GetCommandLineW(), &argc)) ||
+ argc < 0) {
+ return -1;
+ }
+ char **argv = (char **)gmallocn(argc + 1, sizeof(char *));
+ for (i = 0; i < argc; ++i) {
+ n = WideCharToMultiByte(CP_UTF8, 0, args[i], -1, NULL, 0, NULL, NULL);
+ argv[i] = (char *)gmalloc(n);
+ WideCharToMultiByte(CP_UTF8, 0, args[i], -1, argv[i], n, NULL, NULL);
+ }
+ argv[argc] = NULL;
+ LocalFree(args);
+ ret = main(argc, argv);
+ for (i = 0; i < argc; ++i) {
+ gfree(argv[i]);
+ }
+ gfree(argv);
+ return ret;
+}
+#endif
diff --git a/xpdf-qt/xpdf.rc b/xpdf-qt/xpdf.rc
new file mode 100644
index 0000000..b458ba5
--- /dev/null
+++ b/xpdf-qt/xpdf.rc
@@ -0,0 +1 @@
+IDI_ICON1 ICON "xpdf-icon.ico"
diff --git a/xpdf-qt/zoomIn.svg b/xpdf-qt/zoomIn.svg
new file mode 100644
index 0000000..b3d8c14
--- /dev/null
+++ b/xpdf-qt/zoomIn.svg
@@ -0,0 +1,10 @@
+<?xml version="1.0"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg width="80" height="80" version="1.1"
+ xmlns="http://www.w3.org/2000/svg">
+ <polyline stroke="#555555" stroke-width="8" fill="none"
+ points="16,40 64,40"/>
+ <polyline stroke="#555555" stroke-width="8" fill="none"
+ points="40,16 40,64"/>
+</svg>
diff --git a/xpdf-qt/zoomOut.svg b/xpdf-qt/zoomOut.svg
new file mode 100644
index 0000000..2427f12
--- /dev/null
+++ b/xpdf-qt/zoomOut.svg
@@ -0,0 +1,8 @@
+<?xml version="1.0"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg width="80" height="80" version="1.1"
+ xmlns="http://www.w3.org/2000/svg">
+ <polyline stroke="#555555" stroke-width="8" fill="none"
+ points="16,40 64,40"/>
+</svg>
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 <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stdlib.h>
+#include <math.h>
+#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 <a> (which should
+// have 1, 3, or 4 elements). If <adjust> is +1, color is brightened;
+// if <adjust> is -1, color is darkened; otherwise color is not
+// modified.
+void 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 <r> centered at (<cx>, <cy>).
+// <cmd> 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 <r>
+// centered at (<cx>, <cy>).
+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 <r>
+// centered at (<cx>, <cy>).
+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
+ //~ <ui><picture> 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 <aconf.h>
+
+#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 <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stdlib.h>
+#include <math.h>
+#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 <r> centered at (<cx>, <cy>).
+// <cmd> is used to draw the circle ("f", "s", or "b").
+void Annot::drawCircle(double cx, double cy, double r, const char *cmd) {
+ appearBuf->appendf("{0:.4f} {1:.4f} m\n",
+ cx + r, cy);
+ appearBuf->appendf("{0:.4f} {1:.4f} {2:.4f} {3:.4f} {4:.4f} {5:.4f} c\n",
+ cx + r, cy + bezierCircle * r,
+ cx + bezierCircle * r, cy + r,
+ cx, cy + r);
+ appearBuf->appendf("{0:.4f} {1:.4f} {2:.4f} {3:.4f} {4:.4f} {5:.4f} c\n",
+ cx - bezierCircle * r, cy + r,
+ cx - r, cy + bezierCircle * r,
+ cx - r, cy);
+ appearBuf->appendf("{0:.4f} {1:.4f} {2:.4f} {3:.4f} {4:.4f} {5:.4f} c\n",
+ cx - r, cy - bezierCircle * r,
+ cx - bezierCircle * r, cy - r,
+ cx, cy - r);
+ appearBuf->appendf("{0:.4f} {1:.4f} {2:.4f} {3:.4f} {4:.4f} {5:.4f} c\n",
+ cx + bezierCircle * r, cy - r,
+ cx + r, cy - bezierCircle * r,
+ cx + r, cy);
+ appearBuf->appendf("{0:s}\n", cmd);
+}
+
+// Draw the top-left half of an (approximate) circle of radius <r>
+// centered at (<cx>, <cy>).
+void Annot::drawCircleTopLeft(double cx, double cy, double r) {
+ double r2;
+
+ r2 = r / sqrt(2.0);
+ appearBuf->appendf("{0:.4f} {1:.4f} m\n",
+ cx + r2, cy + r2);
+ appearBuf->appendf("{0:.4f} {1:.4f} {2:.4f} {3:.4f} {4:.4f} {5:.4f} c\n",
+ cx + (1 - bezierCircle) * r2,
+ cy + (1 + bezierCircle) * r2,
+ cx - (1 - bezierCircle) * r2,
+ cy + (1 + bezierCircle) * r2,
+ cx - r2,
+ cy + r2);
+ appearBuf->appendf("{0:.4f} {1:.4f} {2:.4f} {3:.4f} {4:.4f} {5:.4f} c\n",
+ cx - (1 + bezierCircle) * r2,
+ cy + (1 - bezierCircle) * r2,
+ cx - (1 + bezierCircle) * r2,
+ cy - (1 - bezierCircle) * r2,
+ cx - r2,
+ cy - r2);
+ appearBuf->append("S\n");
+}
+
+// Draw the bottom-right half of an (approximate) circle of radius <r>
+// centered at (<cx>, <cy>).
+void Annot::drawCircleBottomRight(double cx, double cy, double r) {
+ double r2;
+
+ r2 = r / sqrt(2.0);
+ appearBuf->appendf("{0:.4f} {1:.4f} m\n",
+ cx - r2, cy - r2);
+ appearBuf->appendf("{0:.4f} {1:.4f} {2:.4f} {3:.4f} {4:.4f} {5:.4f} c\n",
+ cx - (1 - bezierCircle) * r2,
+ cy - (1 + bezierCircle) * r2,
+ cx + (1 - bezierCircle) * r2,
+ cy - (1 + bezierCircle) * r2,
+ cx + r2,
+ cy - r2);
+ appearBuf->appendf("{0:.4f} {1:.4f} {2:.4f} {3:.4f} {4:.4f} {5:.4f} c\n",
+ cx + (1 + bezierCircle) * r2,
+ cy - (1 - bezierCircle) * r2,
+ cx + (1 + bezierCircle) * r2,
+ cy + (1 - bezierCircle) * r2,
+ cx + r2,
+ cy + r2);
+ appearBuf->append("S\n");
+}
+
+void Annot::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 <aconf.h>
+
+#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 <x>,<y> 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 <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stdlib.h>
+#include <stddef.h>
+#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 <aconf.h>
+
+#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 <elems> 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 <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#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 <aconf.h>
+
+#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 <aconf.h>
+#include <stdlib.h>
+#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
--- /dev/null
+++ b/xpdf/CMakeFiles/pdfdetach.dir/pdfdetach.cc.o
Binary files 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
--- /dev/null
+++ b/xpdf/CMakeFiles/pdffonts.dir/pdffonts.cc.o
Binary files 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
--- /dev/null
+++ b/xpdf/CMakeFiles/pdfimages.dir/ImageOutputDev.cc.o
Binary files 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
--- /dev/null
+++ b/xpdf/CMakeFiles/pdfimages.dir/pdfimages.cc.o
Binary files 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
--- /dev/null
+++ b/xpdf/CMakeFiles/pdfinfo.dir/pdfinfo.cc.o
Binary files 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
--- /dev/null
+++ b/xpdf/CMakeFiles/pdftohtml.dir/HTMLGen.cc.o
Binary files 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
--- /dev/null
+++ b/xpdf/CMakeFiles/pdftohtml.dir/ShadingImage.cc.o
Binary files 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
--- /dev/null
+++ b/xpdf/CMakeFiles/pdftohtml.dir/SplashOutputDev.cc.o
Binary files 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
--- /dev/null
+++ b/xpdf/CMakeFiles/pdftohtml.dir/TextOutputDev.cc.o
Binary files 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
--- /dev/null
+++ b/xpdf/CMakeFiles/pdftohtml.dir/WebFont.cc.o
Binary files 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
--- /dev/null
+++ b/xpdf/CMakeFiles/pdftohtml.dir/pdftohtml.cc.o
Binary files 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
--- /dev/null
+++ b/xpdf/CMakeFiles/pdftopng.dir/ShadingImage.cc.o
Binary files 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
--- /dev/null
+++ b/xpdf/CMakeFiles/pdftopng.dir/SplashOutputDev.cc.o
Binary files 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
--- /dev/null
+++ b/xpdf/CMakeFiles/pdftopng.dir/pdftopng.cc.o
Binary files 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
--- /dev/null
+++ b/xpdf/CMakeFiles/pdftoppm.dir/ShadingImage.cc.o
Binary files 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
--- /dev/null
+++ b/xpdf/CMakeFiles/pdftoppm.dir/SplashOutputDev.cc.o
Binary files 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
--- /dev/null
+++ b/xpdf/CMakeFiles/pdftoppm.dir/pdftoppm.cc.o
Binary files 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
--- /dev/null
+++ b/xpdf/CMakeFiles/pdftops.dir/PSOutputDev.cc.o
Binary files 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
--- /dev/null
+++ b/xpdf/CMakeFiles/pdftops.dir/PreScanOutputDev.cc.o
Binary files 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
--- /dev/null
+++ b/xpdf/CMakeFiles/pdftops.dir/ShadingImage.cc.o
Binary files 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
--- /dev/null
+++ b/xpdf/CMakeFiles/pdftops.dir/SplashOutputDev.cc.o
Binary files 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
--- /dev/null
+++ b/xpdf/CMakeFiles/pdftops.dir/pdftops.cc.o
Binary files 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
--- /dev/null
+++ b/xpdf/CMakeFiles/pdftotext.dir/TextOutputDev.cc.o
Binary files 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
--- /dev/null
+++ b/xpdf/CMakeFiles/pdftotext.dir/pdftotext.cc.o
Binary files 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
--- /dev/null
+++ b/xpdf/CMakeFiles/xpdf_objs.dir/AcroForm.cc.o
Binary files 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
--- /dev/null
+++ b/xpdf/CMakeFiles/xpdf_objs.dir/Annot.cc.o
Binary files 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
--- /dev/null
+++ b/xpdf/CMakeFiles/xpdf_objs.dir/Array.cc.o
Binary files 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
--- /dev/null
+++ b/xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFont.cc.o
Binary files 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
--- /dev/null
+++ b/xpdf/CMakeFiles/xpdf_objs.dir/BuiltinFontTables.cc.o
Binary files 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
--- /dev/null
+++ b/xpdf/CMakeFiles/xpdf_objs.dir/CMap.cc.o
Binary files 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
--- /dev/null
+++ b/xpdf/CMakeFiles/xpdf_objs.dir/Catalog.cc.o
Binary files 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
--- /dev/null
+++ b/xpdf/CMakeFiles/xpdf_objs.dir/CharCodeToUnicode.cc.o
Binary files 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
--- /dev/null
+++ b/xpdf/CMakeFiles/xpdf_objs.dir/Decrypt.cc.o
Binary files 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
--- /dev/null
+++ b/xpdf/CMakeFiles/xpdf_objs.dir/Dict.cc.o
Binary files 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
--- /dev/null
+++ b/xpdf/CMakeFiles/xpdf_objs.dir/Error.cc.o
Binary files 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
--- /dev/null
+++ b/xpdf/CMakeFiles/xpdf_objs.dir/FontEncodingTables.cc.o
Binary files 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
--- /dev/null
+++ b/xpdf/CMakeFiles/xpdf_objs.dir/Function.cc.o
Binary files 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
--- /dev/null
+++ b/xpdf/CMakeFiles/xpdf_objs.dir/Gfx.cc.o
Binary files 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
--- /dev/null
+++ b/xpdf/CMakeFiles/xpdf_objs.dir/GfxFont.cc.o
Binary files 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
--- /dev/null
+++ b/xpdf/CMakeFiles/xpdf_objs.dir/GfxState.cc.o
Binary files 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
--- /dev/null
+++ b/xpdf/CMakeFiles/xpdf_objs.dir/GlobalParams.cc.o
Binary files 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
--- /dev/null
+++ b/xpdf/CMakeFiles/xpdf_objs.dir/JArithmeticDecoder.cc.o
Binary files 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
--- /dev/null
+++ b/xpdf/CMakeFiles/xpdf_objs.dir/JBIG2Stream.cc.o
Binary files 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
--- /dev/null
+++ b/xpdf/CMakeFiles/xpdf_objs.dir/JPXStream.cc.o
Binary files 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
--- /dev/null
+++ b/xpdf/CMakeFiles/xpdf_objs.dir/Lexer.cc.o
Binary files 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
--- /dev/null
+++ b/xpdf/CMakeFiles/xpdf_objs.dir/Link.cc.o
Binary files 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
--- /dev/null
+++ b/xpdf/CMakeFiles/xpdf_objs.dir/NameToCharCode.cc.o
Binary files 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
--- /dev/null
+++ b/xpdf/CMakeFiles/xpdf_objs.dir/Object.cc.o
Binary files 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
--- /dev/null
+++ b/xpdf/CMakeFiles/xpdf_objs.dir/OptionalContent.cc.o
Binary files 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
--- /dev/null
+++ b/xpdf/CMakeFiles/xpdf_objs.dir/Outline.cc.o
Binary files 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
--- /dev/null
+++ b/xpdf/CMakeFiles/xpdf_objs.dir/OutputDev.cc.o
Binary files 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
--- /dev/null
+++ b/xpdf/CMakeFiles/xpdf_objs.dir/PDF417Barcode.cc.o
Binary files 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
--- /dev/null
+++ b/xpdf/CMakeFiles/xpdf_objs.dir/PDFDoc.cc.o
Binary files 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
--- /dev/null
+++ b/xpdf/CMakeFiles/xpdf_objs.dir/PDFDocEncoding.cc.o
Binary files 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
--- /dev/null
+++ b/xpdf/CMakeFiles/xpdf_objs.dir/PSTokenizer.cc.o
Binary files 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
--- /dev/null
+++ b/xpdf/CMakeFiles/xpdf_objs.dir/Page.cc.o
Binary files 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
--- /dev/null
+++ b/xpdf/CMakeFiles/xpdf_objs.dir/Parser.cc.o
Binary files 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
--- /dev/null
+++ b/xpdf/CMakeFiles/xpdf_objs.dir/SecurityHandler.cc.o
Binary files 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
--- /dev/null
+++ b/xpdf/CMakeFiles/xpdf_objs.dir/Stream.cc.o
Binary files 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
--- /dev/null
+++ b/xpdf/CMakeFiles/xpdf_objs.dir/TextString.cc.o
Binary files 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
--- /dev/null
+++ b/xpdf/CMakeFiles/xpdf_objs.dir/UTF8.cc.o
Binary files 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
--- /dev/null
+++ b/xpdf/CMakeFiles/xpdf_objs.dir/UnicodeMap.cc.o
Binary files 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
--- /dev/null
+++ b/xpdf/CMakeFiles/xpdf_objs.dir/UnicodeRemapping.cc.o
Binary files 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
--- /dev/null
+++ b/xpdf/CMakeFiles/xpdf_objs.dir/UnicodeTypeTable.cc.o
Binary files 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
--- /dev/null
+++ b/xpdf/CMakeFiles/xpdf_objs.dir/XFAScanner.cc.o
Binary files 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
--- /dev/null
+++ b/xpdf/CMakeFiles/xpdf_objs.dir/XRef.cc.o
Binary files 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
--- /dev/null
+++ b/xpdf/CMakeFiles/xpdf_objs.dir/Zoox.cc.o
Binary files 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
--- /dev/null
+++ b/xpdf/CMakeFiles/xpdf_widget_objs.dir/DisplayState.cc.o
Binary files 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
--- /dev/null
+++ b/xpdf/CMakeFiles/xpdf_widget_objs.dir/PDFCore.cc.o
Binary files 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
--- /dev/null
+++ b/xpdf/CMakeFiles/xpdf_widget_objs.dir/PSOutputDev.cc.o
Binary files 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
--- /dev/null
+++ b/xpdf/CMakeFiles/xpdf_widget_objs.dir/PreScanOutputDev.cc.o
Binary files 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
--- /dev/null
+++ b/xpdf/CMakeFiles/xpdf_widget_objs.dir/ShadingImage.cc.o
Binary files 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
--- /dev/null
+++ b/xpdf/CMakeFiles/xpdf_widget_objs.dir/SplashOutputDev.cc.o
Binary files 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
--- /dev/null
+++ b/xpdf/CMakeFiles/xpdf_widget_objs.dir/TextOutputDev.cc.o
Binary files 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
--- /dev/null
+++ b/xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCache.cc.o
Binary files 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
--- /dev/null
+++ b/xpdf/CMakeFiles/xpdf_widget_objs.dir/TileCompositor.cc.o
Binary files 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
--- /dev/null
+++ b/xpdf/CMakeFiles/xpdf_widget_objs.dir/TileMap.cc.o
Binary files 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
+ $<TARGET_OBJECTS:xpdf_objs>
+ 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
+ $<TARGET_OBJECTS:xpdf_objs>
+ 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
+ $<TARGET_OBJECTS:xpdf_objs>
+ 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
+ $<TARGET_OBJECTS:xpdf_objs>
+ 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
+ $<TARGET_OBJECTS:xpdf_objs>
+ 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
+ $<TARGET_OBJECTS:xpdf_objs>
+ 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
+ $<TARGET_OBJECTS:xpdf_objs>
+ 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
+ $<TARGET_OBJECTS:xpdf_objs>
+ 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
+ $<TARGET_OBJECTS:xpdf_objs>
+ 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
+ $<TARGET_OBJECTS:xpdf_objs>
+ 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 <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#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 <aconf.h>
+
+#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 <obj>, which can be a name or a stream. Sets
+ // the initial reference count to 1. Returns NULL on failure.
+ static CMap *parse(CMapCache *cache, GString *collectionA, Object *obj);
+
+ // Create the CMap specified by <collection> and <cMapName>. Sets
+ // the initial reference count to 1. Returns NULL on failure.
+ static CMap *parse(CMapCache *cache, GString *collectionA,
+ GString *cMapNameA);
+
+ // Parse a CMap from <str>. Sets the initial reference count to 1.
+ // Returns NULL on failure.
+ static CMap *parse(CMapCache *cache, GString *collectionA, Stream *str);
+
+ ~CMap();
+
+ void incRefCnt();
+ void decRefCnt();
+
+ // Return collection name (<registry>-<ordering>).
+ GString *getCollection() { return collection; }
+
+ // Return true if this CMap matches the specified <collectionA>, and
+ // <cMapNameA>.
+ GBool match(GString *collectionA, GString *cMapNameA);
+
+ // Return the CID corresponding to the character code starting at
+ // <s>, which contains <len> bytes. Sets *<c> to the char code, and
+ // *<nUsed> to the number of bytes used by the char code.
+ CID getCID(char *s, int len, CharCode *c, int *nUsed);
+
+ // Return the writing mode (0=horizontal, 1=vertical).
+ int getWMode() { return wMode; }
+
+private:
+
+ void parse2(CMapCache *cache, int (*getCharFunc)(void *), void *data);
+ CMap(GString *collectionA, GString *cMapNameA);
+ CMap(GString *collectionA, GString *cMapNameA, int wModeA);
+ void useCMap(CMapCache *cache, char *useName);
+ void useCMap(CMapCache *cache, Object *obj);
+ void copyVector(CMapVectorEntry *dest, CMapVectorEntry *src);
+ void 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 <cMapName> 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 <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <string.h>
+#include <stddef.h>
+#include <limits.h>
+#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 <aconf.h>
+
+#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 <name> is not a destination.
+ LinkDest *findDest(GString *name);
+
+ Object *getDests() { return &dests; }
+
+ Object *getNameTree() { return &nameTree; }
+
+ Object *getOutline() { return &outline; }
+
+ Object *getAcroForm() { return &acroForm; }
+
+ 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 <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#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 <len>-byte hex string <s> into *<val>. Returns false on
+// error.
+static GBool parseHex(char *s, int len, Guint *val) {
+ int i, x;
+
+ *val = 0;
+ for (i = 0; i < len; ++i) {
+ x = hexCharVals[s[i] & 0xff];
+ if (x < 0) {
+ return gFalse;
+ }
+ *val = (*val << 4) + x;
+ }
+ return gTrue;
+}
+
+//------------------------------------------------------------------------
+
+CharCodeToUnicode *CharCodeToUnicode::makeIdentityMapping() {
+ return new CharCodeToUnicode();
+}
+
+CharCodeToUnicode *CharCodeToUnicode::parseCIDToUnicode(GString *fileName,
+ GString *collection) {
+ FILE *f;
+ 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 <ffffffff>.)
+ 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 <ffffffff>.)
+ 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 <aconf.h>
+
+#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 <collection> from the file
+ // specified by <fileName>. 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
+ // <fileName>. 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.
+ // <toUnicode> 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.
+ // <toUnicode> is an array of 65536 Unicode indexes. Sets the
+ // initial reference count to 1.
+ static CharCodeToUnicode *make16BitToUnicode(Unicode *toUnicode);
+
+ // Parse a ToUnicode CMap for an 8- or 16-bit font.
+ static CharCodeToUnicode *parseCMap(GString *buf, int nBits);
+
+ // Parse a ToUnicode CMap for an 8- or 16-bit font, merging it into
+ // <this>.
+ void mergeCMap(GString *buf, int nBits);
+
+ ~CharCodeToUnicode();
+
+ void incRefCnt();
+ void decRefCnt();
+
+ // Return true if this mapping matches the specified <tagA>.
+ GBool match(GString *tagA);
+
+ // Set the mapping for <c>.
+ 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 <tag>. 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 <ctu> 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 <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <string.h>
+#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 <aconf.h>
+
+#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 <fileKey> buffer must have space for at
+ // least 16 bytes. Checks <ownerPassword> and then <userPassword>
+ // and returns true if either is correct. Sets <ownerPasswordOk> if
+ // 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 <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stddef.h>
+#include <string.h>
+#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 <aconf.h>
+
+#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 <key> 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 <entries> 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 <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stdlib.h>
+#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 <aconf.h>
+
+#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 <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stdio.h>
+#include <stddef.h>
+#include <stdarg.h>
+#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 <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include <stdio.h>
+#include "config.h"
+#include "gfile.h"
+
+enum ErrorCategory {
+ errSyntaxWarning, // PDF syntax error which can be worked around;
+ // output will probably be correct
+ errSyntaxError, // PDF syntax error which 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 <aconf.h>
+#include <stdlib.h>
+#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 <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <math.h>
+#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<<m); ++i) {
+ idx = 0;
+ for (j = m - 1, t = i; j >= 1; --j, t <<= 1) {
+ if (sampleSize[j] == 1) {
+ bit = 0;
+ } else {
+ bit = (t >> (m - 1)) & 1;
+ }
+ idx = (idx + bit) * sampleSize[j-1];
+ }
+ if (sampleSize[0] == 1) {
+ bit = 0;
+ } else {
+ bit = (t >> (m - 1)) & 1;
+ }
+ idxOffset[i] = (idx + bit) * n;
+ }
+
+ //----- BitsPerSample
+ if (!dict->lookup("BitsPerSample", &obj1)->isInt()) {
+ error(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<<m); ++j) {
+ sBuf[j] = samples[idx0 + idxOffset[j] + i];
+ }
+
+ // do m sets of interpolations
+ for (j = 0, t = (1<<m); j < m; ++j, t >>= 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 <aconf.h>
+
+#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 <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stddef.h>
+#include <string.h>
+#include <math.h>
+#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 <ref> is already on contentStreamStack, i.e., if there is a loop
+// in the content streams, report an error, and return true.
+GBool Gfx::checkForContentStreamLoop(Object *ref) {
+ Object *objPtr;
+ Object obj1;
+ int i, j;
+
+ if (ref->isRef()) {
+ for (i = 0; i < contentStreamStack->getLength(); ++i) {
+ objPtr = (Object *)contentStreamStack->get(i);
+ if (objPtr->isRef()) {
+ if (ref->getRefNum() == objPtr->getRefNum() &&
+ ref->getRefGen() == objPtr->getRefGen()) {
+ error(errSyntaxError, -1, "Loop in content streams");
+ return gTrue;
+ }
+ } else if (objPtr->isArray()) {
+ for (j = 0; j < objPtr->arrayGetLength(); ++j) {
+ objPtr->arrayGetNF(j, &obj1);
+ if (obj1.isRef()) {
+ if (ref->getRefNum() == obj1.getRefNum() &&
+ ref->getRefGen() == obj1.getRefGen()) {
+ error(errSyntaxError, -1, "Loop in content streams");
+ obj1.free();
+ return gTrue;
+ }
+ }
+ obj1.free();
+ }
+ }
+ }
+ }
+ return gFalse;
+}
+
+void Gfx::go(GBool topLevel) {
+ Object obj;
+ Object args[maxArgs];
+ 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 <aconf.h>
+
+#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. <objRef> should be a
+ // reference wherever possible (for loop-checking).
+ void display(Object *objRef, GBool topLevel = gTrue);
+
+ // Display an annotation, given its appearance (a Form XObject),
+ // border style, and bounding box (in default user space).
+ void drawAnnot(Object *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 <oldGfx>. This
+ // is useful when creating a new Gfx object to handle a pattern,
+ // etc., where it's useful to check for loops that span both Gfx
+ // objects. This function should be called immediately after the
+ // Gfx constructor, i.e., before processing any content streams with
+ // the new Gfx object.
+ void takeContentStreamStack(Gfx *oldGfx);
+
+ // 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 <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <math.h>
+#include <limits.h>
+#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 <aconf.h>
+
+#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 <first>..<last>
+ double width; // char width
+};
+
+struct GfxFontCIDWidthExcepV {
+ CID first; // this record applies to
+ CID last; // CIDs <first>..<last>
+ 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 <ps> is true, includes PS
+ // printer-resident fonts. Returns NULL on failure.
+ GfxFontLoc *locateFont(XRef *xref, GBool ps);
+
+ // Locate a Base-14 font file for a specified font name.
+ static GfxFontLoc *locateBase14Font(GString *base14Name);
+
+ // Read an embedded font file into a buffer.
+ char *readEmbFontFile(XRef *xref, int *len);
+
+ // Get the next char from a string <s> of <len> bytes, returning the
+ // char <code>, its Unicode mapping <u>, its displacement vector
+ // (<dx>, <dy>), and its origin offset vector (<ox>, <oy>). <uSize>
+ // is the number of entries available in <u>, and <uLen> 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 <code>.
+ 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 <code>.
+ Object *getCharProc(int code, Object *proc);
+ Object *getCharProcNF(int code, Object *proc);
+
+ // Return the Type 3 Resources dictionary, or NULL if none.
+ Dict *getResources();
+
+ 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 (<registry>-<ordering>).
+ GString *getCollection();
+
+ // Return the horizontal width for <cid>.
+ 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 <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stddef.h>
+#include <math.h>
+#include <string.h>
+#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 <aconf.h>
+
+#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 <mode> argument can be
+ // csDeviceGray, csDeviceRGB, or csDeviceCMYK.
+ static GfxColorSpace *create(GfxColorSpaceMode mode);
+
+
+ // Convert to gray, RGB, or CMYK.
+ virtual void getGray(GfxColor *color, GfxGray *gray,
+ 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 <maxImgPixel>.
+ virtual void getDefaultRanges(double *decodeLow, double *decodeRange,
+ int maxImgPixel);
+
+ // Returns true if painting operations in this color space never
+ // mark the page (e.g., the "None" colorant).
+ virtual GBool isNonMarking() { return gFalse; }
+
+
+ // Return the 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 <idx>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 <n> 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 (<dx>, <dy>) 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 <path> to <this>.
+ void append(GfxPath *path);
+
+ // Add (<dx>, <dy>) 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 <hDPI>
+ // x <vDPI>, page box <pageBox>, page rotation <rotateA>, and
+ // coordinate system specified by <upsideDown>.
+ GfxState(double hDPIA, double vDPIA, PDFRectangle *pageBox,
+ int rotateA, GBool upsideDown
+ );
+
+ // 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 <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <string.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <time.h>
+#ifdef _WIN32
+# include <shlobj.h>
+#endif
+#if HAVE_PAPER_H
+#include <paper.h>
+#endif
+#if HAVE_FONTCONFIG
+# include <fontconfig/fontconfig.h>
+#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,
+ &regKey) == 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 <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include <stdio.h>
+#ifdef _WIN32
+# include <windows.h>
+#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 <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stdlib.h>
+#include <png.h>
+#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, "<html>\n");
+ pr(writeHTML, htmlStream, "<head>\n");
+ pr(writeHTML, htmlStream, "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n");
+ pr(writeHTML, htmlStream, "<style type=\"text/css\">\n");
+ pr(writeHTML, htmlStream, ".txt { white-space:nowrap; }\n");
+ if (convertFormFields) {
+ pr(writeHTML, htmlStream, ".textfield {\n");
+ pr(writeHTML, htmlStream, " border: 0;\n");
+ pr(writeHTML, htmlStream, " padding: 0;\n");
+ pr(writeHTML, htmlStream, " background: #ccccff;\n");
+ pr(writeHTML, htmlStream, "}\n");
+ pr(writeHTML, htmlStream, ".checkbox {\n");
+ pr(writeHTML, htmlStream, "}\n");
+ }
+ fonts = text->getFonts();
+ fontScales = (double *)gmallocn(fonts->getLength(), sizeof(double));
+ for (i = 0; i < fontDefns->getLength(); ++i) {
+ fontDefn = (HTMLGenFontDefn *)fontDefns->get(i);
+ fontDefn->used = gFalse;
+ }
+ for (i = 0; i < fonts->getLength(); ++i) {
+ font = (TextFontInfo *)fonts->get(i);
+ fontDefn = getFontDefn(font, htmlDir);
+ if (!fontDefn->used && fontDefn->fontFace) {
+ pr(writeHTML, htmlStream, fontDefn->fontFace->getCString());
+ }
+ pf(writeHTML, htmlStream, ".f{0:d} {{ {1:t} }}\n", i, fontDefn->fontSpec);
+ fontScales[i] = fontDefn->scale;
+ fontDefn->used = gTrue;
+ }
+ pr(writeHTML, htmlStream, "</style>\n");
+ pr(writeHTML, htmlStream, "</head>\n");
+ if (primaryDir >= 0) {
+ pr(writeHTML, htmlStream, "<body>\n");
+ } else {
+ pr(writeHTML, htmlStream, "<body dir=\"rtl\">\n");
+ }
+
+ // background image element (part 1)
+ if (primaryDir >= 0) {
+ pf(writeHTML, htmlStream, "<img style=\"position:absolute; left:0px; top:0px;\" width=\"{0:d}\" height=\"{1:d}\" ",
+ (int)(pageW * zoom), (int)(pageH * zoom * vStretch));
+ } else {
+ pf(writeHTML, htmlStream, "<img style=\"position:absolute; right:0px; top:0px;\" width=\"{0:d}\" height=\"{1:d}\" ",
+ (int)(pageW * zoom), (int)(pageH * zoom * vStretch));
+ }
+ if (embedBackgroundImage) {
+ pr(writeHTML, htmlStream, "src=\"data:image/png;base64,\n");
+ writeInfo.base64 = new Base64Encoder(writeHTML, htmlStream);
+ writeInfo.writePNG = NULL;
+ writeInfo.pngStream = NULL;
+ } else {
+ pf(writeHTML, htmlStream, "src=\"{0:s}\"", pngURL);
+ writeInfo.base64 = NULL;
+ writeInfo.writePNG = writePNG;
+ writeInfo.pngStream = pngStream;
+ }
+
+ // background image data - writing to a separate file, or embedding
+ // with base64 encoding
+ if (!(png = png_create_write_struct(PNG_LIBPNG_VER_STRING,
+ NULL, NULL, NULL)) ||
+ !(pngInfo = png_create_info_struct(png))) {
+ return errFileIO;
+ }
+ if (setjmp(png_jmpbuf(png))) {
+ return errFileIO;
+ }
+ png_set_write_fn(png, &writeInfo, pngWriteFunc, NULL);
+ png_set_IHDR(png, pngInfo, bitmap->getWidth(), bitmap->getHeight(),
+ 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
+ PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
+ png_write_info(png, pngInfo);
+ p = bitmap->getDataPtr();
+ for (y = 0; y < bitmap->getHeight(); ++y) {
+ png_write_row(png, (png_bytep)p);
+ p += bitmap->getRowSize();
+ }
+ png_write_end(png, pngInfo);
+ png_destroy_write_struct(&png, &pngInfo);
+ if (embedBackgroundImage) {
+ writeInfo.base64->flush();
+ delete writeInfo.base64;
+ }
+
+ // background image element (part 2)
+ pr(writeHTML, htmlStream, "\">\n");
+
+ // generate the HTML text
+ nextFieldID = 0;
+ cols = text->makeColumns();
+ for (colIdx = 0; colIdx < cols->getLength(); ++colIdx) {
+ col = (TextColumn *)cols->get(colIdx);
+ 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, "<div class=\"txt\" style=\"position:absolute; left:{0:d}px; top:{1:d}px;\">{2:t}</div>\n",
+ (int)(line->getXMin() * zoom),
+ (int)(line->getYMin() * zoom * vStretch), s);
+ } else {
+ pf(writeHTML, htmlStream, "<div class=\"txt\" style=\"position:absolute; right:{0:d}px; top:{1:d}px;\">{2:t}</div>\n",
+ (int)((pageW - line->getXMax()) * zoom),
+ (int)(line->getYMin() * zoom * 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, "</body>\n");
+ pr(writeHTML, htmlStream, "</html>\n");
+
+ return errNone;
+}
+
+// Find a sequence of words, starting at <firstWordIdx>, that have the
+// same writing direction. Returns the index of the last word, and
+// sets *<spanDir> 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 <firstWordIdx> .. <lastWordIdx>, and
+// append them to <s>.
+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 <input> element(s)
+ if (convertFormFields && word0->getFontInfo() == formFieldFont) {
+ for (int i = (spanDir >= 0) ? 0 : word0->getLength() - 1;
+ (spanDir >= 0) ? i < word0->getLength() : i >= 0;
+ i += spanDir) {
+ int fieldIdx = word0->getChar(0) - 0x80000000;
+ if (fieldIdx >= 0 && fieldIdx < formFieldInfo->getLength()) {
+ HTMLGenFormFieldInfo *ffi =
+ (HTMLGenFormFieldInfo *)formFieldInfo->get(fieldIdx);
+ AcroFormField *field = ffi->acroFormField;
+ AcroFormFieldType fieldType = field->getAcroFormFieldType();
+ double llx, lly, urx, ury;
+ field->getBBox(&llx, &lly, &urx, &ury);
+ int width = (int)(urx - llx);
+ Ref fontID;
+ double fontSize;
+ field->getFont(&fontID, &fontSize);
+ if (fontSize == 0) {
+ fontSize = 12;
+ }
+ if (fieldType == acroFormFieldText) {
+ s->appendf("<input type=\"text\" class=\"textfield\" id=\"textfield{0:d}\" style=\"width:{1:d}px; font-size:{2:d}px;\">", nextFieldID, width, (int)(fontSize + 0.5));
+ ++nextFieldID;
+ } else if (fieldType == acroFormFieldCheckbox) {
+ s->appendf("<input type=\"checkbox\" class=\"checkbox\" id=\"checkbox{0:d}\" style=\"width:{1:d}px; font-size:{2:d}px;\">", nextFieldID, width, (int)(fontSize + 0.5));
+ ++nextFieldID;
+ }
+ }
+ }
+
+ if (word0->getSpaceAfter()) {
+ s->append(' ');
+ }
+
+ wordIdx += spanDir;
+
+ // skip invisible words
+ } else if (!drawInvisibleText &&
+ (word0->isInvisible() || word0->isRotated())) {
+ wordIdx += spanDir;
+
+ // generate a <span> containing one or more words
+ } else {
+
+ double r0 = 0, g0 = 0, b0 = 0; // make gcc happy
+ VerticalAlignment vertAlign0 = vertAlignBaseline; // make gcc happy
+ GString *linkURI0 = NULL;
+
+ GBool invisible = word0->isInvisible() || word0->isRotated();
+
+ do {
+ TextWord *word1 = (TextWord *)words->get(wordIdx);
+
+ // get word parameters
+ double r1, g1, b1;
+ word0->getColor(&r1, &g1, &b1);
+ double base1 = word1->getBaseline();
+ VerticalAlignment vertAlign1;
+ if (dropCapLine) {
+ //~ this will fail if there are subscripts or superscripts in
+ //~ the first line of a paragraph with a drop cap
+ vertAlign1 = vertAlignTop;
+ } else if (base1 - base < -1) {
+ vertAlign1 = vertAlignSuper;
+ } else if (base1 - base > 1) {
+ vertAlign1 = vertAlignSub;
+ } else {
+ vertAlign1 = vertAlignBaseline;
+ }
+ GString *linkURI1 = word1->getLinkURI();
+
+ // start of span
+ if (word1 == word0) {
+ r0 = r1;
+ g0 = g1;
+ b0 = b1;
+ vertAlign0 = vertAlign1;
+ linkURI0 = linkURI1;
+
+ int i;
+ for (i = 0; i < fonts->getLength(); ++i) {
+ if (word1->getFontInfo() == (TextFontInfo *)fonts->get(i)) {
+ break;
+ }
+ }
+ if (linkURI1) {
+ s->appendf("<a href=\"{0:t}\">", linkURI0);
+ }
+ // we force spans to be LTR or RTL; this is a kludge, but it's
+ // far easier than implementing the full Unicode bidi algorithm
+ const char *dirTag;
+ if (spanDir == primaryDir) {
+ dirTag = "";
+ } else if (spanDir < 0) {
+ dirTag = " dir=\"rtl\"";
+ } else {
+ dirTag = " dir=\"ltr\"";
+ }
+ s->appendf("<span class=\"f{0:d}\"{1:s} style=\"font-size:{2:d}px;vertical-align:{3:s};{4:s}color:rgba({5:d},{6:d},{7:d},{8:d});\">",
+ i,
+ dirTag,
+ (int)(fontScales[i] * word1->getFontSize() * zoom),
+ vertAlignNames[vertAlign1],
+ (dropCapLine && wordIdx == 0) ? "line-height:75%;" : "",
+ (int)(r0 * 255), (int)(g0 * 255), (int)(b0 * 255),
+ invisible ? 0 : 1);
+
+ // end of span
+ } else if (word1->getFontInfo() != word0->getFontInfo() ||
+ word1->getFontSize() != word0->getFontSize() ||
+ word1->isInvisible() != word0->isInvisible() ||
+ word1->isRotated() != word0->isRotated() ||
+ vertAlign1 != vertAlign0 ||
+ r1 != r0 || g1 != g0 || b1 != b0 ||
+ linkURI1 != linkURI0) {
+ break;
+ }
+
+ // add a space before the word, if needed
+ // -- this only happens with the first word in a reverse section
+ if (spanDir != primaryDir && wordIdx == firstWordIdx) {
+ GBool sp;
+ if (spanDir >= 0) {
+ if (wordIdx > 0) {
+ sp = ((TextWord *)words->get(wordIdx - 1))->getSpaceAfter();
+ } else {
+ sp = gFalse;
+ }
+ } else {
+ sp = word1->getSpaceAfter();
+ }
+ if (sp) {
+ s->append(' ');
+ }
+ }
+
+ // generate the word text
+ for (int i = (spanDir >= 0) ? 0 : word1->getLength() - 1;
+ (spanDir >= 0) ? i < word1->getLength() : i >= 0;
+ i += spanDir) {
+ Unicode u = word1->getChar(i);
+ if (u >= privateUnicodeMapStart &&
+ u <= privateUnicodeMapEnd &&
+ privateUnicodeMap[u - privateUnicodeMapStart]) {
+ u = privateUnicodeMap[u - privateUnicodeMapStart];
+ }
+ appendUTF8(u, s);
+ }
+
+ // add a space after the word, if needed
+ // -- there is never a space after the last word in a reverse
+ // section (this will be handled as a space after the last
+ // word in the previous primary-direction section)
+ GBool sp;
+ if (spanDir != primaryDir && wordIdx == lastWordIdx) {
+ sp = gFalse;
+ } else if (spanDir >= 0) {
+ sp = word1->getSpaceAfter();
+ } else {
+ if (wordIdx > 0) {
+ sp = ((TextWord *)words->get(wordIdx - 1))->getSpaceAfter();
+ } else {
+ sp = gFalse;
+ }
+ }
+ if (sp) {
+ s->append(' ');
+ }
+
+ wordIdx += spanDir;
+ } while ((spanDir >= 0) ? wordIdx <= lastWordIdx
+ : wordIdx >= lastWordIdx);
+
+ s->append("</span>");
+ if (linkURI0) {
+ s->append("</a>");
+ }
+ }
+ }
+}
+
+void HTMLGen::appendUTF8(Unicode u, GString *s) {
+ if (u <= 0x7f) {
+ if (u == '&') {
+ s->append("&amp;");
+ } else if (u == '<') {
+ s->append("&lt;");
+ } else if (u == '>') {
+ s->append("&gt;");
+ } 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 <aconf.h>
+
+#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 <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <ctype.h>
+#include <math.h>
+#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 <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include <stdio.h>
+#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
+ // <fileRoot>-NNN.<type>. Normally, all images are written as PBM
+ // (.pbm) or PPM (.ppm) files. If <dumpJPEG> is set, JPEG images
+ // are written as JPEG (.jpg) files. If <dumpRaw> is set, all
+ // images are written in PDF-native formats. If <list> 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 <aconf.h>
+
+#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 <aconf.h>
+
+#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 *<x> 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 <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stdlib.h>
+#include <limits.h>
+#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 *<x> 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 <aconf.h>
+
+#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 <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <limits.h>
+#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 <aconf.h>
+
+#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 <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include <ctype.h>
+#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 <aconf.h>
+
+#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 <c> 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 <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stddef.h>
+#include <string.h>
+#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 <aconf.h>
+
+#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 <x>,<y> is in a link, return the associated action;
+ // else return NULL.
+ LinkAction *find(double x, double y);
+
+ // Return true if <x>,<y> 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 <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <string.h>
+#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 <aconf.h>
+
+#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 <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stddef.h>
+#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, "<stream>");
+ break;
+ case objRef:
+ fprintf(f, "%d %d R", ref.num, ref.gen);
+ break;
+ case objCmd:
+ fprintf(f, "%s", cmd);
+ break;
+ case objError:
+ fprintf(f, "<error>");
+ break;
+ case objEOF:
+ fprintf(f, "<EOF>");
+ break;
+ case objNone:
+ fprintf(f, "<none>");
+ 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 <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#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 <aconf.h>
+
+#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 <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include "gtypes.h"
+#include "Object.h"
+#include "CharTypes.h"
+
+class GString;
+class GList;
+class PDFDoc;
+class 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 <obj> is a valid OCG or OCMD, sets *<visible> and returns
+ // true; otherwise returns false.
+ GBool evalOCObject(Object *obj, GBool *visible);
+
+private:
+
+ GBool evalOCVisibilityExpr(Object *expr, int recursion);
+
+ XRef *xref;
+ GList *ocgs; // all OCGs [OptionalContentGroup]
+ OCDisplayNode *display; // root node of display tree
+};
+
+//------------------------------------------------------------------------
+
+// Values from the optional content usage dictionary.
+enum OCUsageState {
+ ocUsageOn,
+ ocUsageOff,
+ ocUsageUnset
+};
+
+//------------------------------------------------------------------------
+
+class OptionalContentGroup {
+public:
+
+ static OptionalContentGroup *parse(Ref *refA, Object *obj);
+ ~OptionalContentGroup();
+
+ GBool matches(Ref *refA);
+
+ Unicode *getName();
+ 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 <aconf.h>
+
+#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 <aconf.h>
+
+#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 <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stddef.h>
+#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 <aconf.h>
+
+#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 <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <math.h>
+#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 <aconf.h>
+
+#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 <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <math.h>
+#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 <pg>.
+void PDFCore::loadLinks(int pg) {
+ if (links && linksPage == pg) {
+ return;
+ }
+ if (links) {
+ delete links;
+ }
+ links = doc->getLinks(pg);
+ linksPage = pg;
+}
+
+// Load the annotations for <pg>.
+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 <pg>.
+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 <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include <stdlib.h>
+#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 <scrollToTop> is
+ // set, the window is vertically scrolled to the top; if
+ // <scrollToBottom> is set, the window is vertically scrolled to the
+ // bottom; otherwise, no scrolling is done. If <addToHist> 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 <wholeWindow> 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 <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#ifdef _WIN32
+# include <windows.h>
+#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 <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include <stdio.h>
+#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 <name> is not a destination.
+ LinkDest *findDest(GString *name)
+ { return catalog->findDest(name); }
+
+ // Process the links for a page.
+ void processLinks(OutputDev *out, int page);
+
+#ifndef DISABLE_OUTLINE
+ // Return the outline object.
+ Outline *getOutline() { return outline; }
+
+ // 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 <aconf.h>
+#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 <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stdio.h>
+#include <stddef.h>
+#include <stdarg.h>
+#include <signal.h>
+#include <math.h>
+#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> <ffff>",
+ " endcodespacerange",
+ " 0 usefont",
+ " 1 begincidrange",
+ " <0000> <ffff> 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> <ffff>",
+ " endcodespacerange",
+ " 0 usefont",
+ " 1 begincidrange",
+ " <0000> <ffff> 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 <in> is ASCIIHex-encoded, decode it, delete <in>, and return the
+// binary version. Else return <in> 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<eol>"
+ // 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...><eol>"
+ // 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...~><eol>"
+ // 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...~><eol>"
+ // 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<<m); ++j) {
+ // [e01] [efrac] y(0) ... y(i-1) s(0) s(1) ... s(j-1)
+ writePSFmt("xpdfSamples{0:d}\n", thisFunc);
+ k = m - 1;
+ writePSFmt("{0:d} index {1:d} get\n", i+j+2, 2 * k + ((j >> 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) <k/2 s' values> <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 <textline>.
+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 <text>
+ // instead of <textline>, 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 <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include <stddef.h>
+#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 <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#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 <aconf.h>
+
+#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 <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stddef.h>
+#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 <aconf.h>
+
+#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
+ // <attrs> 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 <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stddef.h>
+#include <string.h>
+#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 <aconf.h>
+
+#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 <simpleOnly> is
+ // true, do not parse compound objects (arrays, dictionaries, or
+ // streams).
+ Object *getObj(Object *obj, GBool simpleOnly = gFalse,
+ Guchar *fileKey = NULL,
+ CryptAlgorithm encAlgorithm = cryptRC4, int keyLength = 0,
+ int objNum = 0, int objGen = 0, int 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 <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <math.h>
+#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 <aconf.h>
+
+#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 <aconf.h>
+
+#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 <aconf.h>
+
+#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 <ownerPassword> and <userPassword> (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 <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <math.h>
+#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 <aconf.h>
+
+#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 <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <string.h>
+#include <math.h>
+#include <limits.h>
+#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 <aconf.h>
+
+#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 <skipTextA> is true, don't draw horizontal text.
+ // If <skipRotatedTextA> is true, don't draw rotated (non-horizontal) text.
+ void setSkipText(GBool skipHorizTextA, GBool skipRotatedTextA)
+ { skipHorizText = skipHorizTextA; skipRotatedText = skipRotatedTextA; }
+
+ int getNestCount() { return nestCount; }
+
+
+ // 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 <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <limits.h>
+#ifdef _WIN32
+#include <io.h>
+#else
+#include <unistd.h>
+#endif
+#include <string.h>
+#include <ctype.h>
+#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", &params, recursion);
+ if (params.isNull()) {
+ params.free();
+ dict->dictLookup("DP", &params, recursion);
+ }
+ if (obj.isName()) {
+ str = makeFilter(obj.getName(), str, &params, 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, &params2, recursion);
+ else
+ params2.initNull();
+ if (obj2.isName()) {
+ str = makeFilter(obj2.getName(), str, &params2, 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 <lengths> of <n> 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 <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include <stdio.h>
+#if HAVE_JPEGLIB
+#include <jpeglib.h>
+#include <setjmp.h>
+#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 <size> bytes from stream. Returns the number of
+ // bytes read -- the returned count will be less than <size> at EOF.
+ virtual int getBlock(char *blk, int size);
+
+ // Get next line from stream.
+ virtual char *getLine(char *buf, int size);
+
+ // Discard the next <n> bytes from stream. Returns the number of
+ // bytes discarded, which will be less than <n> only if EOF is
+ // reached.
+ virtual Guint discardChars(Guint n);
+
+ // Get current position in file.
+ virtual GFileOffset getPos() = 0;
+
+ // Go to a position in the stream. If <dir> is negative, the
+ // position is from the end of the file; otherwise the position is
+ // from the start of the file.
+ virtual void setPos(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 <dict>.
+ // 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. <pix> 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 <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <math.h>
+#include <limits.h>
+#include <ctype.h>
+#ifdef _WIN32
+#include <fcntl.h> // for O_BINARY
+#include <io.h> // 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 <blk> where large char <ch> belongs, and prepend
+// it.
+void TextPage::insertLargeCharInLeaf(TextChar *ch, TextBlock *blk) {
+ TextBlock *child;
+ double y;
+ int i;
+
+ //~ this currently works only for characters in the primary rotation
+
+ //~ this currently just looks down the left edge of blk
+ //~ -- it could be extended to do more
+
+ // estimate the baseline of ch
+ y = ch->yMin + 0.75 * (ch->yMax - ch->yMin);
+
+ if (blk->type == blkLeaf) {
+ blk->prependChild(ch);
+ } else if (blk->type == blkHorizSplit) {
+ for (i = 0; i < blk->children->getLength(); ++i) {
+ child = (TextBlock *)blk->children->get(i);
+ if (y < child->yMax || i == blk->children->getLength() - 1) {
+ insertLargeCharInLeaf(ch, child);
+ blk->updateBounds(i);
+ break;
+ }
+ }
+ } else {
+ insertLargeCharInLeaf(ch, (TextBlock *)blk->children->get(0));
+ blk->updateBounds(0);
+ }
+}
+
+// Merge blk (rot != 0) into primaryTree (rot == 0).
+void TextPage::insertIntoTree(TextBlock *blk, TextBlock *primaryTree) {
+ TextBlock *child;
+
+ // we insert a whole column at a time - so call insertIntoTree
+ // recursively until we get to a column (or line)
+
+ if (blk->tag == blkTagMulticolumn) {
+ while (blk->children->getLength()) {
+ child = (TextBlock *)blk->children->del(0);
+ insertIntoTree(child, primaryTree);
+ }
+ delete blk;
+ } else {
+ insertColumnIntoTree(blk, primaryTree);
+ }
+}
+
+// Insert a column (as an atomic subtree) into tree.
+// Requirement: tree is not a leaf node.
+void TextPage::insertColumnIntoTree(TextBlock *column, TextBlock *tree) {
+ TextBlock *child;
+ int i;
+
+ for (i = 0; i < tree->children->getLength(); ++i) {
+ child = (TextBlock *)tree->children->get(i);
+ if (child->tag == blkTagMulticolumn &&
+ column->xMin >= child->xMin &&
+ column->yMin >= child->yMin &&
+ column->xMax <= child->xMax &&
+ column->yMax <= child->yMax) {
+ insertColumnIntoTree(column, child);
+ tree->tag = blkTagMulticolumn;
+ return;
+ }
+ }
+
+ if (tree->type == blkVertSplit) {
+ if (tree->rot == 1 || tree->rot == 2) {
+ for (i = 0; i < tree->children->getLength(); ++i) {
+ child = (TextBlock *)tree->children->get(i);
+ if (column->xMax > 0.5 * (child->xMin + child->xMax)) {
+ break;
+ }
+ }
+ } else {
+ for (i = 0; i < tree->children->getLength(); ++i) {
+ child = (TextBlock *)tree->children->get(i);
+ if (column->xMin < 0.5 * (child->xMin + child->xMax)) {
+ break;
+ }
+ }
+ }
+ } else if (tree->type == blkHorizSplit) {
+ if (tree->rot >= 2) {
+ for (i = 0; i < tree->children->getLength(); ++i) {
+ child = (TextBlock *)tree->children->get(i);
+ if (column->yMax > 0.5 * (child->yMin + child->yMax)) {
+ break;
+ }
+ }
+ } else {
+ for (i = 0; i < tree->children->getLength(); ++i) {
+ child = (TextBlock *)tree->children->get(i);
+ if (column->yMin < 0.5 * (child->yMin + child->yMax)) {
+ break;
+ }
+ }
+ }
+ } else {
+ // this should never happen
+ return;
+ }
+ tree->children->insert(i, column);
+ tree->tag = blkTagMulticolumn;
+}
+
+// Insert clipped characters back into the TextBlock tree.
+void TextPage::insertClippedChars(GList *clippedChars, TextBlock *tree) {
+ TextChar *ch, *ch2;
+ TextBlock *leaf;
+ double y;
+ int i;
+
+ //~ this currently works only for characters in the primary rotation
+
+ clippedChars->sort(TextChar::cmpX);
+ while (clippedChars->getLength()) {
+ ch = (TextChar *)clippedChars->del(0);
+ if (ch->rot != 0) {
+ continue;
+ }
+ if (!(leaf = findClippedCharLeaf(ch, tree))) {
+ continue;
+ }
+ leaf->addChild(ch, 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 <tree> to which clipped char <ch> can be appended.
+// Returns NULL if there is no appropriate append point.
+TextBlock *TextPage::findClippedCharLeaf(TextChar *ch, TextBlock *tree) {
+ TextBlock *ret, *child;
+ double y;
+ int i;
+
+ //~ this currently works only for characters in the primary rotation
+
+ y = 0.5 * (ch->yMin + ch->yMax);
+ if (tree->type == blkLeaf) {
+ if (tree->rot == 0) {
+ if (y > tree->yMin && y < tree->yMax &&
+ ch->xMin <= tree->xMax + clippedTextMaxWordSpace * ch->fontSize) {
+ return tree;
+ }
+ }
+ } else {
+ for (i = 0; i < tree->children->getLength(); ++i) {
+ child = (TextBlock *)tree->children->get(i);
+ if ((ret = findClippedCharLeaf(ch, child))) {
+ return ret;
+ }
+ }
+ }
+ return NULL;
+}
+
+// Convert the tree of TextBlocks into a list of TextColumns.
+GList *TextPage::buildColumns(TextBlock *tree, 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 <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include <stdio.h>
+#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 <idx>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 <startAtTop> is true, starts looking at the
+ // top of the page; else if <startAtLast> is true, starts looking
+ // immediately after the last find result; else starts looking at
+ // <xMin>,<yMin>. If <stopAtBottom> is true, stops looking at the
+ // bottom of the page; else if <stopAtLast> is true, stops looking
+ // just before the last find result; else stops looking at
+ // <xMax>,<yMax>.
+ 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 <forceEOL> 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 <fileName> is NULL, no file is
+ // written (this is useful, e.g., for searching text). If
+ // <physLayoutA> is true, the original physical layout of the text
+ // is maintained. If <rawOrder> is true, the text is kept in
+ // content stream order.
+ TextOutputDev(char *fileName, TextOutputControl *controlA,
+ GBool append, GBool fileNameIsUTF8 = gFalse);
+
+ // Create a TextOutputDev which will write to a generic stream. If
+ // <physLayoutA> is true, the original physical layout of the text
+ // is maintained. If <rawOrder> is true, the text is kept in
+ // content stream order.
+ TextOutputDev(TextOutputFunc func, void *stream,
+ 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 <startAtTop> is true, starts looking at the
+ // top of the page; else if <startAtLast> is true, starts looking
+ // immediately after the last find result; else starts looking at
+ // <xMin>,<yMin>. If <stopAtBottom> is true, stops looking at the
+ // bottom of the page; else if <stopAtLast> is true, stops looking
+ // just before the last find result; else stops looking at
+ // <xMax>,<yMax>.
+ 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 <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <string.h>
+#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 <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include "CharTypes.h"
+
+class GString;
+
+//------------------------------------------------------------------------
+
+class TextString {
+public:
+
+ // Create an empty TextString.
+ TextString();
+
+ // Create a TextString from a PDF text string.
+ TextString(GString *s);
+
+ // Copy a TextString.
+ TextString(TextString *s);
+
+ ~TextString();
+
+ // Append a Unicode character or PDF text string to this TextString.
+ TextString *append(Unicode c);
+ TextString *append(GString *s);
+
+ // Insert a Unicode character, 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 <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include "gmem.h"
+#include "gmempp.h"
+#include "GList.h"
+#include "GMutex.h"
+#ifdef _WIN32
+# include <windows.h>
+#else
+# include <pthread.h>
+# include <unistd.h>
+#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 <tile> on <tileList>, and return its index if found, or
+// -1 if not found. If <tile> is part of the cache, or if <tileList>
+// 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 <wait> 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 <tile>. 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 <aconf.h>
+
+#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 <finished> is non-NULL, *<finished> 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 <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <string.h>
+#include <math.h>
+#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 <color> 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 <aconf.h>
+
+#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 <finished> is is non-NULL, *<finished>
+ // 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 <aconf.h>
+
+#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 <aconf.h>
+
+#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 <page> 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 <page>
+ // at the bottom of the window.
+ int getPageBottomY(int page);
+
+ // Return the scrollX setting that would place the left side of
+ // <page> 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
+ // <page> 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 <aconf.h>
+#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 <aconf.h>
+
+#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 <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#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 <aconf.h>
+
+#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 <encodingName>. 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
+ // <encodingNameA>.
+ GBool match(GString *encodingNameA);
+
+ // Map Unicode to the target encoding. Fills in <buf> with the
+ // output and returns the number of bytes used. Output will be
+ // truncated at <bufSize> 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 <encodingName>. 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 <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#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 <len>-byte hex string <s> into *<val>. Returns false on
+// error.
+static GBool parseHex(char *s, int len, Guint *val) {
+ int i, x;
+
+ *val = 0;
+ for (i = 0; i < len; ++i) {
+ x = hexCharVals[s[i] & 0xff];
+ if (x < 0) {
+ return gFalse;
+ }
+ *val = (*val << 4) + x;
+ }
+ return gTrue;
+}
+
+//------------------------------------------------------------------------
+
+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 <aconf.h>
+
+#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 <in>.
+ void addRemapping(Unicode in, Unicode *out, int len);
+
+ // Add entries from the specified file to this UnicodeRemapping.
+ void parseFile(GString *fileName);
+
+ // Map <in> to zero or more (up to <size>) output characters in
+ // <out>. 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 <aconf.h>
+#include <stdlib.h>
+#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 <aconf.h>
+
+#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 <aconf.h>
+
+#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 <aconf.h>
+
+#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
+// - <area> nodes are dropped from the name
+// - used for field value lookup in <xfa:datasets>
+//
+// fullName:
+// - all named nodes are treated the same, regardless of bind=global
+// or bind=none
+// - <area> nodes are included in the name, but don't reset the
+// numbering (i.e., <area> nodes are "transparent" with respect to
+// node numbering)
+// - used for field value lookup in <form>
+// - 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 <xfa:datasets> packet
+ val = getDatasetsValue(name->getCString(), dataElem);
+ if (!val && exclGroupName) {
+ val = (GString *)getDatasetsValue(exclGroupName->getCString(), dataElem);
+ }
+
+ //--- check the <form> element
+ if (!val) {
+ val = (GString *)formValues->lookup(fullName);
+ }
+
+ //--- check the <value> 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 <aconf.h>
+
+#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 <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include <ctype.h>
+#include <limits.h>
+#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 <objStrNum>,
+ // 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 <objIdx>th object from this stream, which should be
+ // object number <objNum>, 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 <aconf.h>
+
+#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 <entries> array
+ int last; // last used index in <entries>
+ int rootNum, rootGen; // catalog dict
+ GBool ok; // true if xref table is valid
+ int errCode; // error code (if <ok> is false)
+ 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 <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#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("<?xml")) {
+ return;
+ }
+ parsePtr += 5;
+ parseSpace();
+
+ // version
+ version = NULL;
+ if (match("version")) {
+ parsePtr += 7;
+ parseSpace();
+ if (match("=")) {
+ ++parsePtr;
+ parseSpace();
+ version = parseQuotedString();
+ }
+ }
+ if (!version) {
+ version = new GString("1.0");
+ }
+ parseSpace();
+
+ // encoding
+ encoding = NULL;
+ if (match("encoding")) {
+ parsePtr += 8;
+ parseSpace();
+ if (match("=")) {
+ ++parsePtr;
+ parseSpace();
+ encoding = parseQuotedString();
+ }
+ }
+ parseSpace();
+
+ // standalone
+ standalone = false;
+ if (match("standalone")) {
+ parsePtr += 10;
+ parseSpace();
+ if (match("=")) {
+ ++parsePtr;
+ parseSpace();
+ s = parseQuotedString();
+ standalone = !s->cmp("yes");
+ delete s;
+ }
+ }
+ parseSpace();
+
+ if (match("?>")) {
+ parsePtr += 2;
+ }
+
+ par->addChild(new ZxXMLDecl(version, encoding, standalone));
+}
+
+//~ this just skips everything after the name
+void ZxDoc::parseDocTypeDecl(ZxNode *par) {
+ GString *name;
+ int state;
+ char c, quote;
+
+ if (!match("<!DOCTYPE")) {
+ return;
+ }
+ parsePtr += 9;
+ parseSpace();
+
+ name = parseName();
+ parseSpace();
+
+ state = 0;
+ quote = '\0';
+ while (parsePtr < parseEnd && state < 4) {
+ c = *parsePtr++;
+ switch (state) {
+ case 0: // not in square brackets; not in quotes
+ if (c == '>') {
+ state = 4;
+ } else if (c == '"' || c == '\'') {
+ state = 1;
+ } else if (c == '[') {
+ state = 2;
+ }
+ break;
+ case 1: // not in square brackets; in quotes
+ if (c == quote) {
+ state = 0;
+ }
+ break;
+ case 2: // in square brackets; not in quotes
+ if (c == ']') {
+ state = 0;
+ } else if (c == '"' || c == '\'') {
+ state = 3;
+ }
+ break;
+ case 3: // in square brackets; in quotes
+ if (c == quote) {
+ state = 2;
+ }
+ break;
+ }
+ }
+
+ par->addChild(new ZxDocTypeDecl(name));
+}
+
+// assumes match("<")
+void ZxDoc::parseElement(ZxNode *par) {
+ GString *type;
+ ZxElement *elem;
+ ZxAttr *attr;
+
+ ++parsePtr;
+ type = parseName();
+ elem = new ZxElement(type);
+ parseSpace();
+ while ((attr = parseAttr())) {
+ elem->addAttr(attr);
+ parseSpace();
+ }
+ if (match("/>")) {
+ parsePtr += 2;
+ } else if (match(">")) {
+ ++parsePtr;
+ parseContent(elem);
+ }
+ par->addChild(elem);
+}
+
+ZxAttr *ZxDoc::parseAttr() {
+ GString *name, *value;
+ const char *start;
+ char quote, c;
+ 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("<?")) {
+ parsePI(par);
+ } else if (match("<![CDATA[")) {
+ parseCDSect(par);
+ } else if (match("<!--")) {
+ parseComment(par);
+ } else if (match("<")) {
+ parseElement(par);
+ } else {
+ parseCharData(par);
+ }
+ }
+
+ delete endType;
+}
+
+void ZxDoc::parseCharData(ZxElement *par) {
+ GString *data;
+ const char *start;
+ char c;
+ unsigned int x;
+ int n;
+
+ data = new GString();
+ while (parsePtr < parseEnd && *parsePtr != '<') {
+ if (*parsePtr == '&') {
+ ++parsePtr;
+ if (parsePtr < parseEnd && *parsePtr == '#') {
+ ++parsePtr;
+ if (parsePtr < parseEnd && *parsePtr == 'x') {
+ ++parsePtr;
+ x = 0;
+ while (parsePtr < parseEnd) {
+ c = *parsePtr;
+ if (c >= '0' && c <= '9') {
+ x = (x << 4) + (c - '0');
+ } else if (c >= 'a' && c <= 'f') {
+ x = (x << 4) + (10 + c - 'a');
+ } else if (c >= 'A' && c <= 'F') {
+ x = (x << 4) + (10 + c - 'A');
+ } else {
+ break;
+ }
+ ++parsePtr;
+ }
+ if (parsePtr < parseEnd && *parsePtr == ';') {
+ ++parsePtr;
+ }
+ appendUTF8(data, x);
+ } else {
+ x = 0;
+ while (parsePtr < parseEnd) {
+ c = *parsePtr;
+ if (c >= '0' && c <= '9') {
+ x = x * 10 + (c - '0');
+ } else {
+ break;
+ }
+ ++parsePtr;
+ }
+ if (parsePtr < parseEnd && *parsePtr == ';') {
+ ++parsePtr;
+ }
+ appendUTF8(data, x);
+ }
+ } else {
+ start = parsePtr;
+ for (++parsePtr;
+ parsePtr < parseEnd && *parsePtr != ';' &&
+ *parsePtr != '<' && *parsePtr != '&';
+ ++parsePtr) ;
+ n = (int)(parsePtr - start);
+ if (parsePtr < parseEnd && *parsePtr == ';') {
+ ++parsePtr;
+ }
+ if (n == 2 && !strncmp(start, "lt", 2)) {
+ data->append('<');
+ } else if (n == 2 && !strncmp(start, "gt", 2)) {
+ data->append('>');
+ } else if (n == 3 && !strncmp(start, "amp", 3)) {
+ data->append('&');
+ } else if (n == 4 && !strncmp(start, "apos", 4)) {
+ data->append('\'');
+ } else if (n == 4 && !strncmp(start, "quot", 4)) {
+ data->append('"');
+ } else {
+ data->append(start - 1, (int)(parsePtr - start) + 1);
+ }
+ }
+ } else {
+ start = parsePtr;
+ for (++parsePtr;
+ parsePtr < parseEnd && *parsePtr != '<' && *parsePtr != '&';
+ ++parsePtr) ;
+ data->append(start, (int)(parsePtr - start));
+ }
+ }
+ par->addChild(new ZxCharData(data, true));
+}
+
+void ZxDoc::appendUTF8(GString *s, 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("<![CDATA[")
+void ZxDoc::parseCDSect(ZxNode *par) {
+ const char *start;
+
+ parsePtr += 9;
+ start = parsePtr;
+ while (parsePtr < parseEnd - 3) {
+ if (!strncmp(parsePtr, "]]>", 3)) {
+ par->addChild(new ZxCharData(new GString(start, (int)(parsePtr - start)),
+ false));
+ parsePtr += 3;
+ return;
+ }
+ ++parsePtr;
+ }
+ parsePtr = parseEnd;
+ par->addChild(new ZxCharData(new GString(start, (int)(parsePtr - start)),
+ false));
+}
+
+void ZxDoc::parseMisc(ZxNode *par) {
+ while (1) {
+ if (match("<!--")) {
+ parseComment(par);
+ } else if (match("<?")) {
+ parsePI(par);
+ } else if (parsePtr < parseEnd && (*parsePtr == '\x20' ||
+ *parsePtr == '\x09' ||
+ *parsePtr == '\x0d' ||
+ *parsePtr == '\x0a')) {
+ ++parsePtr;
+ } else {
+ break;
+ }
+ }
+}
+
+// assumes match("<!--")
+void ZxDoc::parseComment(ZxNode *par) {
+ const char *start;
+
+ parsePtr += 4;
+ start = parsePtr;
+ while (parsePtr <= parseEnd - 3) {
+ if (!strncmp(parsePtr, "-->", 3)) {
+ par->addChild(new ZxComment(new GString(start, (int)(parsePtr - start))));
+ parsePtr += 3;
+ return;
+ }
+ ++parsePtr;
+ }
+ parsePtr = parseEnd;
+}
+
+// assumes match("<?")
+void ZxDoc::parsePI(ZxNode *par) {
+ GString *target;
+ const char *start;
+
+ parsePtr += 2;
+ target = parseName();
+ parseSpace();
+ start = parsePtr;
+ while (parsePtr <= parseEnd - 2) {
+ if (!strncmp(parsePtr, "?>", 2)) {
+ par->addChild(new ZxPI(target, new GString(start,
+ (int)(parsePtr - start))));
+ parsePtr += 2;
+ return;
+ }
+ ++parsePtr;
+ }
+ parsePtr = parseEnd;
+ par->addChild(new ZxPI(target, new GString(start, (int)(parsePtr - start))));
+}
+
+//~ this accepts all chars >= 0x80
+//~ this doesn't check for properly-formed UTF-8
+GString *ZxDoc::parseName() {
+ GString *name;
+
+ name = new GString();
+ if (parsePtr < parseEnd && nameStartChar[*parsePtr & 0xff]) {
+ name->append(*parsePtr++);
+ while (parsePtr < parseEnd && nameChar[*parsePtr & 0xff]) {
+ name->append(*parsePtr++);
+ }
+ }
+ return name;
+}
+
+GString *ZxDoc::parseQuotedString() {
+ GString *s;
+ const char *start;
+ char quote;
+
+ if (parsePtr < parseEnd && (*parsePtr == '"' || *parsePtr == '\'')) {
+ quote = *parsePtr++;
+ start = parsePtr;
+ while (parsePtr < parseEnd && *parsePtr != quote) {
+ ++parsePtr;
+ }
+ s = new GString(start, (int)(parsePtr - start));
+ if (parsePtr < parseEnd && *parsePtr == quote) {
+ ++parsePtr;
+ }
+ } else {
+ s = new GString();
+ }
+ return s;
+}
+
+void ZxDoc::parseSpace() {
+ while (parsePtr < parseEnd && (*parsePtr == '\x20' ||
+ *parsePtr == '\x09' ||
+ *parsePtr == '\x0d' ||
+ *parsePtr == '\x0a')) {
+ ++parsePtr;
+ }
+}
+
+bool ZxDoc::match(const char *s) {
+ int n;
+
+ n = (int)strlen(s);
+ return parseEnd - parsePtr >= n && !strncmp(parsePtr, s, n);
+}
+
+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("<?xml version=\"");
+ s->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("<!DOCTYPE ");
+ s->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("<!--");
+ s->append(text);
+ s->append("-->");
+ 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("<?");
+ s->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("</");
+ s->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("&lt;");
+ } else if (c == '>') {
+ out->append("&gt;");
+ } else if (c == '&') {
+ out->append("&amp;");
+ } else if (c == '"') {
+ out->append("&quot;");
+ } 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("&lt;");
+ } else if (c == '>') {
+ s->append("&gt;");
+ } else if (c == '&') {
+ s->append("&amp;");
+ } else {
+ s->append(c);
+ }
+ }
+ } else {
+ s->append("<![CDATA[");
+ s->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 <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include "gtypes.h"
+
+class GString;
+class GList;
+class GHash;
+
+class ZxAttr;
+class ZxDocTypeDecl;
+class ZxElement;
+class ZxXMLDecl;
+
+//------------------------------------------------------------------------
+
+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
--- /dev/null
+++ b/xpdf/pdfdetach
Binary files 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 <aconf.h>
+#include <stdio.h>
+#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", "<PDF-file>", 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
--- /dev/null
+++ b/xpdf/pdffonts
Binary files 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 <aconf.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include <math.h>
+#include <limits.h>
+#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", "<PDF-file>", 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
--- /dev/null
+++ b/xpdf/pdfimages
Binary files 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 <aconf.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#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", "<PDF-file> <image-root>", 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
--- /dev/null
+++ b/xpdf/pdfinfo
Binary files 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 <aconf.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include <time.h>
+#include <math.h>
+#include <ctype.h>
+#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", "<PDF-file>", 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
--- /dev/null
+++ b/xpdf/pdftohtml
Binary files 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 <aconf.h>
+#include <stdio.h>
+#include <stdlib.h>
+#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", "<PDF-file> <html-dir>", 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, "<html>\n");
+ fprintf(html, "<body>\n");
+ for (pg = firstPage; pg <= lastPage; ++pg) {
+ fprintf(html, "<a href=\"page%d.html\">page %d</a><br>\n", pg, pg);
+ }
+ fprintf(html, "</body>\n");
+ fprintf(html, "</html>\n");
+
+ fclose(html);
+
+ return gTrue;
+}
diff --git a/xpdf/pdftopng b/xpdf/pdftopng
new file mode 100755
index 0000000..f3120c5
--- /dev/null
+++ b/xpdf/pdftopng
Binary files 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 <aconf.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <png.h>
+#ifdef _WIN32
+# include <io.h>
+# include <fcntl.h>
+#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", "<PDF-file> <PNG-root>", 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
--- /dev/null
+++ b/xpdf/pdftoppm
Binary files 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 <aconf.h>
+#include <stdio.h>
+#ifdef _WIN32
+# include <io.h>
+# include <fcntl.h>
+#endif
+#ifdef DEBUG_FP_LINUX
+# include <fenv.h>
+# include <fpu_control.h>
+#endif
+#include "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", "<PDF-file> <PPM-root>", 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
--- /dev/null
+++ b/xpdf/pdftops
Binary files 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 <aconf.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#ifdef DEBUG_FP_LINUX
+# include <fenv.h>
+# include <fpu_control.h>
+#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", "<PDF-file> [<PS-file>]", 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
--- /dev/null
+++ b/xpdf/pdftotext
Binary files 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 <aconf.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#ifdef DEBUG_FP_LINUX
+# include <fenv.h>
+# include <fpu_control.h>
+#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", "<PDF-file> [<text-file>]", 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 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
+ <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
+ <security>
+ <requestedPrivileges>
+ <requestedExecutionLevel level="asInvoker" uiAccess="false"></requestedExecutionLevel>
+ </requestedPrivileges>
+ </security>
+ </trustInfo>
+ <application xmlns="urn:schemas-microsoft-com:asm.v3">
+ <windowsSettings xmlns:ws2="http://schemas.microsoft.com/SMI/2016/WindowsSettings">
+ <ws2:longPathAware>true</ws2:longPathAware>
+ </windowsSettings>
+ </application>
+</assembly>